From e8b3503cf48f225569697a7603ad8769ef8942ac Mon Sep 17 00:00:00 2001 From: k-hara Date: Tue, 24 Dec 2013 13:12:14 +0900 Subject: [PATCH] fix Issue 11767 - doubly mixed-in struct "failed semantic analysis" Inherently this is a mangling issue, which had been hidden since 2a3db5d7afd0c26e8a0ec58ff6fb6a8cd9647de6, and then detected by [the assertion for AST sanity](20fe5e8600498fed322a7d5d8305acb2de852cde). Each mixed-in symbols are in independent scope, and their mangled names should also be different. To fix the issue, assign scope-local unique name for each unnamed `TemplateMixin`s, as same as lambdas. --- src/template.c | 28 ++++++++++++++++++++++++++-- test/runnable/mixin1.d | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/template.c b/src/template.c index 0cf2b4991c7f..529b2e806c13 100644 --- a/src/template.c +++ b/src/template.c @@ -7491,7 +7491,31 @@ void TemplateMixin::semantic(Scope *sc) assert(tempdecl); if (!ident) - ident = genIdent(tiargs); + { + /* Assign scope local unique identifier, as same as lambdas. + */ + const char *s = "__mixin"; + + DsymbolTable *symtab; + if (FuncDeclaration *func = sc->parent->isFuncDeclaration()) + { + symtab = func->localsymtab; + if (symtab) + { + // Inside template constraint, symtab is not set yet. + goto L1; + } + } + else + { + symtab = sc->parent->isScopeDsymbol()->symtab; + L1: + assert(symtab); + int num = (int)_aaLen(symtab->tab) + 1; + ident = Lexer::uniqueId(s, num); + symtab->insert(this); + } + } inst = this; parent = sc->parent; @@ -7815,7 +7839,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) tqual->toCBuffer(buf, NULL, hgs); toCBufferTiargs(buf, hgs); - if (ident) + if (ident && memcmp(ident->string, "__mixin", 7) != 0) { buf->writebyte(' '); buf->writestring(ident->toChars()); diff --git a/test/runnable/mixin1.d b/test/runnable/mixin1.d index e1f04439858e..4c24c8368290 100644 --- a/test/runnable/mixin1.d +++ b/test/runnable/mixin1.d @@ -1233,6 +1233,32 @@ class C11487 mixin M.Mix!(M.R); } +/*******************************************/ +// 11767 + +mixin template M11767() +{ + struct S11767 {} +} +mixin M11767!(); +mixin M11767!(); // OK +static assert(!__traits(compiles, S11767)); + +void test11767() +{ + mixin M11767!(); + alias S1 = S11767; + { + mixin M11767!(); + alias S2 = S11767; + static assert(!is(S1 == S2)); + static assert(S1.mangleof == "S6mixin19test11767FZv8__mixin16S11767"); + static assert(S2.mangleof == "S6mixin19test11767FZv8__mixin26S11767"); + } + mixin M11767!(); + static assert(!__traits(compiles, S11767)); +} + /*******************************************/ int main() @@ -1282,6 +1308,7 @@ int main() test2740(); test42(); test9417(); + test11767(); printf("Success\n"); return 0;