Skip to content

Commit

Permalink
Merge branch 'merge_stable_convert' into merge_stable
Browse files Browse the repository at this point in the history
Conflicts:
	src/access.d
	src/aggregate.d
	src/aliasthis.d
	src/apply.d
	src/argtypes.d
	src/arrayop.d
	src/arraytypes.d
	src/attrib.d
	src/builtin.d
	src/canthrow.d
	src/clone.d
	src/cond.d
	src/constfold.d
	src/cppmangle.d
	src/ctfeexpr.d
	src/dcast.d
	src/dclass.d
	src/declaration.d
	src/delegatize.d
	src/denum.d
	src/dimport.d
	src/dinterpret.d
	src/dmacro.d
	src/dmangle.d
	src/dmodule.d
	src/doc.d
	src/dscope.d
	src/dstruct.d
	src/dsymbol.d
	src/dtemplate.d
	src/dversion.d
	src/errors.d
	src/escape.d
	src/expression.d
	src/func.d
	src/globals.d
	src/hdrgen.d
	src/identifier.d
	src/init.d
	src/inline.d
	src/json.d
	src/lexer.d
	src/lib.d
	src/link.d
	src/mars.d
	src/mtype.d
	src/nogc.d
	src/nspace.d
	src/objc.d
	src/opover.d
	src/optimize.d
	src/parse.d
	src/root/file.d
	src/root/outbuffer.d
	src/sapply.d
	src/sideeffect.d
	src/statement.d
	src/staticassert.d
	src/target.d
	src/tokens.d
	src/traits.d
	src/visitor.d
  • Loading branch information
