diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1798,8 +1798,10 @@ unsigned : NumTypeBits; + unsigned HasNonCanonicalUnderlyingType : 1; + // The index of the template parameter this substitution represents. - unsigned Index; + unsigned Index : 16; }; class SubstTemplateTypeParmPackTypeBitfields { @@ -4981,8 +4983,12 @@ /// been replaced with these. They are used solely to record that a /// type was originally written as a template type parameter; /// therefore they are never canonical. -class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { +class SubstTemplateTypeParmType final + : public Type, + public llvm::FoldingSetNode, + private llvm::TrailingObjects { friend class ASTContext; + friend class llvm::TrailingObjects; Decl *ReplacedDecl; @@ -4992,7 +4998,11 @@ public: /// Gets the type that was substituted for the template /// parameter. - QualType getReplacementType() const { return getCanonicalTypeInternal(); } + QualType getReplacementType() const { + return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType + ? *getTrailingObjects() + : getCanonicalTypeInternal(); + } /// Gets the templated entity that was substituted. Decl *getReplacedDecl() const { return ReplacedDecl; } @@ -5011,7 +5021,7 @@ static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement, const Decl *ReplacedDecl, unsigned Index) { ID.AddPointer(ReplacedDecl); - ID.AddPointer(Replacement.getAsOpaquePtr()); + Replacement.Profile(ID); ID.AddInteger(Index); } diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -741,7 +741,7 @@ // The call to getCanonicalType here existed in ASTReader.cpp, too. def : Creator<[{ return ctx.getSubstTemplateTypeParmType( - ctx.getCanonicalType(replacementType), replacedDecl, Index); + replacementType, replacedDecl, Index); }]>; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4752,9 +4752,6 @@ QualType ASTContext::getSubstTemplateTypeParmType(QualType Replacement, Decl *ReplacedDecl, unsigned Index) const { - assert(Replacement.isCanonical() - && "replacement types must always be canonical"); - llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Replacement, ReplacedDecl, Index); void *InsertPos = nullptr; @@ -4762,8 +4759,11 @@ SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); if (!SubstParm) { - SubstParm = new (*this, TypeAlignment) - SubstTemplateTypeParmType(Replacement, ReplacedDecl, Index); + void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc( + !Replacement.isCanonical()), + TypeAlignment); + SubstParm = + new (Mem) SubstTemplateTypeParmType(Replacement, ReplacedDecl, Index); Types.push_back(SubstParm); SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1529,8 +1529,7 @@ return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - ToReplacementTypeOrErr->getCanonicalType(), *ReplacedOrErr, - T->getIndex()); + *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex()); } ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3718,6 +3718,11 @@ : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), Replacement->getDependence()), ReplacedDecl(ReplacedDecl) { + SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType = + Replacement != getCanonicalTypeInternal(); + if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType) + *getTrailingObjects() = Replacement; + SubstTemplateTypeParmTypeBits.Index = Index; assert(ReplacedDecl != nullptr); assert(getReplacedParameter() != nullptr); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3506,8 +3506,8 @@ // Wrap the type in substitution sugar. auto getSubstType = [&](unsigned IndexReplaced, QualType Replacement) { - return SemaRef.Context.getSubstTemplateTypeParmType( - Replacement.getCanonicalType(), BTD, IndexReplaced); + return SemaRef.Context.getSubstTemplateTypeParmType(Replacement, BTD, + IndexReplaced); }; switch (BTD->getBuiltinTemplateKind()) {