diff options
author | Dino Radakovic <dinor@google.com> | 2024-02-13 20:56:28 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-02-13 20:57:21 -0800 |
commit | c14dfbf9c1759c39bf4343b9e54a43975fbba930 (patch) | |
tree | 0400df4eba10f37251c1df5413ca2a7c464c1736 | |
parent | 0a362eb290044fa39f6c6a120e4627ff9998e55b (diff) |
`demangle`: Parse optional single template argument for built-in types
The optional single template argument for built-in types is not documented in LLVM's comments that list the grammar, but it is [intentionally implemented](https://github.com/llvm/llvm-project/commit/4bc4d51c18d5c087dfbdad1753c84bba8dbf3be0).
PiperOrigin-RevId: 606843797
Change-Id: Ib5ef1983812e9ea68a39fe64b87b6ad6ce81b93c
-rw-r--r-- | absl/debugging/internal/demangle.cc | 19 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 32 |
2 files changed, 45 insertions, 6 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 3859e44f..1143ba9e 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -1297,32 +1297,39 @@ static bool ParseCVQualifiers(State *state) { } // <builtin-type> ::= v, etc. # single-character builtin types -// ::= u <source-name> +// ::= u <source-name> [I <type> E] // ::= Dd, etc. # two-character builtin types // // Not supported: // ::= DF <number> _ # _FloatN (N bits) // +// NOTE: [I <type> E] is a vendor extension (http://shortn/_FrINpH1XC5). static bool ParseBuiltinType(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; - const AbbrevPair *p; - for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { + + for (const AbbrevPair *p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { // Guaranteed only 1- or 2-character strings in kBuiltinTypeList. if (p->abbrev[1] == '\0') { if (ParseOneCharToken(state, p->abbrev[0])) { MaybeAppend(state, p->real_name); - return true; + return true; // ::= v, etc. # single-character builtin types } } else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) { MaybeAppend(state, p->real_name); - return true; + return true; // ::= Dd, etc. # two-character builtin types } } ParseState copy = state->parse_state; if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) { - return true; + copy = state->parse_state; + if (ParseOneCharToken(state, 'I') && ParseType(state) && + ParseOneCharToken(state, 'E')) { + return true; // ::= u <source-name> I <type> E + } + state->parse_state = copy; + return true; // ::= u <source-name> } state->parse_state = copy; return false; diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 86e66886..555e5908 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -150,6 +150,38 @@ TEST(Demangle, FunctionTemplateTemplateParamWithConstrainedArg) { EXPECT_STREQ(tmp, "foo<>()"); } +TEST(Demangle, NonTemplateBuiltinType) { + char tmp[100]; + + // void foo(__my_builtin_type t); + // + // foo({}); + ASSERT_TRUE(Demangle("_Z3foou17__my_builtin_type", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "foo()"); +} + +TEST(Demangle, SingleArgTemplateBuiltinType) { + char tmp[100]; + + // template <typename T> + // __my_builtin_type<T> foo(); + // + // foo<int>(); + ASSERT_TRUE(Demangle("_Z3fooIiEu17__my_builtin_typeIT_Ev", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "foo<>()"); +} + +TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) { + char tmp[100]; + + // template <typename T, typename U> + // __my_builtin_type<T, U> foo(); + // + // foo<int, char>(); + ASSERT_FALSE( + Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp))); +} + // Test corner cases of boundary conditions. TEST(Demangle, CornerCases) { char tmp[10]; |