]> granicus.if.org Git - clang/commitdiff
[modules] When building an injected-class-name type, we may have to insert it
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 21 Oct 2014 21:15:18 +0000 (21:15 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 21 Oct 2014 21:15:18 +0000 (21:15 +0000)
into multiple merged classes' TypeForDecl slots.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220331 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReader.cpp
test/Modules/Inputs/cxx-templates-a.h
test/Modules/Inputs/cxx-templates-b.h
test/Modules/Inputs/cxx-templates-c.h
test/Modules/Inputs/cxx-templates-d.h
test/Modules/cxx-templates.cpp

index 3ffbb501efcb11051197ff50ac19706345ea6d41..3a6e6551dbf63586a96e9c37e3b8755b8e0fbfba 100644 (file)
@@ -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);
   }
 
index 135fbb7702f9a4a5be8d2b981350f3b6bccc5888..4340910d1e2a40d1a2b22d1b5ff99cd0fa75fb9b 100644 (file)
@@ -99,3 +99,8 @@ struct MergeAnonUnionMember {
 inline MergeAnonUnionMember<> maum_a() { return {}; }
 
 template<typename T> struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; };
+
+namespace TestInjectedClassName {
+  template<typename T> struct X { X(); };
+  typedef X<char[1]> A;
+}
index 1fd6fd4231643196b849c3143382211e68f3874d..d763c8040ba3d1e81118b6be68ecce76039da270 100644 (file)
@@ -24,6 +24,11 @@ template<typename T> template<typename U>
 constexpr int Outer<T>::Inner<U>::g() { return 2; }
 static_assert(Outer<int>::Inner<int>::g() == 2, "");
 
+namespace TestInjectedClassName {
+  template<typename T> struct X { X(); };
+  typedef X<char[2]> B;
+}
+
 @import cxx_templates_b_impl;
 
 template<typename T, typename> struct Identity { typedef T type; };
index 269db441d583f4cc81d3af1645120ac154ccd586..e5395b6c7ed83b452b838d06e22ca54da43194a8 100644 (file)
@@ -21,3 +21,8 @@ inline MergeAnonUnionMember<> maum_c() { return {}; }
 
 template<typename T> struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; };
 typedef DontWalkPreviousDeclAfterMerging<char>::Inner dwpdam_typedef;
+
+namespace TestInjectedClassName {
+  template<typename T> struct X { X(); };
+  typedef X<char[3]> C;
+}
index 6aefdeca64d0f79d09679f347742a86b349e2a25..1fb1a2282b96fbe7425d712b6a2e05669a0a2889 100644 (file)
@@ -1,3 +1,9 @@
 @import cxx_templates_common;
 
 inline int InstantiateWithAnonymousDeclsD(WithAnonymousDecls<char> x) { return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d) + x.e; }
+
+namespace TestInjectedClassName {
+  template<typename T> struct X { X(); };
+  typedef X<int> D;
+  inline D UseD() { return D(); }
+}
index 13e209acc405fb0953ac1124341a237ab5a982a0..d9c8a8c27d0d839f98bb9c731c835b454d4fca29 100644 (file)
@@ -122,6 +122,10 @@ void g() {
   (void)&WithImplicitSpecialMembers<int>::n;
 
   MergeClassTemplateSpecializations_string s;
+
+  extern TestInjectedClassName::A *use_a;
+  extern TestInjectedClassName::C *use_c;
+  TestInjectedClassName::UseD();
 }
 
 static_assert(Outer<int>::Inner<int>::f() == 1, "");