aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h2
-rw-r--r--include/clang/AST/Type.h16
-rw-r--r--lib/AST/ASTContext.cpp42
-rw-r--r--lib/AST/Type.cpp12
-rw-r--r--test/SemaTemplate/canonical-expr-type.cpp12
5 files changed, 68 insertions, 16 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a1f190a74b..1c64f0be05 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -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;
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 6eaa4e67a7..411a279cd0 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f47e28b8f2..51815d5f31 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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);
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index c8e317c7d3..ed91e80c3e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -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)
diff --git a/test/SemaTemplate/canonical-expr-type.cpp b/test/SemaTemplate/canonical-expr-type.cpp
index 250420bedb..767e0055d8 100644
--- a/test/SemaTemplate/canonical-expr-type.cpp
+++ b/test/SemaTemplate/canonical-expr-type.cpp
@@ -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}}