[clang] ef4bbfe - [clang] AST: SubstTemplateTypeParmType support for non-canonical underlying type

Matheus Izvekov via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 21 05:23:46 PDT 2022


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 <mizvekov at 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


        


More information about the cfe-commits mailing list