Skip to content

Commit

Permalink
Merge pull request #8885 from RazvanN7/Alternate_16082
Browse files Browse the repository at this point in the history
Fix Issues 16082 and 16086
  • Loading branch information
andralex authored Nov 5, 2018
2 parents 7c2a70a + e16020c commit 3d4fe18
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 20 deletions.
2 changes: 2 additions & 0 deletions src/dmd/cli.d
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,8 @@ dmd -cov -unittest myprog.d
"fix integral promotions for unary + - ~ operators"),
Transition(null, "tls", "vtls",
"list all variables going into thread local storage"),
Transition(null, "fixAliasThis", "fixAliasThis",
"when a symbol is resolved, check alias this scope before going to upper scopes"),
];
}

Expand Down
79 changes: 79 additions & 0 deletions src/dmd/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import dmd.doc;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.expression;
import dmd.errors;
import dmd.func;
import dmd.globals;
Expand Down Expand Up @@ -365,6 +366,70 @@ struct Scope
return null;
}

Dsymbol checkAliasThis(AggregateDeclaration ad, Identifier ident, int flags, Expression* exp)
{
import dmd.mtype;
if (!ad || !ad.aliasthis)
return null;

Declaration decl = ad.aliasthis.isDeclaration();
if (!decl)
return null;

Type t = decl.type;
ScopeDsymbol sds;
TypeClass tc;
TypeStruct ts;
switch(t.ty)
{
case Tstruct:
ts = cast(TypeStruct)t;
sds = ts.sym;
break;
case Tclass:
tc = cast(TypeClass)t;
sds = tc.sym;
break;
case Tinstance:
sds = (cast(TypeInstance)t).tempinst;
break;
case Tenum:
sds = (cast(TypeEnum)t).sym;
break;
default: break;
}

if (!sds)
return null;

Dsymbol ret = sds.search(loc, ident, flags);
if (ret)
{
*exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
*exp = new DotIdExp(loc, *exp, ident);
return ret;
}

if (!ts && !tc)
return null;

Dsymbol s;
*exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
if (ts && !(ts.att & AliasThisRec.tracing))
{
ts.att = cast(AliasThisRec)(ts.att | AliasThisRec.tracing);
s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
ts.att = cast(AliasThisRec)(ts.att & ~AliasThisRec.tracing);
}
else if(tc && !(tc.att & AliasThisRec.tracing))
{
tc.att = cast(AliasThisRec)(tc.att | AliasThisRec.tracing);
s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
tc.att = cast(AliasThisRec)(tc.att & ~AliasThisRec.tracing);
}
return s;
}

Dsymbol searchScopes(int flags)
{
for (Scope* sc = &this; sc; sc = sc.enclosing)
Expand All @@ -390,6 +455,20 @@ struct Scope
*pscopesym = sc.scopesym;
return s;
}

if (global.params.fixAliasThis)
{
Expression exp = new ThisExp(loc);
Dsymbol aliasSym = checkAliasThis(sc.scopesym.isAggregateDeclaration(), ident, flags, &exp);
if (aliasSym)
{
//printf("found aliassym: %s\n", aliasSym.toChars());
if (pscopesym)
*pscopesym = new ExpressionDsymbol(exp);
return aliasSym;
}
}

// Stop when we hit a module, but keep going if that is not just under the global scope
if (sc.scopesym.isModule() && !(sc.enclosing && !sc.enclosing.enclosing))
break;
Expand Down
25 changes: 25 additions & 0 deletions src/dmd/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,11 @@ extern (C++) class Dsymbol : RootObject
return null;
}

inout(ExpressionDsymbol) isExpressionDsymbol() inout
{
return null;
}

inout(ThisDeclaration) isThisDeclaration() inout
{
return null;
Expand Down Expand Up @@ -2051,6 +2056,26 @@ extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol

}

/**
* Class that holds an expression in a Dsymbol wraper.
* This is not an AST node, but a class used to pass
* an expression as a function parameter of type Dsymbol.
*/
extern (C++) final class ExpressionDsymbol : Dsymbol
{
Expression exp;
this(Expression exp)
{
super();
this.exp = exp;
}

override inout(ExpressionDsymbol) isExpressionDsymbol() inout
{
return this;
}
}


