Skip to content

Commit

Permalink
Merge pull request #9647 from SSoulaimane/parentDeclfix
Browse files Browse the repository at this point in the history
Move `toParentDecl` to `toParentLocal` and make a new `toParentDecl()` which follows the declaration scope even for static templates
merged-on-behalf-of: Nicholas Wilson <[email protected]>
  • Loading branch information
dlang-bot authored Apr 22, 2019
2 parents 1a12444 + 748698a commit 40d85cf
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 33 deletions.
31 changes: 28 additions & 3 deletions src/dmd/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,9 @@ extern (C++) class Dsymbol : ASTNode
* `toParentDecl()` similar to `toParent2()` but always follows the template declaration scope
* instead of the instantiation scope.
*
* `toParentLocal()` similar to `toParentDecl()` but follows the instantiation scope
* if a template declaration is non-local i.e. global or static.
*
* Examples:
* module mod;
* template Foo(alias a) { mixin Bar!(); }
Expand All @@ -498,6 +501,8 @@ extern (C++) class Dsymbol : ASTNode
* // s.parent == TemplateMixin('mod.test.Foo!().Bar!()')
* // s.toParent() == TemplateInstance('mod.test.Foo!()')
* // s.toParent2() == FuncDeclaration('mod.test')
* // s.toParentDecl() == Module('mod')
* // s.toParentLocal() == FuncDeclaration('mod.test')
*/
final inout(Dsymbol) toParent() inout
{
Expand All @@ -520,14 +525,25 @@ extern (C++) class Dsymbol : ASTNode

/// ditto
final inout(Dsymbol) toParentDecl() inout
{
return toParentDeclImpl(false);
}

/// ditto
final inout(Dsymbol) toParentLocal() inout
{
return toParentDeclImpl(true);
}

private inout(Dsymbol) toParentDeclImpl(bool localOnly) inout
{
auto p = toParent();
if (!p || !p.isTemplateInstance())
return p;
auto ti = p.isTemplateInstance();
if (ti.enclosing && ti.tempdecl && !(cast(TemplateDeclaration)ti.tempdecl).isstatic)
return ti.tempdecl.toParentDecl();
return parent.toParentDecl();
if (ti.tempdecl && (!localOnly || !(cast(TemplateDeclaration)ti.tempdecl).isstatic))
return ti.tempdecl.toParentDeclImpl(localOnly);
return parent.toParentDeclImpl(localOnly);
}

final inout(TemplateInstance) isInstantiated() inout
Expand Down Expand Up @@ -928,6 +944,15 @@ extern (C++) class Dsymbol : ASTNode
return p ? p.isAggregateDeclaration() : null;
}

/// Returns an AggregateDeclaration when toParentLocal() is that.
final inout(AggregateDeclaration) isMemberLocal() inout
{
//printf("Dsymbol::isMemberLocal() '%s'\n", toChars());
auto p = toParentLocal();
//printf("parent is %s %s\n", p.kind(), p.toChars());
return p ? p.isAggregateDeclaration() : null;
}

