]> granicus.if.org Git - clang/commitdiff
Build canonical types for dependently-sized array types.
authorDouglas Gregor <dgregor@apple.com>
Fri, 31 Jul 2009 00:23:35 +0000 (00:23 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 31 Jul 2009 00:23:35 +0000 (00:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77647 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/Type.cpp
test/SemaTemplate/canonical-expr-type.cpp

index a1f190a74b03b6a06f89383db147ad76106a70f8..1c64f0be054af5d5da81e2477c264b1200822136 100644 (file)
@@ -70,7 +70,7 @@ class ASTContext {
   llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
   llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
   std::vector<VariableArrayType*> VariableArrayTypes;
-  std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
+  llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
   std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes;
   llvm::FoldingSet<VectorType> VectorTypes;
   llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
index 6eaa4e67a747af5a3b6ec0c2ac932d8d2b33cf15..411a279cd0c795f05c54c3fa583d2633fd1488d0 100644 (file)
@@ -1180,17 +1180,19 @@ public:
 /// until template instantiation occurs, at which point this will
 /// become either a ConstantArrayType or a VariableArrayType.
 class DependentSizedArrayType : public ArrayType {
+  ASTContext &Context;
+  
   /// SizeExpr - An assignment expression that will instantiate to the
   /// size of the array.
   Stmt *SizeExpr;
   /// Brackets - The left and right array brackets.
   SourceRange Brackets;
   
-  DependentSizedArrayType(QualType et, QualType can, Expr *e,
-                         ArraySizeModifier sm, unsigned tq,
+  DependentSizedArrayType(ASTContext &Context, QualType et, QualType can, 
+                          Expr *e, ArraySizeModifier sm, unsigned tq,
                           SourceRange brackets)
     : ArrayType(DependentSizedArray, et, can, sm, tq),
-      SizeExpr((Stmt*) e), Brackets(brackets) {}
+      Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
   friend class ASTContext;  // ASTContext creates these.
   virtual void Destroy(ASTContext& C);
 
@@ -1214,9 +1216,15 @@ public:
   
   friend class StmtIteratorBase;
   
+  
   void Profile(llvm::FoldingSetNodeID &ID) {
-    assert(0 && "Cannnot unique DependentSizedArrayTypes.");
+    Profile(ID, Context, getElementType(), 
+            getSizeModifier(), getIndexTypeQualifier(), getSizeExpr());
   }
+  
+  static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, 
+                      QualType ET, ArraySizeModifier SizeMod, 
+                      unsigned TypeQuals, Expr *E);
 };
 
 /// DependentSizedExtVectorType - This type represent an extended vector type
index f47e28b8f20005b06375167d9efa1a4ae46c5a87..51815d5f319a63e32448ee9b5b8bd906ab45118b 100644 (file)
@@ -1371,8 +1371,7 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
 
 /// getDependentSizedArrayType - Returns a non-unique reference to
 /// the type for a dependently-sized array of the specified element
-/// type. FIXME: We will need these to be uniqued, or at least
-/// comparable, at some point.
+/// type.
 QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
                                                 Expr *NumElts,
                                                 ArrayType::ArraySizeModifier ASM,
@@ -1381,15 +1380,38 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
   assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) && 
          "Size must be type- or value-dependent!");
 
-  // Since we don't unique expressions, it isn't possible to unique
-  // dependently-sized array types.
-
-  DependentSizedArrayType *New =
-    new (*this,8) DependentSizedArrayType(EltTy, QualType(),
-                                          NumElts, ASM, EltTypeQuals,
-                                          Brackets);
+  llvm::FoldingSetNodeID ID;
+  DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM, 
+                                   EltTypeQuals, NumElts);
 
-  DependentSizedArrayTypes.push_back(New);
+  void *InsertPos = 0;
+  DependentSizedArrayType *Canon
+    = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+  DependentSizedArrayType *New;
+  if (Canon) {
+    // We already have a canonical version of this array type; use it as
+    // the canonical type for a newly-built type.
+    New = new (*this,8) DependentSizedArrayType(*this, EltTy, 
+                                                QualType(Canon, 0),
+                                                NumElts, ASM, EltTypeQuals,
+                                                Brackets);
+  } else {
+    QualType CanonEltTy = getCanonicalType(EltTy);
+    if (CanonEltTy == EltTy) {
+      New = new (*this,8) DependentSizedArrayType(*this, EltTy, QualType(),
+                                                  NumElts, ASM, EltTypeQuals,
+                                                  Brackets);
+      DependentSizedArrayTypes.InsertNode(New, InsertPos);
+    } else {
+      QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
+                                                  ASM, EltTypeQuals,
+                                                  SourceRange());
+      New = new (*this,8) DependentSizedArrayType(*this, EltTy, Canon,
+                                                  NumElts, ASM, EltTypeQuals,
+                                                  Brackets);      
+    }
+  }
+  
   Types.push_back(New);
   return QualType(New, 0);
 }
index c8e317c7d32a13488475bff6a18e0239cbb541ee..ed91e80c3e8f4dadf3c69934241efd27927b759a 100644 (file)
@@ -64,6 +64,18 @@ void DependentSizedArrayType::Destroy(ASTContext& C) {
   C.Deallocate(this);
 }
 
+void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, 
+                                      ASTContext &Context,
+                                      QualType ET,
+                                      ArraySizeModifier SizeMod,
+                                      unsigned TypeQuals,
+                                      Expr *E) {
+  ID.AddPointer(ET.getAsOpaquePtr());
+  ID.AddInteger(SizeMod);
+  ID.AddInteger(TypeQuals);
+  E->Profile(ID, Context, true);
+}
+
 void DependentSizedExtVectorType::Destroy(ASTContext& C) {
   // FIXME: Deallocate size expression, once we're cloning properly.
 //  if (SizeExpr)
index 250420bedb15697c3601900168c45c2e25e2afed..767e0055d8f5c5b686090e4d2235494c4cefb9c3 100644 (file)
@@ -13,4 +13,14 @@ template<typename T, T N>
 void f0(T x, __typeof__((f)(N)) y) { }
 
 template<typename U, U M>
-void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
\ No newline at end of file
+void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
+
+// Test dependently-sized array canonicalization
+template<typename T, int N, int M>
+void f1(T (&array)[N + M]) { } // expected-note{{previous}}
+
+template<typename T, int N, int M>
+void f1(T (&array)[M + N]) { }
+
+template<typename T, int M, int N>
+void f1(T (&array)[M + N]) { } // expected-error{{redefinition}}