Skip to content

Commit

Permalink
Merge pull request #3885 from 9rnsr/fix13321
Browse files Browse the repository at this point in the history
[REG2.065] Issue 13321 - Wrong goto skips declaration error
  • Loading branch information
AndrejMitrovic committed Dec 6, 2014
2 parents b27e150 + ada7e9c commit 1f8174f
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 51 deletions.
7 changes: 7 additions & 0 deletions src/constfold.c
Expand Up @@ -1175,6 +1175,13 @@ UnionExp Cast(Type *type, Type *to, Expression *e1)
return ue;
}

if (e1->op == TOKvector && ((TypeVector *)e1->type)->basetype->equals(type) && type->equals(to))
{
Expression *ex = ((VectorExp *)e1)->e1;
memcpy(&ue, ex, ex->size);
return ue;
}

if (e1->type->implicitConvTo(to) >= MATCHconst ||
to->implicitConvTo(e1->type) >= MATCHconst)
{
Expand Down
3 changes: 3 additions & 0 deletions src/ctfeexpr.c
Expand Up @@ -446,6 +446,9 @@ Expression *resolveSlice(Expression *e)
*/
uinteger_t resolveArrayLength(Expression *e)
{
if (e->op == TOKvector)
e = ((VectorExp *)e)->e1;

if (e->op == TOKnull)
return 0;
if (e->op == TOKslice)
Expand Down
50 changes: 21 additions & 29 deletions src/expression.c
Expand Up @@ -8346,44 +8346,38 @@ Expression *CallExp::semantic(Scope *sc)
// Check for call operator overload
if (t1)
{
AggregateDeclaration *ad;
if (t1->ty == Tstruct)
{
ad = ((TypeStruct *)t1)->sym;
StructDeclaration *sd = ((TypeStruct *)t1)->sym;

// First look for constructor
if (e1->op == TOKtype && ad->ctor)
if (e1->op == TOKtype && sd->ctor)
{
if (!ad->noDefaultCtor && !(arguments && arguments->dim))
if (!sd->noDefaultCtor && !(arguments && arguments->dim))
goto Lx;

// Create variable that will get constructed
Identifier *idtmp = Lexer::uniqueId("__ctmp");
StructLiteralExp *sle = new StructLiteralExp(loc, sd, NULL, e1->type);
if (!sd->fill(loc, sle->elements, true))
return new ErrorExp();

ExpInitializer *ei = NULL;
if (t1->needsNested())
{
StructDeclaration *sd = (StructDeclaration *)ad;
StructLiteralExp *sle = new StructLiteralExp(loc, sd, NULL, e1->type);
if (!sd->fill(loc, sle->elements, true))
return new ErrorExp();
sle->type = type;
ei = new ExpInitializer(loc, sle);
}
VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, ei);
tmp->storage_class |= STCtemp | STCctfe;
/* Copy from the initializer symbol for larger symbols,
* otherwise the literals expressed as code get excessively large.
*/
if (sd->size(loc) > Target::ptrsize * 4 && !t1->needsNested())
sle->sinit = sd->toInitializer();

Expression *e = new DeclarationExp(loc, tmp);
e = new CommaExp(loc, e, new VarExp(loc, tmp));
if (CtorDeclaration *cf = ad->ctor->isCtorDeclaration())
sle->type = type;

Expression *e = sle;
if (CtorDeclaration *cf = sd->ctor->isCtorDeclaration())
{
e = new DotVarExp(loc, e, cf, 1);
}
else if (TemplateDeclaration *td = ad->ctor->isTemplateDeclaration())
else if (TemplateDeclaration *td = sd->ctor->isTemplateDeclaration())
{
e = new DotTemplateExp(loc, e, td);
}
else if (OverloadSet *os = ad->ctor->isOverloadSet())
else if (OverloadSet *os = sd->ctor->isOverloadSet())
{
e = new DotExp(loc, e, new OverExp(loc, os));
}
Expand All @@ -8394,33 +8388,31 @@ Expression *CallExp::semantic(Scope *sc)
return e;
}
// No constructor, look for overload of opCall
if (search_function(ad, Id::call))
if (search_function(sd, Id::call))
goto L1; // overload of opCall, therefore it's a call

if (e1->op != TOKtype)
{
if (ad->aliasthis && e1->type != att1)
if (sd->aliasthis && e1->type != att1)
{
if (!att1 && e1->type->checkAliasThisRec())
att1 = e1->type;
e1 = resolveAliasThis(sc, e1);
goto Lagain;
}
error("%s %s does not overload ()", ad->kind(), ad->toChars());
error("%s %s does not overload ()", sd->kind(), sd->toChars());
return new ErrorExp();
}

/* It's a struct literal
*/
Lx:
Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments, e1->type);
Expression *e = new StructLiteralExp(loc, sd, arguments, e1->type);
e = e->semantic(sc);
return e;
}
else if (t1->ty == Tclass)
{
ad = ((TypeClass *)t1)->sym;
goto L1;
L1:
// Rewrite as e1.call(arguments)
Expression *e = new DotIdExp(loc, e1, Id::call);
Expand Down
7 changes: 6 additions & 1 deletion src/interpret.c
Expand Up @@ -3795,6 +3795,8 @@ class Interpreter : public Visitor
/* Assignment to variable of the form:
* v = newval
*/
if (e1->op == TOKvector)
e1 = ((VectorExp *)e1)->e1;
if (e1->op == TOKvar)
{
VarExp *ve = (VarExp *)e1;
Expand Down Expand Up @@ -4017,6 +4019,7 @@ class Interpreter : public Visitor
return false;
}
if (oldval->op != TOKarrayliteral &&
oldval->op != TOKvector &&
oldval->op != TOKstring &&
oldval->op != TOKslice)
{
Expand Down Expand Up @@ -4142,6 +4145,8 @@ class Interpreter : public Visitor
}
if (aggregate->op == TOKarrayliteral)
existingAE = (ArrayLiteralExp *)aggregate;
else if (aggregate->op == TOKvector)
existingAE = (ArrayLiteralExp *)((VectorExp *)aggregate)->e1;
else if (aggregate->op == TOKstring)
existingSE = (StringExp *)aggregate;
else
Expand Down Expand Up @@ -6181,7 +6186,7 @@ class Interpreter : public Visitor
if (result->op == TOKstructliteral)
return;
if ((e->type->ty == Tsarray || goal == ctfeNeedLvalue) && (
result->op == TOKarrayliteral ||
result->op == TOKarrayliteral || result->op == TOKvector ||
result->op == TOKassocarrayliteral || result->op == TOKstring ||
result->op == TOKclassreference || result->op == TOKslice))
{
Expand Down
2 changes: 1 addition & 1 deletion src/statement.c
Expand Up @@ -4905,7 +4905,7 @@ bool GotoStatement::checkLabel()
error("goto skips declaration of with temporary at %s", vd->loc.toChars());
return true;
}
else if (!(vd->storage_class & STCtemp))
else
{
error("goto skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
return true;
Expand Down
36 changes: 16 additions & 20 deletions test/compilable/test602.d
Expand Up @@ -182,7 +182,6 @@ static assert(!__traits(compiles, (bool b)
if (b) goto label;
}));

/*
// Goto into foreach loop
static assert(!__traits(compiles, (bool b)
{
Expand All @@ -193,9 +192,7 @@ static assert(!__traits(compiles, (bool b)
assert(i);
}
}));
*/

/*
// Goto into foreach loop backwards
static assert(!__traits(compiles, (bool b)
{
Expand All @@ -206,7 +203,6 @@ static assert(!__traits(compiles, (bool b)
}
if (b) goto label;
}));
*/

// Goto into if block with variable
static assert(!__traits(compiles, (bool b)
Expand Down Expand Up @@ -397,20 +393,20 @@ int test11659()
return mixin(expr);
}

/***************************************************/
// 13321

void test13321(bool b)
{
static struct Foo
{
this(int) {}
}
Foo x;
if (b)
goto EXIT;
x = Foo(1);
EXIT:
}
/***************************************************/
// 13321

void test13321(bool b)
{
static struct Foo
{
this(int) {}
}

Foo x;
if (b)
goto EXIT;
x = Foo(1);
EXIT:
}

0 comments on commit 1f8174f

Please sign in to comment.