]> granicus.if.org Git - clang/commitdiff
When de-serializing a type that is supposed to be canonical, call
authorDouglas Gregor <dgregor@apple.com>
Tue, 26 Oct 2010 00:51:02 +0000 (00:51 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 26 Oct 2010 00:51:02 +0000 (00:51 +0000)
getCanonicalType() to make sure that the type we got back is actually
canonical. This is the case for most types, which always build a
canonical type when given canonical components. However, some types that
involve expressions in their canonicalization (e.g., array types with
dependent sizes) don't always build canonical types from canonical
components, because there is no such thing as a "canonical"
expression. Therefore, we do this extra mapping to ensure that the
canonical types we store are actually canonical.

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

lib/AST/ASTContext.cpp
lib/Serialization/ASTReader.cpp
test/PCH/cxx-templates.cpp
test/PCH/cxx-templates.h

index 10f875b1b7683ce92559dc0eb0f3cf9891af5b91..d7ebedf72a036b57d40d8ae70b0b666c058f3499 100644 (file)
@@ -1522,11 +1522,12 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
   DependentSizedArrayType *Canon = 0;
   llvm::FoldingSetNodeID ID;
 
+  QualType CanonicalEltTy = getCanonicalType(EltTy);
   if (NumElts) {
     // Dependently-sized array types that do not have a specified
     // number of elements will have their sizes deduced from an
     // initializer.
-    DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
+    DependentSizedArrayType::Profile(ID, *this, CanonicalEltTy, ASM,
                                      EltTypeQuals, NumElts);
 
     Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -1539,28 +1540,28 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
     New = new (*this, TypeAlignment)
       DependentSizedArrayType(*this, EltTy, QualType(Canon, 0),
                               NumElts, ASM, EltTypeQuals, Brackets);
-  } else {
-    QualType CanonEltTy = getCanonicalType(EltTy);
-    if (CanonEltTy == EltTy) {
-      New = new (*this, TypeAlignment)
-        DependentSizedArrayType(*this, EltTy, QualType(),
-                                NumElts, ASM, EltTypeQuals, Brackets);
-
-      if (NumElts) {
-        DependentSizedArrayType *CanonCheck
-          = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
-        assert(!CanonCheck && "Dependent-sized canonical array type broken");
-        (void)CanonCheck;
-        DependentSizedArrayTypes.InsertNode(New, InsertPos);
-      }
-    } else {
-      QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
-                                                  ASM, EltTypeQuals,
-                                                  SourceRange());
-      New = new (*this, TypeAlignment)
-        DependentSizedArrayType(*this, EltTy, Canon,
-                                NumElts, ASM, EltTypeQuals, Brackets);
+  } else if (CanonicalEltTy == EltTy) {
+    // This is a canonical type. Record it.
+    New = new (*this, TypeAlignment)
+      DependentSizedArrayType(*this, EltTy, QualType(),
+                              NumElts, ASM, EltTypeQuals, Brackets);
+    
+    if (NumElts) {
+#ifndef NDEBUG
+      DependentSizedArrayType *CanonCheck
+        = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+      assert(!CanonCheck && "Dependent-sized canonical array type broken");
+      (void)CanonCheck;
+#endif
+      DependentSizedArrayTypes.InsertNode(New, InsertPos);
     }
+  } else {
+    QualType Canon = getDependentSizedArrayType(CanonicalEltTy, NumElts,
+                                                ASM, EltTypeQuals,
+                                                SourceRange());
+    New = new (*this, TypeAlignment)
+      DependentSizedArrayType(*this, EltTy, Canon,
+                              NumElts, ASM, EltTypeQuals, Brackets);
   }
 
   Types.push_back(New);
index 38e786bff10b477dde91a1dbad2e9d043cf9dee4..c0aff9afde304f0e6d4b8693dc3fb5b012ff6daf 100644 (file)
@@ -2764,6 +2764,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
     }
     TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0]));
     QualType Canonical = GetType(Record[1]);
+    if (!Canonical.isNull())
+      Canonical = Context->getCanonicalType(Canonical);
     return Context->getTypedefType(Decl, Canonical);
   }
 
@@ -2867,6 +2869,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
     NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
     const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
     QualType Canon = GetType(Record[Idx++]);
+    if (!Canon.isNull())
+      Canon = Context->getCanonicalType(Canon);
     return Context->getDependentNameType(Keyword, NNS, Name, Canon);
   }
 
index d36d5449c81c2cbdce37dac84f991b9e9dfceed0..95477992e6776d13ea48c4db653e5f6ef141de93 100644 (file)
@@ -17,7 +17,7 @@ struct A {
   static T my_templf(T x) { return x; }
 };
 
-void test() {
+void test(const int (&a6)[17]) {
   int x = templ_f<int, 5>(3);
   
   S<char, float>::templ();
@@ -32,6 +32,8 @@ void test() {
   s3.m();
 
   TS5 ts(0);
+
+  S6<const int[17]>::t2 b6 = a6;
 }
 
 template struct S4<int>;
index e1f285b19dcb69e3862a9957d113cfba8e977b59..5baa772b5d08f3412161f7a9b53b0da61f6052cf 100644 (file)
@@ -150,3 +150,17 @@ struct TS5 {
 template<class T> void f_PR8134(T);
 template<class T> void f_PR8134(T);
 void g_PR8134() { f_PR8134(0); f_PR8134('x'); }
+
+// rdar8580149
+template <typename T>
+struct S6;
+
+template <typename T, unsigned N>
+struct S6<const T [N]>
+{
+private:
+   typedef const T t1[N];
+public:
+   typedef t1& t2;
+};
+