Skip to content

Commit c14dfbf

Browse files
dinordcopybara-github
authored andcommitted
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](llvm/llvm-project@4bc4d51). PiperOrigin-RevId: 606843797 Change-Id: Ib5ef1983812e9ea68a39fe64b87b6ad6ce81b93c
1 parent 0a362eb commit c14dfbf

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

absl/debugging/internal/demangle.cc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,32 +1297,39 @@ static bool ParseCVQualifiers(State *state) {
12971297
}
12981298

12991299
// <builtin-type> ::= v, etc. # single-character builtin types
1300-
// ::= u <source-name>
1300+
// ::= u <source-name> [I <type> E]
13011301
// ::= Dd, etc. # two-character builtin types
13021302
//
13031303
// Not supported:
13041304
// ::= DF <number> _ # _FloatN (N bits)
13051305
//
1306+
// NOTE: [I <type> E] is a vendor extension (http://shortn/_FrINpH1XC5).
13061307
static bool ParseBuiltinType(State *state) {
13071308
ComplexityGuard guard(state);
13081309
if (guard.IsTooComplex()) return false;
1309-
const AbbrevPair *p;
1310-
for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {
1310+
1311+
for (const AbbrevPair *p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {
13111312
// Guaranteed only 1- or 2-character strings in kBuiltinTypeList.
13121313
if (p->abbrev[1] == '\0') {
13131314
if (ParseOneCharToken(state, p->abbrev[0])) {
13141315
MaybeAppend(state, p->real_name);
1315-
return true;
1316+
return true; // ::= v, etc. # single-character builtin types
13161317
}
13171318
} else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) {
13181319
MaybeAppend(state, p->real_name);
1319-
return true;
1320+
return true; // ::= Dd, etc. # two-character builtin types
13201321
}
13211322
}
13221323

13231324
ParseState copy = state->parse_state;
13241325
if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
1325-
return true;
1326+
copy = state->parse_state;
1327+
if (ParseOneCharToken(state, 'I') && ParseType(state) &&
1328+
ParseOneCharToken(state, 'E')) {
1329+
return true; // ::= u <source-name> I <type> E
1330+
}
1331+
state->parse_state = copy;
1332+
return true; // ::= u <source-name>
13261333
}
13271334
state->parse_state = copy;
13281335
return false;

absl/debugging/internal/demangle_test.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,38 @@ TEST(Demangle, FunctionTemplateTemplateParamWithConstrainedArg) {
150150
EXPECT_STREQ(tmp, "foo<>()");
151151
}
152152

153+
TEST(Demangle, NonTemplateBuiltinType) {
154+
char tmp[100];
155+
156+
// void foo(__my_builtin_type t);
157+
//
158+
// foo({});
159+
ASSERT_TRUE(Demangle("_Z3foou17__my_builtin_type", tmp, sizeof(tmp)));
160+
EXPECT_STREQ(tmp, "foo()");
161+
}
162+
163+
TEST(Demangle, SingleArgTemplateBuiltinType) {
164+
char tmp[100];
165+
166+
// template <typename T>
167+
// __my_builtin_type<T> foo();
168+
//
169+
// foo<int>();
170+
ASSERT_TRUE(Demangle("_Z3fooIiEu17__my_builtin_typeIT_Ev", tmp, sizeof(tmp)));
171+
EXPECT_STREQ(tmp, "foo<>()");
172+
}
173+
174+
TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) {
175+
char tmp[100];
176+
177+
// template <typename T, typename U>
178+
// __my_builtin_type<T, U> foo();
179+
//
180+
// foo<int, char>();
181+
ASSERT_FALSE(
182+
Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp)));
183+
}
184+
153185
// Test corner cases of boundary conditions.
154186
TEST(Demangle, CornerCases) {
155187
char tmp[10];

0 commit comments

Comments
 (0)