summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Dino Radakovic <dinor@google.com>2024-02-13 20:56:28 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2024-02-13 20:57:21 -0800
commitc14dfbf9c1759c39bf4343b9e54a43975fbba930 (patch)
tree0400df4eba10f37251c1df5413ca2a7c464c1736
parent0a362eb290044fa39f6c6a120e4627ff9998e55b (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.cc19
-rw-r--r--absl/debugging/internal/demangle_test.cc32
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];