[llvm] [llvm] [Demangle] Fix MSVC demangling for placeholder return types (PR #106178)

Max Winkler via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 26 22:45:09 PDT 2024


https://github.com/MaxEW707 updated https://github.com/llvm/llvm-project/pull/106178

>From f7d7506efe4210cf286d7ddada98a908c553d670 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Sun, 25 Aug 2024 10:40:16 -0700
Subject: [PATCH] Fix mangling for placeholder return types

---
 .../include/llvm/Demangle/MicrosoftDemangle.h |  1 +
 .../llvm/Demangle/MicrosoftDemangleNodes.h    | 19 ++++++++++++++-
 llvm/lib/Demangle/MicrosoftDemangle.cpp       | 24 +++++++++++++++++++
 llvm/lib/Demangle/MicrosoftDemangleNodes.cpp  |  8 +++++++
 .../Demangle/ms-placeholder-return-type.test  | 18 ++++++++++++++
 5 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Demangle/ms-placeholder-return-type.test

diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangle.h b/llvm/include/llvm/Demangle/MicrosoftDemangle.h
index 6891185a28e57f..2e6a750e3abef9 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangle.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangle.h
@@ -173,6 +173,7 @@ class Demangler {
   TypeNode *demangleType(std::string_view &MangledName,
                          QualifierMangleMode QMM);
   PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName);
+  PlaceholderTypeNode *demanglePlaceholderType(std::string_view &MangledName);
   CustomTypeNode *demangleCustomType(std::string_view &MangledName);
   TagTypeNode *demangleClassType(std::string_view &MangledName);
   PointerTypeNode *demanglePointerType(std::string_view &MangledName);
diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index 30ca43d2bde020..18d6cdb7554934 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -106,6 +106,11 @@ enum class PrimitiveKind {
   Nullptr,
 };
 
+enum class PlaceholderKind {
+  Auto,
+  DecltypeAuto,
+};
+
 enum class CharKind {
   Char,
   Char16,
@@ -251,7 +256,8 @@ enum class NodeKind {
   LocalStaticGuardVariable,
   FunctionSymbol,
   VariableSymbol,
-  SpecialTableSymbol
+  SpecialTableSymbol,
+  PlaceholderType,
 };
 
 struct Node {
@@ -270,6 +276,7 @@ struct Node {
 
 struct TypeNode;
 struct PrimitiveTypeNode;
+struct PlaceholderTypeNode;
 struct FunctionSignatureNode;
 struct IdentifierNode;
 struct NamedIdentifierNode;
@@ -318,6 +325,16 @@ struct PrimitiveTypeNode : public TypeNode {
   PrimitiveKind PrimKind;
 };
 
+struct PlaceholderTypeNode : public TypeNode {
+  explicit PlaceholderTypeNode(PlaceholderKind K)
+      : TypeNode(NodeKind::PlaceholderType), PlaceholderKind(K) {}
+
+  void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
+  void outputPost(OutputBuffer &OB, OutputFlags Flags) const override {}
+
+  PlaceholderKind PlaceholderKind;
+};
+
 struct FunctionSignatureNode : public TypeNode {
   explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
   FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index c5835e8c2e989d..4f2ff5735b569a 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -241,6 +241,11 @@ static bool isFunctionType(std::string_view S) {
          llvm::itanium_demangle::starts_with(S, "$$A6");
 }
 
+static bool isPlaceholderType(std::string_view S) {
+  return llvm::itanium_demangle::starts_with(S, "_P") ||
+         llvm::itanium_demangle::starts_with(S, "_T");
+}
+
 static FunctionRefQualifier
 demangleFunctionRefQualifier(std::string_view &MangledName) {
   if (consumeFront(MangledName, 'G'))
@@ -1865,6 +1870,8 @@ TypeNode *Demangler::demangleType(std::string_view &MangledName,
     }
   } else if (isCustomType(MangledName)) {
     Ty = demangleCustomType(MangledName);
+  } else if (isPlaceholderType(MangledName)) {
+    Ty = demanglePlaceholderType(MangledName);
   } else {
     Ty = demanglePrimitiveType(MangledName);
   }
@@ -1978,6 +1985,23 @@ CustomTypeNode *Demangler::demangleCustomType(std::string_view &MangledName) {
   return CTN;
 }
 
+PlaceholderTypeNode *
+Demangler::demanglePlaceholderType(std::string_view &MangledName) {
+  assert(MangledName.front() == '_');
+
+  MangledName.remove_prefix(1);
+  const char F = MangledName.front();
+  MangledName.remove_prefix(1);
+  switch (F) {
+  case 'P':
+    return Arena.alloc<PlaceholderTypeNode>(PlaceholderKind::Auto);
+  case 'T':
+    return Arena.alloc<PlaceholderTypeNode>(PlaceholderKind::DecltypeAuto);
+  }
+  Error = true;
+  return nullptr;
+}
+
 // Reads a primitive type.
 PrimitiveTypeNode *
 Demangler::demanglePrimitiveType(std::string_view &MangledName) {
diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
index 9a9c34ec6d348c..25c64d75450202 100644
--- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
@@ -153,6 +153,14 @@ void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
   outputQualifiers(OB, Quals, true, false);
 }
 
+void PlaceholderTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
+  switch (PlaceholderKind) {
+    OUTPUT_ENUM_CLASS_VALUE(PlaceholderKind, Auto, "auto");
+    OUTPUT_ENUM_CLASS_VALUE(PlaceholderKind, DecltypeAuto, "decltype(auto)");
+  };
+  outputQualifiers(OB, Quals, true, false);
+}
+
 void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
   output(OB, Flags, ", ");
 }
diff --git a/llvm/test/Demangle/ms-placeholder-return-type.test b/llvm/test/Demangle/ms-placeholder-return-type.test
new file mode 100644
index 00000000000000..18038e636c8d5a
--- /dev/null
+++ b/llvm/test/Demangle/ms-placeholder-return-type.test
@@ -0,0 +1,18 @@
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+?TestNonTemplateAuto@@YA at XZ
+; CHECK: __cdecl TestNonTemplateAuto(void)
+
+??$AutoT at X@@YA?A_PXZ
+; CHECK: auto __cdecl AutoT<void>(void)
+
+??$AutoT at X@@YA?B_PXZ
+; CHECK: auto const __cdecl AutoT<void>(void)
+
+??$AutoT at X@@YA?A_TXZ
+; CHECK: decltype(auto) __cdecl AutoT<void>(void)
+
+??$AutoT at X@@YA?B_TXZ
+; CHECK: decltype(auto) const __cdecl AutoT<void>(void)



More information about the llvm-commits mailing list