Canonicalization of dependent C++0x decltype types.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77643 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 81cab92..f47e28b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1954,9 +1954,26 @@
 /// on canonical type's (which are always unique).
 QualType ASTContext::getDecltypeType(Expr *e) {
   DecltypeType *dt;
-  if (e->isTypeDependent()) // FIXME: canonicalize the expression
-    dt = new (*this, 8) DecltypeType(e, DependentTy);
-  else {
+  if (e->isTypeDependent()) {
+    llvm::FoldingSetNodeID ID;
+    DependentDecltypeType::Profile(ID, *this, e);
+    
+    void *InsertPos = 0;
+    DependentDecltypeType *Canon
+      = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
+    if (Canon) {
+      // We already have a "canonical" version of an equivalent, dependent
+      // decltype type. Use that as our canonical type.
+      dt = new (*this, 8) DecltypeType(e, DependentTy,
+                                       QualType((DecltypeType*)Canon, 0));
+    }
+    else {
+      // Build a new, canonical typeof(expr) type.
+      Canon = new (*this, 8) DependentDecltypeType(*this, e);
+      DependentDecltypeTypes.InsertNode(Canon, InsertPos);
+      dt = Canon;
+    }
+  } else {
     QualType T = getDecltypeForExpr(e, *this);
     dt = new (*this, 8) DecltypeType(e, T, getCanonicalType(T));    
   }
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 76d3546..c8e317c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -968,6 +968,14 @@
   UnderlyingType(underlyingType) {
 }
 
+DependentDecltypeType::DependentDecltypeType(ASTContext &Context, Expr *E)
+  : DecltypeType(E, Context.DependentTy), Context(Context) { }
+
+void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, 
+                                    ASTContext &Context, Expr *E) {
+  E->Profile(ID, Context, true);
+}
+
 TagType::TagType(TypeClass TC, TagDecl *D, QualType can) 
   : Type(TC, can, D->isDependentType()), decl(D, 0) {}