Commit abc0f8d1 by Chris Mihelich Committed by Copybara-Service

Demangle Clang's encoding of __attribute__((enable_if(condition, "message"))).

PiperOrigin-RevId: 638244694
Change-Id: I80393c6c00f1554057a915e0d71f88b7d899818c
parent 1f5a9cdc
...@@ -585,6 +585,7 @@ static bool ParseCVQualifiers(State *state); ...@@ -585,6 +585,7 @@ static bool ParseCVQualifiers(State *state);
static bool ParseBuiltinType(State *state); static bool ParseBuiltinType(State *state);
static bool ParseFunctionType(State *state); static bool ParseFunctionType(State *state);
static bool ParseBareFunctionType(State *state); static bool ParseBareFunctionType(State *state);
static bool ParseOverloadAttribute(State *state);
static bool ParseClassEnumType(State *state); static bool ParseClassEnumType(State *state);
static bool ParseArrayType(State *state); static bool ParseArrayType(State *state);
static bool ParsePointerToMemberType(State *state); static bool ParsePointerToMemberType(State *state);
...@@ -1437,13 +1438,17 @@ static bool ParseFunctionType(State *state) { ...@@ -1437,13 +1438,17 @@ static bool ParseFunctionType(State *state) {
return true; return true;
} }
// <bare-function-type> ::= <(signature) type>+ // <bare-function-type> ::= <overload-attribute>* <(signature) type>+
//
// The <overload-attribute>* prefix is nonstandard; see the comment on
// ParseOverloadAttribute.
static bool ParseBareFunctionType(State *state) { static bool ParseBareFunctionType(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;
DisableAppend(state); DisableAppend(state);
if (OneOrMore(ParseType, state)) { if (ZeroOrMore(ParseOverloadAttribute, state) &&
OneOrMore(ParseType, state)) {
RestoreAppend(state, copy.append); RestoreAppend(state, copy.append);
MaybeAppend(state, "()"); MaybeAppend(state, "()");
return true; return true;
...@@ -1452,6 +1457,25 @@ static bool ParseBareFunctionType(State *state) { ...@@ -1452,6 +1457,25 @@ static bool ParseBareFunctionType(State *state) {
return false; return false;
} }
// <overload-attribute> ::= Ua <name>
//
// The nonstandard <overload-attribute> production is sufficient to accept the
// current implementation of __attribute__((enable_if(condition, "message")))
// and future attributes of a similar shape. See
// https://clang.llvm.org/docs/AttributeReference.html#enable-if and the
// definition of CXXNameMangler::mangleFunctionEncodingBareType in Clang's
// source code.
static bool ParseOverloadAttribute(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
if (ParseTwoCharToken(state, "Ua") && ParseName(state)) {
return true;
}
state->parse_state = copy;
return false;
}
// <class-enum-type> ::= <name> // <class-enum-type> ::= <name>
static bool ParseClassEnumType(State *state) { static bool ParseClassEnumType(State *state) {
ComplexityGuard guard(state); ComplexityGuard guard(state);
......
...@@ -461,6 +461,42 @@ TEST(Demangle, AbiTags) { ...@@ -461,6 +461,42 @@ TEST(Demangle, AbiTags) {
EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp); EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp);
} }
TEST(Demangle, EnableIfAttributeOnGlobalFunction) {
char tmp[80];
// int f(long l) __attribute__((enable_if(l >= 0, ""))) { return l; }
//
// f(long) [enable_if:fp >= 0]
EXPECT_TRUE(Demangle("_Z1fUa9enable_ifIXgefL0p_Li0EEEl", tmp, sizeof(tmp)));
EXPECT_STREQ("f()", tmp);
}
TEST(Demangle, EnableIfAttributeOnNamespaceScopeFunction) {
char tmp[80];
// namespace ns {
// int f(long l) __attribute__((enable_if(l >= 0, ""))) { return l; }
// } // namespace ns
//
// ns::f(long) [enable_if:fp >= 0]
EXPECT_TRUE(Demangle("_ZN2ns1fEUa9enable_ifIXgefL0p_Li0EEEl",
tmp, sizeof(tmp)));
EXPECT_STREQ("ns::f()", tmp);
}
TEST(Demangle, EnableIfAttributeOnFunctionTemplate) {
char tmp[80];
// template <class T>
// T f(T t) __attribute__((enable_if(t >= T{}, ""))) { return t; }
// template int f<int>(int);
//
// int f<int>(int) [enable_if:fp >= int{}]
EXPECT_TRUE(Demangle("_Z1fIiEUa9enable_ifIXgefL0p_tliEEET_S0_",
tmp, sizeof(tmp)));
EXPECT_STREQ("f<>()", tmp);
}
TEST(Demangle, ThisPointerInDependentSignature) { TEST(Demangle, ThisPointerInDependentSignature) {
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