Author: Matheus Izvekov Date: 2022-09-21T14:22:19+02:00 New Revision: ef4bbfe338bd85a9938d47c2d65f0eef874a6f7c
URL: https://github.com/llvm/llvm-project/commit/ef4bbfe338bd85a9938d47c2d65f0eef874a6f7c DIFF: https://github.com/llvm/llvm-project/commit/ef4bbfe338bd85a9938d47c2d65f0eef874a6f7c.diff LOG: [clang] AST: SubstTemplateTypeParmType support for non-canonical underlying type This change allows us to represent in the AST some specific circumstances where we substitute a template parameter type which is part of the underlying type of a previous substitution. This presently happens in some circumstances dealing with substitution of defaulted parameters of template template parameters, and in some other cases during concepts substitution. The main motivation for this change is for the future use in the implementation of template specialization resugaring, as this will allow us to represent a substitution with sugared types. Signed-off-by: Matheus Izvekov <mizve...@gmail.com> Differential Revision: https://reviews.llvm.org/D132816 Added: Modified: clang/include/clang/AST/Type.h clang/include/clang/AST/TypeProperties.td clang/lib/AST/ASTContext.cpp clang/lib/AST/ASTImporter.cpp clang/lib/AST/Type.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/TreeTransform.h clang/test/AST/ast-dump-template-decls.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 9d3aea0a3acda..347088780e4b8 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1798,6 +1798,8 @@ class alignas(8) Type : public ExtQualsTypeCommonBase { unsigned : NumTypeBits; + unsigned HasNonCanonicalUnderlyingType : 1; + /// 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 /// increments towards the beginning. @@ -4985,8 +4987,12 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { /// 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<SubstTemplateTypeParmType, QualType> { friend class ASTContext; + friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>; // The original type parameter. const TemplateTypeParmType *Replaced; @@ -5003,7 +5009,9 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { /// Gets the type that was substituted for the template /// parameter. QualType getReplacementType() const { - return getCanonicalTypeInternal(); + return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType + ? *getTrailingObjects<QualType>() + : getCanonicalTypeInternal(); } Optional<unsigned> getPackIndex() const { @@ -5023,7 +5031,7 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { const TemplateTypeParmType *Replaced, QualType Replacement, Optional<unsigned> PackIndex) { ID.AddPointer(Replaced); - ID.AddPointer(Replacement.getAsOpaquePtr()); + Replacement.Profile(ID); ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); } diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index aa8bb79fc4706..6d4bf515389a1 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -739,10 +739,9 @@ let Class = SubstTemplateTypeParmType in { } def : Creator<[{ - // The call to getCanonicalType here existed in ASTReader.cpp, too. return ctx.getSubstTemplateTypeParmType( cast<TemplateTypeParmType>(replacedParameter), - ctx.getCanonicalType(replacementType), PackIndex); + replacementType, PackIndex); }]>; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 622bad78e59a8..d9811ce19eb6c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4764,9 +4764,6 @@ QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, QualType Replacement, Optional<unsigned> PackIndex) const { - assert(Replacement.isCanonical() - && "replacement types must always be canonical"); - llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex); void *InsertPos = nullptr; @@ -4774,8 +4771,11 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); if (!SubstParm) { - SubstParm = new (*this, TypeAlignment) - SubstTemplateTypeParmType(Parm, Replacement, PackIndex); + void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc<QualType>( + !Replacement.isCanonical()), + TypeAlignment); + SubstParm = + new (Mem) SubstTemplateTypeParmType(Parm, Replacement, PackIndex); Types.push_back(SubstParm); SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 89132de0686fe..f0ba8c91db446 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1530,8 +1530,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - *ReplacedOrErr, ToReplacementTypeOrErr->getCanonicalType(), - T->getPackIndex()); + *ReplacedOrErr, *ToReplacementTypeOrErr, T->getPackIndex()); } ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fa6d3a04aa965..96028f3e36b99 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3650,10 +3650,16 @@ IdentifierInfo *TemplateTypeParmType::getIdentifier() const { } SubstTemplateTypeParmType::SubstTemplateTypeParmType( - const TemplateTypeParmType *Param, QualType Canon, + const TemplateTypeParmType *Param, QualType Replacement, Optional<unsigned> PackIndex) - : Type(SubstTemplateTypeParm, Canon, Canon->getDependence()), + : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), + Replacement->getDependence()), Replaced(Param) { + SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType = + Replacement != getCanonicalTypeInternal(); + if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType) + *getTrailingObjects<QualType>() = Replacement; + SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 2ab59e7a37c0d..5818300cbff2d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3513,8 +3513,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, 0, IndexReplaced, false, cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced))); return SemaRef.Context.getSubstTemplateTypeParmType( - cast<TemplateTypeParmType>(TTP), Replacement.getCanonicalType(), - PackIndexReplaced); + cast<TemplateTypeParmType>(TTP), Replacement, PackIndexReplaced); }; switch (BTD->getBuiltinTemplateKind()) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 9fde9ce8582d1..196cf94d1fc29 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6408,8 +6408,6 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType( if (Replacement.isNull()) return QualType(); - // Always canonicalize the replacement type. - Replacement = SemaRef.Context.getCanonicalType(Replacement); QualType Result = SemaRef.Context.getSubstTemplateTypeParmType( T->getReplacedParameter(), Replacement, T->getPackIndex()); diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index b994f1fccf158..2c534895fa12a 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -162,3 +162,22 @@ using t2 = D<float, char>::B<int, short>; // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0 // CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack } // namespace PR56099 + +namespace subst_default_argument { +template<class A1> class A {}; +template<template<class C1, class C2 = A<C1>> class D1, class D2> using D = D1<D2>; + +template<class E1, class E2> class E {}; +using test1 = D<E, int>; +// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<subst_default_argument::E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>' +// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A +// CHECK-NEXT: |-TemplateArgument type 'int':'int' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar +// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'C1' dependent depth 1 index 0 +// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[^ ]*}} 'C1' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar +// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'type-parameter-0-1' dependent depth 0 index 1 +// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' +// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>' +// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A' +} // namespace subst_default_argument _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits