From: Richard Smith Date: Tue, 21 Oct 2014 21:15:18 +0000 (+0000) Subject: [modules] When building an injected-class-name type, we may have to insert it X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e8998d2b48545308e68401a0aa7fd31dc33bbcc;p=clang [modules] When building an injected-class-name type, we may have to insert it into multiple merged classes' TypeForDecl slots. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220331 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 3ffbb501ef..3a6e6551db 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -5493,13 +5493,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType TST = readType(*Loc.F, Record, Idx); // probably derivable // FIXME: ASTContext::getInjectedClassNameType is not currently suitable // for AST reading, too much interdependencies. - const Type *T; - if (const Type *Existing = D->getTypeForDecl()) - T = Existing; - else if (auto *Prev = D->getPreviousDecl()) - T = Prev->getTypeForDecl(); - else + const Type *T = nullptr; + for (auto *DI = D; DI; DI = DI->getPreviousDecl()) { + if (const Type *Existing = DI->getTypeForDecl()) { + T = Existing; + break; + } + } + if (!T) { T = new (Context, TypeAlignment) InjectedClassNameType(D, TST); + for (auto *DI = D; DI; DI = DI->getPreviousDecl()) + DI->setTypeForDecl(T); + } return QualType(T, 0); } diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index 135fbb7702..4340910d1e 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -99,3 +99,8 @@ struct MergeAnonUnionMember { inline MergeAnonUnionMember<> maum_a() { return {}; } template struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; }; + +namespace TestInjectedClassName { + template struct X { X(); }; + typedef X A; +} diff --git a/test/Modules/Inputs/cxx-templates-b.h b/test/Modules/Inputs/cxx-templates-b.h index 1fd6fd4231..d763c8040b 100644 --- a/test/Modules/Inputs/cxx-templates-b.h +++ b/test/Modules/Inputs/cxx-templates-b.h @@ -24,6 +24,11 @@ template template constexpr int Outer::Inner::g() { return 2; } static_assert(Outer::Inner::g() == 2, ""); +namespace TestInjectedClassName { + template struct X { X(); }; + typedef X B; +} + @import cxx_templates_b_impl; template struct Identity { typedef T type; }; diff --git a/test/Modules/Inputs/cxx-templates-c.h b/test/Modules/Inputs/cxx-templates-c.h index 269db441d5..e5395b6c7e 100644 --- a/test/Modules/Inputs/cxx-templates-c.h +++ b/test/Modules/Inputs/cxx-templates-c.h @@ -21,3 +21,8 @@ inline MergeAnonUnionMember<> maum_c() { return {}; } template struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; }; typedef DontWalkPreviousDeclAfterMerging::Inner dwpdam_typedef; + +namespace TestInjectedClassName { + template struct X { X(); }; + typedef X C; +} diff --git a/test/Modules/Inputs/cxx-templates-d.h b/test/Modules/Inputs/cxx-templates-d.h index 6aefdeca64..1fb1a2282b 100644 --- a/test/Modules/Inputs/cxx-templates-d.h +++ b/test/Modules/Inputs/cxx-templates-d.h @@ -1,3 +1,9 @@ @import cxx_templates_common; inline int InstantiateWithAnonymousDeclsD(WithAnonymousDecls x) { return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d) + x.e; } + +namespace TestInjectedClassName { + template struct X { X(); }; + typedef X D; + inline D UseD() { return D(); } +} diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index 13e209acc4..d9c8a8c27d 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -122,6 +122,10 @@ void g() { (void)&WithImplicitSpecialMembers::n; MergeClassTemplateSpecializations_string s; + + extern TestInjectedClassName::A *use_a; + extern TestInjectedClassName::C *use_c; + TestInjectedClassName::UseD(); } static_assert(Outer::Inner::f() == 1, "");