diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h --- a/llvm/include/llvm/Demangle/Demangle.h +++ b/llvm/include/llvm/Demangle/Demangle.h @@ -67,7 +67,8 @@ /// demangling occurred. std::string demangle(std::string_view MangledName); -bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result); +bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result, + bool CanHaveLeadingDot = true); /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain diff --git a/llvm/lib/Demangle/Demangle.cpp b/llvm/lib/Demangle/Demangle.cpp --- a/llvm/lib/Demangle/Demangle.cpp +++ b/llvm/lib/Demangle/Demangle.cpp @@ -24,7 +24,8 @@ return Result; if (starts_with(MangledName, '_') && - nonMicrosoftDemangle(MangledName.substr(1), Result)) + nonMicrosoftDemangle(MangledName.substr(1), Result, + /*CanHaveLeadingDot=*/false)) return Result; if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) { @@ -46,8 +47,15 @@ static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); } bool llvm::nonMicrosoftDemangle(std::string_view MangledName, - std::string &Result) { + std::string &Result, bool CanHaveLeadingDot) { char *Demangled = nullptr; + + // Do not consider the dot prefix as part of the demangled symbol name. + if (CanHaveLeadingDot && MangledName.size() > 0 && MangledName[0] == '.') { + MangledName.remove_prefix(1); + Result = "."; + } + if (isItaniumEncoding(MangledName)) Demangled = itaniumDemangle(MangledName); else if (isRustEncoding(MangledName)) @@ -58,7 +66,7 @@ if (!Demangled) return false; - Result = Demangled; + Result += Demangled; std::free(Demangled); return true; } diff --git a/llvm/test/tools/llvm-cxxfilt/delimiters.test b/llvm/test/tools/llvm-cxxfilt/delimiters.test --- a/llvm/test/tools/llvm-cxxfilt/delimiters.test +++ b/llvm/test/tools/llvm-cxxfilt/delimiters.test @@ -32,7 +32,7 @@ COM: Piping the echo output causes '⦙' to be converted to '?' in some COM: builds/environments. Redirect echo output to and from %t to work COM: around this. See D111072. -RUN: '_Z3Foo$ ._Z3Foo' > %t +RUN: '_Z3Foo$ Foo._Z3Bar' > %t RUN: llvm-cxxfilt -n < %t | FileCheck %s CHECK: ,,Foo! @@ -66,4 +66,4 @@ CHECK: Foo~,, CHECK: Foo⦙Bar CHECK: Foo,,Bar::Baz Foo,Bar:Baz -CHECK: _Z3Foo$ ._Z3Foo +CHECK: _Z3Foo$ Foo._Z3Bar diff --git a/llvm/test/tools/llvm-cxxfilt/dot-prefix.test b/llvm/test/tools/llvm-cxxfilt/dot-prefix.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-cxxfilt/dot-prefix.test @@ -0,0 +1,4 @@ +## Show that the llvm-cxxfilt does not consider the dot prefix to be part of the symbol name to be demangled. +RUN: llvm-cxxfilt -n ._ZL5func0v | FileCheck %s + +CHECK: .func0() diff --git a/llvm/test/tools/llvm-cxxfilt/strip-underscore.test b/llvm/test/tools/llvm-cxxfilt/strip-underscore.test --- a/llvm/test/tools/llvm-cxxfilt/strip-underscore.test +++ b/llvm/test/tools/llvm-cxxfilt/strip-underscore.test @@ -1,15 +1,17 @@ ## Show the behaviour of --[no-]strip-underscore. This test does not test ## the platform-specific default behaviour. This is tested elsewhere. -RUN: llvm-cxxfilt -_ __ZN2ns1fE _ZSt1f _f | FileCheck %s -check-prefix CHECK-STRIPPED -RUN: llvm-cxxfilt --strip-underscore __ZN2ns1fE _ZSt1f _f | FileCheck %s -check-prefix CHECK-STRIPPED -RUN: llvm-cxxfilt -n __ZN2ns1fE _ZSt1f _f | FileCheck %s -check-prefix CHECK-UNSTRIPPED -RUN: llvm-cxxfilt --no-strip-underscore __ZN2ns1fE _ZSt1f _f | FileCheck %s -check-prefix CHECK-UNSTRIPPED +RUN: llvm-cxxfilt -_ __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED +RUN: llvm-cxxfilt --strip-underscore __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED +RUN: llvm-cxxfilt -n __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED +RUN: llvm-cxxfilt --no-strip-underscore __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED CHECK-STRIPPED: ns::f CHECK-STRIPPED: _ZSt1f CHECK-STRIPPED: _f +CHECK-STRIPPED: ._Z3f.0v CHECK-UNSTRIPPED: __ZN2ns1fE CHECK-UNSTRIPPED: std::f CHECK-UNSTRIPPED: _f +CHECK-UNSTRIPPED: _._Z3f.0v diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -67,12 +67,14 @@ static std::string demangle(const std::string &Mangled) { using llvm::itanium_demangle::starts_with; std::string_view DecoratedStr = Mangled; - if (StripUnderscore) - if (DecoratedStr[0] == '_') - DecoratedStr.remove_prefix(1); + bool CanHaveLeadingDot = true; + if (StripUnderscore && DecoratedStr[0] == '_') { + DecoratedStr.remove_prefix(1); + CanHaveLeadingDot = false; + } std::string Result; - if (nonMicrosoftDemangle(DecoratedStr, Result)) + if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot)) return Result; std::string Prefix;