Skip to content

Commit

Permalink
Merge pull request #164 from 9rnsr/fix4539
Browse files Browse the repository at this point in the history
Retry to fix issue 4539 - Refuse assignment to string literal
  • Loading branch information
WalterBright committed Jan 29, 2012
2 parents 425a97c + 05089ef commit 7f33ed7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 8 deletions.
11 changes: 10 additions & 1 deletion src/expression.c
Expand Up @@ -3379,7 +3379,10 @@ int StringExp::isBool(int result)
#if DMDV2
int StringExp::isLvalue()
{
return 1;
/* string literal is rvalue in default, but
* conversion to reference of static array is only allowed.
*/
return 0;
}
#endif

Expand All @@ -3389,6 +3392,12 @@ Expression *StringExp::toLvalue(Scope *sc, Expression *e)
return this;
}

Expression *StringExp::modifiableLvalue(Scope *sc, Expression *e)
{
error("Cannot modify '%s'", toChars());
return this;
}

unsigned StringExp::charAt(size_t i)
{ unsigned value;

Expand Down
1 change: 1 addition & 0 deletions src/expression.h
Expand Up @@ -385,6 +385,7 @@ struct StringExp : Expression
int isBool(int result);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
unsigned charAt(size_t i);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expand Down
21 changes: 15 additions & 6 deletions src/mtype.c
Expand Up @@ -5673,13 +5673,18 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
Type *tprm = wildmatch ? p->type->substWildTo(wildmatch) : p->type;

// Non-lvalues do not match ref or out parameters
if (p->storageClass & (STCref | STCout))
if (p->storageClass & STCref)
{ if (!arg->isLvalue())
goto Nomatch;
}
{ if (arg->op == TOKstring && tprm->ty == Tsarray)
{ if (targ->ty != Tsarray)
targ = new TypeSArray(targ->nextOf(),
new IntegerExp(0, ((StringExp *)arg)->len,
Type::tindex));
}
else
goto Nomatch;
}

if (p->storageClass & STCref)
{
/* Don't allow static arrays to be passed to mutable references
* to static arrays if the argument cannot be modified.
*/
Expand All @@ -5692,7 +5697,11 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
goto Nomatch;

// ref variable behaves like head-const reference
if (arg->op != TOKstring && !targb->constConv(tprmb))
if (!targb->constConv(tprmb))
goto Nomatch;
}
else if (p->storageClass & STCout)
{ if (!arg->isLvalue())
goto Nomatch;
}

Expand Down
3 changes: 2 additions & 1 deletion test/runnable/test42.d
Expand Up @@ -3995,7 +3995,8 @@ float parse(ref string p)
void test230()
{
float f;
f = parse( "123e+2" );
string s = "123e+2";
f = parse( s );
//printf("f = %g\n", f);
assert( f == 123e+2f );
}
Expand Down
35 changes: 35 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -3317,6 +3317,40 @@ static assert(!is(typeof(Bar4258.init + 1)));
static assert(!is(typeof(Bar4258.init += 1)));
static assert(!is(typeof(1 + Baz4258.init)));

/***************************************************/
// 4539

void test4539()
{
static assert(!__traits(compiles, "hello" = "red"));

void foo1(ref string s){}
void foo2(ref const char[10] s){}
void foo3(ref char[5] s){}

void foo4(ref const char[5] s)
{
assert(s[0] == 'h');
assert(s[4] == 'o');
}
void foo5(ref const ubyte[5] s)
{
assert(s[0] == 0xc3);
assert(s[4] == 0x61);
}

static assert(!__traits(compiles, foo1("hello")));
static assert(!__traits(compiles, foo2("hello")));
static assert(!__traits(compiles, foo3("hello")));

// same as test68, 69, 70
foo4("hello");
foo5(cast(ubyte[5])x"c3fcd3d761");

//import std.conv;
//static assert(!__traits(compiles, parse!int("10") == 10));
}

/***************************************************/
// 1471

Expand Down Expand Up @@ -4594,6 +4628,7 @@ int main()
test155();
test156();
test4258();
test4539();
test4963();
test4031();
test6230();
Expand Down

0 comments on commit 7f33ed7

Please sign in to comment.