Index: libcxxabi/src/cxa_demangle.cpp =================================================================== --- libcxxabi/src/cxa_demangle.cpp +++ libcxxabi/src/cxa_demangle.cpp @@ -1976,6 +1976,9 @@ // conversion operator's type, and are resolved in the enclosing . PODSmallVector ForwardTemplateRefs; + void (*TypeCallback)(void *, const char *) = nullptr; + void *TypeCallbackContext = nullptr; + bool TryToParseTemplateArgs = true; bool PermitForwardTemplateReferences = false; bool ParsingLambdaParams = false; @@ -3218,6 +3221,9 @@ Node *Db::parseType() { Node *Result = nullptr; + if (TypeCallback != nullptr) + TypeCallback(TypeCallbackContext, First); + switch (look()) { // ::= case 'r': Index: llvm/include/llvm/Demangle/Demangle.h =================================================================== --- llvm/include/llvm/Demangle/Demangle.h +++ llvm/include/llvm/Demangle/Demangle.h @@ -31,6 +31,12 @@ char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status); +/// Calls the callback \c Callback with \c Ctx as an argument whenever a type is +/// encountered. Returns true if \c MangledName couldn't be parsed. +bool itaniumFindTypesInMangledName(const char *MangledName, void *Ctx, + void (*Callback)(void *, const char *)); + + enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, int *status, MSDemangleFlags Flags = MSDF_None); Index: llvm/lib/Demangle/ItaniumDemangle.cpp =================================================================== --- llvm/lib/Demangle/ItaniumDemangle.cpp +++ llvm/lib/Demangle/ItaniumDemangle.cpp @@ -1965,6 +1965,9 @@ // conversion operator's type, and are resolved in the enclosing . PODSmallVector ForwardTemplateRefs; + void (*TypeCallback)(void *, const char *) = nullptr; + void *TypeCallbackContext = nullptr; + bool TryToParseTemplateArgs = true; bool PermitForwardTemplateReferences = false; bool ParsingLambdaParams = false; @@ -3207,6 +3210,9 @@ Node *Db::parseType() { Node *Result = nullptr; + if (TypeCallback != nullptr) + TypeCallback(TypeCallbackContext, First); + switch (look()) { // ::= case 'r': @@ -4986,6 +4992,15 @@ return InternalStatus == demangle_success ? Buf : nullptr; } +bool llvm::itaniumFindTypesInMangledName(const char *MangledName, void *Ctx, + void (*Callback)(void *, + const char *)) { + Db Parser(MangledName, MangledName + std::strlen(MangledName)); + Parser.TypeCallback = Callback; + Parser.TypeCallbackContext = Ctx; + return Parser.parse() == nullptr; +} + namespace llvm { ItaniumPartialDemangler::ItaniumPartialDemangler() @@ -5206,5 +5221,4 @@ bool ItaniumPartialDemangler::isData() const { return !isFunction() && !isSpecialName(); } - } Index: llvm/unittests/Demangle/CMakeLists.txt =================================================================== --- llvm/unittests/Demangle/CMakeLists.txt +++ llvm/unittests/Demangle/CMakeLists.txt @@ -4,4 +4,5 @@ add_llvm_unittest(DemangleTests PartialDemangleTest.cpp + FindTypesInMangledNameTest.cpp ) Index: llvm/unittests/Demangle/FindTypesInMangledNameTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/Demangle/FindTypesInMangledNameTest.cpp @@ -0,0 +1,34 @@ +//===------------------ FindTypesInMangledNameTest.cpp --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include "llvm/Demangle/Demangle.h" +#include "gtest/gtest.h" + +TEST(FindTypesInMangledNameTest, Test) { + std::vector Types; + const char *Mangled = "_Z1fiv"; + EXPECT_FALSE(llvm::itaniumFindTypesInMangledName( + Mangled, static_cast(&Types), +[](void *Ty, const char *P) { + static_cast *>(Ty)->push_back(P); + })); + EXPECT_EQ(Types.size(), size_t(2)); + EXPECT_EQ(Mangled + 4, Types.front()); + EXPECT_EQ(Mangled + 5, Types.back()); + + EXPECT_TRUE(llvm::itaniumFindTypesInMangledName( + "Not a mangled name!", nullptr, +[](void *, const char *) {})); + + int TC = 0; + EXPECT_FALSE(llvm::itaniumFindTypesInMangledName( + "_Z1fPRiv", static_cast(&TC), + +[](void *Ctx, const char *) { ++*static_cast(Ctx); })); + EXPECT_EQ(TC, 4); // pointer, reference, int, void. +} Index: llvm/unittests/Demangle/PartialDemangleTest.cpp =================================================================== --- llvm/unittests/Demangle/PartialDemangleTest.cpp +++ llvm/unittests/Demangle/PartialDemangleTest.cpp @@ -58,7 +58,7 @@ "mfn", "void", "(int, char, float, unsigned int, char, double)"}, }; -TEST(PartialDemangleTest, TestNameChopping) { +TEST(PartialDemanglerTest, TestNameChopping) { size_t Size = 1; char *Buf = static_cast(std::malloc(Size)); @@ -86,7 +86,7 @@ std::free(Buf); } -TEST(PartialDemangleTest, TestNameMeta) { +TEST(PartialDemanglerTest, TestNameMeta) { llvm::ItaniumPartialDemangler Demangler; EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv"));