diff --git a/src/declaration.d b/src/declaration.d index f86920c0564f..5f682379c4f7 100644 --- a/src/declaration.d +++ b/src/declaration.d @@ -560,6 +560,28 @@ public: //printf("AliasDeclaration::semantic() %s\n", toChars()); if (aliassym) { + auto fd = aliassym.isFuncLiteralDeclaration(); + auto td = aliassym.isTemplateDeclaration(); + if (fd || td && td.literal) + { + if (fd && fd.semanticRun >= PASSsemanticdone) + return; + + Expression e = new FuncExp(loc, aliassym); + e = e.semantic(sc); + if (e.op == TOKfunction) + { + FuncExp fe = cast(FuncExp)e; + aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd; + } + else + { + aliassym = null; + type = Type.terror; + } + return; + } + if (aliassym.isTemplateInstance()) aliassym.semantic(sc); return; diff --git a/src/parse.d b/src/parse.d index 77f2ca46a4c0..16ed9407e38d 100644 --- a/src/parse.d +++ b/src/parse.d @@ -3848,16 +3848,45 @@ public: if (token.value == TOKlparen) tpl = parseTemplateParameterList(); check(TOKassign); - storage_class = STCundefined; - link = linkage; - structalign = 0; - udas = null; - parseStorageClasses(storage_class, link, structalign, udas); - if (udas) - error("user defined attributes not allowed for %s declarations", Token.toChars(tok)); - t = parseType(); - Declaration v = new AliasDeclaration(loc, ident, t); + + Declaration v; + if (token.value == TOKfunction || + token.value == TOKdelegate || + token.value == TOKlparen && + skipAttributes(peekPastParen(&token), &tk) && + (tk.value == TOKgoesto || tk.value == TOKlcurly) || + token.value == TOKlcurly || + token.value == TOKidentifier && peekNext() == TOKgoesto + ) + { + // function (parameters) { statements... } + // delegate (parameters) { statements... } + // (parameters) { statements... } + // (parameters) => expression + // { statements... } + // identifier => expression + + Dsymbol s = parseFunctionLiteral(); + v = new AliasDeclaration(loc, ident, s); + } + else + { + // StorageClasses type + + storage_class = STCundefined; + link = linkage; + structalign = 0; + udas = null; + parseStorageClasses(storage_class, link, structalign, udas); + + if (udas) + error("user defined attributes not allowed for %s declarations", Token.toChars(tok)); + + t = parseType(); + v = new AliasDeclaration(loc, ident, t); + } v.storage_class = storage_class; + Dsymbol s = v; if (tpl) { @@ -3873,6 +3902,7 @@ public: s = new LinkDeclaration(link, a2); } a.push(s); + switch (token.value) { case TOKsemicolon: @@ -3902,6 +3932,7 @@ public: } return a; } + // alias StorageClasses type ident; } else if (token.value == TOKtypedef) diff --git a/test/runnable/funclit.d b/test/runnable/funclit.d index 1cdeb5e38535..b3811f014384 100644 --- a/test/runnable/funclit.d +++ b/test/runnable/funclit.d @@ -1069,6 +1069,60 @@ void test11774() f11774!int(dg); } +/***************************************************/ +// 12421 + +void test12421() +{ + void test(string decl, bool polymorphic = true)() + { + // parse AliasDeclaration in Statement + mixin("alias f = " ~ decl ~ ";"); + assert(f(1) == 1); + static if (polymorphic) + assert(f("s") == "s"); + + // parse AliasDeclaration in DeclDefs + mixin("template X() { alias g = " ~ decl ~ "; }"); + alias g = X!().g; + assert(g(1) == 1); + static if (polymorphic) + assert(g("s") == "s"); + } + + test!(q{ x => x }); + test!(q{ ( x) => x }); + test!(q{ (int x) => x }, false); + + test!(q{ ( x){ return x; } }); + test!(q{ (int x){ return x; } }, false); + + test!(q{ function ( x) => x }); + test!(q{ function (int x) => x }, false); + test!(q{ function int ( x) => x }, false); + test!(q{ function int (int x) => x }, false); + + test!(q{ delegate ( x) => x }); + test!(q{ delegate (int x) => x }, false); + test!(q{ delegate int ( x) => x }, false); + test!(q{ delegate int (int x) => x }, false); + + test!(q{ function ( x){ return x; } }); + test!(q{ function (int x){ return x; } }, false); + test!(q{ function int ( x){ return x; } }, false); + test!(q{ function int (int x){ return x; } }, false); + + test!(q{ delegate ( x){ return x; } }); + test!(q{ delegate (int x){ return x; } }, false); + test!(q{ delegate int ( x){ return x; } }, false); + test!(q{ delegate int (int x){ return x; } }, false); + + // This is problematic case, and should be disallowed in the future. + alias f = x => y; + int y = 10; + assert(f(1) == 10);; +} + /***************************************************/ // 12508 @@ -1171,6 +1225,7 @@ int main() test10928(); test11661(); test11774(); + test12421(); test12508(); test13879();