[libcxx-commits] [libcxxabi] [llvm] [LLVM Demangler] Set `InConstraintExpr` to `true` when demangling a c… (PR #107385)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 10 01:31:44 PDT 2024


https://github.com/VitaNuo updated https://github.com/llvm/llvm-project/pull/107385

>From c0d56a920b7c9e9f65b568d9694fba6266b305bf Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 1/7] [LLVM Demangler] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures before
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678).

---
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index fb2060fa07f724..5c044def74e881 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -5737,6 +5737,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
   }
 
   if (consumeIf("Tk")) {
+    ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
     Node *Constraint = getDerived().parseName();
     if (!Constraint)
       return nullptr;

>From 11c7302be96c5c50836aa3d0c128cee3023d8cca Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 2/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 .../test/tools/llvm-cxxfilt/demangle-constrained-template.test | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 llvm/test/tools/llvm-cxxfilt/demangle-constrained-template.test

diff --git a/llvm/test/tools/llvm-cxxfilt/demangle-constrained-template.test b/llvm/test/tools/llvm-cxxfilt/demangle-constrained-template.test
new file mode 100644
index 00000000000000..7a038ebb77a06d
--- /dev/null
+++ b/llvm/test/tools/llvm-cxxfilt/demangle-constrained-template.test
@@ -0,0 +1,3 @@
+RUN: llvm-cxxfilt -n _ZN3FooIiE6methodITk4TrueIT_EiEEvS3_ | FileCheck %s
+
+CHECK: void Foo<int>::method<int>(T)
\ No newline at end of file

>From 8d987df851c145066dcd7ccd2f7db6d84008fa7c Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 3/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 568 ++++++++++++++---------
 1 file changed, 344 insertions(+), 224 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 88de234a6e0b92..bfcf7046512287 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -167,7 +167,11 @@ class Node {
 
   /// Three-way bool to track a cached value. Unknown is possible if this node
   /// has an unexpanded parameter pack below it that may affect this cache.
-  enum class Cache : unsigned char { Yes, No, Unknown, };
+  enum class Cache : unsigned char {
+    Yes,
+    No,
+    Unknown,
+  };
 
   /// Operator precedence for expression nodes. Used to determine required
   /// parens in expression emission.
@@ -224,13 +228,13 @@ class Node {
              FunctionCache_) {}
 
   /// Visit the most-derived object corresponding to this object.
-  template<typename Fn> void visit(Fn F) const;
+  template <typename Fn> void visit(Fn F) const;
 
   // The following function is provided by all derived classes:
   //
   // Call F with arguments that, when passed to the constructor of this node,
   // would construct an equivalent node.
-  //template<typename Fn> void match(Fn F) const;
+  // template<typename Fn> void match(Fn F) const;
 
   bool hasRHSComponent(OutputBuffer &OB) const {
     if (RHSComponentCache != Cache::Unknown)
@@ -345,7 +349,7 @@ struct NodeArrayNode : Node {
   NodeArray Array;
   NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Array); }
+  template <typename Fn> void match(Fn F) const { F(Array); }
 
   void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
 };
@@ -358,7 +362,7 @@ class DotSuffix final : public Node {
   DotSuffix(const Node *Prefix_, std::string_view Suffix_)
       : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
+  template <typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
 
   void printLeft(OutputBuffer &OB) const override {
     Prefix->print(OB);
@@ -432,7 +436,7 @@ class QualType final : public Node {
   Qualifiers getQuals() const { return Quals; }
   const Node *getChild() const { return Child; }
 
-  template<typename Fn> void match(Fn F) const { F(Child, Quals); }
+  template <typename Fn> void match(Fn F) const { F(Child, Quals); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Child->hasRHSComponent(OB);
@@ -459,7 +463,7 @@ class ConversionOperatorType final : public Node {
   ConversionOperatorType(const Node *Ty_)
       : Node(KConversionOperatorType), Ty(Ty_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Ty); }
+  template <typename Fn> void match(Fn F) const { F(Ty); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "operator ";
@@ -475,7 +479,7 @@ class PostfixQualifiedType final : public Node {
   PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
       : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
+  template <typename Fn> void match(Fn F) const { F(Ty, Postfix); }
 
   void printLeft(OutputBuffer &OB) const override {
     Ty->printLeft(OB);
@@ -489,7 +493,7 @@ class NameType final : public Node {
 public:
   NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Name); }
+  template <typename Fn> void match(Fn F) const { F(Name); }
 
   std::string_view getName() const { return Name; }
   std::string_view getBaseName() const override { return Name; }
@@ -520,11 +524,12 @@ class BitIntType final : public Node {
 class ElaboratedTypeSpefType : public Node {
   std::string_view Kind;
   Node *Child;
+
 public:
   ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
       : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Kind, Child); }
+  template <typename Fn> void match(Fn F) const { F(Kind, Child); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Kind;
@@ -536,11 +541,12 @@ class ElaboratedTypeSpefType : public Node {
 class TransformedType : public Node {
   std::string_view Transform;
   Node *BaseType;
+
 public:
   TransformedType(std::string_view Transform_, Node *BaseType_)
       : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
+  template <typename Fn> void match(Fn F) const { F(Transform, BaseType); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Transform;
@@ -559,7 +565,7 @@ struct AbiTagAttr : Node {
              Base_->getFunctionCache()),
         Base(Base_), Tag(Tag_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Base, Tag); }
+  template <typename Fn> void match(Fn F) const { F(Base, Tag); }
 
   std::string_view getBaseName() const override { return Base->getBaseName(); }
 
@@ -573,11 +579,12 @@ struct AbiTagAttr : Node {
 
 class EnableIfAttr : public Node {
   NodeArray Conditions;
+
 public:
   EnableIfAttr(NodeArray Conditions_)
       : Node(KEnableIfAttr), Conditions(Conditions_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Conditions); }
+  template <typename Fn> void match(Fn F) const { F(Conditions); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += " [enable_if:";
@@ -596,7 +603,7 @@ class ObjCProtoName : public Node {
   ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
       : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
+  template <typename Fn> void match(Fn F) const { F(Ty, Protocol); }
 
   bool isObjCObject() const {
     return Ty->getKind() == KNameType &&
@@ -621,7 +628,7 @@ class PointerType final : public Node {
 
   const Node *getPointee() const { return Pointee; }
 
-  template<typename Fn> void match(Fn F) const { F(Pointee); }
+  template <typename Fn> void match(Fn F) const { F(Pointee); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Pointee->hasRHSComponent(OB);
@@ -703,7 +710,7 @@ class ReferenceType : public Node {
       : Node(KReferenceType, Pointee_->getRHSComponentCache()),
         Pointee(Pointee_), RK(RK_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
+  template <typename Fn> void match(Fn F) const { F(Pointee, RK); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Pointee->hasRHSComponent(OB);
@@ -746,7 +753,7 @@ class PointerToMemberType final : public Node {
       : Node(KPointerToMemberType, MemberType_->getRHSComponentCache()),
         ClassType(ClassType_), MemberType(MemberType_) {}
 
-  template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
+  template <typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return MemberType->hasRHSComponent(OB);
@@ -780,7 +787,7 @@ class ArrayType final : public Node {
              /*ArrayCache=*/Cache::Yes),
         Base(Base_), Dimension(Dimension_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
+  template <typename Fn> void match(Fn F) const { F(Base, Dimension); }
 
   bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
   bool hasArraySlow(OutputBuffer &) const override { return true; }
@@ -814,7 +821,7 @@ class FunctionType final : public Node {
         Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
         ExceptionSpec(ExceptionSpec_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
   }
 
@@ -860,10 +867,11 @@ class FunctionType final : public Node {
 
 class NoexceptSpec : public Node {
   const Node *E;
+
 public:
   NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
 
-  template<typename Fn> void match(Fn F) const { F(E); }
+  template <typename Fn> void match(Fn F) const { F(E); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "noexcept";
@@ -875,11 +883,12 @@ class NoexceptSpec : public Node {
 
 class DynamicExceptionSpec : public Node {
   NodeArray Types;
+
 public:
   DynamicExceptionSpec(NodeArray Types_)
       : Node(KDynamicExceptionSpec), Types(Types_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Types); }
+  template <typename Fn> void match(Fn F) const { F(Types); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "throw";
@@ -934,7 +943,7 @@ class FunctionEncoding final : public Node {
         Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
         Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
   }
 
@@ -993,7 +1002,7 @@ class LiteralOperator : public Node {
   LiteralOperator(const Node *OpName_)
       : Node(KLiteralOperator), OpName(OpName_) {}
 
-  template<typename Fn> void match(Fn F) const { F(OpName); }
+  template <typename Fn> void match(Fn F) const { F(OpName); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "operator\"\" ";
@@ -1009,7 +1018,7 @@ class SpecialName final : public Node {
   SpecialName(std::string_view Special_, const Node *Child_)
       : Node(KSpecialName), Special(Special_), Child(Child_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Special, Child); }
+  template <typename Fn> void match(Fn F) const { F(Special, Child); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Special;
@@ -1023,10 +1032,10 @@ class CtorVtableSpecialName final : public Node {
 
 public:
   CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
-      : Node(KCtorVtableSpecialName),
-        FirstType(FirstType_), SecondType(SecondType_) {}
+      : Node(KCtorVtableSpecialName), FirstType(FirstType_),
+        SecondType(SecondType_) {}
 
-  template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
+  template <typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "construction vtable for ";
@@ -1043,7 +1052,7 @@ struct NestedName : Node {
   NestedName(Node *Qual_, Node *Name_)
       : Node(KNestedName), Qual(Qual_), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Qual, Name); }
+  template <typename Fn> void match(Fn F) const { F(Qual, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1061,7 +1070,7 @@ struct MemberLikeFriendName : Node {
   MemberLikeFriendName(Node *Qual_, Node *Name_)
       : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Qual, Name); }
+  template <typename Fn> void match(Fn F) const { F(Qual, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1119,7 +1128,7 @@ struct LocalName : Node {
   LocalName(Node *Encoding_, Node *Entity_)
       : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
+  template <typename Fn> void match(Fn F) const { F(Encoding, Entity); }
 
   void printLeft(OutputBuffer &OB) const override {
     Encoding->print(OB);
@@ -1137,7 +1146,7 @@ class QualifiedName final : public Node {
   QualifiedName(const Node *Qualifier_, const Node *Name_)
       : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
+  template <typename Fn> void match(Fn F) const { F(Qualifier, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1159,7 +1168,7 @@ class VectorType final : public Node {
   const Node *getBaseType() const { return BaseType; }
   const Node *getDimension() const { return Dimension; }
 
-  template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
+  template <typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     BaseType->print(OB);
@@ -1177,7 +1186,7 @@ class PixelVectorType final : public Node {
   PixelVectorType(const Node *Dimension_)
       : Node(KPixelVectorType), Dimension(Dimension_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Dimension); }
+  template <typename Fn> void match(Fn F) const { F(Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     // FIXME: This should demangle as "vector pixel".
@@ -1194,7 +1203,7 @@ class BinaryFPType final : public Node {
   BinaryFPType(const Node *Dimension_)
       : Node(KBinaryFPType), Dimension(Dimension_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Dimension); }
+  template <typename Fn> void match(Fn F) const { F(Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "_Float";
@@ -1218,7 +1227,7 @@ class SyntheticTemplateParamName final : public Node {
   SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
       : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Kind, Index); }
+  template <typename Fn> void match(Fn F) const { F(Kind, Index); }
 
   void printLeft(OutputBuffer &OB) const override {
     switch (Kind) {
@@ -1263,7 +1272,7 @@ class TypeTemplateParamDecl final : public Node {
   TypeTemplateParamDecl(Node *Name_)
       : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Name); }
+  template <typename Fn> void match(Fn F) const { F(Name); }
 
   void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
 
@@ -1280,7 +1289,7 @@ class ConstrainedTypeTemplateParamDecl final : public Node {
       : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
         Constraint(Constraint_), Name(Name_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
+  template <typename Fn> void match(Fn F) const { F(Constraint, Name); }
 
   void printLeft(OutputBuffer &OB) const override {
     Constraint->print(OB);
@@ -1299,7 +1308,7 @@ class NonTypeTemplateParamDecl final : public Node {
   NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
       : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Name, Type); }
+  template <typename Fn> void match(Fn F) const { F(Name, Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     Type->printLeft(OB);
@@ -1351,7 +1360,7 @@ class TemplateParamPackDecl final : public Node {
   TemplateParamPackDecl(Node *Param_)
       : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Param); }
+  template <typename Fn> void match(Fn F) const { F(Param); }
 
   void printLeft(OutputBuffer &OB) const override {
     Param->printLeft(OB);
@@ -1396,7 +1405,7 @@ class ParameterPack final : public Node {
       RHSComponentCache = Cache::No;
   }
 
-  template<typename Fn> void match(Fn F) const { F(Data); }
+  template <typename Fn> void match(Fn F) const { F(Data); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     initializePackExpansion(OB);
@@ -1440,11 +1449,12 @@ class ParameterPack final : public Node {
 /// <encoding>.
 class TemplateArgumentPack final : public Node {
   NodeArray Elements;
+
 public:
   TemplateArgumentPack(NodeArray Elements_)
       : Node(KTemplateArgumentPack), Elements(Elements_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Elements); }
+  template <typename Fn> void match(Fn F) const { F(Elements); }
 
   NodeArray getElements() const { return Elements; }
 
@@ -1462,7 +1472,7 @@ class ParameterPackExpansion final : public Node {
   ParameterPackExpansion(const Node *Child_)
       : Node(KParameterPackExpansion), Child(Child_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Child); }
+  template <typename Fn> void match(Fn F) const { F(Child); }
 
   const Node *getChild() const { return Child; }
 
@@ -1507,7 +1517,7 @@ class TemplateArgs final : public Node {
   TemplateArgs(NodeArray Params_, Node *Requires_)
       : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Params, Requires); }
+  template <typename Fn> void match(Fn F) const { F(Params, Requires); }
 
   NodeArray getParams() { return Params; }
 
@@ -1556,7 +1566,7 @@ struct ForwardTemplateReference : Node {
   // We don't provide a matcher for these, because the value of the node is
   // not determined by its construction parameters, and it generally needs
   // special handling.
-  template<typename Fn> void match(Fn F) const = delete;
+  template <typename Fn> void match(Fn F) const = delete;
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     if (Printing)
@@ -1605,7 +1615,7 @@ struct NameWithTemplateArgs : Node {
   NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
       : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
+  template <typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1619,10 +1629,10 @@ class GlobalQualifiedName final : public Node {
   Node *Child;
 
 public:
-  GlobalQualifiedName(Node* Child_)
+  GlobalQualifiedName(Node *Child_)
       : Node(KGlobalQualifiedName), Child(Child_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Child); }
+  template <typename Fn> void match(Fn F) const { F(Child); }
 
   std::string_view getBaseName() const override { return Child->getBaseName(); }
 
@@ -1648,12 +1658,13 @@ class ExpandedSpecialSubstitution : public Node {
 
   ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
       : Node(K_), SSK(SSK_) {}
+
 public:
   ExpandedSpecialSubstitution(SpecialSubKind SSK_)
       : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
   inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
 
-  template<typename Fn> void match(Fn F) const { F(SSK); }
+  template <typename Fn> void match(Fn F) const { F(SSK); }
 
 protected:
   bool isInstantiation() const {
@@ -1695,7 +1706,7 @@ class SpecialSubstitution final : public ExpandedSpecialSubstitution {
   SpecialSubstitution(SpecialSubKind SSK_)
       : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
 
-  template<typename Fn> void match(Fn F) const { F(SSK); }
+  template <typename Fn> void match(Fn F) const { F(SSK); }
 
   std::string_view getBaseName() const override {
     std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
@@ -1726,7 +1737,9 @@ class CtorDtorName final : public Node {
       : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
         Variant(Variant_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
+  template <typename Fn> void match(Fn F) const {
+    F(Basename, IsDtor, Variant);
+  }
 
   void printLeft(OutputBuffer &OB) const override {
     if (IsDtor)
@@ -1741,7 +1754,7 @@ class DtorName : public Node {
 public:
   DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Base); }
+  template <typename Fn> void match(Fn F) const { F(Base); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "~";
@@ -1756,7 +1769,7 @@ class UnnamedTypeName : public Node {
   UnnamedTypeName(std::string_view Count_)
       : Node(KUnnamedTypeName), Count(Count_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Count); }
+  template <typename Fn> void match(Fn F) const { F(Count); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "'unnamed";
@@ -1780,7 +1793,7 @@ class ClosureTypeName : public Node {
         Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
         Count(Count_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(TemplateParams, Requires1, Params, Requires2, Count);
   }
 
@@ -1816,11 +1829,12 @@ class ClosureTypeName : public Node {
 
 class StructuredBindingName : public Node {
   NodeArray Bindings;
+
 public:
   StructuredBindingName(NodeArray Bindings_)
       : Node(KStructuredBindingName), Bindings(Bindings_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Bindings); }
+  template <typename Fn> void match(Fn F) const { F(Bindings); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB.printOpen('[');
@@ -1961,7 +1975,7 @@ class SubobjectExpr : public Node {
       : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
         UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
   }
 
@@ -2041,7 +2055,7 @@ class SizeofParamPackExpr : public Node {
   SizeofParamPackExpr(const Node *Pack_)
       : Node(KSizeofParamPackExpr), Pack(Pack_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Pack); }
+  template <typename Fn> void match(Fn F) const { F(Pack); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "sizeof...";
@@ -2085,7 +2099,7 @@ class NewExpr : public Node {
       : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
         InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
   }
 
@@ -2160,7 +2174,7 @@ class FunctionParam : public Node {
   FunctionParam(std::string_view Number_)
       : Node(KFunctionParam), Number(Number_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Number); }
+  template <typename Fn> void match(Fn F) const { F(Number); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "fp";
@@ -2218,11 +2232,12 @@ class PointerToMemberConversionExpr : public Node {
 class InitListExpr : public Node {
   const Node *Ty;
   NodeArray Inits;
+
 public:
   InitListExpr(const Node *Ty_, NodeArray Inits_)
       : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
+  template <typename Fn> void match(Fn F) const { F(Ty, Inits); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (Ty)
@@ -2237,11 +2252,12 @@ class BracedExpr : public Node {
   const Node *Elem;
   const Node *Init;
   bool IsArray;
+
 public:
   BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
       : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
+  template <typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (IsArray) {
@@ -2262,11 +2278,12 @@ class BracedRangeExpr : public Node {
   const Node *First;
   const Node *Last;
   const Node *Init;
+
 public:
   BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
       : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
 
-  template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
+  template <typename Fn> void match(Fn F) const { F(First, Last, Init); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += '[';
@@ -2291,7 +2308,7 @@ class FoldExpr : public Node {
       : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
         IsLeftFold(IsLeftFold_) {}
 
-  template<typename Fn> void match(Fn F) const {
+  template <typename Fn> void match(Fn F) const {
     F(IsLeftFold, OperatorName, Pack, Init);
   }
 
@@ -2333,7 +2350,7 @@ class ThrowExpr : public Node {
 public:
   ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Op); }
+  template <typename Fn> void match(Fn F) const { F(Op); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "throw ";
@@ -2347,7 +2364,7 @@ class BoolExpr : public Node {
 public:
   BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Value); }
+  template <typename Fn> void match(Fn F) const { F(Value); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Value ? std::string_view("true") : std::string_view("false");
@@ -2360,7 +2377,7 @@ class StringLiteral : public Node {
 public:
   StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Type); }
+  template <typename Fn> void match(Fn F) const { F(Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "\"<";
@@ -2375,7 +2392,7 @@ class LambdaExpr : public Node {
 public:
   LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Type); }
+  template <typename Fn> void match(Fn F) const { F(Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "[]";
@@ -2394,7 +2411,7 @@ class EnumLiteral : public Node {
   EnumLiteral(const Node *Ty_, std::string_view Integer_)
       : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
+  template <typename Fn> void match(Fn F) const { F(Ty, Integer); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB.printOpen();
@@ -2416,7 +2433,7 @@ class IntegerLiteral : public Node {
   IntegerLiteral(std::string_view Type_, std::string_view Value_)
       : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Type, Value); }
+  template <typename Fn> void match(Fn F) const { F(Type, Value); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (Type.size() > 3) {
@@ -2438,12 +2455,13 @@ class IntegerLiteral : public Node {
 class RequiresExpr : public Node {
   NodeArray Parameters;
   NodeArray Requirements;
+
 public:
   RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
       : Node(KRequiresExpr), Parameters(Parameters_),
         Requirements(Requirements_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
+  template <typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "requires";
@@ -2467,6 +2485,7 @@ class ExprRequirement : public Node {
   const Node *Expr;
   bool IsNoexcept;
   const Node *TypeConstraint;
+
 public:
   ExprRequirement(const Node *Expr_, bool IsNoexcept_,
                   const Node *TypeConstraint_)
@@ -2496,9 +2515,9 @@ class ExprRequirement : public Node {
 
 class TypeRequirement : public Node {
   const Node *Type;
+
 public:
-  TypeRequirement(const Node *Type_)
-      : Node(KTypeRequirement), Type(Type_) {}
+  TypeRequirement(const Node *Type_) : Node(KTypeRequirement), Type(Type_) {}
 
   template <typename Fn> void match(Fn F) const { F(Type); }
 
@@ -2511,6 +2530,7 @@ class TypeRequirement : public Node {
 
 class NestedRequirement : public Node {
   const Node *Constraint;
+
 public:
   NestedRequirement(const Node *Constraint_)
       : Node(KNestedRequirement), Constraint(Constraint_) {}
@@ -2536,7 +2556,7 @@ constexpr Node::Kind getFloatLiteralKind(double *) {
 constexpr Node::Kind getFloatLiteralKind(long double *) {
   return Node::KLongDoubleLiteral;
 }
-}
+} // namespace float_literal_impl
 
 template <class Float> class FloatLiteralImpl : public Node {
   const std::string_view Contents;
@@ -2548,7 +2568,7 @@ template <class Float> class FloatLiteralImpl : public Node {
   FloatLiteralImpl(std::string_view Contents_)
       : Node(KindForClass), Contents(Contents_) {}
 
-  template<typename Fn> void match(Fn F) const { F(Contents); }
+  template <typename Fn> void match(Fn F) const { F(Contents); }
 
   void printLeft(OutputBuffer &OB) const override {
     const size_t N = FloatData<Float>::mangled_size;
@@ -2584,8 +2604,7 @@ using LongDoubleLiteral = FloatLiteralImpl<long double>;
 
 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
 /// appropriate derived class.
-template<typename Fn>
-void Node::visit(Fn F) const {
+template <typename Fn> void Node::visit(Fn F) const {
   switch (K) {
 #define NODE(X)                                                                \
   case K##X:                                                                   \
@@ -2596,7 +2615,7 @@ void Node::visit(Fn F) const {
 }
 
 /// Determine the kind of a node from its type.
-template<typename NodeT> struct NodeKind;
+template <typename NodeT> struct NodeKind;
 #define NODE(X)                                                                \
   template <> struct NodeKind<X> {                                             \
     static constexpr Node::Kind Kind = Node::K##X;                             \
@@ -2677,7 +2696,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
 
   bool TryToParseTemplateArgs = true;
   bool PermitForwardTemplateReferences = false;
-  bool InConstraintExpr = false;
+  bool HasIncompleteTemplateParameterTracking = false;
   size_t ParsingLambdaParamsAtLevel = (size_t)-1;
 
   unsigned NumSyntheticTemplateParameters[3] = {};
@@ -2703,7 +2722,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
     ASTAllocator.reset();
   }
 
-  template <class T, class... Args> Node *make(Args &&... args) {
+  template <class T, class... Args> Node *make(Args &&...args) {
     return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
   }
 
@@ -2857,11 +2876,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
 
       Unnameable = NamedCast,
     };
-    char Enc[2];      // Encoding
-    OIKind Kind;      // Kind of operator
-    bool Flag : 1;    // Entry-specific flag
+    char Enc[2];         // Encoding
+    OIKind Kind;         // Kind of operator
+    bool Flag : 1;       // Entry-specific flag
     Node::Prec Prec : 7; // Precedence
-    const char *Name; // Spelling
+    const char *Name;    // Spelling
 
   public:
     constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
@@ -2912,7 +2931,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
   Node *parse(bool ParseParams = true);
 };
 
-const char* parse_discriminator(const char* first, const char* last);
+const char *parse_discriminator(const char *first, const char *last);
 
 // <name> ::= <nested-name> // N
 //        ::= <local-name> # See Scope Encoding below  // Z
@@ -2956,7 +2975,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
 
 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
 //              := Z <function encoding> E s [<discriminator>]
-//              := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
+//              := Z <function encoding> Ed [ <parameter number> ] _ <entity
+//              name>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
   if (!consumeIf('Z'))
@@ -3306,8 +3326,8 @@ const typename AbstractManglingParser<
     {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
 };
 template <typename Derived, typename Alloc>
-const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
-                                                              sizeof(Ops[0]);
+const size_t AbstractManglingParser<Derived, Alloc>::NumOps =
+    sizeof(Ops) / sizeof(Ops[0]);
 
 // If the next 2 chars are an operator encoding, consume them and return their
 // OperatorInfo.  Otherwise return nullptr.
@@ -3353,7 +3373,8 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
       Node *Ty = getDerived().parseType();
       if (Ty == nullptr)
         return nullptr;
-      if (State) State->CtorDtorConversion = true;
+      if (State)
+        State->CtorDtorConversion = true;
       return make<ConversionOperatorType>(Ty);
     }
 
@@ -3419,7 +3440,8 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
       return nullptr;
     int Variant = look() - '0';
     ++First;
-    if (State) State->CtorDtorConversion = true;
+    if (State)
+      State->CtorDtorConversion = true;
     if (IsInherited) {
       if (getDerived().parseName(State) == nullptr)
         return nullptr;
@@ -3431,7 +3453,8 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
                         look(1) == '4' || look(1) == '5')) {
     int Variant = look(1) - '0';
     First += 2;
-    if (State) State->CtorDtorConversion = true;
+    if (State)
+      State->CtorDtorConversion = true;
     return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
   }
 
@@ -3610,13 +3633,21 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
   return getDerived().parseSubstitution();
 }
 
-// <base-unresolved-name> ::= <simple-id>                                # unresolved name
-//          extension     ::= <operator-name>                            # unresolved operator-function-id
-//          extension     ::= <operator-name> <template-args>            # unresolved operator template-id
-//                        ::= on <operator-name>                         # unresolved operator-function-id
-//                        ::= on <operator-name> <template-args>         # unresolved operator template-id
-//                        ::= dn <destructor-name>                       # destructor or pseudo-destructor;
-//                                                                         # e.g. ~X or ~X<N-1>
+// <base-unresolved-name> ::= <simple-id>                                #
+// unresolved name
+//          extension     ::= <operator-name>                            #
+//          unresolved operator-function-id extension     ::= <operator-name>
+//          <template-args>            # unresolved operator template-id
+//                        ::= on <operator-name>                         #
+//                        unresolved operator-function-id
+//                        ::= on <operator-name> <template-args>         #
+//                        unresolved operator template-id
+//                        ::= dn <destructor-name>                       #
+//                        destructor or pseudo-destructor;
+//                                                                         #
+//                                                                         e.g.
+//                                                                         ~X or
+//                                                                         ~X<N-1>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
   if (std::isdigit(look()))
@@ -3640,23 +3671,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
 }
 
 // <unresolved-name>
-//  extension        ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
-//                   ::= [gs] <base-unresolved-name>                     # x or (with "gs") ::x
-//                   ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
-//                                                                       # A::x, N::y, A<T>::z; "gs" means leading "::"
+//  extension        ::= srN <unresolved-type> [<template-args>]
+//  <unresolved-qualifier-level>* E <base-unresolved-name>
+//                   ::= [gs] <base-unresolved-name>                     # x or
+//                   (with "gs") ::x
+//                   ::= [gs] sr <unresolved-qualifier-level>+ E
+//                   <base-unresolved-name>
+//                                                                       # A::x,
+//                                                                       N::y,
+//                                                                       A<T>::z;
+//                                                                       "gs"
+//                                                                       means
+//                                                                       leading
+//                                                                       "::"
 // [gs] has been parsed by caller.
-//                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x / decltype(p)::x
-//  extension        ::= sr <unresolved-type> <template-args> <base-unresolved-name>
-//                                                                       # T::N::x /decltype(p)::N::x
-//  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E <base-unresolved-name>
+//                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x
+//                   / decltype(p)::x
+//  extension        ::= sr <unresolved-type> <template-args>
+//  <base-unresolved-name>
+//                                                                       #
+//                                                                       T::N::x
+//                                                                       /decltype(p)::N::x
+//  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E
+//  <base-unresolved-name>
 //
 // <unresolved-qualifier-level> ::= <simple-id>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
   Node *SoFar = nullptr;
 
-  // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
-  // srN <unresolved-type>                   <unresolved-qualifier-level>+ E <base-unresolved-name>
+  // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E
+  // <base-unresolved-name> srN <unresolved-type> <unresolved-qualifier-level>+
+  // E <base-unresolved-name>
   if (consumeIf("srN")) {
     SoFar = getDerived().parseUnresolvedType();
     if (SoFar == nullptr)
@@ -3789,11 +3835,15 @@ std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
   return R;
 }
 
-// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
+// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y]
+// <bare-function-type> [<ref-qualifier>] E
 //
-// <exception-spec> ::= Do                # non-throwing exception-specification (e.g., noexcept, throw())
-//                  ::= DO <expression> E # computed (instantiation-dependent) noexcept
-//                  ::= Dw <type>+ E      # dynamic exception specification with instantiation-dependent types
+// <exception-spec> ::= Do                # non-throwing exception-specification
+// (e.g., noexcept, throw())
+//                  ::= DO <expression> E # computed (instantiation-dependent)
+//                  noexcept
+//                  ::= Dw <type>+ E      # dynamic exception specification with
+//                  instantiation-dependent types
 //
 // <ref-qualifier> ::= R                   # & ref-qualifier
 // <ref-qualifier> ::= O                   # && ref-qualifier
@@ -3822,7 +3872,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
       Names.push_back(T);
     }
     ExceptionSpec =
-      make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
+        make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
     if (!ExceptionSpec)
       return nullptr;
   }
@@ -3858,12 +3908,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
   }
 
   NodeArray Params = popTrailingNodeArray(ParamsBegin);
-  return make<FunctionType>(ReturnType, Params, CVQuals,
-                            ReferenceQualifier, ExceptionSpec);
+  return make<FunctionType>(ReturnType, Params, CVQuals, ReferenceQualifier,
+                            ExceptionSpec);
 }
 
 // extension:
-// <vector-type>           ::= Dv <positive dimension number> _ <extended element type>
+// <vector-type>           ::= Dv <positive dimension number> _ <extended
+// element type>
 //                         ::= Dv [<dimension expression>] _ <element type>
 // <extended element type> ::= <element type>
 //                         ::= p # AltiVec vector pixel
@@ -3902,7 +3953,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
   return make<VectorType>(ElemType, /*Dimension=*/nullptr);
 }
 
-// <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class member access (C++0x)
+// <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class
+// member access (C++0x)
 //             ::= DT <expression> E  # decltype of an expression (C++0x)
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
@@ -3962,10 +4014,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
   return make<PointerToMemberType>(ClassType, MemberType);
 }
 
-// <class-enum-type> ::= <name>     # non-dependent type name, dependent type name, or dependent typename-specifier
-//                   ::= Ts <name>  # dependent elaborated type specifier using 'struct' or 'class'
-//                   ::= Tu <name>  # dependent elaborated type specifier using 'union'
-//                   ::= Te <name>  # dependent elaborated type specifier using 'enum'
+// <class-enum-type> ::= <name>     # non-dependent type name, dependent type
+// name, or dependent typename-specifier
+//                   ::= Ts <name>  # dependent elaborated type specifier using
+//                   'struct' or 'class'
+//                   ::= Tu <name>  # dependent elaborated type specifier using
+//                   'union'
+//                   ::= Te <name>  # dependent elaborated type specifier using
+//                   'enum'
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
   std::string_view ElabSpef;
@@ -3988,7 +4044,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
 
 // <qualified-type>     ::= <qualifiers> <type>
 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
-// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
+// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended
+// type qualifier
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
   if (consumeIf('U')) {
@@ -3996,7 +4053,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
     if (Qual.empty())
       return nullptr;
 
-    // extension            ::= U <objc-name> <objc-type>  # objc-type<identifier>
+    // extension            ::= U <objc-name> <objc-type>  #
+    // objc-type<identifier>
     if (starts_with(Qual, "objcproto")) {
       constexpr size_t Len = sizeof("objcproto") - 1;
       std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
@@ -4054,8 +4112,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
 // extension   ::= U <objc-name> <objc-type>  # objc-type<identifier>
 // extension   ::= <vector-type> # <vector-type> starts with Dv
 //
-// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 + <number of digits in k1> + k1
-// <objc-type> ::= <source-name>  # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
+// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 +
+// <number of digits in k1> + k1 <objc-type> ::= <source-name>  #
+// PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseType() {
   Node *Result = nullptr;
@@ -4066,9 +4125,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
   case 'V':
   case 'K': {
     unsigned AfterQuals = 0;
-    if (look(AfterQuals) == 'r') ++AfterQuals;
-    if (look(AfterQuals) == 'V') ++AfterQuals;
-    if (look(AfterQuals) == 'K') ++AfterQuals;
+    if (look(AfterQuals) == 'r')
+      ++AfterQuals;
+    if (look(AfterQuals) == 'V')
+      ++AfterQuals;
+    if (look(AfterQuals) == 'K')
+      ++AfterQuals;
 
     if (look(AfterQuals) == 'F' ||
         (look(AfterQuals) == 'D' &&
@@ -4202,11 +4264,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     case 'f':
       First += 2;
       return make<NameType>("decimal32");
-    //                ::= Dh   # IEEE 754r half-precision floating point (16 bits)
+    //                ::= Dh   # IEEE 754r half-precision floating point (16
+    //                bits)
     case 'h':
       First += 2;
       return make<NameType>("half");
-    //                ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
+    //                ::= DF <number> _ # ISO/IEC TS 18661 binary floating point
+    //                (N bits)
     case 'F': {
       First += 2;
       Node *DimensionNumber = make<NameType>(parseNumber());
@@ -4216,10 +4280,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
         return nullptr;
       return make<BinaryFPType>(DimensionNumber);
     }
-    //                ::= DB <number> _                             # C23 signed _BitInt(N)
-    //                ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
-    //                ::= DU <number> _                             # C23 unsigned _BitInt(N)
-    //                ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
+    //                ::= DB <number> _                             # C23 signed
+    //                _BitInt(N)
+    //                ::= DB <instantiation-dependent expression> _ # C23 signed
+    //                _BitInt(N)
+    //                ::= DU <number> _                             # C23
+    //                unsigned _BitInt(N)
+    //                ::= DU <instantiation-dependent expression> _ # C23
+    //                unsigned _BitInt(N)
     case 'B':
     case 'U': {
       bool Signed = look(1) == 'B';
@@ -4482,10 +4550,14 @@ Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
   return CVR;
 }
 
-// <function-param> ::= fp <top-level CV-Qualifiers> _                                     # L == 0, first parameter
-//                  ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _   # L == 0, second and later parameters
-//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _         # L > 0, first parameter
-//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _   # L > 0, second and later parameters
+// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
+//                  ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative
+//                  number> _   # L == 0, second and later parameters
+//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers>
+//                  _         # L > 0, first parameter
+//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers>
+//                  <parameter-2 non-negative number> _   # L > 0, second and
+//                  later parameters
 //                  ::= fpT      # 'this' expression (not part of standard?)
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
@@ -4512,8 +4584,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
   return nullptr;
 }
 
-// cv <type> <expression>                               # conversion with one argument
-// cv <type> _ <expression>* E                          # conversion with a different number of arguments
+// cv <type> <expression>                               # conversion with one
+// argument cv <type> _ <expression>* E                          # conversion
+// with a different number of arguments
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
   if (!consumeIf("cv"))
@@ -4545,13 +4618,20 @@ Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
   return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
 }
 
-// <expr-primary> ::= L <type> <value number> E                          # integer literal
-//                ::= L <type> <value float> E                           # floating literal
-//                ::= L <string type> E                                  # string literal
-//                ::= L <nullptr type> E                                 # nullptr literal (i.e., "LDnE")
-//                ::= L <lambda type> E                                  # lambda expression
-// FIXME:         ::= L <type> <real-part float> _ <imag-part float> E   # complex floating point literal (C 2000)
-//                ::= L <mangled-name> E                                 # external name
+// <expr-primary> ::= L <type> <value number> E                          #
+// integer literal
+//                ::= L <type> <value float> E                           #
+//                floating literal
+//                ::= L <string type> E                                  #
+//                string literal
+//                ::= L <nullptr type> E                                 #
+//                nullptr literal (i.e., "LDnE")
+//                ::= L <lambda type> E                                  #
+//                lambda expression
+// FIXME:         ::= L <type> <real-part float> _ <imag-part float> E   #
+// complex floating point literal (C 2000)
+//                ::= L <mangled-name> E                                 #
+//                external name
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
   if (!consumeIf('L'))
@@ -4669,9 +4749,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
 }
 
 // <braced-expression> ::= <expression>
-//                     ::= di <field source-name> <braced-expression>    # .name = expr
-//                     ::= dx <index expression> <braced-expression>     # [expr] = expr
-//                     ::= dX <range begin expression> <range end expression> <braced-expression>
+//                     ::= di <field source-name> <braced-expression>    # .name
+//                     = expr
+//                     ::= dx <index expression> <braced-expression>     #
+//                     [expr] = expr
+//                     ::= dX <range begin expression> <range end expression>
+//                     <braced-expression>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
   if (look() == 'd') {
@@ -4746,9 +4829,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
   const auto *Op = parseOperatorEncoding();
   if (!Op)
     return nullptr;
-  if (!(Op->getKind() == OperatorInfo::Binary
-        || (Op->getKind() == OperatorInfo::Member
-            && Op->getName().back() == '*')))
+  if (!(Op->getKind() == OperatorInfo::Binary ||
+        (Op->getKind() == OperatorInfo::Member && Op->getName().back() == '*')))
     return nullptr;
 
   Node *Pack = getDerived().parseExpr();
@@ -4787,8 +4869,8 @@ AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
   return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
 }
 
-// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
-// <union-selector> ::= _ [<number>]
+// <expression> ::= so <referent type> <expr> [<offset number>]
+// <union-selector>* [p] E <union-selector> ::= _ [<number>]
 //
 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
 template <typename Derived, typename Alloc>
@@ -4818,7 +4900,8 @@ template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
   // Within this expression, all enclosing template parameter lists are in
   // scope.
-  ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
+  ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(
+      HasIncompleteTemplateParameterTracking, true);
   return getDerived().parseExpr();
 }
 
@@ -4885,43 +4968,85 @@ Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {
 
 // <expression> ::= <unary operator-name> <expression>
 //              ::= <binary operator-name> <expression> <expression>
-//              ::= <ternary operator-name> <expression> <expression> <expression>
+//              ::= <ternary operator-name> <expression> <expression>
+//              <expression>
 //              ::= cl <expression>+ E                                   # call
-//              ::= cv <type> <expression>                               # conversion with one argument
-//              ::= cv <type> _ <expression>* E                          # conversion with a different number of arguments
-//              ::= [gs] nw <expression>* _ <type> E                     # new (expr-list) type
-//              ::= [gs] nw <expression>* _ <type> <initializer>         # new (expr-list) type (init)
-//              ::= [gs] na <expression>* _ <type> E                     # new[] (expr-list) type
-//              ::= [gs] na <expression>* _ <type> <initializer>         # new[] (expr-list) type (init)
-//              ::= [gs] dl <expression>                                 # delete expression
-//              ::= [gs] da <expression>                                 # delete[] expression
-//              ::= pp_ <expression>                                     # prefix ++
-//              ::= mm_ <expression>                                     # prefix --
-//              ::= ti <type>                                            # typeid (type)
-//              ::= te <expression>                                      # typeid (expression)
-//              ::= dc <type> <expression>                               # dynamic_cast<type> (expression)
-//              ::= sc <type> <expression>                               # static_cast<type> (expression)
-//              ::= cc <type> <expression>                               # const_cast<type> (expression)
-//              ::= rc <type> <expression>                               # reinterpret_cast<type> (expression)
-//              ::= st <type>                                            # sizeof (a type)
-//              ::= sz <expression>                                      # sizeof (an expression)
-//              ::= at <type>                                            # alignof (a type)
-//              ::= az <expression>                                      # alignof (an expression)
-//              ::= nx <expression>                                      # noexcept (expression)
+//              ::= cv <type> <expression>                               #
+//              conversion with one argument
+//              ::= cv <type> _ <expression>* E                          #
+//              conversion with a different number of arguments
+//              ::= [gs] nw <expression>* _ <type> E                     # new
+//              (expr-list) type
+//              ::= [gs] nw <expression>* _ <type> <initializer>         # new
+//              (expr-list) type (init)
+//              ::= [gs] na <expression>* _ <type> E                     # new[]
+//              (expr-list) type
+//              ::= [gs] na <expression>* _ <type> <initializer>         # new[]
+//              (expr-list) type (init)
+//              ::= [gs] dl <expression>                                 #
+//              delete expression
+//              ::= [gs] da <expression>                                 #
+//              delete[] expression
+//              ::= pp_ <expression>                                     #
+//              prefix ++
+//              ::= mm_ <expression>                                     #
+//              prefix --
+//              ::= ti <type>                                            #
+//              typeid (type)
+//              ::= te <expression>                                      #
+//              typeid (expression)
+//              ::= dc <type> <expression>                               #
+//              dynamic_cast<type> (expression)
+//              ::= sc <type> <expression>                               #
+//              static_cast<type> (expression)
+//              ::= cc <type> <expression>                               #
+//              const_cast<type> (expression)
+//              ::= rc <type> <expression>                               #
+//              reinterpret_cast<type> (expression)
+//              ::= st <type>                                            #
+//              sizeof (a type)
+//              ::= sz <expression>                                      #
+//              sizeof (an expression)
+//              ::= at <type>                                            #
+//              alignof (a type)
+//              ::= az <expression>                                      #
+//              alignof (an expression)
+//              ::= nx <expression>                                      #
+//              noexcept (expression)
 //              ::= <template-param>
 //              ::= <function-param>
-//              ::= dt <expression> <unresolved-name>                    # expr.name
-//              ::= pt <expression> <unresolved-name>                    # expr->name
-//              ::= ds <expression> <expression>                         # expr.*expr
-//              ::= sZ <template-param>                                  # size of a parameter pack
-//              ::= sZ <function-param>                                  # size of a function parameter pack
-//              ::= sP <template-arg>* E                                 # sizeof...(T), size of a captured template parameter pack from an alias template
-//              ::= sp <expression>                                      # pack expansion
-//              ::= tw <expression>                                      # throw expression
-//              ::= tr                                                   # throw with no operand (rethrow)
-//              ::= <unresolved-name>                                    # f(p), N::f(p), ::f(p),
-//                                                                       # freestanding dependent name (e.g., T::x),
-//                                                                       # objectless nonstatic member reference
+//              ::= dt <expression> <unresolved-name>                    #
+//              expr.name
+//              ::= pt <expression> <unresolved-name>                    #
+//              expr->name
+//              ::= ds <expression> <expression>                         #
+//              expr.*expr
+//              ::= sZ <template-param>                                  # size
+//              of a parameter pack
+//              ::= sZ <function-param>                                  # size
+//              of a function parameter pack
+//              ::= sP <template-arg>* E                                 #
+//              sizeof...(T), size of a captured template parameter pack from an
+//              alias template
+//              ::= sp <expression>                                      # pack
+//              expansion
+//              ::= tw <expression>                                      # throw
+//              expression
+//              ::= tr                                                   # throw
+//              with no operand (rethrow)
+//              ::= <unresolved-name>                                    # f(p),
+//              N::f(p), ::f(p),
+//                                                                       #
+//                                                                       freestanding
+//                                                                       dependent
+//                                                                       name
+//                                                                       (e.g.,
+//                                                                       T::x),
+//                                                                       #
+//                                                                       objectless
+//                                                                       nonstatic
+//                                                                       member
+//                                                                       reference
 //              ::= fL <binary-operator-name> <expression> <expression>
 //              ::= fR <binary-operator-name> <expression> <expression>
 //              ::= fl <binary-operator-name> <expression>
@@ -5342,7 +5467,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
       Node *Name = getDerived().parseName();
       if (Name == nullptr)
         return nullptr;
-      return make<SpecialName>("thread-local initialization routine for ", Name);
+      return make<SpecialName>("thread-local initialization routine for ",
+                               Name);
     }
     // T <call-offset> <base encoding>
     default: {
@@ -5492,44 +5618,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
                                 NameInfo.ReferenceQualifier);
 }
 
-template <class Float>
-struct FloatData;
-
-template <>
-struct FloatData<float>
-{
-    static const size_t mangled_size = 8;
-    static const size_t max_demangled_size = 24;
-    static constexpr const char* spec = "%af";
+template <class Float> struct FloatData;
+
+template <> struct FloatData<float> {
+  static const size_t mangled_size = 8;
+  static const size_t max_demangled_size = 24;
+  static constexpr const char *spec = "%af";
 };
 
-template <>
-struct FloatData<double>
-{
-    static const size_t mangled_size = 16;
-    static const size_t max_demangled_size = 32;
-    static constexpr const char* spec = "%a";
+template <> struct FloatData<double> {
+  static const size_t mangled_size = 16;
+  static const size_t max_demangled_size = 32;
+  static constexpr const char *spec = "%a";
 };
 
-template <>
-struct FloatData<long double>
-{
-#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
-    defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
+template <> struct FloatData<long double> {
+#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) ||        \
+    defined(__wasm__) || defined(__riscv) || defined(__loongarch__) ||         \
     defined(__ve__)
-    static const size_t mangled_size = 32;
+  static const size_t mangled_size = 32;
 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
-    static const size_t mangled_size = 16;
+  static const size_t mangled_size = 16;
 #else
-    static const size_t mangled_size = 20;  // May need to be adjusted to 16 or 24 on other platforms
+  static const size_t mangled_size =
+      20; // May need to be adjusted to 16 or 24 on other platforms
 #endif
-    // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
-    // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
-    // Negatives are one character longer than positives.
-    // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
-    // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
-    static const size_t max_demangled_size = 42;
-    static constexpr const char *spec = "%LaL";
+  // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
+  // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
+  // Negatives are one character longer than positives.
+  // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
+  // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
+  static const size_t max_demangled_size = 42;
+  static constexpr const char *spec = "%LaL";
 };
 
 template <typename Alloc, typename Derived>
@@ -5551,8 +5671,7 @@ Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
 // <seq-id> ::= <0-9A-Z>+
 template <typename Alloc, typename Derived>
 bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
-  if (!(look() >= '0' && look() <= '9') &&
-      !(look() >= 'A' && look() <= 'Z'))
+  if (!(look() >= '0' && look() <= '9') && !(look() >= 'A' && look() <= 'Z'))
     return true;
 
   size_t Id = 0;
@@ -5676,7 +5795,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
   // substitute them all within a <constraint-expression>, so print the
   // parameter numbering instead for now.
   // TODO: Track all enclosing template parameters and substitute them here.
-  if (InConstraintExpr) {
+  if (HasIncompleteTemplateParameterTracking) {
     return make<NameType>(std::string_view(Begin, First - 1 - Begin));
   }
 
@@ -5714,7 +5833,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
 }
 
 // <template-param-decl> ::= Ty                          # type parameter
-//                       ::= Tk <concept name> [<template-args>] # constrained type parameter
+//                       ::= Tk <concept name> [<template-args>] # constrained
+//                       type parameter
 //                       ::= Tn <type>                   # non-type parameter
 //                       ::= Tt <template-param-decl>* E # template parameter
 //                       ::= Tp <template-param-decl>    # parameter pack
@@ -5877,7 +5997,7 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
       }
       if (Arg->getKind() == Node::KTemplateArgumentPack) {
         TableEntry = make<ParameterPack>(
-            static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
+            static_cast<TemplateArgumentPack *>(TableEntry)->getElements());
         if (!TableEntry)
           return nullptr;
       }

>From 39e8babedfbb3cc23727fb766a421ed7b1c7c9d1 Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 4/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index bfcf7046512287..a6ac67116a45cc 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -4898,10 +4898,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
 
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
-  // Within this expression, all enclosing template parameter lists are in
-  // scope.
+  // We don't track enclosing template parameter levels well enough to reliably
+  // demangle template parameter substitutions, so print an arbitrary
+  // string in place of a parameter for now.
+  // TODO: Track all enclosing template parameters and demangle substitutions.
   ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(
-      HasIncompleteTemplateParameterTracking, true);
+    HasIncompleteTemplateParameterTracking, true);
   return getDerived().parseExpr();
 }
 

>From 9e09f303f3a3115d0ab5ecad965620eca75752c0 Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 5/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 5c044def74e881..e3c28c9bd15b88 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -2677,7 +2677,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
 
   bool TryToParseTemplateArgs = true;
   bool PermitForwardTemplateReferences = false;
-  bool InConstraintExpr = false;
+  bool HasIncompleteTemplateParameterTracking = false;
   size_t ParsingLambdaParamsAtLevel = (size_t)-1;
 
   unsigned NumSyntheticTemplateParameters[3] = {};
@@ -4816,9 +4816,11 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
 
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
-  // Within this expression, all enclosing template parameter lists are in
-  // scope.
-  ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
+  // We don't track enclosing template parameter levels well enough to reliably
+  // demangle template parameter substitutions, so print an arbitrary
+  // string in place of a parameter for now.
+  // TODO: Track all enclosing template parameters and demangle substitutions.
+  ScopedOverride<bool> SaveInConstraintExpr(HasIncompleteTemplateParameterTracking, true);
   return getDerived().parseExpr();
 }
 
@@ -5676,7 +5678,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
   // substitute them all within a <constraint-expression>, so print the
   // parameter numbering instead for now.
   // TODO: Track all enclosing template parameters and substitute them here.
-  if (InConstraintExpr) {
+  if (HasIncompleteTemplateParameterTracking) {
     return make<NameType>(std::string_view(Begin, First - 1 - Begin));
   }
 
@@ -5737,7 +5739,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
   }
 
   if (consumeIf("Tk")) {
-    ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
+    ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(
+      HasIncompleteTemplateParameterTracking, true);
     Node *Constraint = getDerived().parseName();
     if (!Constraint)
       return nullptr;

>From 071ad2fdf2d389bc435210912f6cc5ef8a656097 Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 6/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 574 +++++++++--------------
 1 file changed, 226 insertions(+), 348 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index a6ac67116a45cc..88de234a6e0b92 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -167,11 +167,7 @@ class Node {
 
   /// Three-way bool to track a cached value. Unknown is possible if this node
   /// has an unexpanded parameter pack below it that may affect this cache.
-  enum class Cache : unsigned char {
-    Yes,
-    No,
-    Unknown,
-  };
+  enum class Cache : unsigned char { Yes, No, Unknown, };
 
   /// Operator precedence for expression nodes. Used to determine required
   /// parens in expression emission.
@@ -228,13 +224,13 @@ class Node {
              FunctionCache_) {}
 
   /// Visit the most-derived object corresponding to this object.
-  template <typename Fn> void visit(Fn F) const;
+  template<typename Fn> void visit(Fn F) const;
 
   // The following function is provided by all derived classes:
   //
   // Call F with arguments that, when passed to the constructor of this node,
   // would construct an equivalent node.
-  // template<typename Fn> void match(Fn F) const;
+  //template<typename Fn> void match(Fn F) const;
 
   bool hasRHSComponent(OutputBuffer &OB) const {
     if (RHSComponentCache != Cache::Unknown)
@@ -349,7 +345,7 @@ struct NodeArrayNode : Node {
   NodeArray Array;
   NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Array); }
+  template<typename Fn> void match(Fn F) const { F(Array); }
 
   void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
 };
@@ -362,7 +358,7 @@ class DotSuffix final : public Node {
   DotSuffix(const Node *Prefix_, std::string_view Suffix_)
       : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
+  template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
 
   void printLeft(OutputBuffer &OB) const override {
     Prefix->print(OB);
@@ -436,7 +432,7 @@ class QualType final : public Node {
   Qualifiers getQuals() const { return Quals; }
   const Node *getChild() const { return Child; }
 
-  template <typename Fn> void match(Fn F) const { F(Child, Quals); }
+  template<typename Fn> void match(Fn F) const { F(Child, Quals); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Child->hasRHSComponent(OB);
@@ -463,7 +459,7 @@ class ConversionOperatorType final : public Node {
   ConversionOperatorType(const Node *Ty_)
       : Node(KConversionOperatorType), Ty(Ty_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Ty); }
+  template<typename Fn> void match(Fn F) const { F(Ty); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "operator ";
@@ -479,7 +475,7 @@ class PostfixQualifiedType final : public Node {
   PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
       : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Ty, Postfix); }
+  template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
 
   void printLeft(OutputBuffer &OB) const override {
     Ty->printLeft(OB);
@@ -493,7 +489,7 @@ class NameType final : public Node {
 public:
   NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Name); }
+  template<typename Fn> void match(Fn F) const { F(Name); }
 
   std::string_view getName() const { return Name; }
   std::string_view getBaseName() const override { return Name; }
@@ -524,12 +520,11 @@ class BitIntType final : public Node {
 class ElaboratedTypeSpefType : public Node {
   std::string_view Kind;
   Node *Child;
-
 public:
   ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
       : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Kind, Child); }
+  template<typename Fn> void match(Fn F) const { F(Kind, Child); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Kind;
@@ -541,12 +536,11 @@ class ElaboratedTypeSpefType : public Node {
 class TransformedType : public Node {
   std::string_view Transform;
   Node *BaseType;
-
 public:
   TransformedType(std::string_view Transform_, Node *BaseType_)
       : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Transform, BaseType); }
+  template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Transform;
@@ -565,7 +559,7 @@ struct AbiTagAttr : Node {
              Base_->getFunctionCache()),
         Base(Base_), Tag(Tag_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Base, Tag); }
+  template<typename Fn> void match(Fn F) const { F(Base, Tag); }
 
   std::string_view getBaseName() const override { return Base->getBaseName(); }
 
@@ -579,12 +573,11 @@ struct AbiTagAttr : Node {
 
 class EnableIfAttr : public Node {
   NodeArray Conditions;
-
 public:
   EnableIfAttr(NodeArray Conditions_)
       : Node(KEnableIfAttr), Conditions(Conditions_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Conditions); }
+  template<typename Fn> void match(Fn F) const { F(Conditions); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += " [enable_if:";
@@ -603,7 +596,7 @@ class ObjCProtoName : public Node {
   ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
       : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Ty, Protocol); }
+  template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
 
   bool isObjCObject() const {
     return Ty->getKind() == KNameType &&
@@ -628,7 +621,7 @@ class PointerType final : public Node {
 
   const Node *getPointee() const { return Pointee; }
 
-  template <typename Fn> void match(Fn F) const { F(Pointee); }
+  template<typename Fn> void match(Fn F) const { F(Pointee); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Pointee->hasRHSComponent(OB);
@@ -710,7 +703,7 @@ class ReferenceType : public Node {
       : Node(KReferenceType, Pointee_->getRHSComponentCache()),
         Pointee(Pointee_), RK(RK_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Pointee, RK); }
+  template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return Pointee->hasRHSComponent(OB);
@@ -753,7 +746,7 @@ class PointerToMemberType final : public Node {
       : Node(KPointerToMemberType, MemberType_->getRHSComponentCache()),
         ClassType(ClassType_), MemberType(MemberType_) {}
 
-  template <typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
+  template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     return MemberType->hasRHSComponent(OB);
@@ -787,7 +780,7 @@ class ArrayType final : public Node {
              /*ArrayCache=*/Cache::Yes),
         Base(Base_), Dimension(Dimension_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Base, Dimension); }
+  template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
 
   bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
   bool hasArraySlow(OutputBuffer &) const override { return true; }
@@ -821,7 +814,7 @@ class FunctionType final : public Node {
         Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
         ExceptionSpec(ExceptionSpec_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
   }
 
@@ -867,11 +860,10 @@ class FunctionType final : public Node {
 
 class NoexceptSpec : public Node {
   const Node *E;
-
 public:
   NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
 
-  template <typename Fn> void match(Fn F) const { F(E); }
+  template<typename Fn> void match(Fn F) const { F(E); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "noexcept";
@@ -883,12 +875,11 @@ class NoexceptSpec : public Node {
 
 class DynamicExceptionSpec : public Node {
   NodeArray Types;
-
 public:
   DynamicExceptionSpec(NodeArray Types_)
       : Node(KDynamicExceptionSpec), Types(Types_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Types); }
+  template<typename Fn> void match(Fn F) const { F(Types); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "throw";
@@ -943,7 +934,7 @@ class FunctionEncoding final : public Node {
         Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
         Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
   }
 
@@ -1002,7 +993,7 @@ class LiteralOperator : public Node {
   LiteralOperator(const Node *OpName_)
       : Node(KLiteralOperator), OpName(OpName_) {}
 
-  template <typename Fn> void match(Fn F) const { F(OpName); }
+  template<typename Fn> void match(Fn F) const { F(OpName); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "operator\"\" ";
@@ -1018,7 +1009,7 @@ class SpecialName final : public Node {
   SpecialName(std::string_view Special_, const Node *Child_)
       : Node(KSpecialName), Special(Special_), Child(Child_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Special, Child); }
+  template<typename Fn> void match(Fn F) const { F(Special, Child); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Special;
@@ -1032,10 +1023,10 @@ class CtorVtableSpecialName final : public Node {
 
 public:
   CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
-      : Node(KCtorVtableSpecialName), FirstType(FirstType_),
-        SecondType(SecondType_) {}
+      : Node(KCtorVtableSpecialName),
+        FirstType(FirstType_), SecondType(SecondType_) {}
 
-  template <typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
+  template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "construction vtable for ";
@@ -1052,7 +1043,7 @@ struct NestedName : Node {
   NestedName(Node *Qual_, Node *Name_)
       : Node(KNestedName), Qual(Qual_), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Qual, Name); }
+  template<typename Fn> void match(Fn F) const { F(Qual, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1070,7 +1061,7 @@ struct MemberLikeFriendName : Node {
   MemberLikeFriendName(Node *Qual_, Node *Name_)
       : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Qual, Name); }
+  template<typename Fn> void match(Fn F) const { F(Qual, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1128,7 +1119,7 @@ struct LocalName : Node {
   LocalName(Node *Encoding_, Node *Entity_)
       : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Encoding, Entity); }
+  template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
 
   void printLeft(OutputBuffer &OB) const override {
     Encoding->print(OB);
@@ -1146,7 +1137,7 @@ class QualifiedName final : public Node {
   QualifiedName(const Node *Qualifier_, const Node *Name_)
       : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Qualifier, Name); }
+  template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1168,7 +1159,7 @@ class VectorType final : public Node {
   const Node *getBaseType() const { return BaseType; }
   const Node *getDimension() const { return Dimension; }
 
-  template <typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
+  template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     BaseType->print(OB);
@@ -1186,7 +1177,7 @@ class PixelVectorType final : public Node {
   PixelVectorType(const Node *Dimension_)
       : Node(KPixelVectorType), Dimension(Dimension_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Dimension); }
+  template<typename Fn> void match(Fn F) const { F(Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     // FIXME: This should demangle as "vector pixel".
@@ -1203,7 +1194,7 @@ class BinaryFPType final : public Node {
   BinaryFPType(const Node *Dimension_)
       : Node(KBinaryFPType), Dimension(Dimension_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Dimension); }
+  template<typename Fn> void match(Fn F) const { F(Dimension); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "_Float";
@@ -1227,7 +1218,7 @@ class SyntheticTemplateParamName final : public Node {
   SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
       : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Kind, Index); }
+  template<typename Fn> void match(Fn F) const { F(Kind, Index); }
 
   void printLeft(OutputBuffer &OB) const override {
     switch (Kind) {
@@ -1272,7 +1263,7 @@ class TypeTemplateParamDecl final : public Node {
   TypeTemplateParamDecl(Node *Name_)
       : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Name); }
+  template<typename Fn> void match(Fn F) const { F(Name); }
 
   void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
 
@@ -1289,7 +1280,7 @@ class ConstrainedTypeTemplateParamDecl final : public Node {
       : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
         Constraint(Constraint_), Name(Name_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Constraint, Name); }
+  template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
 
   void printLeft(OutputBuffer &OB) const override {
     Constraint->print(OB);
@@ -1308,7 +1299,7 @@ class NonTypeTemplateParamDecl final : public Node {
   NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
       : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Name, Type); }
+  template<typename Fn> void match(Fn F) const { F(Name, Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     Type->printLeft(OB);
@@ -1360,7 +1351,7 @@ class TemplateParamPackDecl final : public Node {
   TemplateParamPackDecl(Node *Param_)
       : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Param); }
+  template<typename Fn> void match(Fn F) const { F(Param); }
 
   void printLeft(OutputBuffer &OB) const override {
     Param->printLeft(OB);
@@ -1405,7 +1396,7 @@ class ParameterPack final : public Node {
       RHSComponentCache = Cache::No;
   }
 
-  template <typename Fn> void match(Fn F) const { F(Data); }
+  template<typename Fn> void match(Fn F) const { F(Data); }
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     initializePackExpansion(OB);
@@ -1449,12 +1440,11 @@ class ParameterPack final : public Node {
 /// <encoding>.
 class TemplateArgumentPack final : public Node {
   NodeArray Elements;
-
 public:
   TemplateArgumentPack(NodeArray Elements_)
       : Node(KTemplateArgumentPack), Elements(Elements_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Elements); }
+  template<typename Fn> void match(Fn F) const { F(Elements); }
 
   NodeArray getElements() const { return Elements; }
 
@@ -1472,7 +1462,7 @@ class ParameterPackExpansion final : public Node {
   ParameterPackExpansion(const Node *Child_)
       : Node(KParameterPackExpansion), Child(Child_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Child); }
+  template<typename Fn> void match(Fn F) const { F(Child); }
 
   const Node *getChild() const { return Child; }
 
@@ -1517,7 +1507,7 @@ class TemplateArgs final : public Node {
   TemplateArgs(NodeArray Params_, Node *Requires_)
       : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Params, Requires); }
+  template<typename Fn> void match(Fn F) const { F(Params, Requires); }
 
   NodeArray getParams() { return Params; }
 
@@ -1566,7 +1556,7 @@ struct ForwardTemplateReference : Node {
   // We don't provide a matcher for these, because the value of the node is
   // not determined by its construction parameters, and it generally needs
   // special handling.
-  template <typename Fn> void match(Fn F) const = delete;
+  template<typename Fn> void match(Fn F) const = delete;
 
   bool hasRHSComponentSlow(OutputBuffer &OB) const override {
     if (Printing)
@@ -1615,7 +1605,7 @@ struct NameWithTemplateArgs : Node {
   NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
       : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
+  template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
 
   std::string_view getBaseName() const override { return Name->getBaseName(); }
 
@@ -1629,10 +1619,10 @@ class GlobalQualifiedName final : public Node {
   Node *Child;
 
 public:
-  GlobalQualifiedName(Node *Child_)
+  GlobalQualifiedName(Node* Child_)
       : Node(KGlobalQualifiedName), Child(Child_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Child); }
+  template<typename Fn> void match(Fn F) const { F(Child); }
 
   std::string_view getBaseName() const override { return Child->getBaseName(); }
 
@@ -1658,13 +1648,12 @@ class ExpandedSpecialSubstitution : public Node {
 
   ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
       : Node(K_), SSK(SSK_) {}
-
 public:
   ExpandedSpecialSubstitution(SpecialSubKind SSK_)
       : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
   inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
 
-  template <typename Fn> void match(Fn F) const { F(SSK); }
+  template<typename Fn> void match(Fn F) const { F(SSK); }
 
 protected:
   bool isInstantiation() const {
@@ -1706,7 +1695,7 @@ class SpecialSubstitution final : public ExpandedSpecialSubstitution {
   SpecialSubstitution(SpecialSubKind SSK_)
       : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
 
-  template <typename Fn> void match(Fn F) const { F(SSK); }
+  template<typename Fn> void match(Fn F) const { F(SSK); }
 
   std::string_view getBaseName() const override {
     std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
@@ -1737,9 +1726,7 @@ class CtorDtorName final : public Node {
       : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
         Variant(Variant_) {}
 
-  template <typename Fn> void match(Fn F) const {
-    F(Basename, IsDtor, Variant);
-  }
+  template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (IsDtor)
@@ -1754,7 +1741,7 @@ class DtorName : public Node {
 public:
   DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Base); }
+  template<typename Fn> void match(Fn F) const { F(Base); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "~";
@@ -1769,7 +1756,7 @@ class UnnamedTypeName : public Node {
   UnnamedTypeName(std::string_view Count_)
       : Node(KUnnamedTypeName), Count(Count_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Count); }
+  template<typename Fn> void match(Fn F) const { F(Count); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "'unnamed";
@@ -1793,7 +1780,7 @@ class ClosureTypeName : public Node {
         Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
         Count(Count_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(TemplateParams, Requires1, Params, Requires2, Count);
   }
 
@@ -1829,12 +1816,11 @@ class ClosureTypeName : public Node {
 
 class StructuredBindingName : public Node {
   NodeArray Bindings;
-
 public:
   StructuredBindingName(NodeArray Bindings_)
       : Node(KStructuredBindingName), Bindings(Bindings_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Bindings); }
+  template<typename Fn> void match(Fn F) const { F(Bindings); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB.printOpen('[');
@@ -1975,7 +1961,7 @@ class SubobjectExpr : public Node {
       : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
         UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
   }
 
@@ -2055,7 +2041,7 @@ class SizeofParamPackExpr : public Node {
   SizeofParamPackExpr(const Node *Pack_)
       : Node(KSizeofParamPackExpr), Pack(Pack_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Pack); }
+  template<typename Fn> void match(Fn F) const { F(Pack); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "sizeof...";
@@ -2099,7 +2085,7 @@ class NewExpr : public Node {
       : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
         InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
   }
 
@@ -2174,7 +2160,7 @@ class FunctionParam : public Node {
   FunctionParam(std::string_view Number_)
       : Node(KFunctionParam), Number(Number_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Number); }
+  template<typename Fn> void match(Fn F) const { F(Number); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "fp";
@@ -2232,12 +2218,11 @@ class PointerToMemberConversionExpr : public Node {
 class InitListExpr : public Node {
   const Node *Ty;
   NodeArray Inits;
-
 public:
   InitListExpr(const Node *Ty_, NodeArray Inits_)
       : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Ty, Inits); }
+  template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (Ty)
@@ -2252,12 +2237,11 @@ class BracedExpr : public Node {
   const Node *Elem;
   const Node *Init;
   bool IsArray;
-
 public:
   BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
       : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
+  template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (IsArray) {
@@ -2278,12 +2262,11 @@ class BracedRangeExpr : public Node {
   const Node *First;
   const Node *Last;
   const Node *Init;
-
 public:
   BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
       : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
 
-  template <typename Fn> void match(Fn F) const { F(First, Last, Init); }
+  template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += '[';
@@ -2308,7 +2291,7 @@ class FoldExpr : public Node {
       : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
         IsLeftFold(IsLeftFold_) {}
 
-  template <typename Fn> void match(Fn F) const {
+  template<typename Fn> void match(Fn F) const {
     F(IsLeftFold, OperatorName, Pack, Init);
   }
 
@@ -2350,7 +2333,7 @@ class ThrowExpr : public Node {
 public:
   ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Op); }
+  template<typename Fn> void match(Fn F) const { F(Op); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "throw ";
@@ -2364,7 +2347,7 @@ class BoolExpr : public Node {
 public:
   BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Value); }
+  template<typename Fn> void match(Fn F) const { F(Value); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += Value ? std::string_view("true") : std::string_view("false");
@@ -2377,7 +2360,7 @@ class StringLiteral : public Node {
 public:
   StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Type); }
+  template<typename Fn> void match(Fn F) const { F(Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "\"<";
@@ -2392,7 +2375,7 @@ class LambdaExpr : public Node {
 public:
   LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Type); }
+  template<typename Fn> void match(Fn F) const { F(Type); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "[]";
@@ -2411,7 +2394,7 @@ class EnumLiteral : public Node {
   EnumLiteral(const Node *Ty_, std::string_view Integer_)
       : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Ty, Integer); }
+  template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB.printOpen();
@@ -2433,7 +2416,7 @@ class IntegerLiteral : public Node {
   IntegerLiteral(std::string_view Type_, std::string_view Value_)
       : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Type, Value); }
+  template<typename Fn> void match(Fn F) const { F(Type, Value); }
 
   void printLeft(OutputBuffer &OB) const override {
     if (Type.size() > 3) {
@@ -2455,13 +2438,12 @@ class IntegerLiteral : public Node {
 class RequiresExpr : public Node {
   NodeArray Parameters;
   NodeArray Requirements;
-
 public:
   RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
       : Node(KRequiresExpr), Parameters(Parameters_),
         Requirements(Requirements_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
+  template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
 
   void printLeft(OutputBuffer &OB) const override {
     OB += "requires";
@@ -2485,7 +2467,6 @@ class ExprRequirement : public Node {
   const Node *Expr;
   bool IsNoexcept;
   const Node *TypeConstraint;
-
 public:
   ExprRequirement(const Node *Expr_, bool IsNoexcept_,
                   const Node *TypeConstraint_)
@@ -2515,9 +2496,9 @@ class ExprRequirement : public Node {
 
 class TypeRequirement : public Node {
   const Node *Type;
-
 public:
-  TypeRequirement(const Node *Type_) : Node(KTypeRequirement), Type(Type_) {}
+  TypeRequirement(const Node *Type_)
+      : Node(KTypeRequirement), Type(Type_) {}
 
   template <typename Fn> void match(Fn F) const { F(Type); }
 
@@ -2530,7 +2511,6 @@ class TypeRequirement : public Node {
 
 class NestedRequirement : public Node {
   const Node *Constraint;
-
 public:
   NestedRequirement(const Node *Constraint_)
       : Node(KNestedRequirement), Constraint(Constraint_) {}
@@ -2556,7 +2536,7 @@ constexpr Node::Kind getFloatLiteralKind(double *) {
 constexpr Node::Kind getFloatLiteralKind(long double *) {
   return Node::KLongDoubleLiteral;
 }
-} // namespace float_literal_impl
+}
 
 template <class Float> class FloatLiteralImpl : public Node {
   const std::string_view Contents;
@@ -2568,7 +2548,7 @@ template <class Float> class FloatLiteralImpl : public Node {
   FloatLiteralImpl(std::string_view Contents_)
       : Node(KindForClass), Contents(Contents_) {}
 
-  template <typename Fn> void match(Fn F) const { F(Contents); }
+  template<typename Fn> void match(Fn F) const { F(Contents); }
 
   void printLeft(OutputBuffer &OB) const override {
     const size_t N = FloatData<Float>::mangled_size;
@@ -2604,7 +2584,8 @@ using LongDoubleLiteral = FloatLiteralImpl<long double>;
 
 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
 /// appropriate derived class.
-template <typename Fn> void Node::visit(Fn F) const {
+template<typename Fn>
+void Node::visit(Fn F) const {
   switch (K) {
 #define NODE(X)                                                                \
   case K##X:                                                                   \
@@ -2615,7 +2596,7 @@ template <typename Fn> void Node::visit(Fn F) const {
 }
 
 /// Determine the kind of a node from its type.
-template <typename NodeT> struct NodeKind;
+template<typename NodeT> struct NodeKind;
 #define NODE(X)                                                                \
   template <> struct NodeKind<X> {                                             \
     static constexpr Node::Kind Kind = Node::K##X;                             \
@@ -2696,7 +2677,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
 
   bool TryToParseTemplateArgs = true;
   bool PermitForwardTemplateReferences = false;
-  bool HasIncompleteTemplateParameterTracking = false;
+  bool InConstraintExpr = false;
   size_t ParsingLambdaParamsAtLevel = (size_t)-1;
 
   unsigned NumSyntheticTemplateParameters[3] = {};
@@ -2722,7 +2703,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
     ASTAllocator.reset();
   }
 
-  template <class T, class... Args> Node *make(Args &&...args) {
+  template <class T, class... Args> Node *make(Args &&... args) {
     return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
   }
 
@@ -2876,11 +2857,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
 
       Unnameable = NamedCast,
     };
-    char Enc[2];         // Encoding
-    OIKind Kind;         // Kind of operator
-    bool Flag : 1;       // Entry-specific flag
+    char Enc[2];      // Encoding
+    OIKind Kind;      // Kind of operator
+    bool Flag : 1;    // Entry-specific flag
     Node::Prec Prec : 7; // Precedence
-    const char *Name;    // Spelling
+    const char *Name; // Spelling
 
   public:
     constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
@@ -2931,7 +2912,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
   Node *parse(bool ParseParams = true);
 };
 
-const char *parse_discriminator(const char *first, const char *last);
+const char* parse_discriminator(const char* first, const char* last);
 
 // <name> ::= <nested-name> // N
 //        ::= <local-name> # See Scope Encoding below  // Z
@@ -2975,8 +2956,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
 
 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
 //              := Z <function encoding> E s [<discriminator>]
-//              := Z <function encoding> Ed [ <parameter number> ] _ <entity
-//              name>
+//              := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
   if (!consumeIf('Z'))
@@ -3326,8 +3306,8 @@ const typename AbstractManglingParser<
     {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
 };
 template <typename Derived, typename Alloc>
-const size_t AbstractManglingParser<Derived, Alloc>::NumOps =
-    sizeof(Ops) / sizeof(Ops[0]);
+const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
+                                                              sizeof(Ops[0]);
 
 // If the next 2 chars are an operator encoding, consume them and return their
 // OperatorInfo.  Otherwise return nullptr.
@@ -3373,8 +3353,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
       Node *Ty = getDerived().parseType();
       if (Ty == nullptr)
         return nullptr;
-      if (State)
-        State->CtorDtorConversion = true;
+      if (State) State->CtorDtorConversion = true;
       return make<ConversionOperatorType>(Ty);
     }
 
@@ -3440,8 +3419,7 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
       return nullptr;
     int Variant = look() - '0';
     ++First;
-    if (State)
-      State->CtorDtorConversion = true;
+    if (State) State->CtorDtorConversion = true;
     if (IsInherited) {
       if (getDerived().parseName(State) == nullptr)
         return nullptr;
@@ -3453,8 +3431,7 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
                         look(1) == '4' || look(1) == '5')) {
     int Variant = look(1) - '0';
     First += 2;
-    if (State)
-      State->CtorDtorConversion = true;
+    if (State) State->CtorDtorConversion = true;
     return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
   }
 
@@ -3633,21 +3610,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
   return getDerived().parseSubstitution();
 }
 
-// <base-unresolved-name> ::= <simple-id>                                #
-// unresolved name
-//          extension     ::= <operator-name>                            #
-//          unresolved operator-function-id extension     ::= <operator-name>
-//          <template-args>            # unresolved operator template-id
-//                        ::= on <operator-name>                         #
-//                        unresolved operator-function-id
-//                        ::= on <operator-name> <template-args>         #
-//                        unresolved operator template-id
-//                        ::= dn <destructor-name>                       #
-//                        destructor or pseudo-destructor;
-//                                                                         #
-//                                                                         e.g.
-//                                                                         ~X or
-//                                                                         ~X<N-1>
+// <base-unresolved-name> ::= <simple-id>                                # unresolved name
+//          extension     ::= <operator-name>                            # unresolved operator-function-id
+//          extension     ::= <operator-name> <template-args>            # unresolved operator template-id
+//                        ::= on <operator-name>                         # unresolved operator-function-id
+//                        ::= on <operator-name> <template-args>         # unresolved operator template-id
+//                        ::= dn <destructor-name>                       # destructor or pseudo-destructor;
+//                                                                         # e.g. ~X or ~X<N-1>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
   if (std::isdigit(look()))
@@ -3671,38 +3640,23 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
 }
 
 // <unresolved-name>
-//  extension        ::= srN <unresolved-type> [<template-args>]
-//  <unresolved-qualifier-level>* E <base-unresolved-name>
-//                   ::= [gs] <base-unresolved-name>                     # x or
-//                   (with "gs") ::x
-//                   ::= [gs] sr <unresolved-qualifier-level>+ E
-//                   <base-unresolved-name>
-//                                                                       # A::x,
-//                                                                       N::y,
-//                                                                       A<T>::z;
-//                                                                       "gs"
-//                                                                       means
-//                                                                       leading
-//                                                                       "::"
+//  extension        ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
+//                   ::= [gs] <base-unresolved-name>                     # x or (with "gs") ::x
+//                   ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
+//                                                                       # A::x, N::y, A<T>::z; "gs" means leading "::"
 // [gs] has been parsed by caller.
-//                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x
-//                   / decltype(p)::x
-//  extension        ::= sr <unresolved-type> <template-args>
-//  <base-unresolved-name>
-//                                                                       #
-//                                                                       T::N::x
-//                                                                       /decltype(p)::N::x
-//  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E
-//  <base-unresolved-name>
+//                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x / decltype(p)::x
+//  extension        ::= sr <unresolved-type> <template-args> <base-unresolved-name>
+//                                                                       # T::N::x /decltype(p)::N::x
+//  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E <base-unresolved-name>
 //
 // <unresolved-qualifier-level> ::= <simple-id>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
   Node *SoFar = nullptr;
 
-  // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E
-  // <base-unresolved-name> srN <unresolved-type> <unresolved-qualifier-level>+
-  // E <base-unresolved-name>
+  // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
+  // srN <unresolved-type>                   <unresolved-qualifier-level>+ E <base-unresolved-name>
   if (consumeIf("srN")) {
     SoFar = getDerived().parseUnresolvedType();
     if (SoFar == nullptr)
@@ -3835,15 +3789,11 @@ std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
   return R;
 }
 
-// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y]
-// <bare-function-type> [<ref-qualifier>] E
+// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
 //
-// <exception-spec> ::= Do                # non-throwing exception-specification
-// (e.g., noexcept, throw())
-//                  ::= DO <expression> E # computed (instantiation-dependent)
-//                  noexcept
-//                  ::= Dw <type>+ E      # dynamic exception specification with
-//                  instantiation-dependent types
+// <exception-spec> ::= Do                # non-throwing exception-specification (e.g., noexcept, throw())
+//                  ::= DO <expression> E # computed (instantiation-dependent) noexcept
+//                  ::= Dw <type>+ E      # dynamic exception specification with instantiation-dependent types
 //
 // <ref-qualifier> ::= R                   # & ref-qualifier
 // <ref-qualifier> ::= O                   # && ref-qualifier
@@ -3872,7 +3822,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
       Names.push_back(T);
     }
     ExceptionSpec =
-        make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
+      make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
     if (!ExceptionSpec)
       return nullptr;
   }
@@ -3908,13 +3858,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
   }
 
   NodeArray Params = popTrailingNodeArray(ParamsBegin);
-  return make<FunctionType>(ReturnType, Params, CVQuals, ReferenceQualifier,
-                            ExceptionSpec);
+  return make<FunctionType>(ReturnType, Params, CVQuals,
+                            ReferenceQualifier, ExceptionSpec);
 }
 
 // extension:
-// <vector-type>           ::= Dv <positive dimension number> _ <extended
-// element type>
+// <vector-type>           ::= Dv <positive dimension number> _ <extended element type>
 //                         ::= Dv [<dimension expression>] _ <element type>
 // <extended element type> ::= <element type>
 //                         ::= p # AltiVec vector pixel
@@ -3953,8 +3902,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
   return make<VectorType>(ElemType, /*Dimension=*/nullptr);
 }
 
-// <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class
-// member access (C++0x)
+// <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class member access (C++0x)
 //             ::= DT <expression> E  # decltype of an expression (C++0x)
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
@@ -4014,14 +3962,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
   return make<PointerToMemberType>(ClassType, MemberType);
 }
 
-// <class-enum-type> ::= <name>     # non-dependent type name, dependent type
-// name, or dependent typename-specifier
-//                   ::= Ts <name>  # dependent elaborated type specifier using
-//                   'struct' or 'class'
-//                   ::= Tu <name>  # dependent elaborated type specifier using
-//                   'union'
-//                   ::= Te <name>  # dependent elaborated type specifier using
-//                   'enum'
+// <class-enum-type> ::= <name>     # non-dependent type name, dependent type name, or dependent typename-specifier
+//                   ::= Ts <name>  # dependent elaborated type specifier using 'struct' or 'class'
+//                   ::= Tu <name>  # dependent elaborated type specifier using 'union'
+//                   ::= Te <name>  # dependent elaborated type specifier using 'enum'
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
   std::string_view ElabSpef;
@@ -4044,8 +3988,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
 
 // <qualified-type>     ::= <qualifiers> <type>
 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
-// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended
-// type qualifier
+// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
   if (consumeIf('U')) {
@@ -4053,8 +3996,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
     if (Qual.empty())
       return nullptr;
 
-    // extension            ::= U <objc-name> <objc-type>  #
-    // objc-type<identifier>
+    // extension            ::= U <objc-name> <objc-type>  # objc-type<identifier>
     if (starts_with(Qual, "objcproto")) {
       constexpr size_t Len = sizeof("objcproto") - 1;
       std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
@@ -4112,9 +4054,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
 // extension   ::= U <objc-name> <objc-type>  # objc-type<identifier>
 // extension   ::= <vector-type> # <vector-type> starts with Dv
 //
-// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 +
-// <number of digits in k1> + k1 <objc-type> ::= <source-name>  #
-// PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
+// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 + <number of digits in k1> + k1
+// <objc-type> ::= <source-name>  # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseType() {
   Node *Result = nullptr;
@@ -4125,12 +4066,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
   case 'V':
   case 'K': {
     unsigned AfterQuals = 0;
-    if (look(AfterQuals) == 'r')
-      ++AfterQuals;
-    if (look(AfterQuals) == 'V')
-      ++AfterQuals;
-    if (look(AfterQuals) == 'K')
-      ++AfterQuals;
+    if (look(AfterQuals) == 'r') ++AfterQuals;
+    if (look(AfterQuals) == 'V') ++AfterQuals;
+    if (look(AfterQuals) == 'K') ++AfterQuals;
 
     if (look(AfterQuals) == 'F' ||
         (look(AfterQuals) == 'D' &&
@@ -4264,13 +4202,11 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
     case 'f':
       First += 2;
       return make<NameType>("decimal32");
-    //                ::= Dh   # IEEE 754r half-precision floating point (16
-    //                bits)
+    //                ::= Dh   # IEEE 754r half-precision floating point (16 bits)
     case 'h':
       First += 2;
       return make<NameType>("half");
-    //                ::= DF <number> _ # ISO/IEC TS 18661 binary floating point
-    //                (N bits)
+    //                ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
     case 'F': {
       First += 2;
       Node *DimensionNumber = make<NameType>(parseNumber());
@@ -4280,14 +4216,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
         return nullptr;
       return make<BinaryFPType>(DimensionNumber);
     }
-    //                ::= DB <number> _                             # C23 signed
-    //                _BitInt(N)
-    //                ::= DB <instantiation-dependent expression> _ # C23 signed
-    //                _BitInt(N)
-    //                ::= DU <number> _                             # C23
-    //                unsigned _BitInt(N)
-    //                ::= DU <instantiation-dependent expression> _ # C23
-    //                unsigned _BitInt(N)
+    //                ::= DB <number> _                             # C23 signed _BitInt(N)
+    //                ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
+    //                ::= DU <number> _                             # C23 unsigned _BitInt(N)
+    //                ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
     case 'B':
     case 'U': {
       bool Signed = look(1) == 'B';
@@ -4550,14 +4482,10 @@ Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
   return CVR;
 }
 
-// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
-//                  ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative
-//                  number> _   # L == 0, second and later parameters
-//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers>
-//                  _         # L > 0, first parameter
-//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers>
-//                  <parameter-2 non-negative number> _   # L > 0, second and
-//                  later parameters
+// <function-param> ::= fp <top-level CV-Qualifiers> _                                     # L == 0, first parameter
+//                  ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _   # L == 0, second and later parameters
+//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _         # L > 0, first parameter
+//                  ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _   # L > 0, second and later parameters
 //                  ::= fpT      # 'this' expression (not part of standard?)
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
@@ -4584,9 +4512,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
   return nullptr;
 }
 
-// cv <type> <expression>                               # conversion with one
-// argument cv <type> _ <expression>* E                          # conversion
-// with a different number of arguments
+// cv <type> <expression>                               # conversion with one argument
+// cv <type> _ <expression>* E                          # conversion with a different number of arguments
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
   if (!consumeIf("cv"))
@@ -4618,20 +4545,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
   return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
 }
 
-// <expr-primary> ::= L <type> <value number> E                          #
-// integer literal
-//                ::= L <type> <value float> E                           #
-//                floating literal
-//                ::= L <string type> E                                  #
-//                string literal
-//                ::= L <nullptr type> E                                 #
-//                nullptr literal (i.e., "LDnE")
-//                ::= L <lambda type> E                                  #
-//                lambda expression
-// FIXME:         ::= L <type> <real-part float> _ <imag-part float> E   #
-// complex floating point literal (C 2000)
-//                ::= L <mangled-name> E                                 #
-//                external name
+// <expr-primary> ::= L <type> <value number> E                          # integer literal
+//                ::= L <type> <value float> E                           # floating literal
+//                ::= L <string type> E                                  # string literal
+//                ::= L <nullptr type> E                                 # nullptr literal (i.e., "LDnE")
+//                ::= L <lambda type> E                                  # lambda expression
+// FIXME:         ::= L <type> <real-part float> _ <imag-part float> E   # complex floating point literal (C 2000)
+//                ::= L <mangled-name> E                                 # external name
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
   if (!consumeIf('L'))
@@ -4749,12 +4669,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
 }
 
 // <braced-expression> ::= <expression>
-//                     ::= di <field source-name> <braced-expression>    # .name
-//                     = expr
-//                     ::= dx <index expression> <braced-expression>     #
-//                     [expr] = expr
-//                     ::= dX <range begin expression> <range end expression>
-//                     <braced-expression>
+//                     ::= di <field source-name> <braced-expression>    # .name = expr
+//                     ::= dx <index expression> <braced-expression>     # [expr] = expr
+//                     ::= dX <range begin expression> <range end expression> <braced-expression>
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
   if (look() == 'd') {
@@ -4829,8 +4746,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
   const auto *Op = parseOperatorEncoding();
   if (!Op)
     return nullptr;
-  if (!(Op->getKind() == OperatorInfo::Binary ||
-        (Op->getKind() == OperatorInfo::Member && Op->getName().back() == '*')))
+  if (!(Op->getKind() == OperatorInfo::Binary
+        || (Op->getKind() == OperatorInfo::Member
+            && Op->getName().back() == '*')))
     return nullptr;
 
   Node *Pack = getDerived().parseExpr();
@@ -4869,8 +4787,8 @@ AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
   return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
 }
 
-// <expression> ::= so <referent type> <expr> [<offset number>]
-// <union-selector>* [p] E <union-selector> ::= _ [<number>]
+// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
+// <union-selector> ::= _ [<number>]
 //
 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
 template <typename Derived, typename Alloc>
@@ -4898,12 +4816,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
 
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
-  // We don't track enclosing template parameter levels well enough to reliably
-  // demangle template parameter substitutions, so print an arbitrary
-  // string in place of a parameter for now.
-  // TODO: Track all enclosing template parameters and demangle substitutions.
-  ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(
-    HasIncompleteTemplateParameterTracking, true);
+  // Within this expression, all enclosing template parameter lists are in
+  // scope.
+  ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
   return getDerived().parseExpr();
 }
 
@@ -4970,85 +4885,43 @@ Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {
 
 // <expression> ::= <unary operator-name> <expression>
 //              ::= <binary operator-name> <expression> <expression>
-//              ::= <ternary operator-name> <expression> <expression>
-//              <expression>
+//              ::= <ternary operator-name> <expression> <expression> <expression>
 //              ::= cl <expression>+ E                                   # call
-//              ::= cv <type> <expression>                               #
-//              conversion with one argument
-//              ::= cv <type> _ <expression>* E                          #
-//              conversion with a different number of arguments
-//              ::= [gs] nw <expression>* _ <type> E                     # new
-//              (expr-list) type
-//              ::= [gs] nw <expression>* _ <type> <initializer>         # new
-//              (expr-list) type (init)
-//              ::= [gs] na <expression>* _ <type> E                     # new[]
-//              (expr-list) type
-//              ::= [gs] na <expression>* _ <type> <initializer>         # new[]
-//              (expr-list) type (init)
-//              ::= [gs] dl <expression>                                 #
-//              delete expression
-//              ::= [gs] da <expression>                                 #
-//              delete[] expression
-//              ::= pp_ <expression>                                     #
-//              prefix ++
-//              ::= mm_ <expression>                                     #
-//              prefix --
-//              ::= ti <type>                                            #
-//              typeid (type)
-//              ::= te <expression>                                      #
-//              typeid (expression)
-//              ::= dc <type> <expression>                               #
-//              dynamic_cast<type> (expression)
-//              ::= sc <type> <expression>                               #
-//              static_cast<type> (expression)
-//              ::= cc <type> <expression>                               #
-//              const_cast<type> (expression)
-//              ::= rc <type> <expression>                               #
-//              reinterpret_cast<type> (expression)
-//              ::= st <type>                                            #
-//              sizeof (a type)
-//              ::= sz <expression>                                      #
-//              sizeof (an expression)
-//              ::= at <type>                                            #
-//              alignof (a type)
-//              ::= az <expression>                                      #
-//              alignof (an expression)
-//              ::= nx <expression>                                      #
-//              noexcept (expression)
+//              ::= cv <type> <expression>                               # conversion with one argument
+//              ::= cv <type> _ <expression>* E                          # conversion with a different number of arguments
+//              ::= [gs] nw <expression>* _ <type> E                     # new (expr-list) type
+//              ::= [gs] nw <expression>* _ <type> <initializer>         # new (expr-list) type (init)
+//              ::= [gs] na <expression>* _ <type> E                     # new[] (expr-list) type
+//              ::= [gs] na <expression>* _ <type> <initializer>         # new[] (expr-list) type (init)
+//              ::= [gs] dl <expression>                                 # delete expression
+//              ::= [gs] da <expression>                                 # delete[] expression
+//              ::= pp_ <expression>                                     # prefix ++
+//              ::= mm_ <expression>                                     # prefix --
+//              ::= ti <type>                                            # typeid (type)
+//              ::= te <expression>                                      # typeid (expression)
+//              ::= dc <type> <expression>                               # dynamic_cast<type> (expression)
+//              ::= sc <type> <expression>                               # static_cast<type> (expression)
+//              ::= cc <type> <expression>                               # const_cast<type> (expression)
+//              ::= rc <type> <expression>                               # reinterpret_cast<type> (expression)
+//              ::= st <type>                                            # sizeof (a type)
+//              ::= sz <expression>                                      # sizeof (an expression)
+//              ::= at <type>                                            # alignof (a type)
+//              ::= az <expression>                                      # alignof (an expression)
+//              ::= nx <expression>                                      # noexcept (expression)
 //              ::= <template-param>
 //              ::= <function-param>
-//              ::= dt <expression> <unresolved-name>                    #
-//              expr.name
-//              ::= pt <expression> <unresolved-name>                    #
-//              expr->name
-//              ::= ds <expression> <expression>                         #
-//              expr.*expr
-//              ::= sZ <template-param>                                  # size
-//              of a parameter pack
-//              ::= sZ <function-param>                                  # size
-//              of a function parameter pack
-//              ::= sP <template-arg>* E                                 #
-//              sizeof...(T), size of a captured template parameter pack from an
-//              alias template
-//              ::= sp <expression>                                      # pack
-//              expansion
-//              ::= tw <expression>                                      # throw
-//              expression
-//              ::= tr                                                   # throw
-//              with no operand (rethrow)
-//              ::= <unresolved-name>                                    # f(p),
-//              N::f(p), ::f(p),
-//                                                                       #
-//                                                                       freestanding
-//                                                                       dependent
-//                                                                       name
-//                                                                       (e.g.,
-//                                                                       T::x),
-//                                                                       #
-//                                                                       objectless
-//                                                                       nonstatic
-//                                                                       member
-//                                                                       reference
+//              ::= dt <expression> <unresolved-name>                    # expr.name
+//              ::= pt <expression> <unresolved-name>                    # expr->name
+//              ::= ds <expression> <expression>                         # expr.*expr
+//              ::= sZ <template-param>                                  # size of a parameter pack
+//              ::= sZ <function-param>                                  # size of a function parameter pack
+//              ::= sP <template-arg>* E                                 # sizeof...(T), size of a captured template parameter pack from an alias template
+//              ::= sp <expression>                                      # pack expansion
+//              ::= tw <expression>                                      # throw expression
+//              ::= tr                                                   # throw with no operand (rethrow)
+//              ::= <unresolved-name>                                    # f(p), N::f(p), ::f(p),
+//                                                                       # freestanding dependent name (e.g., T::x),
+//                                                                       # objectless nonstatic member reference
 //              ::= fL <binary-operator-name> <expression> <expression>
 //              ::= fR <binary-operator-name> <expression> <expression>
 //              ::= fl <binary-operator-name> <expression>
@@ -5469,8 +5342,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
       Node *Name = getDerived().parseName();
       if (Name == nullptr)
         return nullptr;
-      return make<SpecialName>("thread-local initialization routine for ",
-                               Name);
+      return make<SpecialName>("thread-local initialization routine for ", Name);
     }
     // T <call-offset> <base encoding>
     default: {
@@ -5620,38 +5492,44 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
                                 NameInfo.ReferenceQualifier);
 }
 
-template <class Float> struct FloatData;
-
-template <> struct FloatData<float> {
-  static const size_t mangled_size = 8;
-  static const size_t max_demangled_size = 24;
-  static constexpr const char *spec = "%af";
+template <class Float>
+struct FloatData;
+
+template <>
+struct FloatData<float>
+{
+    static const size_t mangled_size = 8;
+    static const size_t max_demangled_size = 24;
+    static constexpr const char* spec = "%af";
 };
 
-template <> struct FloatData<double> {
-  static const size_t mangled_size = 16;
-  static const size_t max_demangled_size = 32;
-  static constexpr const char *spec = "%a";
+template <>
+struct FloatData<double>
+{
+    static const size_t mangled_size = 16;
+    static const size_t max_demangled_size = 32;
+    static constexpr const char* spec = "%a";
 };
 
-template <> struct FloatData<long double> {
-#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) ||        \
-    defined(__wasm__) || defined(__riscv) || defined(__loongarch__) ||         \
+template <>
+struct FloatData<long double>
+{
+#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
+    defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
     defined(__ve__)
-  static const size_t mangled_size = 32;
+    static const size_t mangled_size = 32;
 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
-  static const size_t mangled_size = 16;
+    static const size_t mangled_size = 16;
 #else
-  static const size_t mangled_size =
-      20; // May need to be adjusted to 16 or 24 on other platforms
+    static const size_t mangled_size = 20;  // May need to be adjusted to 16 or 24 on other platforms
 #endif
-  // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
-  // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
-  // Negatives are one character longer than positives.
-  // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
-  // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
-  static const size_t max_demangled_size = 42;
-  static constexpr const char *spec = "%LaL";
+    // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
+    // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
+    // Negatives are one character longer than positives.
+    // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
+    // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
+    static const size_t max_demangled_size = 42;
+    static constexpr const char *spec = "%LaL";
 };
 
 template <typename Alloc, typename Derived>
@@ -5673,7 +5551,8 @@ Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
 // <seq-id> ::= <0-9A-Z>+
 template <typename Alloc, typename Derived>
 bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
-  if (!(look() >= '0' && look() <= '9') && !(look() >= 'A' && look() <= 'Z'))
+  if (!(look() >= '0' && look() <= '9') &&
+      !(look() >= 'A' && look() <= 'Z'))
     return true;
 
   size_t Id = 0;
@@ -5797,7 +5676,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
   // substitute them all within a <constraint-expression>, so print the
   // parameter numbering instead for now.
   // TODO: Track all enclosing template parameters and substitute them here.
-  if (HasIncompleteTemplateParameterTracking) {
+  if (InConstraintExpr) {
     return make<NameType>(std::string_view(Begin, First - 1 - Begin));
   }
 
@@ -5835,8 +5714,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
 }
 
 // <template-param-decl> ::= Ty                          # type parameter
-//                       ::= Tk <concept name> [<template-args>] # constrained
-//                       type parameter
+//                       ::= Tk <concept name> [<template-args>] # constrained type parameter
 //                       ::= Tn <type>                   # non-type parameter
 //                       ::= Tt <template-param-decl>* E # template parameter
 //                       ::= Tp <template-param-decl>    # parameter pack
@@ -5999,7 +5877,7 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
       }
       if (Arg->getKind() == Node::KTemplateArgumentPack) {
         TableEntry = make<ParameterPack>(
-            static_cast<TemplateArgumentPack *>(TableEntry)->getElements());
+            static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
         if (!TableEntry)
           return nullptr;
       }

>From 5b379fa5f9d6d062dec7b3f365f5fecac03b058b Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Thu, 5 Sep 2024 11:38:23 +0000
Subject: [PATCH 7/7] [ItaniumDemangle] Set `InConstraintExpr` to `true` when
 demangling a constraint expression. This prevents demangler failures until
 the TODO in the
 [demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
 is fixed.

---
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index e3c28c9bd15b88..c0511cbcec8bad 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -4816,11 +4816,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
 
 template <typename Derived, typename Alloc>
 Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
-  // We don't track enclosing template parameter levels well enough to reliably
-  // demangle template parameter substitutions, so print an arbitrary
-  // string in place of a parameter for now.
-  // TODO: Track all enclosing template parameters and demangle substitutions.
-  ScopedOverride<bool> SaveInConstraintExpr(HasIncompleteTemplateParameterTracking, true);
+  // Within this expression, all enclosing template parameter lists are in
+  // scope.
+  ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(HasIncompleteTemplateParameterTracking, true);
   return getDerived().parseExpr();
 }
 
@@ -5739,6 +5737,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
   }
 
   if (consumeIf("Tk")) {
+    // We don't track enclosing template parameter levels well enough to reliably
+    // demangle template parameter substitutions, so print an arbitrary
+    // string in place of a parameter for now.
+    // TODO: Track all enclosing template parameters and demangle substitutions.
     ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(
       HasIncompleteTemplateParameterTracking, true);
     Node *Constraint = getDerived().parseName();



More information about the libcxx-commits mailing list