[llvm] [MsDemangle] Use LLVM style RTTI for AST nodes (PR #143410)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 09:47:42 PDT 2025


https://github.com/Nerixyz created https://github.com/llvm/llvm-project/pull/143410

The inheritance hierarchy for `llvm::ms_demangle::Node` ([doxygen](https://llvm.org/doxygen/structllvm_1_1ms__demangle_1_1Node.html)) is a bit more involved. One thing that's missing without RTTI is the ability to determine if a node is a symbol, identifier, or type (or one would need to check for every kind).

This PR adds support for `dyn_cast`, `isa`, and friends to `llvm::ms_demangle::Node`. As the type already has a `kind()`, this mainly adds `classof` to the nodes as well as some start and end markers in the `NodeKind` enum.

>From 86c1777eff2123b44b8b23e88559045b75cf9968 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Mon, 9 Jun 2025 18:46:41 +0200
Subject: [PATCH] [MsDemangle] Use LLVM style RTTI for AST nodes

---
 .../llvm/Demangle/MicrosoftDemangleNodes.h    | 175 ++++++++++++++++--
 1 file changed, 156 insertions(+), 19 deletions(-)

diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index d72fb47cd9b04..732aad5623ed2 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -226,35 +226,51 @@ enum class TagKind { Class, Struct, Union, Enum };
 
 enum class NodeKind {
   Unknown,
+
+  SymbolStart,
   Md5Symbol,
-  PrimitiveType,
-  FunctionSignature,
-  Identifier,
-  NamedIdentifier,
-  VcallThunkIdentifier,
-  LocalStaticGuardIdentifier,
-  IntrinsicFunctionIdentifier,
+  EncodedStringLiteral,
+  FunctionSymbol,
+  LocalStaticGuardVariable,
+  SpecialTableSymbol,
+  VariableSymbol,
+  SymbolEnd,
+
+  IdentifierStart,
   ConversionOperatorIdentifier,
   DynamicStructorIdentifier,
-  StructorIdentifier,
+  IntrinsicFunctionIdentifier,
   LiteralOperatorIdentifier,
-  ThunkSignature,
-  PointerType,
-  TagType,
+  LocalStaticGuardIdentifier,
+  NamedIdentifier,
+  RttiBaseClassDescriptor,
+  StructorIdentifier,
+  VcallThunkIdentifier,
+  IdentifierEnd,
+
+  TypeStart,
   ArrayType,
   Custom,
+
+  FunctionSignature,
+  ThunkSignature,
+  FunctionSignatureEnd,
+
   IntrinsicType,
+  PointerType,
+  PrimitiveType,
+  TagType,
+  TypeEnd,
+
+  PointerAuthQualifier,
+
+  IntegerLiteral,
+
   NodeArray,
+
   QualifiedName,
+
   TemplateParameterReference,
-  EncodedStringLiteral,
-  IntegerLiteral,
-  RttiBaseClassDescriptor,
-  LocalStaticGuardVariable,
-  FunctionSymbol,
-  VariableSymbol,
-  SpecialTableSymbol,
-  PointerAuthQualifier,
 };
 
 struct Node {
@@ -309,6 +325,10 @@ struct TypeNode : public Node {
     outputPost(OB, Flags);
   }
 
+  static bool classof(const Node *N) {
+    return N->kind() >= NodeKind::TypeStart && N->kind() <= NodeKind::TypeEnd;
+  }
+
   Qualifiers Quals = Q_None;
 };
 
@@ -319,6 +339,10 @@ struct PrimitiveTypeNode : public TypeNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override {}
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::PrimitiveType;
+  }
+
   PrimitiveKind PrimKind;
 };
 
@@ -329,6 +353,11 @@ struct FunctionSignatureNode : public TypeNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() >= NodeKind::FunctionSignature &&
+           N->kind() <= NodeKind::FunctionSignatureEnd;
+  }
+
   // Valid if this FunctionTypeNode is the Pointee of a PointerType or
   // MemberPointerType.
   PointerAffinity Affinity = PointerAffinity::None;
@@ -357,6 +386,11 @@ struct FunctionSignatureNode : public TypeNode {
 struct IdentifierNode : public Node {
   explicit IdentifierNode(NodeKind K) : Node(K) {}
 
+  static bool classof(const Node *N) {
+    return N->kind() >= NodeKind::IdentifierStart &&
+           N->kind() <= NodeKind::IdentifierEnd;
+  }
+
   NodeArrayNode *TemplateParams = nullptr;
 
 protected:
@@ -368,6 +402,10 @@ struct VcallThunkIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::VcallThunkIdentifier;
+  }
+
   uint64_t OffsetInVTable = 0;
 };
 
@@ -377,6 +415,10 @@ struct DynamicStructorIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::DynamicStructorIdentifier;
+  }
+
   VariableSymbolNode *Variable = nullptr;
   QualifiedNameNode *Name = nullptr;
   bool IsDestructor = false;
@@ -387,6 +429,10 @@ struct NamedIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::NamedIdentifier;
+  }
+
   std::string_view Name;
 };
 
@@ -397,6 +443,10 @@ struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::IntrinsicFunctionIdentifier;
+  }
+
   IntrinsicFunctionKind Operator;
 };
 
@@ -406,6 +456,10 @@ struct LiteralOperatorIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::LiteralOperatorIdentifier;
+  }
+
   std::string_view Name;
 };
 
@@ -415,6 +469,10 @@ struct LocalStaticGuardIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::LocalStaticGuardIdentifier;
+  }
+
   bool IsThread = false;
   uint32_t ScopeIndex = 0;
 };
