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 : 16; + unsigned Index : 15; /// Represents the index within a pack if this represents a substitution /// from a pack expansion. This index starts at the end of the pack and @@ -4988,8 +4990,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; @@ -4999,7 +5005,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; } @@ -5026,7 +5036,7 @@ const Decl *ReplacedDecl, unsigned Index, Optional PackIndex) { ID.AddPointer(ReplacedDecl); - ID.AddPointer(Replacement.getAsOpaquePtr()); + Replacement.Profile(ID); ID.AddInteger(Index); ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); } 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 @@ -744,7 +744,7 @@ // The call to getCanonicalType here existed in ASTReader.cpp, too. def : Creator<[{ return ctx.getSubstTemplateTypeParmType( - ctx.getCanonicalType(replacementType), replacedDecl, Index, PackIndex); + replacementType, replacedDecl, Index, PackIndex); }]>; } 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 @@ -4756,9 +4756,6 @@ ASTContext::getSubstTemplateTypeParmType(QualType Replacement, Decl *ReplacedDecl, unsigned Index, Optional PackIndex) const { - assert(Replacement.isCanonical() - && "replacement types must always be canonical"); - llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Replacement, ReplacedDecl, Index, PackIndex); @@ -4767,7 +4764,10 @@ SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); if (!SubstParm) { - SubstParm = new (*this, TypeAlignment) + void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc( + !Replacement.isCanonical()), + TypeAlignment); + SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, ReplacedDecl, Index, PackIndex); 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,7 +1529,7 @@ return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - ToReplacementTypeOrErr->getCanonicalType(), *ReplacedOrErr, T->getIndex(), + *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex()); } 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 @@ -3719,6 +3719,11 @@ : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), Replacement->getDependence()), ReplacedDecl(ReplacedDecl) { + SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType = + Replacement != getCanonicalTypeInternal(); + if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType) + *getTrailingObjects() = Replacement; + SubstTemplateTypeParmTypeBits.Index = Index; SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0; assert(ReplacedDecl != 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 @@ -3508,7 +3508,7 @@ auto getSubstType = [&](QualType Replacement, unsigned IndexReplaced, Optional PackIndexReplaced) { return SemaRef.Context.getSubstTemplateTypeParmType( - Replacement.getCanonicalType(), BTD, IndexReplaced, PackIndexReplaced); + Replacement, BTD, IndexReplaced, PackIndexReplaced); }; switch (BTD->getBuiltinTemplateKind()) {