Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/stable' into merge_stable_convert
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinNowak committed Aug 29, 2015
2 parents 9d9cb89 + 955eb73 commit 1cfd4a9
Show file tree
Hide file tree
Showing 24 changed files with 533 additions and 253 deletions.
2 changes: 1 addition & 1 deletion src/cppmangle.c
Expand Up @@ -1437,7 +1437,7 @@ class VisualCPPMangler : public Visitor

t->accept(this);

if ((t->ty == Tpointer || t->ty == Treference) && global.params.is64bit)
if ((t->ty == Tpointer || t->ty == Treference || t->ty == Tclass) && global.params.is64bit)
{
buf.writeByte('E');
}
Expand Down
78 changes: 56 additions & 22 deletions src/declaration.c
Expand Up @@ -384,6 +384,11 @@ void AliasDeclaration::semantic(Scope *sc)
* try to alias y to 3.
*/
s = type->toDsymbol(sc);
if (errors != global.errors)
{
s = NULL;
type = Type::terror;
}
if (s && s == this)
{
error("cannot resolve");
Expand Down Expand Up @@ -1384,17 +1389,26 @@ void VarDeclaration::semantic(Scope *sc)
init = ei;
}

Expression *exp = ei->exp;
Expression *e1 = new VarExp(loc, this);
if (isBlit)
ei->exp = new BlitExp(loc, e1, ei->exp);
exp = new BlitExp(loc, e1, exp);
else
ei->exp = new ConstructExp(loc, e1, ei->exp);
exp = new ConstructExp(loc, e1, exp);
canassign++;
ei->exp = ei->exp->semantic(sc);
exp = exp->semantic(sc);
canassign--;
ei->exp->optimize(WANTvalue);
exp = exp->optimize(WANTvalue);

if (exp->op == TOKerror)
{
init = new ErrorInitializer();
ei = NULL;
}
else
ei->exp = exp;

if (isScope())
if (ei && isScope())
{
Expression *ex = ei->exp;
while (ex->op == TOKcomma)
Expand Down Expand Up @@ -1789,16 +1803,46 @@ bool lambdaCheckForNestedRef(Expression *e, Scope *sc);
bool VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("VarDeclaration::checkNestedReference() %s\n", toChars());
if (parent && parent != sc->parent &&
!isDataseg() && !(storage_class & STCmanifest) &&
sc->intypeof != 1 && !(sc->flags & SCOPEctfe))
if (sc->intypeof == 1 || (sc->flags & SCOPEctfe))
return false;
if (!parent || parent == sc->parent)
return false;
if (isDataseg() || (storage_class & STCmanifest))
return false;

// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
if (!fdthis)
return false; // out of function scope

Dsymbol *p = toParent2();

// Function literals from fdthis to p must be delegates
// TODO: here is similar to checkFrameAccess.
for (Dsymbol *s = fdthis; s && s != p; s = s->toParent2())
{
// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
fld->tok = TOKdelegate;

if (FuncDeclaration *fd = s->isFuncDeclaration())
{
if (!fd->isThis() && !fd->isNested())
break;
}
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
if (ad2->storage_class & STCstatic)
break;
}
}

if (1)
{
// The function that this variable is in
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
FuncDeclaration *fdv = p->isFuncDeclaration();

if (fdv && fdthis && fdv != fdthis)
if (fdv && fdv != fdthis)
{
// Add fdthis to nestedrefs[] if not already there
for (size_t i = 0; 1; i++)
Expand Down Expand Up @@ -1858,16 +1902,6 @@ bool VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
}
}

// Function literals from fdthis to fdv must be delegates
for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2())
{
// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
{
fld->tok = TOKdelegate;
}
}

// Add this to fdv->closureVars[] if not already there
for (size_t i = 0; 1; i++)
{
Expand Down
73 changes: 2 additions & 71 deletions src/dsymbol.c
Expand Up @@ -449,50 +449,12 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, (void *)this, idchars);
}

/*************************************
* Take an index in a TypeTuple.
*/
Dsymbol *Dsymbol::takeTypeTupleIndex(Loc loc, Scope *sc, Dsymbol *s, RootObject *id, Expression *indexExpr)
{
TupleDeclaration *td = s->isTupleDeclaration();
if (!td)
{
error(loc, "expected TypeTuple when indexing ('[%s]'), got '%s'.",
id->toChars(), s->toChars());
return NULL;
}
sc = sc->startCTFE();
indexExpr = indexExpr->semantic(sc);
sc = sc->endCTFE();

indexExpr = indexExpr->ctfeInterpret();
const uinteger_t d = indexExpr->toUInteger();

if (d >= td->objects->dim)
{
error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim);
return NULL;
}
RootObject *o = (*td->objects)[(size_t)d];
if (o->dyncast() == DYNCAST_TYPE)
{
Type *t = (Type *)o;
return t->toDsymbol(sc)->toAlias();
}
else
{
assert(o->dyncast() == DYNCAST_DSYMBOL);
return (Dsymbol *)o;
}
}

