diff --git a/llvm/docs/CommandGuide/llvm-cxxfilt.rst b/llvm/docs/CommandGuide/llvm-cxxfilt.rst index 0933f0b5bed87..6743e361d752a 100644 --- a/llvm/docs/CommandGuide/llvm-cxxfilt.rst +++ b/llvm/docs/CommandGuide/llvm-cxxfilt.rst @@ -57,6 +57,11 @@ OPTIONS Do not strip a leading underscore. This is the default for all platforms except Mach-O based hosts. +.. option:: --quote + + Add `"` `"` around demangled function symbols. Do not quote already quoted + symbols. + .. option:: --strip-underscore, -_ Strip a single leading underscore, if present, from each input name before diff --git a/llvm/test/tools/llvm-cxxfilt/quote.test b/llvm/test/tools/llvm-cxxfilt/quote.test new file mode 100644 index 0000000000000..15ced1f6935b8 --- /dev/null +++ b/llvm/test/tools/llvm-cxxfilt/quote.test @@ -0,0 +1,26 @@ +// Show that llvm-cxxfilt --quote adds quotes around demangled symbols, unless +// the symbol is already quoted. + +RUN: split-file %s %t + +RUN: llvm-cxxfilt --quote < %t/symbols-in-file.test | FileCheck --match-full-lines --check-prefix=CHECK-FILE %s +CHECK-FILE: "bar()" "bar()" +CHECK-FILE-NEXT: "bar()" "bar()" +CHECK-FILE: log() +CHECK-FILE: "import thunk for std::future" + +// Check it works with CLI symbols too. Since a quoted mangled name is not a +// mangled name, it should be unchanged. +RUN: llvm-cxxfilt --quote _Z3firv '"_Z3barv"' 'saw()' | FileCheck --match-full-lines --check-prefix=CHECK-CLI %s +CHECK-CLI: "fir()" +CHECK-CLI-NEXT: "_Z3barv" +CHECK-CLI-NEXT: saw() + +//--- symbols-in-file.test +_Z3barv "_Z3barv" +"_Z3barv" _Z3barv +// This is not mangled, thus it should not be quoted. +log() +// Check that an "import thunk for" prefix can be quoted along the demangled +// name. +__imp__ZSt6futureIvE diff --git a/llvm/tools/llvm-cxxfilt/Opts.td b/llvm/tools/llvm-cxxfilt/Opts.td index 034cb267aab80..a40bc75354a13 100644 --- a/llvm/tools/llvm-cxxfilt/Opts.td +++ b/llvm/tools/llvm-cxxfilt/Opts.td @@ -15,6 +15,7 @@ multiclass Eq { } def help : FF<"help", "Display this help">; +def quote : FF<"quote", "Quote demangled function names with \" \" if not already quoted">; defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">; def types : FF<"types", "Attempt to demangle types as well as function names">; def no_params : FF<"no-params", "Skip function parameters and return types">; diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index f90adb6cacb99..41b379e8fd396 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -54,6 +54,7 @@ class CxxfiltOptTable : public opt::GenericOptTable { } // namespace static bool ParseParams; +static bool Quote; static bool StripUnderscore; static bool Types; @@ -64,7 +65,15 @@ static void error(const Twine &Message) { exit(1); } -static std::string demangle(const std::string &Mangled) { +// Quote Undecorated with "" if asked for and not already followed by a '"'. +static std::string optionalQuote(const std::string &Undecorated, + StringRef Delimiters) { + if (Quote && (Delimiters.empty() || Delimiters[0] != '"')) + return '"' + Undecorated + '"'; + return Undecorated; +} + +static std::string demangle(const std::string &Mangled, StringRef Delimiters) { using llvm::itanium_demangle::starts_with; std::string_view DecoratedStr = Mangled; bool CanHaveLeadingDot = true; @@ -76,7 +85,7 @@ static std::string demangle(const std::string &Mangled) { std::string Result; if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot, ParseParams)) - return Result; + return optionalQuote(Result, Delimiters); std::string Prefix; char *Undecorated = nullptr; @@ -89,7 +98,8 @@ static std::string demangle(const std::string &Mangled) { Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams); } - Result = Undecorated ? Prefix + Undecorated : Mangled; + Result = + Undecorated ? optionalQuote(Prefix + Undecorated, Delimiters) : Mangled; free(Undecorated); return Result; } @@ -137,9 +147,10 @@ static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) { SmallVector, 16> Words; SplitStringDelims(Mangled, Words, IsLegalItaniumChar); for (const auto &Word : Words) - Result += ::demangle(std::string(Word.first)) + Word.second.str(); + Result += + ::demangle(std::string(Word.first), Word.second) + Word.second.str(); } else - Result = ::demangle(std::string(Mangled)); + Result = ::demangle(std::string(Mangled), ""); OS << Result << '\n'; OS.flush(); } @@ -170,6 +181,8 @@ int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) { ParseParams = !Args.hasArg(OPT_no_params); + Quote = Args.hasArg(OPT_quote); + Types = Args.hasArg(OPT_types); std::vector Decorated = Args.getAllArgValues(OPT_INPUT);