[llvm] [libcxxabi] [libcxxabi][ItaniumDemangle] Demangle explicitly named object parameters (PR #72881)

Michael Buch via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 24 14:36:06 PST 2023


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/72881

>From d9243de8658011c20db84dd091d7d76a8751ad06 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Sat, 18 Nov 2023 12:54:38 +0000
Subject: [PATCH 1/5] [libcxxabi][ItaniumDemangle] Demangle explicitly named
 object parameters

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 30 +++++++++++++++++-------
 libcxxabi/test/test_demangle.pass.cpp    | 10 ++++++++
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 2336b84da293bcc..f9a0c059e86e8bd 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -2780,6 +2780,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
     Qualifiers CVQualifiers = QualNone;
     FunctionRefQual ReferenceQualifier = FrefQualNone;
     size_t ForwardTemplateRefsBegin;
+    bool HasExplicitObjectParameter = false;
 
     NameState(AbstractManglingParser *Enclosing)
         : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
@@ -3438,15 +3439,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
   if (!consumeIf('N'))
     return nullptr;
 
-  Qualifiers CVTmp = parseCVQualifiers();
-  if (State) State->CVQualifiers = CVTmp;
+  // 'H' specifies that the encoding that follows
+  // has an explicit object parameter.
+  if (!consumeIf('H')) {
+    Qualifiers CVTmp = parseCVQualifiers();
+    if (State)
+      State->CVQualifiers = CVTmp;
 
-  if (consumeIf('O')) {
-    if (State) State->ReferenceQualifier = FrefQualRValue;
-  } else if (consumeIf('R')) {
-    if (State) State->ReferenceQualifier = FrefQualLValue;
-  } else {
-    if (State) State->ReferenceQualifier = FrefQualNone;
+    if (consumeIf('O')) {
+      if (State)
+        State->ReferenceQualifier = FrefQualRValue;
+    } else if (consumeIf('R')) {
+      if (State)
+        State->ReferenceQualifier = FrefQualLValue;
+    } else {
+      if (State)
+        State->ReferenceQualifier = FrefQualNone;
+    }
+  } else if (State) {
+    State->HasExplicitObjectParameter = true;
   }
 
   Node *SoFar = nullptr;
@@ -5424,6 +5435,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
         return nullptr;
       Names.push_back(Ty);
     } while (!IsEndOfEncoding() && look() != 'Q');
+    // Ignore the explicit 'this' parameter.
+    if (NameInfo.HasExplicitObjectParameter)
+      ++ParamsBegin;
     Params = popTrailingNodeArray(ParamsBegin);
   }
 
diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp
index 77741a952850ab9..a6b6d45a3783bb1 100644
--- a/libcxxabi/test/test_demangle.pass.cpp
+++ b/libcxxabi/test/test_demangle.pass.cpp
@@ -30174,6 +30174,16 @@ const char* cases[][2] =
     {"_Z2f5IKiEvu14__remove_constIT_E", "void f5<int const>(__remove_const(int const))"},
     {"_Z2f5IPiEvu16__remove_pointerIT_E", "void f5<int*>(__remove_pointer(int*))"},
     {"_Z2f5IiEvu14__remove_cvrefIT_E", "void f5<int>(__remove_cvref(int))"},
+
+    // C++23 explicit object parameter
+    {"_ZNH3Foo3fooES_i", "Foo::foo(int)"},
+    {"_ZNH3Foo3fooERKS_i", "Foo::foo(int)"},
+    {"_ZNH1X3fooIRS_EEvOT_i", "void X::foo<X&>(int)"},
+    {"_ZZNH2ns3Foo3fooES0_iENH4Foo24foo2EOKS1_", "ns::Foo::foo(int)::Foo2::foo2()" },
+    {"_ZNH2ns3FooB7Foo_tag3fooB7foo_tagERKS0_i", "ns::Foo[abi:Foo_tag]::foo[abi:foo_tag](int)" },
+    {"_ZZN3Foo3fooEiENH4Foo24foo2EOKS0_", "Foo::foo(int)::Foo2::foo2()"},
+    {"_ZZNH3Foo3fooES_iENK4Foo24foo2Ev", "Foo::foo(int)::Foo2::foo2() const" },
+    {"_ZNH3FooclERKS_", "Foo::operator()()"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);

>From b728f87399c15c08d1bd1e338a695a3ab3fe3344 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 24 Nov 2023 12:47:01 +0000
Subject: [PATCH 2/5] fixup! print the explicit parameter

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 32 +++++++++++++++++++++---
 libcxxabi/src/demangle/ItaniumNodes.def  |  1 +
 libcxxabi/test/test_demangle.pass.cpp    | 16 ++++++------
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index f9a0c059e86e8bd..57dda9b42106a56 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -890,6 +890,27 @@ class DynamicExceptionSpec : public Node {
   }
 };
 
+/// Represents the explicitly named object parameter.
+/// E.g.,
+/// \code{.cpp}
+///   struct Foo {
+///     void bar(this Foo && self);
+///   };
+/// \endcode
+class ExplicitObjectParameter final : public Node {
+  Node *Base;
+
+public:
+  ExplicitObjectParameter(Node *Base_)
+      : Node(KExplicitObjectParameter, Cache::Yes), Base(Base_) {}
+
+  template <typename Fn> void match(Fn F) const { F(Base); }
+
+  void printLeft(OutputBuffer &OB) const override { OB += "this "; }
+
+  void printRight(OutputBuffer &OB) const override { Base->print(OB); }
+};
+
 class FunctionEncoding final : public Node {
   const Node *Ret;
   const Node *Name;
@@ -5433,11 +5454,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
       Node *Ty = getDerived().parseType();
       if (Ty == nullptr)
         return nullptr;
+
+      const bool IsFirstParam = (Names.size() - ParamsBegin) == 0;
+      if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
+        Ty = make<ExplicitObjectParameter>(Ty);
+
+      if (Ty == nullptr)
+        return nullptr;
+
       Names.push_back(Ty);
     } while (!IsEndOfEncoding() && look() != 'Q');
-    // Ignore the explicit 'this' parameter.
-    if (NameInfo.HasExplicitObjectParameter)
-      ++ParamsBegin;
     Params = popTrailingNodeArray(ParamsBegin);
   }
 
diff --git a/libcxxabi/src/demangle/ItaniumNodes.def b/libcxxabi/src/demangle/ItaniumNodes.def
index e27c111de3389c5..18f5d52b47e9113 100644
--- a/libcxxabi/src/demangle/ItaniumNodes.def
+++ b/libcxxabi/src/demangle/ItaniumNodes.def
@@ -99,5 +99,6 @@ NODE(RequiresExpr)
 NODE(ExprRequirement)
 NODE(TypeRequirement)
 NODE(NestedRequirement)
+NODE(ExplicitObjectParameter)
 
 #undef NODE
diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp
index a6b6d45a3783bb1..bf5473ee7eb8a2f 100644
--- a/libcxxabi/test/test_demangle.pass.cpp
+++ b/libcxxabi/test/test_demangle.pass.cpp
@@ -30176,14 +30176,14 @@ const char* cases[][2] =
     {"_Z2f5IiEvu14__remove_cvrefIT_E", "void f5<int>(__remove_cvref(int))"},
 
     // C++23 explicit object parameter
-    {"_ZNH3Foo3fooES_i", "Foo::foo(int)"},
-    {"_ZNH3Foo3fooERKS_i", "Foo::foo(int)"},
-    {"_ZNH1X3fooIRS_EEvOT_i", "void X::foo<X&>(int)"},
-    {"_ZZNH2ns3Foo3fooES0_iENH4Foo24foo2EOKS1_", "ns::Foo::foo(int)::Foo2::foo2()" },
-    {"_ZNH2ns3FooB7Foo_tag3fooB7foo_tagERKS0_i", "ns::Foo[abi:Foo_tag]::foo[abi:foo_tag](int)" },
-    {"_ZZN3Foo3fooEiENH4Foo24foo2EOKS0_", "Foo::foo(int)::Foo2::foo2()"},
-    {"_ZZNH3Foo3fooES_iENK4Foo24foo2Ev", "Foo::foo(int)::Foo2::foo2() const" },
-    {"_ZNH3FooclERKS_", "Foo::operator()()"},
+    {"_ZNH3Foo3fooES_i", "Foo::foo(this Foo, int)"},
+    {"_ZNH3Foo3fooERKS_i", "Foo::foo(this Foo const&, int)"},
+    {"_ZNH1X3fooIRS_EEvOT_i", "void X::foo<X&>(this X&, int)"},
+    {"_ZZNH2ns3Foo3fooES0_iENH4Foo24foo2EOKS1_", "ns::Foo::foo(this ns::Foo, int)::Foo2::foo2(this Foo2 const&&)" },
+    {"_ZNH2ns3FooB7Foo_tag3fooB7foo_tagERKS0_i", "ns::Foo[abi:Foo_tag]::foo[abi:foo_tag](this ns::Foo[abi:Foo_tag] const&, int)" },
+    {"_ZZN3Foo3fooEiENH4Foo24foo2EOKS0_", "Foo::foo(int)::Foo2::foo2(this Foo2 const&&)"},
+    {"_ZZNH3Foo3fooES_iENK4Foo24foo2Ev", "Foo::foo(this Foo, int)::Foo2::foo2() const" },
+    {"_ZNH3FooclERKS_", "Foo::operator()(this Foo const&)"},
 };
 
 const unsigned N = sizeof(cases) / sizeof(cases[0]);