@@ -425,6 +483,10 @@ struct ConversionOperatorIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::ConversionOperatorIdentifier;
+  }
+
   // The type that this operator converts too.
   TypeNode *TargetType = nullptr;
 };
@@ -437,6 +499,10 @@ struct StructorIdentifierNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::StructorIdentifier;
+  }
+
   // The name of the class that this is a structor of.
   IdentifierNode *Class = nullptr;
   bool IsDestructor = false;
@@ -448,6 +514,10 @@ struct ThunkSignatureNode : public FunctionSignatureNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::ThunkSignature;
+  }
+
   struct ThisAdjustor {
     uint32_t StaticOffset = 0;
     int32_t VBPtrOffset = 0;
@@ -463,6 +533,10 @@ struct PointerTypeNode : public TypeNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::PointerType;
+  }
+
   // Is this a pointer, reference, or rvalue-reference?
   PointerAffinity Affinity = PointerAffinity::None;
 
@@ -482,6 +556,8 @@ struct TagTypeNode : public TypeNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) { return N->kind() == NodeKind::TagType; }
+
   QualifiedNameNode *QualifiedName = nullptr;
   TagKind Tag;
 };
@@ -495,6 +571,10 @@ struct ArrayTypeNode : public TypeNode {
   void outputDimensionsImpl(OutputBuffer &OB, OutputFlags Flags) const;
   void outputOneDimension(OutputBuffer &OB, OutputFlags Flags, Node *N) const;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::ArrayType;
+  }
+
   // A list of array dimensions.  e.g. [3,4,5] in `int Foo[3][4][5]`
   NodeArrayNode *Dimensions = nullptr;
 
@@ -505,6 +585,10 @@ struct ArrayTypeNode : public TypeNode {
 struct IntrinsicNode : public TypeNode {
   IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
   void output(OutputBuffer &OB, OutputFlags Flags) const override {}
+
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::IntrinsicType;
+  }
 };
 
 struct CustomTypeNode : public TypeNode {
@@ -513,6 +597,8 @@ struct CustomTypeNode : public TypeNode {
   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) { return N->kind() == NodeKind::Custom; }
+
   IdentifierNode *Identifier = nullptr;
 };
 
@@ -524,6 +610,10 @@ struct NodeArrayNode : public Node {
   void output(OutputBuffer &OB, OutputFlags Flags,
               std::string_view Separator) const;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::NodeArray;
+  }
+
   Node **Nodes = nullptr;
   size_t Count = 0;
 };
@@ -533,6 +623,10 @@ struct QualifiedNameNode : public Node {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::QualifiedName;
+  }
+
   NodeArrayNode *Components = nullptr;
 
   IdentifierNode *getUnqualifiedIdentifier() {
@@ -547,6 +641,10 @@ struct TemplateParameterReferenceNode : public Node {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::TemplateParameterReference;
+  }
+
   SymbolNode *Symbol = nullptr;
 
   int ThunkOffsetCount = 0;
@@ -562,6 +660,10 @@ struct IntegerLiteralNode : public Node {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::IntegerLiteral;
+  }
+
   uint64_t Value = 0;
   bool IsNegative = false;
 };
@@ -572,6 +674,10 @@ struct RttiBaseClassDescriptorNode : public IdentifierNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::RttiBaseClassDescriptor;
+  }
+
   uint32_t NVOffset = 0;
   int32_t VBPtrOffset = 0;
   uint32_t VBTableOffset = 0;
@@ -581,6 +687,12 @@ struct RttiBaseClassDescriptorNode : public IdentifierNode {
 struct SymbolNode : public Node {
   explicit SymbolNode(NodeKind K) : Node(K) {}
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
+
+  static bool classof(const Node *N) {
+    return N->kind() >= NodeKind::SymbolStart &&
+           N->kind() <= NodeKind::SymbolEnd;
+  }
+
   QualifiedNameNode *Name = nullptr;
 };
 
@@ -589,6 +701,11 @@ struct SpecialTableSymbolNode : public SymbolNode {
       : SymbolNode(NodeKind::SpecialTableSymbol) {}
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
+
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::SpecialTableSymbol;
+  }
+
   QualifiedNameNode *TargetName = nullptr;
   Qualifiers Quals = Qualifiers::Q_None;
 };
@@ -599,6 +716,10 @@ struct LocalStaticGuardVariableNode : public SymbolNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::LocalStaticGuardVariable;
+  }
+
   bool IsVisible = false;
 };
 
@@ -607,6 +728,10 @@ struct EncodedStringLiteralNode : public SymbolNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::EncodedStringLiteral;
+  }
+
   std::string_view DecodedString;
   bool IsTruncated = false;
   CharKind Char = CharKind::Char;
@@ -617,6 +742,10 @@ struct VariableSymbolNode : public SymbolNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::VariableSymbol;
+  }
+
   StorageClass SC = StorageClass::None;
   TypeNode *Type = nullptr;
 };
@@ -626,6 +755,10 @@ struct FunctionSymbolNode : public SymbolNode {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::FunctionSymbol;
+  }
+
   FunctionSignatureNode *Signature = nullptr;
 };
 
@@ -641,6 +774,10 @@ struct PointerAuthQualifierNode : public Node {
 
   void output(OutputBuffer &OB, OutputFlags Flags) const override;
 
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::PointerAuthQualifier;
+  }
+
   // List of arguments.
   NodeArrayNode *Components = nullptr;
 };



More information about the llvm-commits mailing list