Skip to content

Conversation

@slydiman
Copy link
Contributor

Reverts #135119 because of the assert in ASTContext.cpp, line 5619.
See #135352 for details.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang-tools-extra clangd clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Apr 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 11, 2025

@llvm/pr-subscribers-clang-modules
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clangd

Author: Dmitry Vasilyev (slydiman)

Changes

Reverts llvm/llvm-project#135119 because of the assert in ASTContext.cpp, line 5619.
See #135352 for details.


Patch is 89.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135354.diff

28 Files Affected:

  • (modified) clang-tools-extra/clangd/AST.cpp (+1-2)
  • (modified) clang/docs/ReleaseNotes.rst (-2)
  • (modified) clang/include/clang/AST/ASTContext.h (+15-31)
  • (modified) clang/include/clang/AST/PropertiesBase.td (+1-4)
  • (modified) clang/include/clang/AST/TemplateBase.h (+2-11)
  • (modified) clang/include/clang/AST/Type.h (+4-3)
  • (modified) clang/include/clang/AST/TypeProperties.td (+25-5)
  • (modified) clang/lib/AST/ASTContext.cpp (+107-129)
  • (modified) clang/lib/AST/ASTDiagnostic.cpp (+4-4)
  • (modified) clang/lib/AST/ASTImporter.cpp (+13-21)
  • (modified) clang/lib/AST/DeclTemplate.cpp (+2-5)
  • (modified) clang/lib/AST/QualTypeNames.cpp (+1-2)
  • (modified) clang/lib/AST/TemplateBase.cpp (+4-15)
  • (modified) clang/lib/AST/Type.cpp (+23-27)
  • (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+10-8)
  • (modified) clang/lib/Sema/SemaExpr.cpp (+3-17)
  • (modified) clang/lib/Sema/SemaLookup.cpp (+1-2)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+84-78)
  • (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+18-27)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+5-6)
  • (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+1-2)
  • (modified) clang/lib/Sema/TreeTransform.h (+4-9)
  • (modified) clang/test/CXX/class.derived/class.derived.general/p2.cpp (+1-1)
  • (modified) clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp (+2-2)
  • (modified) clang/test/SemaCXX/undefined-partial-specialization.cpp (+1-1)
  • (modified) clang/test/SemaTemplate/make_integer_seq.cpp (+45-16)
  • (modified) clang/test/SemaTemplate/type_pack_element.cpp (+42-15)
  • (modified) clang/unittests/AST/TypePrinterTest.cpp (+3-3)
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 3b991e5e9013f..66b587f00ff4a 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -439,8 +439,7 @@ QualType declaredType(const TypeDecl *D) {
   if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
     if (const auto *Args = CTSD->getTemplateArgsAsWritten())
       return Context.getTemplateSpecializationType(
-          TemplateName(CTSD->getSpecializedTemplate()), Args->arguments(),
-          /*CanonicalArgs=*/std::nullopt);
+          TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
   return Context.getTypeDeclType(D);
 }
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 69c7369755c67..db8dad268a8a7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -301,8 +301,6 @@ Improvements to Clang's diagnostics
 - Clang now better preserves the sugared types of pointers to member.
 - Clang now better preserves the presence of the template keyword with dependent
   prefixes.
-- Clang now in more cases avoids printing 'type-parameter-X-X' instead of the name of
-  the template parameter.
 - Clang now respects the current language mode when printing expressions in
   diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
   a bunch of HLSL types being printed as their C++ equivalents.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b8ea2af9215d2..b1e6344576eb5 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -367,6 +367,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                      const ASTContext&>
     CanonTemplateTemplateParms;
 
+  TemplateTemplateParmDecl *
+    getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
+
   /// The typedef for the __int128_t type.
   mutable TypedefDecl *Int128Decl = nullptr;
 
@@ -1808,26 +1811,22 @@ class ASTContext : public RefCountedBase<ASTContext> {
                           bool ParameterPack,
                           TemplateTypeParmDecl *ParmDecl = nullptr) const;
 
-  QualType getCanonicalTemplateSpecializationType(
-      TemplateName T, ArrayRef<TemplateArgument> CanonicalArgs) const;
+  QualType getTemplateSpecializationType(TemplateName T,
+                                         ArrayRef<TemplateArgument> Args,
+                                         QualType Canon = QualType()) const;
 
   QualType
-  getTemplateSpecializationType(TemplateName T,
-                                ArrayRef<TemplateArgument> SpecifiedArgs,
-                                ArrayRef<TemplateArgument> CanonicalArgs,
-                                QualType Underlying = QualType()) const;
+  getCanonicalTemplateSpecializationType(TemplateName T,
+                                         ArrayRef<TemplateArgument> Args) const;
 
-  QualType
-  getTemplateSpecializationType(TemplateName T,
-                                ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
-                                ArrayRef<TemplateArgument> CanonicalArgs,
-                                QualType Canon = QualType()) const;
+  QualType getTemplateSpecializationType(TemplateName T,
+                                         ArrayRef<TemplateArgumentLoc> Args,
+                                         QualType Canon = QualType()) const;
 
-  TypeSourceInfo *getTemplateSpecializationTypeInfo(
-      TemplateName T, SourceLocation TLoc,
-      const TemplateArgumentListInfo &SpecifiedArgs,
-      ArrayRef<TemplateArgument> CanonicalArgs,
-      QualType Canon = QualType()) const;
+  TypeSourceInfo *
+  getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
+                                    const TemplateArgumentListInfo &Args,
+                                    QualType Canon = QualType()) const;
 
   QualType getParenType(QualType NamedType) const;
 
@@ -2943,21 +2942,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
     const;
 
-  /// Canonicalize the given template argument list.
-  ///
-  /// Returns true if any arguments were non-canonical, false otherwise.
-  bool
-  canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
-
-  /// Canonicalize the given TemplateTemplateParmDecl.
-  TemplateTemplateParmDecl *
-  getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
-
-  TemplateTemplateParmDecl *findCanonicalTemplateTemplateParmDeclInternal(
-      TemplateTemplateParmDecl *TTP) const;
-  TemplateTemplateParmDecl *insertCanonicalTemplateTemplateParmDeclInternal(
-      TemplateTemplateParmDecl *CanonTTP) const;
-
   /// Type Query functions.  If the type is an instance of the specified class,
   /// return the Type pointer for the underlying maximally pretty type.  This
   /// is a member of ASTContext because this may need to do some amount of
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 33336d57b6298..90537d47dd9c9 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -877,14 +877,11 @@ let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
   def : Property<"expression", ExprRef> {
     let Read = [{ node.getAsExpr() }];
   }
-  def : Property<"IsCanonical", Bool> {
-    let Read = [{ node.isCanonicalExpr() }];
-  }
   def : Property<"isDefaulted", Bool> {
     let Read = [{ node.getIsDefaulted() }];
   }
   def : Creator<[{
-    return TemplateArgument(expression, IsCanonical, isDefaulted);
+    return TemplateArgument(expression, isDefaulted);
   }]>;
 }
 let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index 279feb858e665..bea624eb04942 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -167,8 +167,6 @@ class TemplateArgument {
     unsigned Kind : 31;
     LLVM_PREFERRED_TYPE(bool)
     unsigned IsDefaulted : 1;
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned IsCanonicalExpr : 1;
     uintptr_t V;
   };
   union {
@@ -189,8 +187,7 @@ class TemplateArgument {
 
 public:
   /// Construct an empty, invalid template argument.
-  constexpr TemplateArgument()
-      : TypeOrValue{Null, /*IsDefaulted=*/0, /*IsCanonicalExpr=*/0, /*V=*/0} {}
+  constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {}
 
   /// Construct a template type argument.
   TemplateArgument(QualType T, bool isNullPtr = false,
@@ -265,10 +262,9 @@ class TemplateArgument {
   /// This form of template argument only occurs in template argument
   /// lists used for dependent types and for expression; it will not
   /// occur in a non-dependent, canonical template argument list.
-  TemplateArgument(Expr *E, bool IsCanonical, bool IsDefaulted = false) {
+  explicit TemplateArgument(Expr *E, bool IsDefaulted = false) {
     TypeOrValue.Kind = Expression;
     TypeOrValue.IsDefaulted = IsDefaulted;
-    TypeOrValue.IsCanonicalExpr = IsCanonical;
     TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
   }
 
@@ -411,11 +407,6 @@ class TemplateArgument {
     return reinterpret_cast<Expr *>(TypeOrValue.V);
   }
 
-  bool isCanonicalExpr() const {
-    assert(getKind() == Expression && "Unexpected kind");
-    return TypeOrValue.IsCanonicalExpr;
-  }
-
   /// Iterator that traverses the elements of a template argument pack.
   using pack_iterator = const TemplateArgument *;
 
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index dc57170bf9160..9f6189440fabf 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -6676,9 +6676,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
   /// replacement must, recursively, be one of these).
   TemplateName Template;
 
-  TemplateSpecializationType(TemplateName T, bool IsAlias,
+  TemplateSpecializationType(TemplateName T,
                              ArrayRef<TemplateArgument> Args,
-                             QualType Underlying);
+                             QualType Canon,
+                             QualType Aliased);
 
 public:
   /// Determine whether any of the given template arguments are dependent.
@@ -6746,7 +6747,7 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
 
   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
   static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
-                      ArrayRef<TemplateArgument> Args, QualType Underlying,
+                      ArrayRef<TemplateArgument> Args,
                       const ASTContext &Context);
 
   static bool classof(const Type *T) {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 3bf9239e9cbf5..66d490850678a 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -737,19 +737,39 @@ let Class = DependentAddressSpaceType in {
 }
 
 let Class = TemplateSpecializationType in {
+  def : Property<"dependent", Bool> {
+    let Read = [{ node->isDependentType() }];
+  }
   def : Property<"templateName", TemplateName> {
     let Read = [{ node->getTemplateName() }];
   }
-  def : Property<"args", Array<TemplateArgument>> {
+  def : Property<"templateArguments", Array<TemplateArgument>> {
     let Read = [{ node->template_arguments() }];
   }
-  def : Property<"UnderlyingType", QualType> {
-    let Read = [{ node->isCanonicalUnqualified() ? QualType() :
-                                                   node->desugar() }];
+  def : Property<"underlyingType", Optional<QualType>> {
+    let Read = [{
+      node->isTypeAlias()
+        ? std::optional<QualType>(node->getAliasedType())
+        : node->isCanonicalUnqualified()
+            ? std::nullopt
+            : std::optional<QualType>(node->getCanonicalTypeInternal())
+    }];
   }
 
   def : Creator<[{
-    return ctx.getTemplateSpecializationType(templateName, args, std::nullopt, UnderlyingType);
+    QualType result;
+    if (!underlyingType) {
+      result = ctx.getCanonicalTemplateSpecializationType(templateName,
+                                                          templateArguments);
+    } else {
+      result = ctx.getTemplateSpecializationType(templateName,
+                                                 templateArguments,
+                                                 *underlyingType);
+    }
+    if (dependent)
+      const_cast<Type *>(result.getTypePtr())
+          ->addDependence(TypeDependence::DependentInstantiation);
+    return result;
   }]>;
 }
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b8e6245230475..00e2fa267a460 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -844,31 +844,6 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
   return CanonTTP;
 }
 
-TemplateTemplateParmDecl *
-ASTContext::findCanonicalTemplateTemplateParmDeclInternal(
-    TemplateTemplateParmDecl *TTP) const {
-  llvm::FoldingSetNodeID ID;
-  CanonicalTemplateTemplateParm::Profile(ID, *this, TTP);
-  void *InsertPos = nullptr;
-  CanonicalTemplateTemplateParm *Canonical =
-      CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
-  return Canonical ? Canonical->getParam() : nullptr;
-}
-
-TemplateTemplateParmDecl *
-ASTContext::insertCanonicalTemplateTemplateParmDeclInternal(
-    TemplateTemplateParmDecl *CanonTTP) const {
-  llvm::FoldingSetNodeID ID;
-  CanonicalTemplateTemplateParm::Profile(ID, *this, CanonTTP);
-  void *InsertPos = nullptr;
-  if (auto *Existing =
-          CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos))
-    return Existing->getParam();
-  CanonTemplateTemplateParms.InsertNode(
-      new (*this) CanonicalTemplateTemplateParm(CanonTTP), InsertPos);
-  return CanonTTP;
-}
-
 /// Check if a type can have its sanitizer instrumentation elided based on its
 /// presence within an ignorelist.
 bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
@@ -3108,19 +3083,12 @@ static auto getCanonicalTemplateArguments(const ASTContext &C,
                                           ArrayRef<TemplateArgument> Args,
                                           bool &AnyNonCanonArgs) {
   SmallVector<TemplateArgument, 16> CanonArgs(Args);
-  AnyNonCanonArgs |= C.canonicalizeTemplateArguments(CanonArgs);
-  return CanonArgs;
-}
-
-bool ASTContext::canonicalizeTemplateArguments(
-    MutableArrayRef<TemplateArgument> Args) const {
-  bool AnyNonCanonArgs = false;
-  for (auto &Arg : Args) {
+  for (auto &Arg : CanonArgs) {
     TemplateArgument OrigArg = Arg;
-    Arg = getCanonicalTemplateArgument(Arg);
+    Arg = C.getCanonicalTemplateArgument(Arg);
     AnyNonCanonArgs |= !Arg.structurallyEquals(OrigArg);
   }
-  return AnyNonCanonArgs;
+  return CanonArgs;
 }
 
 //===----------------------------------------------------------------------===//
@@ -5570,121 +5538,132 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
   return QualType(TypeParm, 0);
 }
 
-TypeSourceInfo *ASTContext::getTemplateSpecializationTypeInfo(
-    TemplateName Name, SourceLocation NameLoc,
-    const TemplateArgumentListInfo &SpecifiedArgs,
-    ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
-  QualType TST = getTemplateSpecializationType(Name, SpecifiedArgs.arguments(),
-                                               CanonicalArgs, Underlying);
+TypeSourceInfo *
+ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
+                                              SourceLocation NameLoc,
+                                        const TemplateArgumentListInfo &Args,
+                                              QualType Underlying) const {
+  assert(!Name.getAsDependentTemplateName() &&
+         "No dependent template names here!");
+  QualType TST =
+      getTemplateSpecializationType(Name, Args.arguments(), Underlying);
 
   TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
   TemplateSpecializationTypeLoc TL =
       DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
   TL.setTemplateKeywordLoc(SourceLocation());
   TL.setTemplateNameLoc(NameLoc);
-  TL.setLAngleLoc(SpecifiedArgs.getLAngleLoc());
-  TL.setRAngleLoc(SpecifiedArgs.getRAngleLoc());
+  TL.setLAngleLoc(Args.getLAngleLoc());
+  TL.setRAngleLoc(Args.getRAngleLoc());
   for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
-    TL.setArgLocInfo(i, SpecifiedArgs[i].getLocInfo());
+    TL.setArgLocInfo(i, Args[i].getLocInfo());
   return DI;
 }
 
-QualType ASTContext::getTemplateSpecializationType(
-    TemplateName Template, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
-    ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
-  SmallVector<TemplateArgument, 4> SpecifiedArgVec;
-  SpecifiedArgVec.reserve(SpecifiedArgs.size());
-  for (const TemplateArgumentLoc &Arg : SpecifiedArgs)
-    SpecifiedArgVec.push_back(Arg.getArgument());
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+                                          ArrayRef<TemplateArgumentLoc> Args,
+                                          QualType Underlying) const {
+  assert(!Template.getAsDependentTemplateName() &&
+         "No dependent template names here!");
 
-  return getTemplateSpecializationType(Template, SpecifiedArgVec, CanonicalArgs,
-                                       Underlying);
+  SmallVector<TemplateArgument, 4> ArgVec;
+  ArgVec.reserve(Args.size());
+  for (const TemplateArgumentLoc &Arg : Args)
+    ArgVec.push_back(Arg.getArgument());
+
+  return getTemplateSpecializationType(Template, ArgVec, Underlying);
 }
 
-[[maybe_unused]] static bool
-hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) {
+#ifndef NDEBUG
+static bool hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) {
   for (const TemplateArgument &Arg : Args)
     if (Arg.isPackExpansion())
       return true;
-  return false;
-}
 
-QualType ASTContext::getCanonicalTemplateSpecializationType(
-    TemplateName Template, ArrayRef<TemplateArgument> Args) const {
-  assert(Template ==
-         getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true));
-  assert(!Args.empty());
-#ifndef NDEBUG
-  for (const auto &Arg : Args)
-    assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg)));
-#endif
-
-  llvm::FoldingSetNodeID ID;
-  TemplateSpecializationType::Profile(ID, Template, Args, QualType(), *this);
-  void *InsertPos = nullptr;
-  if (auto *T = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos))
-    return QualType(T, 0);
-
-  void *Mem = Allocate(sizeof(TemplateSpecializationType) +
-                           sizeof(TemplateArgument) * Args.size(),
-                       alignof(TemplateSpecializationType));
-  auto *Spec = new (Mem)
-      TemplateSpecializationType(Template, /*IsAlias=*/false, Args, QualType());
-  assert(Spec->isDependentType() &&
-         "canonical template specialization must be dependent");
-  Types.push_back(Spec);
-  TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
-  return QualType(Spec, 0);
+  return true;
 }
+#endif
 
-QualType ASTContext::getTemplateSpecializationType(
-    TemplateName Template, ArrayRef<TemplateArgument> SpecifiedArgs,
-    ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
-  assert(!Template.getUnderlying().getAsDependentTemplateName() &&
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+                                          ArrayRef<TemplateArgument> Args,
+                                          QualType Underlying) const {
+  assert(!Template.getAsDependentTemplateName() &&
          "No dependent template names here!");
 
   const auto *TD = Template.getAsTemplateDecl(/*IgnoreDeduced=*/true);
   bool IsTypeAlias = TD && TD->isTypeAlias();
-  if (Underlying.isNull()) {
-    TemplateName CanonTemplate =
-        getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true);
-    bool NonCanonical = Template != CanonTemplate;
-    SmallVector<TemplateArgument, 4> CanonArgsVec;
-    if (CanonicalArgs.empty()) {
-      CanonArgsVec = SmallVector<TemplateArgument, 4>(SpecifiedArgs);
-      NonCanonical |= canonicalizeTemplateArguments(CanonArgsVec);
-      CanonicalArgs = CanonArgsVec;
-    } else {
-      NonCanonical |= !llvm::equal(
-          SpecifiedArgs, CanonicalArgs,
-          [](const TemplateArgument &A, const TemplateArgument &B) {
-            return A.structurallyEquals(B);
-          });
-    }
-
-    // We can get here with an alias template when the specialization
-    // contains a pack expansion that does not match up with a parameter
-    // pack, or a builtin template which cannot be resolved due to dependency.
-    assert((!isa_and_nonnull<TypeAliasTemplateDecl>(TD) ||
-            hasAnyPackExpansions(CanonicalArgs)) &&
+  QualType CanonType;
+  if (!Underlying.isNull())
+    CanonType = getCanonicalType(Underlying);
+  else {
+    // We can get here with an alias template when the specialization contains
+    // a pack expansion that does not match up with a parameter pack.
+    assert((!IsTypeAlias || hasAnyPackExpansions(Args)) &&
            "Caller must compute aliased type");
     IsTypeAlias = false;
-
-    Underlying =
-        getCanonicalTemplateSpecializationType(CanonTemplate, CanonicalArgs);
-    if (!NonCanonical)
-      return Underlying;
+    CanonType = getCanonicalTemplateSpecializationType(Template, Args);
   }
+
+  // Allocate the (non-canonical) template specialization type, but don't
+  // try to unique it: these types typically have location information that
+  // we don't unique and don't want to lose.
   void *Mem = Allocate(sizeof(TemplateSpecializationType) +
-                           sizeof(TemplateArgument) * SpecifiedArgs.size() +
+                           sizeof(TemplateArgument) * Args.size() +
                            (IsTypeAlias ? sizeof(QualType) : 0),
                        alignof(TemplateSpecializationType));
-  auto *Spec = new (Mem) TemplateSpecializationType(Template, IsTypeAlias,
-                                                    SpecifiedArgs, Underly...
[truncated]

@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- clang-tools-extra/clangd/AST.cpp clang/include/clang/AST/ASTContext.h clang/include/clang/AST/TemplateBase.h clang/include/clang/AST/Type.h clang/lib/AST/ASTContext.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/ASTImporter.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/QualTypeNames.cpp clang/lib/AST/TemplateBase.cpp clang/lib/AST/Type.cpp clang/lib/Sema/SemaCXXScopeSpec.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaLookup.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/lib/Sema/SemaTemplateVariadic.cpp clang/lib/Sema/TreeTransform.h clang/test/CXX/class.derived/class.derived.general/p2.cpp clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp clang/test/SemaCXX/undefined-partial-specialization.cpp clang/test/SemaTemplate/make_integer_seq.cpp clang/test/SemaTemplate/type_pack_element.cpp clang/unittests/AST/TypePrinterTest.cpp
View the diff from clang-format here.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b1e634457..d0b6b2fcf 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -368,7 +368,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
     CanonTemplateTemplateParms;
 
   TemplateTemplateParmDecl *
-    getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
+  getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
 
   /// The typedef for the __int128_t type.
   mutable TypedefDecl *Int128Decl = nullptr;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 9f6189440..36ffa5423 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -6676,10 +6676,8 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
   /// replacement must, recursively, be one of these).
   TemplateName Template;
 
-  TemplateSpecializationType(TemplateName T,
-                             ArrayRef<TemplateArgument> Args,
-                             QualType Canon,
-                             QualType Aliased);
+  TemplateSpecializationType(TemplateName T, ArrayRef<TemplateArgument> Args,
+                             QualType Canon, QualType Aliased);
 
 public:
   /// Determine whether any of the given template arguments are dependent.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 00e2fa267..0122652be 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5538,11 +5538,9 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
   return QualType(TypeParm, 0);
 }
 
-TypeSourceInfo *
-ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
-                                              SourceLocation NameLoc,
-                                        const TemplateArgumentListInfo &Args,
-                                              QualType Underlying) const {
+TypeSourceInfo *ASTContext::getTemplateSpecializationTypeInfo(
+    TemplateName Name, SourceLocation NameLoc,
+    const TemplateArgumentListInfo &Args, QualType Underlying) const {
   assert(!Name.getAsDependentTemplateName() &&
          "No dependent template names here!");
   QualType TST =
@@ -5613,9 +5611,8 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
                            sizeof(TemplateArgument) * Args.size() +
                            (IsTypeAlias ? sizeof(QualType) : 0),
                        alignof(TemplateSpecializationType));
-  auto *Spec
-    = new (Mem) TemplateSpecializationType(Template, Args, CanonType,
-                                         IsTypeAlias ? Underlying : QualType());
+  auto *Spec = new (Mem) TemplateSpecializationType(
+      Template, Args, CanonType, IsTypeAlias ? Underlying : QualType());
 
   Types.push_back(Spec);
   return QualType(Spec, 0);
@@ -5640,20 +5637,18 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
   // Determine whether this canonical template specialization type already
   // exists.
   llvm::FoldingSetNodeID ID;
-  TemplateSpecializationType::Profile(ID, CanonTemplate,
-                                      CanonArgs, *this);
+  TemplateSpecializationType::Profile(ID, CanonTemplate, CanonArgs, *this);
 
   void *InsertPos = nullptr;
-  TemplateSpecializationType *Spec
-    = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+  TemplateSpecializationType *Spec =
+      TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
 
   if (!Spec) {
     // Allocate a new canonical template specialization type.
     void *Mem = Allocate((sizeof(TemplateSpecializationType) +
                           sizeof(TemplateArgument) * CanonArgs.size()),
                          alignof(TemplateSpecializationType));
-    Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
-                                                CanonArgs,
+    Spec = new (Mem) TemplateSpecializationType(CanonTemplate, CanonArgs,
                                                 QualType(), QualType());
     Types.push_back(Spec);
     TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index ccfef9c7a..fb8de20b8 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -127,8 +127,8 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
 
         if (DesugarArgument) {
           ShouldAKA = true;
-          QT = Context.getTemplateSpecializationType(
-              TST->getTemplateName(), Args, QT);
+          QT = Context.getTemplateSpecializationType(TST->getTemplateName(),
+                                                     Args, QT);
         }
         break;
       }
@@ -1142,9 +1142,9 @@ class TemplateDiff {
       return nullptr;
 
     Ty = Context.getTemplateSpecializationType(
-             TemplateName(CTSD->getSpecializedTemplate()),
-             CTSD->getTemplateArgs().asArray(),
-             Ty.getLocalUnqualifiedType().getCanonicalType());
+        TemplateName(CTSD->getSpecializedTemplate()),
+        CTSD->getTemplateArgs().asArray(),
+        Ty.getLocalUnqualifiedType().getCanonicalType());
 
     return Ty->getAs<TemplateSpecializationType>();
   }
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f7cd54e44..0e32a39ac 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1662,16 +1662,15 @@ ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
 
   QualType ToCanonType;
   if (!T->isCanonicalUnqualified()) {
-    QualType FromCanonType
-      = Importer.getFromContext().getCanonicalType(QualType(T, 0));
+    QualType FromCanonType =
+        Importer.getFromContext().getCanonicalType(QualType(T, 0));
     if (ExpectedType TyOrErr = import(FromCanonType))
       ToCanonType = *TyOrErr;
     else
       return TyOrErr.takeError();
   }
-  return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr,
-                                                               ToTemplateArgs,
-                                                               ToCanonType);
+  return Importer.getToContext().getTemplateSpecializationType(
+      *ToTemplateOrErr, ToTemplateArgs, ToCanonType);
 }
 
 ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 5c151254c..95c5fb18f 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -139,8 +139,7 @@ static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
     // allocate new type in the AST.
     if (MightHaveChanged) {
       QualType QT = Ctx.getTemplateSpecializationType(
-          TST->getTemplateName(), FQArgs,
-          TST->getCanonicalTypeInternal());
+          TST->getTemplateName(), FQArgs, TST->getCanonicalTypeInternal());
       // getTemplateSpecializationType returns a fully qualified
       // version of the specialization itself, so no need to qualify
       // it.
@@ -171,8 +170,7 @@ static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
       if (MightHaveChanged) {
         TemplateName TN(TSTDecl->getSpecializedTemplate());
         QualType QT = Ctx.getTemplateSpecializationType(
-            TN, FQArgs,
-            TSTRecord->getCanonicalTypeInternal());
+            TN, FQArgs, TSTRecord->getCanonicalTypeInternal());
         // getTemplateSpecializationType returns a fully qualified
         // version of the specialization itself, so no need to qualify
         // it.
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index f6dffeb0a..897388612 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4391,9 +4391,8 @@ TemplateSpecializationType::TemplateSpecializationType(
     TemplateName T, ArrayRef<TemplateArgument> Args, QualType Canon,
     QualType AliasedType)
     : Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon,
-           (Canon.isNull()
-                ? TypeDependence::DependentInstantiation
-                : toSemanticDependence(Canon->getDependence())) |
+           (Canon.isNull() ? TypeDependence::DependentInstantiation
+                           : toSemanticDependence(Canon->getDependence())) |
                (toTypeDependence(T.getDependence()) &
                 TypeDependence::UnexpandedPack)),
       Template(T) {
@@ -4447,11 +4446,10 @@ void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
     getAliasedType().Profile(ID);
 }
 
-void
-TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
-                                    TemplateName T,
-                                    ArrayRef<TemplateArgument> Args,
-                                    const ASTContext &Context) {
+void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+                                         TemplateName T,
+                                         ArrayRef<TemplateArgument> Args,
+                                         const ASTContext &Context) {
   T.Profile(ID);
   for (const TemplateArgument &Arg : Args)
     Arg.Profile(ID, Context);
@@ -5264,9 +5262,9 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
 }
 
 void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
-                      QualType Deduced, AutoTypeKeyword Keyword,
-                      bool IsDependent, ConceptDecl *CD,
-                      ArrayRef<TemplateArgument> Arguments) {
+                       QualType Deduced, AutoTypeKeyword Keyword,
+                       bool IsDependent, ConceptDecl *CD,
+                       ArrayRef<TemplateArgument> Arguments) {
   ID.AddPointer(Deduced.getAsOpaquePtr());
   ID.AddInteger((unsigned)Keyword);
   ID.AddBoolean(IsDependent);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 68ee006c6..3cdd3ee76 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -69,14 +69,14 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
 
       // Look through type alias templates, per C++0x [temp.dep.type]p1.
       NNSType = Context.getCanonicalType(NNSType);
-      if (const TemplateSpecializationType *SpecType
-            = NNSType->getAs<TemplateSpecializationType>()) {
+      if (const TemplateSpecializationType *SpecType =
+              NNSType->getAs<TemplateSpecializationType>()) {
         // We are entering the context of the nested name specifier, so try to
         // match the nested name specifier to either a primary class template
         // or a class template partial specialization.
-        if (ClassTemplateDecl *ClassTemplate
-              = dyn_cast_or_null<ClassTemplateDecl>(
-                            SpecType->getTemplateName().getAsTemplateDecl())) {
+        if (ClassTemplateDecl *ClassTemplate =
+                dyn_cast_or_null<ClassTemplateDecl>(
+                    SpecType->getTemplateName().getAsTemplateDecl())) {
           QualType ContextType =
               Context.getCanonicalType(QualType(SpecType, 0));
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3d7fa3827..2d2d8a47f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3288,7 +3288,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
     //    __type_pack_element<Index, T_1, ..., T_N>
     // are treated like T_Index.
     assert(Converted.size() == 2 &&
-      "__type_pack_element should be given an index and a parameter pack");
+           "__type_pack_element should be given an index and a parameter pack");
 
     TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
     if (IndexArg.isDependent() || Ts.isDependent())
@@ -3502,8 +3502,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
       return Context.getTemplateSpecializationType(Name,
                                                    TemplateArgs.arguments());
 
-    Diag(TemplateLoc, diag::err_template_id_not_a_type)
-      << Name;
+    Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name;
     NoteAllFoundTemplates(Name);
     return QualType();
   }
@@ -8532,8 +8531,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     CanonType = Context.getTemplateSpecializationType(CanonTemplate,
                                                       CTAI.CanonicalConverted);
 
-    if (Context.hasSameType(CanonType,
-                        ClassTemplate->getInjectedClassNameSpecialization()) &&
+    if (Context.hasSameType(
+            CanonType, ClassTemplate->getInjectedClassNameSpecialization()) &&
         (!Context.getLangOpts().CPlusPlus20 ||
          !TemplateParams->hasAssociatedConstraints())) {
       // C++ [temp.class.spec]p9b3:

@slydiman slydiman merged commit cbba960 into main Apr 11, 2025
17 of 18 checks passed
@slydiman slydiman deleted the revert-135119-users/mizvekov/tst-refactor branch April 11, 2025 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category clang-tools-extra clangd

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants