From 32adc8bd6f05d1e26cc221102e48609da2c446ba Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 26 Oct 2010 00:51:02 +0000 Subject: [PATCH] When de-serializing a type that is supposed to be canonical, call 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 | 45 +++++++++++++++++---------------- lib/Serialization/ASTReader.cpp | 4 +++ test/PCH/cxx-templates.cpp | 4 ++- test/PCH/cxx-templates.h | 14 ++++++++++ 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 10f875b1b7..d7ebedf72a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 38e786bff1..c0aff9afde 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2764,6 +2764,8 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { } TypedefDecl *Decl = cast(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); } diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp index d36d5449c8..95477992e6 100644 --- a/test/PCH/cxx-templates.cpp +++ b/test/PCH/cxx-templates.cpp @@ -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(3); S::templ(); @@ -32,6 +32,8 @@ void test() { s3.m(); TS5 ts(0); + + S6::t2 b6 = a6; } template struct S4; diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index e1f285b19d..5baa772b5d 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -150,3 +150,17 @@ struct TS5 { template void f_PR8134(T); template void f_PR8134(T); void g_PR8134() { f_PR8134(0); f_PR8134('x'); } + +// rdar8580149 +template +struct S6; + +template +struct S6 +{ +private: + typedef const T t1[N]; +public: + typedef t1& t2; +}; + -- 2.40.0