Skip to content

[llvm-cxxfilt] Added the option --no-params #75348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions libcxxabi/src/demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -2794,7 +2794,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseClassEnumType();
Node *parseQualifiedType();

Node *parseEncoding();
Node *parseEncoding(bool ParseParams = true);
bool parseCallOffset();
Node *parseSpecialName();

Expand Down Expand Up @@ -2911,7 +2911,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseDestructorName();

/// Top-level entry point into the parser.
Node *parse();
Node *parse(bool ParseParams = true);
};

const char* parse_discriminator(const char* first, const char* last);
Expand Down Expand Up @@ -5405,7 +5405,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
// ::= <data name>
// ::= <special-name>
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
// The template parameters of an encoding are unrelated to those of the
// enclosing context.
SaveTemplateParams SaveTemplateParamsScope(this);
Expand All @@ -5431,6 +5431,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
if (IsEndOfEncoding())
return Name;

// ParseParams may be false at the top level only, when called from parse().
// For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
// false when demangling 3fooILZ3BarEET_f but is always true when demangling
// 3Bar.
if (!ParseParams) {
while (consume())
;
return Name;
}

Node *Attrs = nullptr;
if (consumeIf("Ua9enable_ifI")) {
size_t BeforeArgs = Names.size();
Expand Down Expand Up @@ -5895,9 +5905,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parse() {
Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
if (consumeIf("_Z") || consumeIf("__Z")) {
Node *Encoding = getDerived().parseEncoding();
Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr)
return nullptr;
if (look() == '.') {
Expand All @@ -5911,7 +5921,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
}

if (consumeIf("___Z") || consumeIf("____Z")) {
Node *Encoding = getDerived().parseEncoding();
Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
bool RequireNumber = consumeIf('_');
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/CommandGuide/llvm-cxxfilt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ OPTIONS

Print a summary of command line options.

.. option:: --no-params, -p

Do not demangle function parameters or return types.

.. option:: --no-strip-underscore, -n

Do not strip a leading underscore. This is the default for all platforms
Expand Down
5 changes: 3 additions & 2 deletions llvm/include/llvm/Demangle/Demangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum : int {
/// Returns a non-NULL pointer to a NUL-terminated C style string
/// that should be explicitly freed, if successful. Otherwise, may return
/// nullptr if mangled_name is not a valid mangling or is nullptr.
char *itaniumDemangle(std::string_view mangled_name);
char *itaniumDemangle(std::string_view mangled_name, bool ParseParams = true);

enum MSDemangleFlags {
MSDF_None = 0,
Expand Down Expand Up @@ -68,7 +68,8 @@ char *dlangDemangle(std::string_view MangledName);
std::string demangle(std::string_view MangledName);

bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result,
bool CanHaveLeadingDot = true);
bool CanHaveLeadingDot = true,
bool ParseParams = true);

/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain
Expand Down
22 changes: 16 additions & 6 deletions llvm/include/llvm/Demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -2793,7 +2793,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseClassEnumType();
Node *parseQualifiedType();

Node *parseEncoding();
Node *parseEncoding(bool ParseParams = true);
bool parseCallOffset();
Node *parseSpecialName();

Expand Down Expand Up @@ -2910,7 +2910,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseDestructorName();

/// Top-level entry point into the parser.
Node *parse();
Node *parse(bool ParseParams = true);
};

const char* parse_discriminator(const char* first, const char* last);
Expand Down Expand Up @@ -5404,7 +5404,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
// ::= <data name>
// ::= <special-name>
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
// The template parameters of an encoding are unrelated to those of the
// enclosing context.
SaveTemplateParams SaveTemplateParamsScope(this);
Expand All @@ -5430,6 +5430,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
if (IsEndOfEncoding())
return Name;

// ParseParams may be false at the top level only, when called from parse().
// For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
// false when demangling 3fooILZ3BarEET_f but is always true when demangling
// 3Bar.
if (!ParseParams) {
while (consume())
;
return Name;
}

Node *Attrs = nullptr;
if (consumeIf("Ua9enable_ifI")) {
size_t BeforeArgs = Names.size();
Expand Down Expand Up @@ -5894,9 +5904,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parse() {
Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
if (consumeIf("_Z") || consumeIf("__Z")) {
Node *Encoding = getDerived().parseEncoding();
Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr)
return nullptr;
if (look() == '.') {
Expand All @@ -5910,7 +5920,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
}

if (consumeIf("___Z") || consumeIf("____Z")) {
Node *Encoding = getDerived().parseEncoding();
Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
bool RequireNumber = consumeIf('_');
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Demangle/Demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); }
static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); }

bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
std::string &Result, bool CanHaveLeadingDot) {
std::string &Result, bool CanHaveLeadingDot,
bool ParseParams) {
char *Demangled = nullptr;

// Do not consider the dot prefix as part of the demangled symbol name.
Expand All @@ -57,7 +58,7 @@ bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
}

