Skip to content

Commit ce058ad

Browse files
committed
Handle cv qualifiers on function pointers and handle unnamed types
1 parent 66cd10a commit ce058ad

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

src/prune_symbol.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,11 @@ namespace detail {
413413
| operator
414414
| name
415415
| lambda
416+
| unnamed
416417
417418
function-pointer := "(" pointer-refs-junk symbol ")"
418419
419-
pointer-refs-junk := { function-pointer-modifier } { pointer-refs }
420+
pointer-refs-junk := { function-pointer-modifier } { pointer-refs } { ignored-identifier }
420421
421422
anonymous-namespace := "(anonymous namespace)" | "`anonymous namespace'"
422423
@@ -445,6 +446,9 @@ namespace detail {
445446
| LITERAL // 'lambda*' or `symbol'
446447
| "<" IDENTIFIER ">" // lambda_*
447448
449+
unnamed := "{" "unnamed" "#" LITERAL "}"
450+
| LITERAL // 'unnamed*'
451+
448452
balanced-punctuation := "(" balanced-punctuation-innards ")"
449453
| "[" balanced-punctuation-innards "]"
450454
| "<" balanced-punctuation-innards ">"
@@ -695,17 +699,30 @@ namespace detail {
695699
return did_consume;
696700
}
697701

698-
NODISCARD Result<bool, parse_error> accept_lambda() {
702+
NODISCARD Result<bool, parse_error> accept_lambda_or_unnamed() {
699703
// LLVM does main::'lambda'<...>(...)::operator()<...>(...) -- apparently this can be 'lambda<count>'
700704
// GCC does main::{lambda<...>(...)#1}::operator()<...>(...)
701705
// MSVC does `int main(void)'::`2'::<lambda_1>::operator()<...>(...)
702706
// https://github.com/llvm/llvm-project/blob/90beda2aba3cac34052827c560449fcb184c7313/libcxxabi/src/demangle/ItaniumDemangle.h#L1848-L1850 TODO: What about the count?
703707
// https://github.com/gcc-mirror/gcc/blob/b76f1fb7bf8a7b66b8acd469309257f8b18c0c51/libiberty/cp-demangle.c#L6210-L6251 TODO: What special characters can appear?
704708
TRY_TOK(opening_brace, tokenizer.accept({token_type::punctuation, "{"}));
705709
if(opening_brace) {
710+
optional<token> token1;
711+
optional<token> token2;
706712
TRY_TOK(lambda_token, tokenizer.accept({token_type::identifier, "lambda"}));
707-
if(!lambda_token) {
708-
return parse_error{};
713+
if(lambda_token) {
714+
token1 = lambda_token;
715+
} else {
716+
TRY_TOK(unnamed_token, tokenizer.accept({token_type::identifier, "unnamed"}));
717+
if(!unnamed_token) {
718+
return parse_error{};
719+
}
720+
TRY_TOK(type_token, tokenizer.accept({token_type::identifier, "type"}));
721+
if(!type_token) {
722+
return parse_error{};
723+
}
724+
token1 = unnamed_token;
725+
token2 = type_token;
709726
}
710727
TRY_PARSE(consume_punctuation(), (void)0);
711728
TRY_TOK(hash_token, tokenizer.accept({token_type::punctuation, "#"}));
@@ -721,7 +738,10 @@ namespace detail {
721738
return parse_error{};
722739
}
723740
append_output({token_type::punctuation, "<"});
724-
append_output(lambda_token.unwrap());
741+
append_output(token1.unwrap());
742+
if(token2) {
743+
append_output(token2.unwrap());
744+
}
725745
append_output(hash_token.unwrap());
726746
append_output(discriminator_token.unwrap());
727747
append_output({token_type::punctuation, ">"});
@@ -731,7 +751,10 @@ namespace detail {
731751
if(
732752
maybe_literal_token
733753
&& maybe_literal_token.unwrap().type == token_type::literal
734-
&& maybe_literal_token.unwrap().str.starts_with("'lambda")
754+
&& (
755+
maybe_literal_token.unwrap().str.starts_with("'lambda")
756+
|| maybe_literal_token.unwrap().str.starts_with("'unnamed")
757+
)
735758
&& maybe_literal_token.unwrap().str.ends_with("'")
736759
) {
737760
tokenizer.advance();
@@ -822,7 +845,10 @@ namespace detail {
822845
} else if(
823846
next
824847
&& next.unwrap().type == token_type::identifier
825-
&& is_microsoft_calling_convention(next.unwrap().str)
848+
&& (
849+
is_microsoft_calling_convention(next.unwrap().str)
850+
|| is_ignored_identifier(next.unwrap().str)
851+
)
826852
) {
827853
tokenizer.advance();
828854
} else {
@@ -851,7 +877,7 @@ namespace detail {
851877
TRY_PARSE(accept_anonymous_namespace(), return true);
852878
TRY_PARSE(accept_operator(), return true);
853879
TRY_PARSE(accept_identifier_token(), return true);
854-
TRY_PARSE(accept_lambda(), return true);
880+
TRY_PARSE(accept_lambda_or_unnamed(), return true);
855881
return false;
856882
}
857883

test/unit/lib/prune_symbol.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,12 @@ TEST(PruneSymbolTests, FunctionPointers) {
412412
DO_TEST("void (__cdecl&baz<int>(void))(int,double)", "baz");
413413
}
414414

415+
TEST(PruneSymbolTests, UnnamedTypes) {
416+
// https://godbolt.org/z/jx8GnrW4v
417+
DO_TEST("main::'unnamed'::foo()", "main::<unnamed>::foo");
418+
DO_TEST("main::{unnamed type#1}::foo()", "main::<unnamed type#1>::foo");
419+
}
420+
415421
TEST(PruneSymbolTests, TemplateHeavySymbols) {
416422
// https://godbolt.org/z/z1nrMsYfs
417423
DO_TEST("__find_if<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, __gnu_cxx::__ops::_Iter_pred<main()::<lambda(auto:19)> > >", "__find_if");
@@ -481,4 +487,13 @@ TEST(PruneSymbolTests, Extra) {
481487
DO_TEST("void foo<std::basic_string<char>>(std::basic_string<char> const&)", "foo");
482488
}
483489

490+
TEST(PruneSymbolTests, RegressionTests) {
491+
// Symbols I've observed not pruning correctly
492+
DO_TEST("void (* const&std::_Any_data::_M_access<void (*)(cpptrace::v1::log_level, char const*)>() const)(cpptrace::v1::log_level, char const*)", "std::_Any_data::_M_access");
493+
DO_TEST("void (* const*std::__addressof<void (* const)(cpptrace::v1::log_level, char const*)>(void (* const&)(cpptrace::v1::log_level, char const*)))(cpptrace::v1::log_level, char const*)", "std::__addressof");
494+
DO_TEST("void (* const&std::forward<void (* const&)(cpptrace::v1::log_level, char const*)>(std::remove_reference<void (* const&)(cpptrace::v1::log_level, char const*)>::type&))(cpptrace::v1::log_level, char const*)", "std::forward");
495+
DO_TEST("fmt::v10::detail::parse_format_specs<char>(char const*, char const*, fmt::v10::detail::dynamic_format_specs<char>&, fmt::v10::basic_format_parse_context<char>&, fmt::v10::detail::type)::{unnamed type#1}::operator()(fmt::v10::detail::state, bool)", "fmt::v10::detail::parse_format_specs::<unnamed type#1>::operator()");
496+
DO_TEST("fmt::v10::detail::parse_format_specs<char>(char const*, char const*, fmt::v10::detail::dynamic_format_specs<char>&, fmt::v10::basic_format_parse_context<char>&, fmt::v10::detail::type)::{unnamed type#2}::operator()(fmt::v10::presentation_type, int)", "fmt::v10::detail::parse_format_specs::<unnamed type#2>::operator()");
497+
}
498+
484499
}

0 commit comments

Comments
 (0)