// is this a member of a ClassDeclaration?
final ClassDeclaration isClassMember()
{
Expand Down
10 changes: 6 additions & 4 deletions src/dmd/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class Dsymbol : public ASTNode
Dsymbol *toParent2();
Dsymbol *toParent3();
Dsymbol *toParentDecl();
Dsymbol *toParentLocal();
TemplateInstance *isInstantiated();
TemplateInstance *isSpeculative();
Ungag ungagSpeculative();
Expand Down Expand Up @@ -207,10 +208,11 @@ class Dsymbol : public ASTNode
virtual bool isDeprecated(); // is Dsymbol deprecated?
virtual bool isOverloadable();
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
AggregateDeclaration *isMember(); // is this a member of an AggregateDeclaration?
AggregateDeclaration *isMember2(); // is this a member of an AggregateDeclaration?
AggregateDeclaration *isMemberDecl(); // is this a member of an AggregateDeclaration?
ClassDeclaration *isClassMember(); // is this a member of a ClassDeclaration?
AggregateDeclaration *isMember(); // is toParent() an AggregateDeclaration?
AggregateDeclaration *isMember2(); // is toParent2() an AggregateDeclaration?
AggregateDeclaration *isMemberDecl(); // is toParentDecl() an AggregateDeclaration?
AggregateDeclaration *isMemberLocal(); // is toParentLocal() an AggregateDeclaration?
ClassDeclaration *isClassMember(); // isMember() is a ClassDeclaration?
virtual Type *getType(); // is this a type?
virtual bool needThis(); // need a 'this' pointer?
virtual Prot prot();
Expand Down
16 changes: 8 additions & 8 deletions src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -5082,23 +5082,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Use the base class's 'this' member
if (cldec.storage_class & STC.static_)
cldec.error("static class cannot inherit from nested class `%s`", cldec.baseClass.toChars());
if (cldec.toParentDecl() != cldec.baseClass.toParentDecl() &&
(!cldec.toParentDecl() ||
!cldec.baseClass.toParentDecl().getType() ||
!cldec.baseClass.toParentDecl().getType().isBaseOf(cldec.toParentDecl().getType(), null)))
if (cldec.toParentLocal() != cldec.baseClass.toParentLocal() &&
(!cldec.toParentLocal() ||
!cldec.baseClass.toParentLocal().getType() ||
!cldec.baseClass.toParentLocal().getType().isBaseOf(cldec.toParentLocal().getType(), null)))
{
if (cldec.toParentDecl())
if (cldec.toParentLocal())
{
cldec.error("is nested within `%s`, but super class `%s` is nested within `%s`",
cldec.toParentDecl().toChars(),
cldec.toParentLocal().toChars(),
cldec.baseClass.toChars(),
cldec.baseClass.toParentDecl().toChars());
cldec.baseClass.toParentLocal().toChars());
}
else
{
cldec.error("is not nested, but super class `%s` is nested within `%s`",
cldec.baseClass.toChars(),
cldec.baseClass.toParentDecl().toChars());
cldec.baseClass.toParentLocal().toChars());
}
cldec.enclosing = null;
}
Expand Down
4 changes: 2 additions & 2 deletions src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ private elem *callfunc(const ref Loc loc,
}
}