>From 9b1dde91ff6cbadc8f9645709f493f38ff5f6d1f Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 24 Nov 2023 13:03:59 +0000
Subject: [PATCH 3/5] fixup! assert nullness in ExplicitObjectParamter
 constructor

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 57dda9b42106a56..4874fdfeb67398c 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -902,7 +902,9 @@ class ExplicitObjectParameter final : public Node {
 
 public:
   ExplicitObjectParameter(Node *Base_)
-      : Node(KExplicitObjectParameter, Cache::Yes), Base(Base_) {}
+      : Node(KExplicitObjectParameter, Cache::Yes), Base(Base_) {
+    assert(Base != nullptr);
+  }
 
   template <typename Fn> void match(Fn F) const { F(Base); }
 

>From 6122d54236563dbfad68ffe15ad275a323e7732e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 24 Nov 2023 22:32:21 +0000
Subject: [PATCH 4/5] fixup! remove redundant printRight; simplify IsFirstParam
 check

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

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 4874fdfeb67398c..e7d668291b56bb2 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -902,13 +902,16 @@ class ExplicitObjectParameter final : public Node {
 
 public:
   ExplicitObjectParameter(Node *Base_)
-      : Node(KExplicitObjectParameter, Cache::Yes), Base(Base_) {
+      : Node(KExplicitObjectParameter), Base(Base_) {
     assert(Base != nullptr);
   }
 
   template <typename Fn> void match(Fn F) const { F(Base); }
 
-  void printLeft(OutputBuffer &OB) const override { OB += "this "; }
+  void printLeft(OutputBuffer &OB) const override {
+    OB += "this ";
+    Base->print(OB);
+  }
 
   void printRight(OutputBuffer &OB) const override { Base->print(OB); }
 };
@@ -5457,7 +5460,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
       if (Ty == nullptr)
         return nullptr;
 
-      const bool IsFirstParam = (Names.size() - ParamsBegin) == 0;
+      const bool IsFirstParam = ParamsBegin == Names.size();
       if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
         Ty = make<ExplicitObjectParameter>(Ty);
 

>From 59b24f45d66d6888e945c4531f886beae0cc7424 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 24 Nov 2023 22:34:40 +0000
Subject: [PATCH 5/5] fixup! sync libcxxabi into llvm

---
 llvm/include/llvm/Demangle/ItaniumDemangle.h | 62 +++++++++++++++++---
 llvm/include/llvm/Demangle/ItaniumNodes.def  |  1 +
 2 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index f68c37258ce0992..59aed240b7e24ed 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -19,6 +19,7 @@
 #include "DemangleConfig.h"
 #include "StringViewExtras.h"
 #include "Utility.h"
+#include <__cxxabi_config.h>
 #include <algorithm>
 #include <cassert>
 #include <cctype>
@@ -889,6 +890,32 @@ class DynamicExceptionSpec : public Node {
   }
 };
 
+/// Represents the explicitly named object parameter.
+/// E.g.,
+/// \code{.cpp}
+///   struct Foo {
+///     void bar(this Foo && self);
+///   };
+/// \endcode
+class ExplicitObjectParameter final : public Node {
+  Node *Base;
+
+public:
+  ExplicitObjectParameter(Node *Base_)
+      : Node(KExplicitObjectParameter), Base(Base_) {
+    assert(Base != nullptr);
+  }
+
+  template <typename Fn> void match(Fn F) const { F(Base); }
+
+  void printLeft(OutputBuffer &OB) const override {
+    OB += "this ";
+    Base->print(OB);
+  }
+
+  void printRight(OutputBuffer &OB) const override { Base->print(OB); }
+};
+
 class FunctionEncoding final : public Node {
   const Node *Ret;
   const Node *Name;
@@ -2779,6 +2806,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
     Qualifiers CVQualifiers = QualNone;
     FunctionRefQual ReferenceQualifier = FrefQualNone;
     size_t ForwardTemplateRefsBegin;
+    bool HasExplicitObjectParameter = false;
 
     NameState(AbstractManglingParser *Enclosing)
         : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
@@ -3437,15 +3465,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
   if (!consumeIf('N'))
     return nullptr;
 
-  Qualifiers CVTmp = parseCVQualifiers();
-  if (State) State->CVQualifiers = CVTmp;
+  // 'H' specifies that the encoding that follows
+  // has an explicit object parameter.
+  if (!consumeIf('H')) {
+    Qualifiers CVTmp = parseCVQualifiers();
+    if (State)
+      State->CVQualifiers = CVTmp;
 
-  if (consumeIf('O')) {
-    if (State) State->ReferenceQualifier = FrefQualRValue;
-  } else if (consumeIf('R')) {
-    if (State) State->ReferenceQualifier = FrefQualLValue;
-  } else {
-    if (State) State->ReferenceQualifier = FrefQualNone;
+    if (consumeIf('O')) {
+      if (State)
+        State->ReferenceQualifier = FrefQualRValue;
+    } else if (consumeIf('R')) {
+      if (State)
+        State->ReferenceQualifier = FrefQualLValue;
+    } else {
+      if (State)
+        State->ReferenceQualifier = FrefQualNone;
+    }
+  } else if (State) {
+    State->HasExplicitObjectParameter = true;
   }
 
   Node *SoFar = nullptr;
@@ -5421,6 +5459,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
       Node *Ty = getDerived().parseType();
       if (Ty == nullptr)
         return nullptr;
+
+      const bool IsFirstParam = ParamsBegin == Names.size();
+      if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
+        Ty = make<ExplicitObjectParameter>(Ty);
+
+      if (Ty == nullptr)
+        return nullptr;
+
       Names.push_back(Ty);
     } while (!IsEndOfEncoding() && look() != 'Q');
     Params = popTrailingNodeArray(ParamsBegin);
diff --git a/llvm/include/llvm/Demangle/ItaniumNodes.def b/llvm/include/llvm/Demangle/ItaniumNodes.def
index 30a93eccaee37e9..330552663ee658d 100644
--- a/llvm/include/llvm/Demangle/ItaniumNodes.def
+++ b/llvm/include/llvm/Demangle/ItaniumNodes.def
@@ -99,5 +99,6 @@ NODE(RequiresExpr)
 NODE(ExprRequirement)
 NODE(TypeRequirement)
 NODE(NestedRequirement)
+NODE(ExplicitObjectParameter)
 
 #undef NODE



More information about the llvm-commits mailing list