Index: include/llvm/Demangle/Demangle.h =================================================================== --- include/llvm/Demangle/Demangle.h +++ include/llvm/Demangle/Demangle.h @@ -63,6 +63,9 @@ /// the function is a non-static member function. bool hasFunctionQualifiers() const; + /// If this symbol describes a constructor or destructor. + bool isCtorOrDtor() const; + /// If this symbol describes a function. bool isFunction() const; Index: lib/Demangle/ItaniumDemangle.cpp =================================================================== --- lib/Demangle/ItaniumDemangle.cpp +++ lib/Demangle/ItaniumDemangle.cpp @@ -935,12 +935,11 @@ } }; -class QualifiedName final : public Node { +struct QualifiedName final : Node { // qualifier::name - const Node *Qualifier; - const Node *Name; + Node *Qualifier; + Node *Name; -public: QualifiedName(Node* Qualifier_, Node* Name_) : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {} @@ -5264,6 +5263,37 @@ return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone; } +bool ItaniumPartialDemangler::isCtorOrDtor() const { + Node* N = static_cast(RootNode); + // ctors and dtors are eligible in LLD --icf=safe, it is fine if some are not + // recognized as ctor or dtor (false negatives). + while (N) { + switch (N->getKind()) { + default: + return false; + case Node::KCtorDtorName: + case Node::KDtorName: + return true; + case Node::KFunctionEncoding: + N = static_cast(N)->getName(); + break; + case Node::KLocalName: + N = static_cast(N)->Entity; + break; + case Node::KNameWithTemplateArgs: + N = static_cast(N)->Name; + break; + case Node::KNestedName: + N = static_cast(N)->Name; + break; + case Node::KQualifiedName: + N = static_cast(N)->Name; + break; + } + } + return false; +} + bool ItaniumPartialDemangler::isFunction() const { assert(RootNode != nullptr && "must call partialDemangle()"); return static_cast(RootNode)->getKind() == Node::KFunctionEncoding; Index: unittests/Demangle/PartialDemangleTest.cpp =================================================================== --- unittests/Demangle/PartialDemangleTest.cpp +++ unittests/Demangle/PartialDemangleTest.cpp @@ -109,6 +109,29 @@ EXPECT_TRUE(Demangler.isData()); } +TEST(PartialDemanglerTest, TestCtorOrDtor) { + static const char* Pos[] = { + "_ZN1AC1Ev", // A::A() + "_ZN1AC1IiEET_", // A::A(int) + "_ZN1AD2Ev", // A::~A() + "_ZN1BIiEC1IcEET_" // B::B(char) + }; + static const char* Neg[] = { + "_Z1fv", + "_ZN1A1gIiEEvT_", // void A::g(int) + }; + + llvm::ItaniumPartialDemangler D; + for (const char* N : Pos) { + EXPECT_FALSE(D.partialDemangle(N)); + EXPECT_TRUE(D.isCtorOrDtor()); + } + for (const char* N : Neg) { + EXPECT_FALSE(D.partialDemangle(N)); + EXPECT_FALSE(D.isCtorOrDtor()); + } +} + TEST(PartialDemanglerTest, TestMisc) { llvm::ItaniumPartialDemangler D1, D2;