Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 9571 - link error due to using unique ids in anonymous funcliteral #2566

Merged
merged 1 commit into from
Sep 17, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,6 @@ class FuncLiteralDeclaration : public FuncDeclaration
ForeachStatement *fes, Identifier *id = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *syntaxCopy(Dsymbol *);
Dsymbol *syntaxCopy(Dsymbol *s, bool keepId);
bool isNested();
bool isVirtual();

Expand Down
44 changes: 41 additions & 3 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "hdrgen.h"
#include "parse.h"
#include "doc.h"

#include "aav.h"

Expression *createTypeInfoArray(Scope *sc, Expression *args[], size_t dim);
Expression *expandVar(int result, VarDeclaration *v);
Expand Down Expand Up @@ -6018,7 +6018,39 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td)
tok = fd->tok; // save original kind of function/delegate/(infer)
}

FuncLiteralDeclaration *getFuncLit(Dsymbols *members);
void FuncExp::genIdent(Scope *sc)
{
if (fd->ident == Id::empty)
{
const char *s;
if (fd->fes) s = "__foreachbody";
else if (fd->tok == TOKreserved) s = "__lambda";
else if (fd->tok == TOKdelegate) s = "__dgliteral";
else s = "__funcliteral";

DsymbolTable *symtab;
if (sc->flags & (SCOPEstaticif | SCOPEstaticassert))
{
// e.g. in template constraint
}
else if (FuncDeclaration *func = sc->parent->isFuncDeclaration())
{
symtab = func->localsymtab;
goto L1;
}
else
{
symtab = sc->parent->isScopeDsymbol()->symtab;
L1:
assert(symtab);
int num = _aaLen(symtab->tab) + 1;
Identifier *id = Lexer::uniqueId(s, num);
fd->ident = id;
if (td) td->ident = id;
symtab->insert(td ? (Dsymbol *)td : (Dsymbol *)fd);
}
}
}

Expression *FuncExp::syntaxCopy()
{
Expand All @@ -6027,7 +6059,9 @@ Expression *FuncExp::syntaxCopy()
if (td)
{
td2 = (TemplateDeclaration *)td->syntaxCopy(NULL);
fd2 = getFuncLit(td2->members);
assert(td2->members->dim == 1);
fd2 = (*td2->members)[0]->isFuncLiteralDeclaration();
assert(fd2);
}
else
{
Expand Down Expand Up @@ -6058,6 +6092,8 @@ Expression *FuncExp::semantic(Scope *sc)
//if (fd->treq)
// fd->treq = fd->treq->semantic(loc, sc);

genIdent(sc);

// Set target of return type inference
if (fd->treq && !fd->type->nextOf())
{ TypeFunction *tfv = NULL;
Expand Down Expand Up @@ -6151,6 +6187,8 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments)
return checkarg;
}

genIdent(sc);

assert(td->parameters && td->parameters->dim);
td->semantic(sc);

Expand Down
1 change: 1 addition & 0 deletions src/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ class FuncExp : public Expression
TOK tok;

FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
void genIdent(Scope *sc);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, Expressions *arguments);
Expand Down
21 changes: 2 additions & 19 deletions src/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -3789,39 +3789,22 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
TOK tok, ForeachStatement *fes, Identifier *id)
: FuncDeclaration(loc, endloc, NULL, STCundefined, type)
{
if (!id)
{
const char *s;
if (fes) s = "__foreachbody";
else if (tok == TOKreserved) s = "__lambda";
else if (tok == TOKdelegate) s = "__dgliteral";
else s = "__funcliteral";
id = Lexer::uniqueId(s);
}
this->ident = id;
this->ident = id ? id : Id::empty;
this->tok = tok;
this->fes = fes;
this->treq = NULL;
//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
}

Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
{
return syntaxCopy(s, false);
}

Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s, bool keepId)
{
FuncLiteralDeclaration *f;

//printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
if (s)
f = (FuncLiteralDeclaration *)s;
else
{
Identifier *id = keepId ? ident : NULL;
f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes, id);
}
f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes, ident);
f->treq = treq; // don't need to copy
FuncDeclaration::syntaxCopy(f);
return f;
Expand Down
16 changes: 1 addition & 15 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,6 @@ RootObject *objectSyntaxCopy(RootObject *o)
}
#endif