MartinNowak committed Aug 29, 2015
2 parents d436d7b + 22d697d commit 3c1a00e
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/cppmangle.d
Expand Up @@ -1443,7 +1443,7 @@ else static if (TARGET_WINDOS)
if (t.ty != Tpointer)
t = t.mutableOf();
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
64 changes: 45 additions & 19 deletions src/declaration.d
Expand Up @@ -1603,16 +1603,24 @@ public:
ei = new ExpInitializer(_init.loc, e);
_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);
if (isScope())
exp = exp.optimize(WANTvalue);
if (exp.op == TOKerror)
{
_init = new ErrorInitializer();
ei = null;
}
else
ei.exp = exp;
if (ei && isScope())
{
Expression ex = ei.exp;
while (ex.op == TOKcomma)
Expand Down Expand Up @@ -2176,13 +2184,40 @@ public:
final bool 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();
if (fdv && fdthis && fdv != fdthis)
FuncDeclaration fdv = p.isFuncDeclaration();
if (fdv && fdv != fdthis)
{
// Add fdthis to nestedrefs[] if not already there
for (size_t i = 0; 1; i++)
Expand Down Expand Up @@ -2235,15 +2270,6 @@ public:
}
}
}
// 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
10 changes: 10 additions & 0 deletions src/expression.d
Expand Up @@ -3716,6 +3716,9 @@ public:
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 @@ -5865,6 +5868,9 @@ public:
}
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 @@ -6463,6 +6469,7 @@ public:
declaration.semantic3(sc);
}
}
// todo: error in declaration should be propagated.
type = Type.tvoid;
return this;
}
Expand Down Expand Up @@ -9377,6 +9384,9 @@ public:
return new ErrorExp();
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
43 changes: 33 additions & 10 deletions src/func.d
Expand Up @@ -3307,16 +3307,43 @@ public:
final bool 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())
{
// 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 (isNested())
{
// The function that this function is in
FuncDeclaration fdv2 = toParent2().isFuncDeclaration();
// The current function
FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
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 @@ -3335,7 +3362,7 @@ public:
}
}
}
FuncDeclaration fdv = toParent2().isFuncDeclaration();
FuncDeclaration fdv = p.isFuncDeclaration();
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis.getLevel(loc, sc, fdv);
Expand All @@ -3346,10 +3373,6 @@ public:
if (lv == 0)
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
7 changes: 1 addition & 6 deletions src/nogc.d
Expand Up @@ -55,13 +55,8 @@ public:
VarDeclaration v = e.declaration.isVarDeclaration();
if (v && !(v.storage_class & STCmanifest) && !v.isDataseg() && v._init)
{
if (v._init.isVoidInitializer())
if (ExpInitializer ei = v._init.isExpInitializer())
{
}
else
{
ExpInitializer ei = v._init.isExpInitializer();
assert(ei);
doCond(ei.exp);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/opover.d
Expand Up @@ -890,7 +890,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
if (s)
{
functionResolve(&m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
result = new ErrorExp();
return;
Expand All @@ -900,7 +900,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
if (s_r)
{
functionResolve(&m, s_r, e.loc, sc, tiargs, e.e2.type, &args1);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
result = new ErrorExp();
return;
Expand Down Expand Up @@ -977,7 +977,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
if (s_r)
{
functionResolve(&m, s_r, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
result = new ErrorExp();
return;
Expand All @@ -987,7 +987,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
if (s)
{
functionResolve(&m, s, e.loc, sc, tiargs, e.e2.type, &args1);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
result = new ErrorExp();
return;
Expand Down Expand Up @@ -1347,7 +1347,7 @@ extern (C++) Expression op_overload(Expression e, Scope* sc)
if (s)
{
functionResolve(&m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
result = new ErrorExp();
return;
Expand Down Expand Up @@ -1459,15 +1459,15 @@ extern (C++) Expression compare_overload(BinExp e, Scope* sc, Identifier id)
if (s)
{
functionResolve(&m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
return new ErrorExp();
}
FuncDeclaration lastf = m.lastf;
int count = m.count;
if (s_r)
{
functionResolve(&m, s_r, e.loc, sc, tiargs, e.e2.type, &args1);
if (m.lastf && m.lastf.errors)
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
return new ErrorExp();
}
if (m.count > 1)
Expand Down
12 changes: 9 additions & 3 deletions src/statement.d
Expand Up @@ -4328,18 +4328,24 @@ public:
{
if (tf.next && tf.next.ty != Tvoid)
{
error("mismatched function return type inference of void and %s", tf.next.toChars());
if (tf.next.ty != Terror)
{
error("mismatched function return type inference of void and %s", tf.next.toChars());
}
errors = true;
tf.next = Type.terror;
}
tf.next = Type.tvoid;
else
tf.next = Type.tvoid;
tret = tf.next;
tbret = tret.toBasetype();
}
if (inferRef) // deduce 'auto ref'
tf.isref = false;
if (tbret.ty != Tvoid) // if non-void return
{
error("return expression expected");
if (tbret.ty != Terror)
error("return expression expected");
errors = true;
}
else if (fd.isMain())
Expand Down
54 changes: 54 additions & 0 deletions test/compilable/test14973.d
@@ -0,0 +1,54 @@
template map(fun...)
{
auto map(R)(R r)
{
return MapResult!(fun, R)(r);
}
}

struct MapResult(alias fun, R)
{
R _input;

@property bool empty() { return _input.length == 0; }
@property auto front() { return fun(_input[0]); }
void popFront() { _input = _input[1..$]; }
}

class Foo
{
int baz() { return 1; }
void bar()
{
auto s = [1].map!(i => baz()); // compiles
auto r = [1].map!(
// lambda1
i =>
[1].map!(
// lambda2
j =>
baz()
)
); // compiles <- error
}
}

class Bar
{
int baz;
void bar()
{
auto s = [1].map!(i => baz); // compiles
auto r = [1].map!(
// lambda1
i =>
[1].map!(
// lambda2
j =>
baz
)
); // compiles <- error
}
}

void main() {}
2 changes: 1 addition & 1 deletion test/fail_compilation/diag9831.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag9831.d(12): Error: function diag9831.main.__lambda1 cannot access frame of function D main
fail_compilation/diag9831.d(12): Error: cannot match delegate literal to function pointer type 'int function(int x)'
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail11545.d
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail11545.d(14): Error: need 'this' for 'x' of type 'int'
fail_compilation/fail11545.d(18): Error: need 'this' for 'x' of type 'int'
fail_compilation/fail11545.d(17): Error: cannot implicitly convert expression (__lambda5) of type int delegate() pure nothrow @nogc @safe to int function()
fail_compilation/fail11545.d(17): Error: cannot implicitly convert expression (__lambda5) of type int delegate() pure nothrow @nogc @safe to int function()
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail120.d
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail120.d(12): Error: need 'this' for 'nodes' of type 'int[2]'
fail_compilation/fail120.d(13): Error: need 'this' for 'nodes' of type 'int[2]'
fail_compilation/fail120.d(12): Error: non-constant nested delegate literal expression __lambda4
fail_compilation/fail120.d(13): Error: non-constant nested delegate literal expression __lambda5
---
*/

Expand Down

0 comments on commit 3c1a00e

Please sign in to comment.