if (isItaniumEncoding(MangledName))
Demangled = itaniumDemangle(MangledName);
Demangled = itaniumDemangle(MangledName, ParseParams);
else if (isRustEncoding(MangledName))
Demangled = rustDemangle(MangledName);
else if (isDLangEncoding(MangledName))
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Demangle/ItaniumDemangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,13 +366,13 @@ class DefaultAllocator {

using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;

char *llvm::itaniumDemangle(std::string_view MangledName) {
char *llvm::itaniumDemangle(std::string_view MangledName, bool ParseParams) {
if (MangledName.empty())
return nullptr;

Demangler Parser(MangledName.data(),
MangledName.data() + MangledName.length());
Node *AST = Parser.parse();
Node *AST = Parser.parse(ParseParams);
if (!AST)
return nullptr;

Expand Down
34 changes: 34 additions & 0 deletions llvm/test/tools/llvm-cxxfilt/no-params.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
RUN: llvm-cxxfilt _Z3fooILZ3BarEET_f _Z3fooIPFcfEET_d _ZN1f2baC2ERKNS_2baIT_EE _Z3foov.123 | FileCheck %s --check-prefix=CHECK-PARAMS
RUN: llvm-cxxfilt -p _Z3fooILZ3BarEET_f _Z3fooIPFcfEET_d _ZN1f2baC2ERKNS_2baIT_EE _Z3foov.123 | FileCheck %s --check-prefix=CHECK-NO-PARAMS --match-full-lines
RUN: llvm-cxxfilt --no-params _Z3fooILZ3BarEET_f _Z3fooIPFcfEET_d _ZN1f2baC2ERKNS_2baIT_EE _Z3foov.123 | FileCheck %s --check-prefix=CHECK-NO-PARAMS --match-full-lines

# Check that -p or --no-params flag omits function parameters and the return
# type.

CHECK-PARAMS: Bar foo<Bar>(float)
CHECK-NO-PARAMS: foo<Bar>

# Check that only the top-level function is impacted by the switch, and that
# nested function types in the encoding (e.g. where a function type is being
# used as a template parameter) still include their parameters.
#
# template <typename T> T foo(double);
# typedef char (*F)(float);
# F foo<F>(double)

CHECK-PARAMS: char (*foo<char (*)(float)>(double))(float)
CHECK-NO-PARAMS: foo<char (*)(float)>

# Use an invalid mangled name broken in the function parameters to check how -p
# or --no-params flag works. If the option is given we should be able to
# demangle the function name just fine. If it is not given, demangling will fail
# because of the invalid params.

CHECK-PARAMS: _ZN1f2baC2ERKNS_2baIT_EE
CHECK-NO-PARAMS: f::ba::ba

# Check that a vendor specific suffix is also omitted when --no-params is
# specified. This matches c++filt's behaviour.

CHECK-PARAMS: foo() (.123)
CHECK-NO-PARAMS: foo
2 changes: 2 additions & 0 deletions llvm/tools/llvm-cxxfilt/Opts.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ multiclass Eq<string name, string help> {
def help : FF<"help", "Display this help">;
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">;
def version : FF<"version", "Display the version">;

defm : Eq<"format", "Specify mangling format. Currently ignored because only 'gnu' is supported">;
Expand All @@ -25,4 +26,5 @@ def : F<"s", "Alias for --format">;
def : F<"_", "Alias for --strip-underscore">, Alias<strip_underscore>;
def : F<"h", "Alias for --help">, Alias<help>;
def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
def : F<"p", "Alias for --no-params">, Alias<no_params>;
def : F<"t", "Alias for --types">, Alias<types>;
10 changes: 7 additions & 3 deletions llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class CxxfiltOptTable : public opt::GenericOptTable {
};
} // namespace

static bool ParseParams;
static bool StripUnderscore;
static bool Types;

Expand All @@ -74,18 +75,19 @@ static std::string demangle(const std::string &Mangled) {
}

std::string Result;
if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot))
if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot,
ParseParams))
return Result;

std::string Prefix;
char *Undecorated = nullptr;

if (Types)
Undecorated = itaniumDemangle(DecoratedStr);
Undecorated = itaniumDemangle(DecoratedStr, ParseParams);

if (!Undecorated && starts_with(DecoratedStr, "__imp_")) {
Prefix = "import thunk for ";
Undecorated = itaniumDemangle(DecoratedStr.substr(6));
Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams);
}

Result = Undecorated ? Prefix + Undecorated : Mangled;
Expand Down Expand Up @@ -173,6 +175,8 @@ int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
else
StripUnderscore = Triple(sys::getProcessTriple()).isOSBinFormatMachO();

ParseParams = !Args.hasArg(OPT_no_params);

Types = Args.hasArg(OPT_types);

std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);
Expand Down