/***********************************************************
* Table of Dsymbol's
Expand Down
9 changes: 9 additions & 0 deletions src/dmd/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class WithScopeSymbol;
class ArrayScopeSymbol;
class SymbolDeclaration;
class Expression;
class ExpressionDsymbol;
class DeleteDeclaration;
class OverloadSet;
struct AA;
Expand Down Expand Up @@ -250,6 +251,7 @@ class Dsymbol : public RootObject
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual ExpressionDsymbol *isExpressionDsymbol() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
Expand Down Expand Up @@ -360,6 +362,13 @@ class ForwardingScopeDsymbol : public ScopeDsymbol
ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return this; }
};

class ExpressionDsymbol : public Dsymbol
{
Expression *exp;

ExpressionDsymbol *isExpressionDsymbol() { return this; }
};

// Table of Dsymbol's

class DsymbolTable : public RootObject
Expand Down
13 changes: 12 additions & 1 deletion src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2389,14 +2389,25 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
}

if (global.params.fixAliasThis)
{
ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
if (expDsym)
{
//printf("expDsym = %s\n", expDsym.exp.toChars());
result = expDsym.exp.expressionSemantic(sc);
return;
}
}
// Haven't done overload resolution yet, so pass 1
e = resolve(exp.loc, sc, s, true);
}
result = e;
return;
}

if (hasThis(sc))
if (!global.params.fixAliasThis && hasThis(sc))
{
for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
{
Expand Down
1 change: 1 addition & 0 deletions src/dmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ struct Param
bool bug10378; // use pre- https://issues.dlang.org/show_bug.cgi?id=10378 search strategy
bool fix16997; // fix integral promotions for unary + - ~ operators
// https://issues.dlang.org/show_bug.cgi?id=16997
bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes
bool vsafe; // use enhanced @safe checking
bool ehnogc; // use @nogc exception handling
bool dtorFields; // destruct fields of partially constructed objects
Expand Down
60 changes: 60 additions & 0 deletions test/compilable/testAliasLookup.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// REQUIRED_ARGS: -transition=fixAliasThis

// https://issues.dlang.org/show_bug.cgi?id=16086
struct A
{
void tail() {}
}

struct S16086
{
struct Inner2
{
Inner a;
alias a this;
}

struct Inner
{
int unique_identifier_name;
int tail = 2;
}

Inner2 inner;
alias inner this;

auto works()
{
return unique_identifier_name;
}

auto fails()
{
int a = tail;
return tail; // Line 22
// The workaround: return this.tail;
}
}

// https://issues.dlang.org/show_bug.cgi?id=16082
struct S16082
{
struct Inner
{
int any_name_but_modulename;
int aliasthis = 5;
}

Inner inner;
alias inner this;

auto works()
{
return any_name_but_modulename;
}
auto fails()
{
return aliasthis; // Line 20
}
}

37 changes: 18 additions & 19 deletions test/runnable/imports/a12037.d
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,28 @@ private template CustomFloatParams(uint precision, uint exponentWidth)
) CustomFloatParams;
}

struct CustomFloat(uint precision, uint exponentWidth)
if ((1 + precision + exponentWidth) % 8 == 0 && precision + exponentWidth > 0)
private union ToBinary(F)
if (is(typeof(CustomFloatParams!(F.sizeof*8))) || is(F == real))
{
private:
union ToBinary(F)
if (is(typeof(CustomFloatParams!(F.sizeof*8))) || is(F == real))
{
F set;
F set;

// If on Linux or Mac, where 80-bit reals are padded, ignore the
// padding.
CustomFloat!(CustomFloatParams!(min(F.sizeof*8, 80))) get;
// If on Linux or Mac, where 80-bit reals are padded, ignore the
// padding.
CustomFloat!(CustomFloatParams!(min(F.sizeof*8, 80))) get;

// Convert F to the correct binary type.
static typeof(get) opCall(F value)
{
ToBinary r;
r.set = value;
return r.get;
}
alias get this;
// Convert F to the correct binary type.
static typeof(get) opCall(F value)
{
ToBinary r;
r.set = value;
return r.get;
}
alias get this;
}

struct CustomFloat(uint precision, uint exponentWidth)
if ((1 + precision + exponentWidth) % 8 == 0 && precision + exponentWidth > 0)
{
public:
@property bool sign() { return 1; }
@property void sign(bool) {}
Expand All @@ -65,7 +64,7 @@ public:
@property F get(F)()
if (is(F == float) || is(F == double) || is(F == real))
{
ToBinary!F result;
ToBinary result;
return F.init;
}

Expand Down

0 comments on commit 3d4fe18

Please sign in to comment.