Commit 696b3278 by Chris Mihelich Committed by Copybara-Service

Try not to lose easy type combinators in S::operator const int*() and the like.

PiperOrigin-RevId: 641411131
Change-Id: Icba1307cccb8957e09f087a7b544f7fe8bfd8333
parent f875817b
...@@ -589,6 +589,7 @@ static bool ParseFloatNumber(State *state); ...@@ -589,6 +589,7 @@ static bool ParseFloatNumber(State *state);
static bool ParseSeqId(State *state); static bool ParseSeqId(State *state);
static bool ParseIdentifier(State *state, size_t length); static bool ParseIdentifier(State *state, size_t length);
static bool ParseOperatorName(State *state, int *arity); static bool ParseOperatorName(State *state, int *arity);
static bool ParseConversionOperatorType(State *state);
static bool ParseSpecialName(State *state); static bool ParseSpecialName(State *state);
static bool ParseCallOffset(State *state); static bool ParseCallOffset(State *state);
static bool ParseNVOffset(State *state); static bool ParseNVOffset(State *state);
...@@ -1056,7 +1057,7 @@ static bool ParseOperatorName(State *state, int *arity) { ...@@ -1056,7 +1057,7 @@ static bool ParseOperatorName(State *state, int *arity) {
// First check with "cv" (cast) case. // First check with "cv" (cast) case.
ParseState copy = state->parse_state; ParseState copy = state->parse_state;
if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") && if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") &&
EnterNestedName(state) && ParseType(state) && EnterNestedName(state) && ParseConversionOperatorType(state) &&
LeaveNestedName(state, copy.nest_level)) { LeaveNestedName(state, copy.nest_level)) {
if (arity != nullptr) { if (arity != nullptr) {
*arity = 1; *arity = 1;
...@@ -1105,6 +1106,65 @@ static bool ParseOperatorName(State *state, int *arity) { ...@@ -1105,6 +1106,65 @@ static bool ParseOperatorName(State *state, int *arity) {
return false; return false;
} }
// <operator-name> ::= cv <type> # (cast)
//
// The name of a conversion operator is the one place where cv-qualifiers, *, &,
// and other simple type combinators are expected to appear in our stripped-down
// demangling (elsewhere they appear in function signatures or template
// arguments, which we omit from the output). We make reasonable efforts to
// render simple cases accurately.
static bool ParseConversionOperatorType(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
// Scan pointers, const, and other easy mangling prefixes with postfix
// demanglings. Remember the range of input for later rescanning.
//
// See `ParseType` and the `switch` below for the meaning of each char.
const char* begin_simple_prefixes = RemainingInput(state);
while (ParseCharClass(state, "OPRCGrVK")) {}
const char* end_simple_prefixes = RemainingInput(state);
// Emit the base type first.
if (!ParseType(state)) {
state->parse_state = copy;
return false;
}
// Then rescan the easy type combinators in reverse order to emit their
// demanglings in the expected output order.
while (begin_simple_prefixes != end_simple_prefixes) {
switch (*--end_simple_prefixes) {
case 'P':
MaybeAppend(state, "*");
break;
case 'R':
MaybeAppend(state, "&");
break;
case 'O':
MaybeAppend(state, "&&");
break;
case 'C':
MaybeAppend(state, " _Complex");
break;
case 'G':
MaybeAppend(state, " _Imaginary");
break;
case 'r':
MaybeAppend(state, " restrict");
break;
case 'V':
MaybeAppend(state, " volatile");
break;
case 'K':
MaybeAppend(state, " const");
break;
}
}
return true;
}
// <special-name> ::= TV <type> // <special-name> ::= TV <type>
// ::= TT <type> // ::= TT <type>
// ::= TI <type> // ::= TI <type>
...@@ -1442,12 +1502,18 @@ static bool ParseExtendedQualifier(State *state) { ...@@ -1442,12 +1502,18 @@ static bool ParseExtendedQualifier(State *state) {
ComplexityGuard guard(state); ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false; if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state; ParseState copy = state->parse_state;
if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
Optional(ParseTemplateArgs(state))) { if (!ParseOneCharToken(state, 'U')) return false;
return true;
bool append = state->parse_state.append;
DisableAppend(state);
if (!ParseSourceName(state)) {
state->parse_state = copy;
return false;
} }
state->parse_state = copy; Optional(ParseTemplateArgs(state));
return false; RestoreAppend(state, append);
return true;
} }
// <builtin-type> ::= v, etc. # single-character builtin types // <builtin-type> ::= v, etc. # single-character builtin types
......
...@@ -708,6 +708,73 @@ TEST(Demangle, DependentBitInt) { ...@@ -708,6 +708,73 @@ TEST(Demangle, DependentBitInt) {
EXPECT_STREQ("S::operator _BitInt(?)<>()", tmp); EXPECT_STREQ("S::operator _BitInt(?)<>()", tmp);
} }
TEST(Demangle, ConversionToPointerType) {
char tmp[80];
// S::operator int*() const
EXPECT_TRUE(Demangle("_ZNK1ScvPiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int*()", tmp);
}
TEST(Demangle, ConversionToLvalueReferenceType) {
char tmp[80];
// S::operator int&() const
EXPECT_TRUE(Demangle("_ZNK1ScvRiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int&()", tmp);
}
TEST(Demangle, ConversionToRvalueReferenceType) {
char tmp[80];
// S::operator int&&() const
EXPECT_TRUE(Demangle("_ZNK1ScvOiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int&&()", tmp);
}
TEST(Demangle, ConversionToComplexFloatingPointType) {
char tmp[80];
// S::operator float _Complex() const
EXPECT_TRUE(Demangle("_ZNK1ScvCfEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator float _Complex()", tmp);
}
TEST(Demangle, ConversionToImaginaryFloatingPointType) {
char tmp[80];
// S::operator float _Imaginary() const
EXPECT_TRUE(Demangle("_ZNK1ScvGfEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator float _Imaginary()", tmp);
}
TEST(Demangle, ConversionToPointerToCvQualifiedType) {
char tmp[80];
// S::operator int const volatile restrict*() const
EXPECT_TRUE(Demangle("_ZNK1ScvPrVKiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int const volatile restrict*()", tmp);
}
TEST(Demangle, ConversionToLayeredPointerType) {
char tmp[80];
// S::operator int const* const*() const
EXPECT_TRUE(Demangle("_ZNK1ScvPKPKiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int const* const*()", tmp);
}
TEST(Demangle, ConversionToTypeWithExtendedQualifier) {
char tmp[80];
// S::operator int const AS128*() const
//
// Because our scan of easy type constructors stops at the extended qualifier,
// the demangling preserves the * but loses the const.
EXPECT_TRUE(Demangle("_ZNK1ScvPU5AS128KiEv", tmp, sizeof(tmp)));
EXPECT_STREQ("S::operator int*()", tmp);
}
TEST(Demangle, GlobalInitializers) { TEST(Demangle, GlobalInitializers) {
char tmp[80]; char tmp[80];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment