Skip to content

[clang] Track final substitution for Subst* AST nodes #132748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 2, 2025

Conversation

mizvekov
Copy link
Contributor

@mizvekov mizvekov commented Mar 24, 2025

This patch re-adds Subst* nodes for 'Final' substitutions, adding a bit to these nodes to differentiate them from non-Final ones, which for example helps track forward progress in resugaring.

This was originally changed when we added support for sugared substitutions in the template instantiator (326feaa), and later applied to NTTP and default argument substitution (ab11408) and type alias templates (7f78f99).

This kind of instantiation is favored for entities which we don't track specializations, like the aforementioned cases because:

  • Without tracking specializations, its not possible to (correctly) resugar these later.
  • A change to track specialization and adding resugar pass would have been more expensive.

While the node could have been still useful, its removal helped offset the extra costs of the sugared instantiation.

Otherwise, adding them would also necessitate tracking which nodes don't need to be resugared later, which this patch does.

Adding the node back does add a little bit of performance penalty on itself:
image

0.25% on stage2-clang.

And this will make resugaring a little bit more expensive later when that's upstreamed, since there are more AST nodes to walk, and more AST nodes to produce.

Before:
image

After:
image

Which on the current implementation and applications of resugaring transform, is an extra 0.24% on stage2-clang.

Some upstream users reported desirability of keeping these Subst* nodes in all cases, and we had added a special frontend flag to control its removal.

The flag itself will remain for the time being, in order to ease with the transition.
It will be removed in a follow-up.

@mizvekov mizvekov self-assigned this Mar 24, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Mar 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 24, 2025

@llvm/pr-subscribers-clang-tools-extra
@llvm/pr-subscribers-clangd
@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

This patch re-adds Subst* nodes for 'Final' substitutions, adding a bit to these nodes to differentiate them from non-Final ones, which for example helps track forward progress in resugaring.

This was originally changed when we added support for sugared substitutions in the template instantiator (326feaa), and later applied to NTTP and default argument substitution (ab11408) and type alias templates (7f78f99).

This kind of instantiation is favored for entities which we don't track specializations, like the aforementioned cases because:

  • Without tracking specializations, its not possible to (correctly) resugar these later.
  • A change to track specialization and adding resugar pass would have been more expensive.

While the node could have been still useful, its removal helped offset the extra costs of the sugared instantiation.

Otherwise, adding them would also necessitate tracking which nodes don't need to be resugared later, which this patch does.

Adding the node back does add a little bit of performance penalty on itself:
image

0.25% on stage2-clang.

And this will make resugaring a little bit more expensive later when that's upstreamed, since there are more AST nodes to walk, and more AST nodes to produce.

Before:
image

After:
image

Which on the current implementation and applications of resugaring transform, is an extra 0.24% on stage2-clang.

Some upstream users reported desirability of keeping these Subst* nodes in all cases, and we had added a special frontend flag to control its removal, which this patch now also removes.


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

21 Files Affected:

  • (modified) clang/include/clang/AST/ASTContext.h (+9-8)
  • (modified) clang/include/clang/AST/ExprCXX.h (+20-5)
  • (modified) clang/include/clang/AST/PropertiesBase.td (+2-1)
  • (modified) clang/include/clang/AST/TemplateName.h (+12-5)
  • (modified) clang/include/clang/AST/Type.h (+14-10)
  • (modified) clang/include/clang/AST/TypeProperties.td (+2-2)
  • (modified) clang/include/clang/Basic/LangOptions.def (-1)
  • (modified) clang/include/clang/Driver/Options.td (-6)
  • (modified) clang/lib/AST/ASTContext.cpp (+8-7)
  • (modified) clang/lib/AST/ASTImporter.cpp (+5-4)
  • (modified) clang/lib/AST/ExprCXX.cpp (+4-2)
  • (modified) clang/lib/AST/TemplateName.cpp (+4-2)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+4)
  • (modified) clang/lib/AST/Type.cpp (+18-4)
  • (modified) clang/lib/Sema/SemaTemplate.cpp (+4-10)
  • (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+18-30)
  • (modified) clang/lib/Sema/TreeTransform.h (+2-1)
  • (removed) clang/test/AST/ast-dump-retain-subst-template-type-parm-type-ast-nodes.cpp (-18)
  • (modified) clang/test/AST/ast-dump-template-decls.cpp (+12-6)
  • (modified) clang/test/Misc/diag-template-diffing-cxx11.cpp (+37-37)
  • (modified) clang/test/SemaTemplate/make_integer_seq.cpp (+6-2)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 1f7c75559e1e9..2ef8112225767 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1795,10 +1795,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
       QualType Wrapped, QualType Contained,
       const HLSLAttributedResourceType::Attributes &Attrs);
 
-  QualType
-  getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
-                               unsigned Index,
-                               std::optional<unsigned> PackIndex) const;
+  QualType getSubstTemplateTypeParmType(QualType Replacement,
+                                        Decl *AssociatedDecl, unsigned Index,
+                                        std::optional<unsigned> PackIndex,
+                                        bool Final) const;
   QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
                                             unsigned Index, bool Final,
                                             const TemplateArgument &ArgPack);
@@ -2396,10 +2396,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                         const IdentifierInfo *Name) const;
   TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
                                         OverloadedOperatorKind Operator) const;
-  TemplateName
-  getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
-                               unsigned Index,
-                               std::optional<unsigned> PackIndex) const;
+  TemplateName getSubstTemplateTemplateParm(TemplateName replacement,
+                                            Decl *AssociatedDecl,
+                                            unsigned Index,
+                                            std::optional<unsigned> PackIndex,
+                                            bool Final) const;
   TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
                                                 Decl *AssociatedDecl,
                                                 unsigned Index,
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 223d74993e9e6..028ee82718d50 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -4514,7 +4514,9 @@ class SubstNonTypeTemplateParmExpr : public Expr {
   llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef;
 
   unsigned Index : 15;
-  unsigned PackIndex : 16;
+  unsigned PackIndex : 15;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Final : 1;
 
   explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
       : Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
@@ -4523,11 +4525,12 @@ class SubstNonTypeTemplateParmExpr : public Expr {
   SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
                                SourceLocation Loc, Expr *Replacement,
                                Decl *AssociatedDecl, unsigned Index,
-                               std::optional<unsigned> PackIndex, bool RefParam)
+                               std::optional<unsigned> PackIndex, bool RefParam,
+                               bool Final)
       : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
         Replacement(Replacement),
         AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index),
-        PackIndex(PackIndex ? *PackIndex + 1 : 0) {
+        PackIndex(PackIndex ? *PackIndex + 1 : 0), Final(Final) {
     assert(AssociatedDecl != nullptr);
     SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
     setDependence(computeDependence(this));
@@ -4555,6 +4558,10 @@ class SubstNonTypeTemplateParmExpr : public Expr {
     return PackIndex - 1;
   }
 
+  // This substitution is Final, which means the substitution is fully
+  // sugared: it doesn't need to be resugared later.
+  bool getFinal() const { return Final; }
+
   NonTypeTemplateParmDecl *getParameter() const;
 
   bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
@@ -4598,7 +4605,10 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
   const TemplateArgument *Arguments;
 
   /// The number of template arguments in \c Arguments.
-  unsigned NumArguments : 16;
+  unsigned NumArguments : 15;
+
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned Final : 1;
 
   unsigned Index : 16;
 
@@ -4612,7 +4622,8 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
   SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
                                    SourceLocation NameLoc,
                                    const TemplateArgument &ArgPack,
-                                   Decl *AssociatedDecl, unsigned Index);
+                                   Decl *AssociatedDecl, unsigned Index,
+                                   bool Final);
 
   /// A template-like entity which owns the whole pattern being substituted.
   /// This will own a set of template parameters.
@@ -4622,6 +4633,10 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
   /// This should match the result of `getParameterPack()->getIndex()`.
   unsigned getIndex() const { return Index; }
 
+  // This substitution will be Final, which means the substitution will be fully
+  // sugared: it doesn't need to be resugared later.
+  bool getFinal() const { return Final; }
+
   /// Retrieve the non-type template parameter pack being substituted.
   NonTypeTemplateParmDecl *getParameterPack() const;
 
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 5f3a885832e2e..416914db2f7c8 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -729,8 +729,9 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
   def : Property<"packIndex", Optional<UInt32>> {
     let Read = [{ parm->getPackIndex() }];
   }
+  def : Property<"final", Bool> { let Read = [{ parm->getFinal() }]; }
   def : Creator<[{
-    return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
+    return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex, final);
   }]>;
 }
 let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index ce97f834bfc1d..313802502f818 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -413,9 +413,11 @@ class SubstTemplateTemplateParmStorage
 
   SubstTemplateTemplateParmStorage(TemplateName Replacement,
                                    Decl *AssociatedDecl, unsigned Index,
-                                   std::optional<unsigned> PackIndex)
+                                   std::optional<unsigned> PackIndex,
+                                   bool Final)
       : UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
-                                    PackIndex ? *PackIndex + 1 : 0),
+                                    ((PackIndex ? *PackIndex + 1 : 0) << 1) |
+                                        Final),
         Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
     assert(AssociatedDecl != nullptr);
   }
@@ -429,10 +431,15 @@ class SubstTemplateTemplateParmStorage
   /// This should match the result of `getParameter()->getIndex()`.
   unsigned getIndex() const { return Bits.Index; }
 
+  // This substitution is Final, which means the substitution is fully
+  // sugared: it doesn't need to be resugared later.
+  bool getFinal() const { return Bits.Data & 1; }
+
   std::optional<unsigned> getPackIndex() const {
-    if (Bits.Data == 0)
+    auto Data = Bits.Data >> 1;
+    if (Data == 0)
       return std::nullopt;
-    return Bits.Data - 1;
+    return Data - 1;
   }
 
   TemplateTemplateParmDecl *getParameter() const;
@@ -442,7 +449,7 @@ class SubstTemplateTemplateParmStorage
 
   static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
                       Decl *AssociatedDecl, unsigned Index,
-                      std::optional<unsigned> PackIndex);
+                      std::optional<unsigned> PackIndex, bool Final);
 };
 
 class DeducedTemplateStorage : public UncommonTemplateNameStorage,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 3b80f962a3bc6..16fde176fb909 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2158,12 +2158,15 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
     // The index of the template parameter this substitution represents.
     unsigned Index : 15;
 
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned Final : 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.
     /// Positive non-zero number represents the index + 1.
     /// Zero means this is not substituted from an expansion.
-    unsigned PackIndex : 16;
+    unsigned PackIndex : 15;
   };
 
   class SubstTemplateTypeParmPackTypeBitfields {
@@ -6384,7 +6387,8 @@ class SubstTemplateTypeParmType final
   Decl *AssociatedDecl;
 
   SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
-                            unsigned Index, std::optional<unsigned> PackIndex);
+                            unsigned Index, std::optional<unsigned> PackIndex,
+                            bool Final);
 
 public:
   /// Gets the type that was substituted for the template
@@ -6407,6 +6411,10 @@ class SubstTemplateTypeParmType final
   /// This should match the result of `getReplacedParameter()->getIndex()`.
   unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }
 
+  // This substitution is Final, which means the substitution is fully
+  // sugared: it doesn't need to be resugared later.
+  unsigned getFinal() const { return SubstTemplateTypeParmTypeBits.Final; }
+
   std::optional<unsigned> getPackIndex() const {
     if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
       return std::nullopt;
@@ -6418,17 +6426,12 @@ class SubstTemplateTypeParmType final
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
-            getPackIndex());
+            getPackIndex(), getFinal());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
                       const Decl *AssociatedDecl, unsigned Index,
-                      std::optional<unsigned> PackIndex) {
-    Replacement.Profile(ID);
-    ID.AddPointer(AssociatedDecl);
-    ID.AddInteger(Index);
-    ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
-  }
+                      std::optional<unsigned> PackIndex, bool Final);
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == SubstTemplateTypeParm;
@@ -6475,7 +6478,8 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
   /// This should match the result of `getReplacedParameter()->getIndex()`.
   unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; }
 
-  // When true the substitution will be 'Final' (subst node won't be placed).
+  // This substitution will be Final, which means the substitution will be fully
+  // sugared: it doesn't need to be resugared later.
   bool getFinal() const;
 
   unsigned getNumArgs() const {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 4d89d8a47396a..93f391e99c5ab 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -827,11 +827,11 @@ let Class = SubstTemplateTypeParmType in {
   def : Property<"PackIndex", Optional<UInt32>> {
     let Read = [{ node->getPackIndex() }];
   }
+  def : Property<"Final", Bool> { let Read = [{ node->getFinal() }]; }
 
-  // The call to getCanonicalType here existed in ASTReader.cpp, too.
   def : Creator<[{
     return ctx.getSubstTemplateTypeParmType(
-        replacementType, associatedDecl, Index, PackIndex);
+        replacementType, associatedDecl, Index, PackIndex, Final);
   }]>;
 }
 
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 3879cc7942877..930c1c06d1a76 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -161,7 +161,6 @@ LANGOPT(Coroutines        , 1, 0, "C++20 coroutines")
 LANGOPT(CoroAlignedAllocation, 1, 0, "prefer Aligned Allocation according to P2014 Option 2")
 LANGOPT(DllExportInlines  , 1, 1, "dllexported classes dllexport inline methods")
 LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features")
-LANGOPT(RetainSubstTemplateTypeParmTypeAstNodes, 1, 0, "retain SubstTemplateTypeParmType nodes in the AST's representation of alias template specializations")
 
 LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics")
 LANGOPT(PointerAuthCalls  , 1, 0, "function pointer authentication")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index fbd5cf632c350..3f68a55e85d8e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3506,12 +3506,6 @@ defm application_extension : BoolFOption<"application-extension",
   PosFlag<SetTrue, [], [ClangOption, CC1Option],
           "Restrict code to those available for App Extensions">,
   NegFlag<SetFalse>>;
-defm retain_subst_template_type_parm_type_ast_nodes : BoolFOption<"retain-subst-template-type-parm-type-ast-nodes",
-  LangOpts<"RetainSubstTemplateTypeParmTypeAstNodes">, DefaultFalse,
-  PosFlag<SetTrue, [], [CC1Option], "Enable">,
-  NegFlag<SetFalse, [], [], "Disable">,
-  BothFlags<[], [], " retain SubstTemplateTypeParmType nodes in the AST's representation"
-  " of alias template specializations">>;
 defm sized_deallocation : BoolFOption<"sized-deallocation",
   LangOpts<"SizedDeallocation">, Default<cpp14.KeyPath>,
   PosFlag<SetTrue, [], [], "Enable C++14 sized global deallocation functions">,
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4d2ca9ec1a123..0e3c6535808e0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5449,10 +5449,10 @@ QualType ASTContext::getHLSLAttributedResourceType(
 /// Retrieve a substitution-result type.
 QualType ASTContext::getSubstTemplateTypeParmType(
     QualType Replacement, Decl *AssociatedDecl, unsigned Index,
-    std::optional<unsigned> PackIndex) const {
+    std::optional<unsigned> PackIndex, bool Final) const {
   llvm::FoldingSetNodeID ID;
   SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
-                                     PackIndex);
+                                     PackIndex, Final);
   void *InsertPos = nullptr;
   SubstTemplateTypeParmType *SubstParm =
       SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -5462,7 +5462,7 @@ QualType ASTContext::getSubstTemplateTypeParmType(
                              !Replacement.isCanonical()),
                          alignof(SubstTemplateTypeParmType));
     SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
-                                                    Index, PackIndex);
+                                                    Index, PackIndex, Final);
     Types.push_back(SubstParm);
     SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
   }
@@ -10130,10 +10130,10 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
 
 TemplateName ASTContext::getSubstTemplateTemplateParm(
     TemplateName Replacement, Decl *AssociatedDecl, unsigned Index,
-    std::optional<unsigned> PackIndex) const {
+    std::optional<unsigned> PackIndex, bool Final) const {
   llvm::FoldingSetNodeID ID;
   SubstTemplateTemplateParmStorage::Profile(ID, Replacement, AssociatedDecl,
-                                            Index, PackIndex);
+                                            Index, PackIndex, Final);
 
   void *insertPos = nullptr;
   SubstTemplateTemplateParmStorage *subst
@@ -10141,7 +10141,7 @@ TemplateName ASTContext::getSubstTemplateTemplateParm(
 
   if (!subst) {
     subst = new (*this) SubstTemplateTemplateParmStorage(
-        Replacement, AssociatedDecl, Index, PackIndex);
+        Replacement, AssociatedDecl, Index, PackIndex, Final);
     SubstTemplateTemplateParms.InsertNode(subst, insertPos);
   }
 
@@ -14243,7 +14243,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
     if (PackIndex != SY->getPackIndex())
       return QualType();
     return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
-                                            CD, Index, PackIndex);
+                                            CD, Index, PackIndex,
+                                            SX->getFinal() && SY->getFinal());
   }
   case Type::ObjCTypeParam:
     // FIXME: Try to merge these.
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index d397c9285ed76..4e27f9d884a83 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1631,8 +1631,8 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
     return ToReplacementTypeOrErr.takeError();
 
   return Importer.getToContext().getSubstTemplateTypeParmType(
-      *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(),
-      T->getPackIndex());
+      *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex(),
+      T->getFinal());
 }
 
 ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
@@ -8945,7 +8945,8 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
 
   return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
       ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl,
-      E->getIndex(), E->getPackIndex(), E->isReferenceParameter());
+      E->getIndex(), E->getPackIndex(), E->isReferenceParameter(),
+      E->getFinal());
 }
 
 ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
@@ -9958,7 +9959,7 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {
 
     return ToContext.getSubstTemplateTemplateParm(
         *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(),
-        Subst->getPackIndex());
+        Subst->getPackIndex(), Subst->getFinal());
   }
 
   case TemplateName::SubstTemplateTemplateParmPack: {
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index a000e988e6834..a0bc50c449d82 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1760,10 +1760,12 @@ QualType SubstNonTypeTemplateParmExpr::getParameterType(
 
 SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr(
     QualType T, ExprValueKind ValueKind, SourceLocation NameLoc,
-    const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index)
+    const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
+    bool Final)
     : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary),
       AssociatedDecl(AssociatedDecl), Arguments(ArgPack.pack_begin()),
-      NumArguments(ArgPack.pack_size()), Index(Index), NameLoc(NameLoc) {
+      NumArguments(ArgPack.pack_size()), Final(Final), Index(Index),
+      NameLoc(NameLoc) {
   assert(AssociatedDecl != nullptr);
   setDependence(ExprDependence::TypeValueInstantiation |
                 ExprDependence::UnexpandedPack);
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 9e0a7dc2b8cdc..109cc3c4771ee 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -77,16 +77,18 @@ SubstTemplateTemplateParmStorage::getParameter() const {
 }
 
 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
-  Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
+  Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex(),
+          getFinal());
 }
 
 void SubstTemplateTemplateParmStorage::Profile(
     llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
-    unsigned Index, std::optional<unsigned> PackIndex) {
+    unsigned In...
[truncated]

@mizvekov
Copy link
Contributor Author

FYI @ymand @jvoung

@@ -265,14 +265,14 @@ int k9 = f9(V9<double>());
// CHECK-ELIDE-TREE: S9<
// CHECK-ELIDE-TREE: [2 * ...],
// CHECK-ELIDE-TREE: U9<
// CHECK-ELIDE-TREE: [(no qualifiers) != const] double>>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not obvious why this changed, can you explain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, with the Subst type node, you get difference when printing if the node is top-level qualified, versus when it is bottom-qualified. So you can get harmless differences in the order const appears, and in this case here differences in the order you see qualifiers as you single step desugar the types.

The tree-differ could be improved to remove these inconsistencies, but given the harmless nature of the effect we don't need to do it now.

@mizvekov mizvekov force-pushed the users/mizvekov/GH101754 branch from 6b4f7cb to c4cbf3b Compare March 24, 2025 16:21
@mizvekov mizvekov force-pushed the users/mizvekov/subst_final branch from f767185 to 4260717 Compare March 24, 2025 16:22
@mizvekov mizvekov force-pushed the users/mizvekov/GH101754 branch from c4cbf3b to 1b3a8e3 Compare March 27, 2025 01:06
@mizvekov mizvekov force-pushed the users/mizvekov/subst_final branch from 4260717 to db17b41 Compare March 27, 2025 01:43
@mizvekov mizvekov force-pushed the users/mizvekov/subst_final branch from db17b41 to 3917bdd Compare March 27, 2025 01:43
@mizvekov mizvekov force-pushed the users/mizvekov/GH101754 branch from 1b3a8e3 to a2a372d Compare March 30, 2025 17:25
@mizvekov mizvekov force-pushed the users/mizvekov/subst_final branch from 3917bdd to 7db83f2 Compare March 30, 2025 17:25
Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't clear to me where the actual 'work' is happening here, can you point it out? Most of the patch is smuggling the bool around, but I don't see where the actual check/use of final is.

Also-- Are there other opportunities here with this flag we can take advantage of? Anywhere we would attempt to sugar this that we could escape early? If so, maybe we can get part of the 0.25% back.

@@ -1302,6 +1302,8 @@ void TextNodeDumper::dumpBareTemplateName(TemplateName TN) {
OS << " index " << STS->getIndex();
if (std::optional<unsigned int> PackIndex = STS->getPackIndex())
OS << " pack_index " << *PackIndex;
if (STS->getFinal())
OS << " final";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as final is a keyword in C++ I wonder if we can find a better name for this. I certainly wouldn't see this in an AST and know what it means. I wonder if we should find a better name than final throughout this patch. Something like, FullySugared or something? Though open to other/better names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am open for suggestions, but I'd prefer to change this in a follow up, since the term is existing and this would make the patch much larger.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullySugared seems fine to me, unless you have a better idea. I would be ok with changing the name in a followup, which wouldn't really require review once we agree on a name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullySugared seems fine to me, unless you have a better idea. I would be ok with changing the name in a followup, which wouldn't really require review once we agree on a name.

+1

@mizvekov
Copy link
Contributor Author

mizvekov commented Apr 1, 2025

It isn't clear to me where the actual 'work' is happening here, can you point it out? Most of the patch is smuggling the bool around, but I don't see where the actual check/use of final is.

The users are external. My resugarer, which I am in the process of upstreaming, uses this flag in order to skip nodes which we shouldn't attempt to resugar. Otherwise, not adding the nodes in the first place was better performing, but the folks who are developing the nullability attribute are asking for it.

Also-- Are there other opportunities here with this flag we can take advantage of? Anywhere we would attempt to sugar this that we could escape early? If so, maybe we can get part of the 0.25% back.

Since we don't really use this within upstream clang itself, I don't think there are really any opportunities.
If the resugarer is made more efficient, maybe the secondary 0.24% impact can be mitigated a bit, but it's unclear how much and even if so.

@erichkeane
Copy link
Collaborator

It isn't clear to me where the actual 'work' is happening here, can you point it out? Most of the patch is smuggling the bool around, but I don't see where the actual check/use of final is.

The users are external. My resugarer, which I am in the process of upstreaming, uses this flag in order to skip nodes which we shouldn't attempt to resugar. Otherwise, not adding the nodes in the first place was better performing, but the folks who are developing the nullability attribute are asking for it.

Also-- Are there other opportunities here with this flag we can take advantage of? Anywhere we would attempt to sugar this that we could escape early? If so, maybe we can get part of the 0.25% back.

Since we don't really use this within upstream clang itself, I don't think there are really any opportunities. If the resugarer is made more efficient, maybe the secondary 0.24% impact can be mitigated a bit, but it's unclear how much and even if so.

Ah, got it! I missed that. Thanks!

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the name, I'm Ok with this. Followup patch to change the name to something more descriptive is very much wanted, but review of that should be trivial once we agree on a name. I am ok with fully-sugared/FullySugared, but open to other suggestions/not particularly attached to that (basically, final being a keyword, then appearing in odd places is going to be a big readability problem).

@mizvekov mizvekov requested review from ymand and jvoung April 1, 2025 16:50
@mizvekov
Copy link
Contributor Author

mizvekov commented Apr 1, 2025

@ymand @jvoung I'd like to know if you tried this patch within google and within your tooling, and if you can report whether it is suited and if there is any noteworthy performance impact.

@jvoung
Copy link
Contributor

jvoung commented Apr 1, 2025

Running some experiments now and will report back soon, thanks!

@mizvekov mizvekov force-pushed the users/mizvekov/GH101754 branch from a2a372d to 6ba9bbe Compare April 1, 2025 22:48
@jvoung
Copy link
Contributor

jvoung commented Apr 2, 2025

One question is, would you be okay with doing the flag removal separately? I.e., make it a no-op first, then delete it as a follow up with some time to adjust? That may allow integrating the change more incrementally (1) merge + update test expectations (2) stop using the flag, then (3) merge again with the flag deleted.

Taking out the flag removal is possible, I can separate that to another PR, but we should do it as soon as possible because its a bit awkward leaving a flag with no effect, and there would be no precedent for a 'deprecated' flag warning for a frontend flag.

Got it, yes not too long, just wanted to make the merges a little smoother. Thanks!

@mizvekov mizvekov merged commit f302f35 into main Apr 2, 2025
9 of 10 checks passed
@mizvekov mizvekov deleted the users/mizvekov/subst_final branch April 2, 2025 22:27
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 2, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-amdgpu-runtime-2 running on rocm-worker-hw-02 while building clang at step 5 "compile-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/2721

Here is the relevant piece of the build log for the reference
Step 5 (compile-openmp) failure: build (failure)
...
0.164 [381/130/186] Building CXX object libc/src/stdlib/CMakeFiles/libc.src.stdlib.memalignment.dir/memalignment.cpp.o
0.164 [380/130/187] Building CXX object libc/src/strings/CMakeFiles/libc.src.strings.strncasecmp.dir/strncasecmp.cpp.o
0.164 [379/130/188] Generating header stdlib.h from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/runtimes/../libc/include/stdlib.yaml
0.165 [378/130/189] Generating /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa/llvm-libc-decls/stdio.h
0.165 [377/130/190] Generating header stdio.h from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/runtimes/../libc/include/stdio.yaml
0.166 [376/130/191] Generating /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa/llvm-libc-decls/time.h
0.166 [375/130/192] Generating /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa/llvm-libc-decls/signal.h
0.167 [374/130/193] Building CXX object libc/src/__support/GPU/CMakeFiles/libc.src.__support.GPU.allocator.dir/allocator.cpp.o
0.168 [373/130/194] Building CXX object libc/src/string/CMakeFiles/libc.src.string.strstr.dir/strstr.cpp.o
0.170 [372/130/195] Building CXX object libc/src/strings/CMakeFiles/libc.src.strings.bcopy.dir/bcopy.cpp.o
FAILED: libc/src/strings/CMakeFiles/libc.src.strings.bcopy.dir/bcopy.cpp.o 
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang++ --target=amdgcn-amd-amdhsa -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git -D__LIBC_USE_FLOAT16_CONVERSION -I/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc -isystem /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa -O3 -DNDEBUG --target=amdgcn-amd-amdhsa -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS "-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)" -fpie -DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -Wglobal-constructors -nogpulib -fvisibility=hidden -fconvergent-functions -flto -Wno-multi-gpu -DLIBC_COPT_PUBLIC_PACKAGING -UNDEBUG -MD -MT libc/src/strings/CMakeFiles/libc.src.strings.bcopy.dir/bcopy.cpp.o -MF libc/src/strings/CMakeFiles/libc.src.strings.bcopy.dir/bcopy.cpp.o.d -o libc/src/strings/CMakeFiles/libc.src.strings.bcopy.dir/bcopy.cpp.o -c /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/strings/bcopy.cpp
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/strings/bcopy.cpp:12:
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/string/memory_utils/inline_memmove.h:33:
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/string/memory_utils/generic/builtin.h:14:
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/string/memory_utils/utils.h:15:
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:43:13: error: unknown type name 'uint8_t'
   43 | LIBC_INLINE uint8_t
      |             ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:44:48: error: use of undeclared identifier 'uint8_t'
   44 | Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
      |                                                ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:44:48: error: use of undeclared identifier 'uint8_t'
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:44:57: error: unknown type name 'uint8_t'
   44 | Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
      |                                                         ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:49:13: error: unknown type name 'uint8_t'
   49 | LIBC_INLINE uint8_t
      |             ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:50:51: error: use of undeclared identifier 'uint8_t'
   50 | Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
      |                                                   ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:50:51: error: use of undeclared identifier 'uint8_t'
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:50:60: error: unknown type name 'uint8_t'
   50 | Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
      |                                                            ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:55:13: error: unknown type name 'uint16_t'
   55 | LIBC_INLINE uint16_t
      |             ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:56:48: error: use of undeclared identifier 'uint16_t'
   56 | Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
      |                                                ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:56:48: error: use of undeclared identifier 'uint16_t'
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:56:58: error: unknown type name 'uint16_t'
   56 | Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
      |                                                          ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/__support/endian_internal.h:61:13: error: unknown type name 'uint16_t'
   61 | LIBC_INLINE uint16_t
      |             ^

mizvekov added a commit that referenced this pull request Apr 2, 2025
…_type_ast_nodes

This is a folow-up to #132748, where we deferred the flag removal
in order to ease transition for external users.
@fmayer
Copy link
Contributor

fmayer commented Apr 4, 2025

Looks like this change broke the MSAN bot: https://lab.llvm.org/buildbot/#/builders/169/builds/10068

@thurstond FYI

@mizvekov
Copy link
Contributor Author

mizvekov commented Apr 5, 2025

@fmayer this patch touches nowhere near where those backtraces indicate.
#130182 is a far more likely culprit.

@thurstond
Copy link
Contributor

@fmayer this patch touches nowhere near where those backtraces indicate. #130182 is a far more likely culprit.

#130182 cannot be the cause of the ongoing MSan buildbot failures, because it was already reverted two days ago in #134239

@mizvekov
Copy link
Contributor Author

mizvekov commented Apr 5, 2025

@thurstond Well can you provide a more recent buildbot failure link where #130182 is not on the list of possible culpirits? Because the link @fmayer provided for sure included it.

@thurstond
Copy link
Contributor

@thurstond Well can you provide a more recent buildbot failure link where #130182 is not on the list of possible culpirits? Because the link @fmayer provided for sure included it.

@mizvekov I localized the MSan error to this patch by re-running the buildbot script with this patch and immediately prior, in both cases also reverting #130182 to remove noise:

Repro:

cd ~/llvm-project
# This patch
git checkout f302f35526553abcb46dab278c4494c3d01deb45
# Revert #130182
git revert 76fa9530c9ac7f81a49b840556f51f4838efbfe1

# Buildbot
mkdir ~/buildbot_repro
cd ~/buildbot_repro
git clone https://github.com/llvm/llvm-zorg.git
BUILDBOT_MONO_REPO_PATH=~/llvm-project bash llvm-zorg/zorg/buildbot/builders/sanitizers/buildbot_fast.sh
# For speed, I commented out build_stage2_asan_ubsan and check_stage2_asan_ubsan in the script above

This repro'ed the MSan failures:

  Clang :: ASTMerge/class-template-partial-spec/test.cpp
  Clang :: Analysis/ctu-inherited-default-ctor.cpp

The MSan failures are not present when using the immediately prior patch:

# Immediately prior to this patch
git checkout 990a086d9da0bc2fd53a6a4c95ecbbe23a297a83
git revert 76fa9530c9ac7f81a49b840556f51f4838efbfe1

# Same buildbot steps as before

Please let me know if you encounter any issues reproducing the error.

@thurstond
Copy link
Contributor

If it is not quick and easy to fix forward, please consider reverting in the meantime, so that the buildbots can be green and provide useful feedback to contributors. Thanks!

mizvekov added a commit that referenced this pull request Apr 6, 2025
This fixes a couple of mistakes introduced when merging
#132748

Fixes msan failure reported here: #132748 (comment)
@mizvekov
Copy link
Contributor Author

mizvekov commented Apr 6, 2025

This will be fixed here: #134560

@thurstond
Copy link
Contributor

This will be fixed here: #134560

Thank you!

mizvekov added a commit that referenced this pull request Apr 7, 2025
This fixes a couple of mistakes introduced when merging
#132748

Fixes msan failure reported here:
#132748 (comment)
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 7, 2025
…(#134560)

This fixes a couple of mistakes introduced when merging
llvm/llvm-project#132748

Fixes msan failure reported here:
llvm/llvm-project#132748 (comment)
@pranavk
Copy link
Contributor

pranavk commented Apr 9, 2025

This causes another mangling issue similar to this.

Here's the repro:

namespace {
template <int> struct enable_if {
  typedef int type;
};
template <bool _Bp, class> using enable_if_t = enable_if<_Bp>::type;
template <int __v> struct integral_constant {
  static const int value = __v;
};
template <bool _Val> using _BoolConstant = integral_constant<_Val>;
template <class _Tp, class _Up>
using _IsNotSame = _BoolConstant<__is_same(_Tp, _Up)>;
template <class...> using __expand_to_true = integral_constant<true>;
template <class...> __expand_to_true<> __and_helper(int);
template <class... _Pred> using _And = decltype(__and_helper<_Pred...>(0));
template <int> struct _OrImpl {
  template <class, class _First, class> using _Result = _OrImpl<_First::value>;
};
template <class... _Args>
using _Or =
    _OrImpl<sizeof...(_Args)>::template _Result<integral_constant<false>,
                                                _Args...>;
struct optional {
  template <class _Up, enable_if_t<_And<_IsNotSame<_Up, optional>,
                                        _Or<_IsNotSame<_Up, int>, int>>::value,
                                   int> = 0>
  void operator=(_Up);
};
} // namespace
optional f_opt;
void f() { f_opt = int{}; }

clang -c -std=gnu++20 -x c++ /tmp/reduced.i
llvm-readelf -s -W reduced.o | grep -P 'optional.*aS.*srNS[0-9]_I'

The subexpression srNS5_I...E violates the grammar at https://itanium-cxx-abi.github.io/cxx-abi/abi.html#expressions. The srN must be followed by an <unresolved-type>, which is allowed to be a <substitution> such as S5_, but not a substitution followed by I...E template arguments. LLVM, GNU, and Abseil demanglers correctly reject this name.

@pranavk
Copy link
Contributor

pranavk commented Apr 9, 2025

With this commit, I get:

llvm-readelf -s -W reduced.o | grep -P 'optional.*aS.*srNS[0-9]_I'
6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT   UND _ZN12_GLOBAL__N_18optionalaSIiTnNS_9enable_ifIXsr4_AndINS_17integral_constantIXu9__is_sameT_S0_EEEENS_7_OrImplIXsrNS3_IXu9__is_sameS4_iEEEE5valueEEEEE5valueEE4typeELi0EEEvS4_

Before this, the same symbol was:

6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT   UND _ZN12_GLOBAL__N_18optionalaSIiTnNS_9enable_ifIXsr4_AndINS_17integral_constantIXu9__is_sameT_S0_EEEENS_7_OrImplIXsr10_IsNotSameIS4_iEE5valueEEEEE5valueEE4typeELi0EEEvS4_

@mizvekov
Copy link
Contributor Author

@pranavk this test case is fixed by the same fix as for the first mangling issue: #135111

@pranavk
Copy link
Contributor

pranavk commented Apr 10, 2025

@pranavk this test case is fixed by the same fix as for the first mangling issue: #135111

@mizvekov I could still repro this issue after #135111

@mizvekov
Copy link
Contributor Author

Ops, you are right, looking into it.

mizvekov added a commit that referenced this pull request Apr 11, 2025
This fixes a regression introduced here: #132748
which was originally reported here: #132748 (comment)

Some time in the clang-20 time frame, we had removed subst* nodes produced
from template type alias instantiation.

This ended up accidentally fixing an issue where the result from
an alias template substitution is mistaken for the susbtitution
of an outer non-alias template, incorrectly applying the unresolved-type
production to it.

This fixes it by ignoring subst* nodes produced from type aliases.
Though builtin templates currently don't place subst* nodes, if
we ever decide to place them, this fix should cover them as well.

No release notes since this regression was never released.
mizvekov added a commit that referenced this pull request Apr 11, 2025
This fixes a regression introduced here: #132748
which was originally reported here: #132748 (comment)

Some time in the clang-20 time frame, we had removed subst* nodes produced
from template type alias instantiation.

This ended up accidentally fixing an issue where the result from
an alias template substitution is mistaken for the susbtitution
of an outer non-alias template, incorrectly applying the unresolved-type
production to it.

This fixes it by ignoring subst* nodes produced from type aliases.
Though builtin templates currently don't place subst* nodes, if
we ever decide to place them, this fix should cover them as well.

No release notes since this regression was never released.
@mizvekov
Copy link
Contributor Author

@pranavk this will be fixed by #135312

mizvekov added a commit that referenced this pull request Apr 14, 2025
…-type-ast-nodes (#134177)

This is a follow-up to #132748, where we deferred the flag removal in
order to ease transition for external users.

The plan is to merge this in the nearish future, in two weeks or so is
my best guess.
copybara-service bot pushed a commit to google/crubit that referenced this pull request Apr 15, 2025
…ity code.

llvm/llvm-project#132748 makes this flag a no-op

PiperOrigin-RevId: 747946560
Change-Id: Id2c92df6b2eb2c62dcdf8bb59e96b8e3cb118723
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…-type-ast-nodes (llvm#134177)

This is a follow-up to llvm#132748, where we deferred the flag removal in
order to ease transition for external users.

The plan is to merge this in the nearish future, in two weeks or so is
my best guess.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:as-a-library libclang and C++ API 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.

10 participants