FuncLiteralDeclaration *getFuncLit(Dsymbols *members)
{
assert(members->dim == 1);
assert((*members)[0]->isFuncLiteralDeclaration());
return (FuncLiteralDeclaration *)(*members)[0];
}


/* ======================== TemplateDeclaration ============================= */

Expand Down Expand Up @@ -546,8 +539,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
if (constraint)
e = constraint->syntaxCopy();
Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
Identifier *id = literal ? getFuncLit(d)->ident : ident;
td = new TemplateDeclaration(loc, id, p, e, d, ismixin);
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin);
td->literal = literal;
return td;
}
Expand Down Expand Up @@ -5559,12 +5551,6 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// Copy the syntax trees from the TemplateDeclaration
if (members && speculative)
{} // Don't copy again so they were previously created.
else if (tempdecl->literal)
{
FuncLiteralDeclaration *fld = getFuncLit(tempdecl->members);
members = new Dsymbols();
members->push(fld->syntaxCopy(NULL, true));
}
else
members = Dsymbol::arraySyntaxCopy(tempdecl->members);

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/test8793.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
TEST_OUTPUT:
---
fail_compilation/test8793.d(13): Error: cannot implicitly convert expression (__lambda2) of type bool delegate(const(int) x) @system to bool delegate(const(int)) pure
fail_compilation/test8793.d(14): Error: cannot implicitly convert expression (__lambda4) of type bool delegate(const(int) x) @system to bool delegate(const(int)) pure
fail_compilation/test8793.d(16): Error: cannot implicitly convert expression (__lambda6) of type bool delegate(const(int) x) nothrow @safe to bool delegate(const(int)) pure
fail_compilation/test8793.d(14): Error: cannot implicitly convert expression (__lambda2) of type bool delegate(const(int) x) @system to bool delegate(const(int)) pure
fail_compilation/test8793.d(16): Error: cannot implicitly convert expression (__lambda2) of type bool delegate(const(int) x) nothrow @safe to bool delegate(const(int)) pure
---
*/

Expand Down
8 changes: 4 additions & 4 deletions test/runnable/Fix5140.d
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ void main(string[] args) nothrow
static assert(getTemplCallingModule() == "Fix5140");
static assert(getCalleeModule() == "imports.Fix5140a");

static assert(getCallingFunc() == "Fix5140.main.__lambda1");
static assert(getTemplCallingFunc() == "Fix5140.main.__lambda1");
static assert(getCallingFunc() == "Fix5140.main.__lambda3");
static assert(getTemplCallingFunc() == "Fix5140.main.__lambda3");
static assert(getCalleeFunc() == "imports.Fix5140a.getCalleeFunc");

static assert(getCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y)");
static assert(getTemplCallingPrettyFunc() == "Fix5140.main.__lambda1(int x, int y)");
static assert(getCallingPrettyFunc() == "Fix5140.main.__lambda3(int x, int y)");
static assert(getTemplCallingPrettyFunc() == "Fix5140.main.__lambda3(int x, int y)");
static assert(getCalleePrettyFunc(1, 1.0) == "string imports.Fix5140a.getCalleePrettyFunc(int x, float y)");
};
funcLiteral(1, 2);
Expand Down
10 changes: 10 additions & 0 deletions test/runnable/imports/link9571a.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
struct MapResult(alias fun)
{
void bar() { fun(0); }
}
auto foo()
{
alias MapResult!(function(int c) => 0) M;
M m;
m.bar();
}
9 changes: 9 additions & 0 deletions test/runnable/link9571.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// COMPILE_SEPARATELY
// EXTRA_SOURCES: imports/link9571a.d

import imports.link9571a;

void main()
{
foo();
}