Skip to content

Commit 0b554dd

Browse files
authored
[llvm-cxxfilt][macOS] Don't strip underscores on macOS by default (#106233)
Currently, `llvm-cxxfilt` will strip the leading underscore of its input on macOS. Historically MachO symbols were prefixed with an extra underscore and this is why this default exists. However, nowadays, the `ItaniumDemangler` supports all of the following mangling prefixes: `_Z`, `__Z`, `___Z`, `____Z`. So really `llvm-cxxfilt` can simply forward the mangled name to the demangler and let the library decide whether it's a valid encoding. Compiling C++ on macOS nowadays will generate symbols with `_Z` and `___Z` prefixes. So users trying to demangle these symbols will have to know that they need to add the `-n` prefix. This routinely catches people off-guard. This patch removes the `-n` default for macOS and allows calling into the `ItaniumDemangler` with all the `_Z` prefixes that the demangler supports (1-4 underscores). rdar://132714940
1 parent 3dbb6be commit 0b554dd

File tree

6 files changed

+22
-33
lines changed

6 files changed

+22
-33
lines changed

llvm/lib/Demangle/Demangle.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ std::string llvm::demangle(std::string_view MangledName) {
3838
}
3939

4040
static bool isItaniumEncoding(std::string_view S) {
41-
// Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'.
42-
return starts_with(S, "_Z") || starts_with(S, "___Z");
41+
// Itanium demangler supports prefixes with 1-4 underscores.
42+
const size_t Pos = S.find_first_not_of('_');
43+
return Pos > 0 && Pos <= 4 && S[Pos] == 'Z';
4344
}
4445

4546
static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); }
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
RUN: llvm-cxxfilt -n _Z1fi __Z1fi f ___ZSt1ff_block_invoke | FileCheck %s
1+
RUN: llvm-cxxfilt -n _Z1fi __Z1fi _____Z1fi f ___ZSt1ff_block_invoke ____ZSt1ff_block_invoke | FileCheck %s
22

33
CHECK: f(int)
4-
CHECK-NEXT: __Z1fi
4+
CHECK-NEXT: f(int)
5+
CHECK-NEXT: _____Z1fi
56
CHECK-NEXT: f
67
CHECK-NEXT: invocation function for block in std::f(float)
8+
CHECK-NEXT: invocation function for block in std::f(float)

llvm/test/tools/llvm-cxxfilt/strip-underscore-default-darwin.test

Lines changed: 0 additions & 7 deletions
This file was deleted.

llvm/test/tools/llvm-cxxfilt/strip-underscore-default.test

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1-
## Show the behaviour of --[no-]strip-underscore. This test does not test
2-
## the platform-specific default behaviour. This is tested elsewhere.
1+
## Show the behaviour of --[no-]strip-underscore.
32

4-
RUN: llvm-cxxfilt -_ __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED
5-
RUN: llvm-cxxfilt --strip-underscore __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED
6-
RUN: llvm-cxxfilt -n __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED
7-
RUN: llvm-cxxfilt --no-strip-underscore __ZN2ns1fE _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED
3+
RUN: llvm-cxxfilt -_ ___ZN2ns1fE _____Z1fi_block_invoke _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED
4+
RUN: llvm-cxxfilt --strip-underscore __ZN2ns1fE _____Z1fi_block_invoke _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-STRIPPED
5+
RUN: llvm-cxxfilt -n ___ZN2ns1fE _____Z1fi_block_invoke _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED
6+
RUN: llvm-cxxfilt --no-strip-underscore ___ZN2ns1fE _____Z1fi_block_invoke _ZSt1f _f _._Z3f.0v | FileCheck %s -check-prefix CHECK-UNSTRIPPED
7+
RUN: llvm-cxxfilt -n -_ _ZSt1f | FileCheck %s -check-prefix OVERRIDE-STRIPPED
8+
RUN: llvm-cxxfilt -_ -n _ZSt1f | FileCheck %s -check-prefix OVERRIDE-UNSTRIPPED
89

910
CHECK-STRIPPED: ns::f
11+
CHECK-STRIPPED: invocation function for block in f(int)
1012
CHECK-STRIPPED: _ZSt1f
1113
CHECK-STRIPPED: _f
1214
CHECK-STRIPPED: ._Z3f.0v
1315

14-
CHECK-UNSTRIPPED: __ZN2ns1fE
16+
CHECK-UNSTRIPPED: ___ZN2ns1fE
17+
CHECK-UNSTRIPPED: _____Z1fi_block_invoke
1518
CHECK-UNSTRIPPED: std::f
1619
CHECK-UNSTRIPPED: _f
1720
CHECK-UNSTRIPPED: _._Z3f.0v
21+
22+
OVERRIDE-STRIPPED: _ZSt1f
23+
OVERRIDE-UNSTRIPPED: std::f

llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,8 @@ int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
165165
return 0;
166166
}
167167

168-
// The default value depends on the default triple. Mach-O has symbols
169-
// prefixed with "_", so strip by default.
170-
if (opt::Arg *A =
171-
Args.getLastArg(OPT_strip_underscore, OPT_no_strip_underscore))
172-
StripUnderscore = A->getOption().matches(OPT_strip_underscore);
173-
else
174-
StripUnderscore = Triple(sys::getProcessTriple()).isOSBinFormatMachO();
168+
StripUnderscore =
169+
Args.hasFlag(OPT_strip_underscore, OPT_no_strip_underscore, false);
175170

176171
ParseParams = !Args.hasArg(OPT_no_params);
177172

0 commit comments

Comments
 (0)