From: Douglas Gregor Date: Fri, 31 Jul 2009 00:23:35 +0000 (+0000) Subject: Build canonical types for dependently-sized array types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04d4beee4b86af20a9e4457023d3925cab8f9908;p=clang Build canonical types for dependently-sized array types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77647 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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 ConstantArrayTypes; llvm::FoldingSet IncompleteArrayTypes; std::vector VariableArrayTypes; - std::vector DependentSizedArrayTypes; + llvm::FoldingSet DependentSizedArrayTypes; std::vector DependentSizedExtVectorTypes; llvm::FoldingSet VectorTypes; llvm::FoldingSet 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 void f0(T x, __typeof__((f)(N)) y) { } template -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 +void f1(T (&array)[N + M]) { } // expected-note{{previous}} + +template +void f1(T (&array)[M + N]) { } + +template +void f1(T (&array)[M + N]) { } // expected-error{{redefinition}}