/***************************************
* Search for identifier id as a member of 'this'.
* id may be a template instance.
* Returns:
* symbol found, NULL if not
*/

Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
{
//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
Expand All @@ -514,39 +476,6 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
sm = s->search(loc, (Identifier *)id);
break;

case DYNCAST_TYPE:
{
Type *index = (Type *)id;
Expression *expr = NULL;
Type *t = NULL;
Dsymbol *sym = NULL;

index->resolve(loc, sc, &expr, &t, &sym);
if (expr)
{
sm = takeTypeTupleIndex(loc, sc, s, id, expr);
}
else if (t)
{
index->error(loc, "expected an expression as index, got a type (%s)", t->toChars());
return NULL;
}
else
{
index->error(loc, "index is not an expression");
return NULL;
}
break;
}

case DYNCAST_EXPRESSION:
sm = takeTypeTupleIndex(loc, sc, s, id, (Expression *)id);
if (!sm)
{
return NULL;
}
break;

case DYNCAST_DSYMBOL:
{
// It's a template instance
Expand Down Expand Up @@ -579,6 +508,8 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
break;
}

case DYNCAST_TYPE:
case DYNCAST_EXPRESSION:
default:
assert(0);
}
Expand Down
3 changes: 0 additions & 3 deletions src/dsymbol.h
Expand Up @@ -274,9 +274,6 @@ class Dsymbol : public RootObject
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual void accept(Visitor *v) { v->visit(this); }

private:
Dsymbol *takeTypeTupleIndex(Loc loc, Scope *sc, Dsymbol *s, RootObject *id, Expression *indexExpr);
};

// Dsymbol that generates a scope
Expand Down
12 changes: 12 additions & 0 deletions src/expression.c
Expand Up @@ -3368,6 +3368,10 @@ Expression *DsymbolExp::semantic(Scope *sc)
v->semantic(v->scope);
s = v->toAlias(); // Need this if 'v' is a tuple variable
}

// Change the ancestor lambdas to delegate before hasThis(sc) call.
if (v->checkNestedReference(sc, loc))
return new ErrorExp();
}
if (s->needThis() && hasThis(sc))
{
Expand Down Expand Up @@ -5324,6 +5328,9 @@ Expression *VarExp::semantic(Scope *sc)
}
else if (FuncDeclaration *fd = var->isFuncDeclaration())
{
// TODO: If fd isn't yet resolved its overload, the checkNestedReference
// call would cause incorrect validation.
// Maybe here should be moved in CallExp, or AddrExp for functions.
if (fd->checkNestedReference(sc, loc))
return new ErrorExp();
}
Expand Down Expand Up @@ -6049,6 +6056,7 @@ Expression *DeclarationExp::semantic(Scope *sc)
declaration->semantic3(sc);
}
}
// todo: error in declaration should be propagated.

type = Type::tvoid;
return this;
Expand Down Expand Up @@ -8981,6 +8989,10 @@ Expression *CallExp::semantic(Scope *sc)

if (f->needThis())
{
// Change the ancestor lambdas to delegate before hasThis(sc) call.
if (f->checkNestedReference(sc, loc))
return new ErrorExp();

if (hasThis(sc))
{
// Supply an implicit 'this', as in
Expand Down
52 changes: 38 additions & 14 deletions src/func.c
Expand Up @@ -4134,20 +4134,50 @@ const char *FuncDeclaration::kind()
bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
if (parent && parent != sc->parent && this->isNested() &&
this->ident != Id::require && this->ident != Id::ensure)
if (!parent || parent == sc->parent)
return false;
if (ident == Id::require || ident == Id::ensure)
return false;
if (!isThis() && !isNested())
return false;

// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
if (!fdthis)
return false; // out of function scope

Dsymbol *p = toParent2();

// Function literals from fdthis to p must be delegates
// TODO: here is similar to checkFrameAccess.
for (Dsymbol *s = fdthis; s && s != p; s = s->toParent2())
{
// The function that this function is in
FuncDeclaration *fdv2 = toParent2()->isFuncDeclaration();
// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
fld->tok = TOKdelegate;

if (FuncDeclaration *fd = s->isFuncDeclaration())
{
if (!fd->isThis() && !fd->isNested())
break;
}
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
if (ad2->storage_class & STCstatic)
break;
}
}

// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
if (isNested())
{
// The function that this function is in
FuncDeclaration *fdv2 = p->isFuncDeclaration();

//printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
//printf("fdv2 = %s in [%s]\n", fdv2->toChars(), fdv2->loc.toChars());
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());

if (fdv2 && fdthis && fdv2 != fdthis)
if (fdv2 && fdv2 != fdthis)
{
// Add this function to the list of those which called us
if (fdthis != this)
Expand All @@ -4167,7 +4197,7 @@ bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
}
}

FuncDeclaration *fdv = toParent2()->isFuncDeclaration();
FuncDeclaration *fdv = p->isFuncDeclaration();
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis->getLevel(loc, sc, fdv);
Expand All @@ -4179,12 +4209,6 @@ bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
return false; // same level call

// Uplevel call

// BUG: may need to walk up outer scopes like Declaration::checkNestedReference() does

// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = fdthis->isFuncLiteralDeclaration())
fld->tok = TOKdelegate;
}
}
return false;
Expand Down

0 comments on commit 1cfd4a9

Please sign in to comment.