if (fd && fd.isMemberDecl())
if (fd && fd.isMemberLocal())
{
assert(op == NotIntrinsic); // members should not be intrinsics

Expand Down Expand Up @@ -1678,7 +1678,7 @@ elem *toElem(Expression e, IRState *irs)
//printf("cdthis = %s\n", cdthis.toChars());
assert(cd.isNested());
int offset = 0;
Dsymbol cdp = cd.toParentDecl(); // class we're nested in
Dsymbol cdp = cd.toParentLocal(); // class we're nested in

//printf("member = %p\n", member);
//printf("cdp = %s\n", cdp.toChars());
Expand Down
6 changes: 3 additions & 3 deletions src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ bool isNeedThisScope(Scope* sc, Declaration d)
return false;
//printf("d = %s, ad = %s\n", d.toChars(), ad.toChars());

for (Dsymbol s = sc.parent; s; s = s.toParentDecl())
for (Dsymbol s = sc.parent; s; s = s.toParentLocal())
{
//printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2());
if (AggregateDeclaration ad2 = s.isAggregateDeclaration())
Expand All @@ -200,7 +200,7 @@ bool isNeedThisScope(Scope* sc, Declaration d)
}
if (FuncDeclaration f = s.isFuncDeclaration())
{
if (f.isMemberDecl())
if (f.isMemberLocal())
break;
}
}
Expand Down Expand Up @@ -910,7 +910,7 @@ extern (C++) abstract class Expression : ASTNode
if (auto dve = this.isDotVarExp())
{
if (isNeedThisScope(sc, dve.var))
for (Dsymbol s = sc.func; s; s = s.toParentDecl())
for (Dsymbol s = sc.func; s; s = s.toParentLocal())
{
FuncDeclaration ff = s.isFuncDeclaration();
if (!ff)
Expand Down
12 changes: 6 additions & 6 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ Lagain:
}
if (TemplateDeclaration td = s.isTemplateDeclaration())
{
Dsymbol p = td.toParentDecl();
Dsymbol p = td.toParentLocal();
FuncDeclaration fdthis = hasThis(sc);
AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
if (fdthis && ad && isAggregate(fdthis.vthis.type) == ad && (td._scope.stc & STC.static_) == 0)
Expand Down Expand Up @@ -3075,7 +3075,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
{
Dsymbol p = td.toParentDecl();
Dsymbol p = td.toParentLocal();
FuncDeclaration fdthis = hasThis(sc);
AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
if (fdthis && ad && isAggregate(fdthis.vthis.type) == ad && (td._scope.stc & STC.static_) == 0)
Expand Down Expand Up @@ -3325,7 +3325,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* We need a 'this' pointer for the nested class.
* Ensure we have the right one.
*/
Dsymbol s = cd.toParentDecl();
Dsymbol s = cd.toParentLocal();

//printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
if (auto cdn = s.isClassDeclaration())
Expand All @@ -3334,7 +3334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
// Supply an implicit 'this' and try again
exp.thisexp = new ThisExp(exp.loc);
for (Dsymbol sp = sc.parent; 1; sp = sp.toParentDecl())
for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
{
if (!sp)
{
Expand Down Expand Up @@ -4345,7 +4345,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (exp.f.needThis())
{
AggregateDeclaration ad = exp.f.toParentDecl().isAggregateDeclaration();
AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
if (ue.e1.op == TOK.error)
{
Expand Down Expand Up @@ -5915,7 +5915,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e.type = e.type.typeSemantic(e.loc, sc);

FuncDeclaration f = e.func.toAliasFunc();
AggregateDeclaration ad = f.toParentDecl().isAggregateDeclaration();
AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
if (f.needThis())
e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);

Expand Down
4 changes: 2 additions & 2 deletions src/dmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ extern (C++) class FuncDeclaration : Declaration
if (isInstantiated() && !isVirtualMethod() &&
((ti = parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == ident))
{
AggregateDeclaration ad = isMemberDecl();
AggregateDeclaration ad = isMemberLocal();
if (ad && ad.sizeok != Sizeok.done)
{
/* Currently dmd cannot resolve forward references per methods,
Expand Down Expand Up @@ -1610,7 +1610,7 @@ extern (C++) class FuncDeclaration : Declaration
override inout(AggregateDeclaration) isThis() inout
{
//printf("+FuncDeclaration::isThis() '%s'\n", toChars());
auto ad = (storage_class & STC.static_) ? objc.isThis(this) : isMemberDecl();
auto ad = (storage_class & STC.static_) ? objc.isThis(this) : isMemberLocal();
//printf("-FuncDeclaration::isThis() %p\n", ad);
return ad;
}
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/semantic3.d
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
sym.endlinnum = funcdecl.endloc.linnum;
sc2 = sc2.push(sym);

auto ad2 = funcdecl.isMemberDecl();
auto ad2 = funcdecl.isMemberLocal();

/* If this is a class constructor
*/
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/statementsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -3310,7 +3310,7 @@ else

if (sc.ctorflow.fieldinit.length) // if aggregate fields are being constructed
{
auto ad = fd.isMemberDecl();
auto ad = fd.isMemberLocal();
assert(ad);
foreach (i, v; ad.fields)
{
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/tocvdebug.d
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ uint cv4_memfunctypidx(FuncDeclaration fd)
//printf("cv4_memfunctypidx(fd = '%s')\n", fd.toChars());

type *t = Type_toCtype(fd.type);
if (AggregateDeclaration ad = fd.isMemberDecl())
if (AggregateDeclaration ad = fd.isMemberLocal())
{
// It's a member function, which gets a special type record

Expand Down
4 changes: 2 additions & 2 deletions src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -3870,7 +3870,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
if (mt.sym.vthis.semanticRun == PASS.init)
mt.sym.vthis.dsymbolSemantic(null);

if (auto cdp = mt.sym.toParentDecl().isClassDeclaration())
if (auto cdp = mt.sym.toParentLocal().isClassDeclaration())
{
auto dve = new DotVarExp(e.loc, e, mt.sym.vthis);
dve.type = cdp.type.addMod(e.type.mod);
Expand All @@ -3880,7 +3880,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
/* https://issues.dlang.org/show_bug.cgi?id=15839
* Find closest parent class through nested functions.
*/
for (auto p = mt.sym.toParentDecl(); p; p = p.toParentDecl())
for (auto p = mt.sym.toParentLocal(); p; p = p.toParentLocal())
{
auto fd = p.isFuncDeclaration();
if (!fd)
Expand Down
10 changes: 10 additions & 0 deletions test/compilable/test6541.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class C
{
static synchronized func(alias a)() {}
}

void main()
{
int a;
C.func!a();
}
24 changes: 24 additions & 0 deletions test/compilable/testtempl2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class C
{
int m;
auto fun()
{
inc!m();
new N!m;
}
}

auto inc(alias m)()
{
++m;
}

class N(alias m)
{
}

void main()
{
auto c = new C;
c.new N!(c.m);
}

0 comments on commit 40d85cf

Please sign in to comment.