Index: llvm/trunk/include/llvm/Demangle/Demangle.h =================================================================== --- llvm/trunk/include/llvm/Demangle/Demangle.h +++ llvm/trunk/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: llvm/trunk/lib/Demangle/ItaniumDemangle.cpp =================================================================== --- llvm/trunk/lib/Demangle/ItaniumDemangle.cpp +++ llvm/trunk/lib/Demangle/ItaniumDemangle.cpp @@ -5264,6 +5264,38 @@ return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone; } +bool ItaniumPartialDemangler::isCtorOrDtor() const { + Node *N = static_cast(RootNode); + while (N) { + switch (N->getKind()) { + default: + return false; + case Node::KCtorDtorName: + return true; + + case Node::KAbiTagAttr: + N = static_cast(N)->Base; + break; + 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::KStdQualifiedName: + N = static_cast(N)->Child; + break; + } + } + return false; +} + bool ItaniumPartialDemangler::isFunction() const { assert(RootNode != nullptr && "must call partialDemangle()"); return static_cast(RootNode)->getKind() == Node::KFunctionEncoding; Index: llvm/trunk/unittests/Demangle/PartialDemangleTest.cpp =================================================================== --- llvm/trunk/unittests/Demangle/PartialDemangleTest.cpp +++ llvm/trunk/unittests/Demangle/PartialDemangleTest.cpp @@ -109,6 +109,32 @@ 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) + "_ZN1AC1B1TEv", // A::A[abi:T]() + "_ZNSt1AD2Ev", // std::A::~A() + "_ZN2ns1AD1Ev", // ns::A::~A() + }; + 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;