Skip to content

Commit

Permalink
Merge pull request #7998 from WalterBright/expToVariable
Browse files Browse the repository at this point in the history
add expToVariable() function
  • Loading branch information
WalterBright committed Mar 11, 2018
2 parents 0f10515 + 5fb4b3a commit 9380471
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 77 deletions.
15 changes: 1 addition & 14 deletions src/dmd/escape.d
Expand Up @@ -202,20 +202,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
if (!er.byref.dim && !er.byvalue.dim && !er.byfunc.dim && !er.byexp.dim)
return false;

VarDeclaration va;
while (e1.op == TOK.dotVariable)
e1 = (cast(DotVarExp)e1).e1;

if (e1.op == TOK.variable)
va = (cast(VarExp)e1).var.isVarDeclaration();
else if (e1.op == TOK.this_)
va = (cast(ThisExp)e1).var.isVarDeclaration();
else if (e1.op == TOK.index)
{
auto ie = cast(IndexExp)e1;
if (ie.e1.op == TOK.variable && ie.e1.type.toBasetype().ty == Tsarray)
va = (cast(VarExp)ie.e1).var.isVarDeclaration();
}
VarDeclaration va = expToVariable(e1);

if (va && e.op == TOK.concatenateElemAssign)
{
Expand Down
49 changes: 48 additions & 1 deletion src/dmd/expression.d
Expand Up @@ -1072,7 +1072,12 @@ extern (C++) int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
}

/****************************************
* Get TemplateDeclaration enclosing FuncDeclaration.
* If `s` is a function template, i.e. the only member of a template
* and that member is a function, return that template.
* Params:
* s = symbol that might be a function template
* Returns:
* template for that function, otherwise null
*/
extern (C++) TemplateDeclaration getFuncTemplateDecl(Dsymbol s)
{
Expand Down Expand Up @@ -1531,6 +1536,48 @@ StringExp semanticString(Scope *sc, Expression exp, const char* s)
return se;
}

/***************************************************
* Given an Expression, find the variable it really is.
*
* For example, `a[index]` is really `a`, and `s.f` is really `s`.
* Params:
* e = Expression to look at
* Returns:
* variable if there is one, null if not
*/
VarDeclaration expToVariable(Expression e)
{
while (1)
{
switch (e.op)
{
case TOK.variable:
return (cast(VarExp)e).var.isVarDeclaration();

case TOK.dotVariable:
e = (cast(DotVarExp)e).e1;
continue;

case TOK.index:
{
IndexExp ei = cast(IndexExp)e;
e = ei.e1;
Type ti = e.type.toBasetype();
if (ti.ty == Tsarray)
continue;
return null;
}

case TOK.this_:
case TOK.super_:
return (cast(ThisExp)e).var.isVarDeclaration();

default:
return null;
}
}
}

enum OwnedBy : int
{
code, // normal code expression in AST
Expand Down
76 changes: 15 additions & 61 deletions src/dmd/expressionsem.d
Expand Up @@ -4614,25 +4614,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct)
{
if (e.e1.op == TOK.variable)
if (auto v = expToVariable(e.e1))
{
VarExp ve = cast(VarExp)e.e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v)
{
if (!checkAddressVar(sc, e, v))
return setError();
}
}
else if ((e.e1.op == TOK.this_ || e.e1.op == TOK.super_))
{
ThisExp ve = cast(ThisExp)e.e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v)
{
if (!checkAddressVar(sc, e, v))
return setError();
}
if (!checkAddressVar(sc, e, v))
return setError();
}
}

Expand Down Expand Up @@ -4801,21 +4786,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
return setError();

if (dve.e1.op == TOK.variable && global.params.vsafe)
{
VarExp ve = cast(VarExp)dve.e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v)
{
if (!checkAddressVar(sc, exp, v))
return setError();
}
}
else if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) && global.params.vsafe)
if (global.params.vsafe)
{
ThisExp ve = cast(ThisExp)dve.e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v && v.storage_class & STC.ref_)
if (VarDeclaration v = expToVariable(dve.e1))
{
if (!checkAddressVar(sc, exp, v))
return setError();
Expand Down Expand Up @@ -4886,9 +4859,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe)
{
ThisExp ve = cast(ThisExp)exp.e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v)
if (VarDeclaration v = expToVariable(exp.e1))
{
if (!checkAddressVar(sc, exp, v))
return setError();
Expand Down Expand Up @@ -5571,37 +5542,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Slicing a static array is like taking the address of it.
* Perform checks as if e[] was &e
*/
VarDeclaration v;
if (exp.e1.op == TOK.dotVariable)
if (VarDeclaration v = expToVariable(exp.e1))
{
DotVarExp dve = cast(DotVarExp)exp.e1;
if (dve.e1.op == TOK.variable)
if (exp.e1.op == TOK.dotVariable)
{
VarExp ve = cast(VarExp)dve.e1;
v = ve.var.isVarDeclaration();
}
else if (dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_)
{
ThisExp ve = cast(ThisExp)dve.e1;
v = ve.var.isVarDeclaration();
if (v && !(v.storage_class & STC.ref_))
DotVarExp dve = cast(DotVarExp)exp.e1;
if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) &&
!(v.storage_class & STC.ref_))
{
// because it's a class
v = null;
}
}
}
else if (exp.e1.op == TOK.variable)
{
VarExp ve = cast(VarExp)exp.e1;
v = ve.var.isVarDeclaration();
}
else if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_)
{
ThisExp ve = cast(ThisExp)exp.e1;
v = ve.var.isVarDeclaration();
}

if (v)
{
if (!checkAddressVar(sc, exp, v))
if (v && !checkAddressVar(sc, exp, v))
return setError();
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/retscope.d
Expand Up @@ -202,7 +202,7 @@ void* escapeDg1(scope void* d) @safe
/*
TEST_OUTPUT:
---
fail_compilation/retscope.d(213): Error: scope variable `p` assigned to non-scope `e`
fail_compilation/retscope.d(213): Error: scope variable `p` assigned to non-scope `e.e`
---
*/
struct Escaper3 { void* e; }
Expand Down

0 comments on commit 9380471

Please sign in to comment.