diff options
-rw-r--r-- | absl/debugging/internal/demangle.cc | 13 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 60 |
2 files changed, 71 insertions, 2 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 1a5828fa..7901a410 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -1304,7 +1304,8 @@ static bool ParseDecltype(State *state) { // ::= <decltype> // ::= <substitution> // ::= Dp <type> # pack expansion of (C++0x) -// ::= Dv <num-elems> _ # GNU vector extension +// ::= Dv <(elements) number> _ <type> # GNU vector extension +// ::= Dv <(bytes) expression> _ <type> // ::= Dk <type-constraint> # constrained auto // static bool ParseType(State *state) { @@ -1372,8 +1373,16 @@ static bool ParseType(State *state) { return true; } + // GNU vector extension Dv <number> _ <type> if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) && - ParseOneCharToken(state, '_')) { + ParseOneCharToken(state, '_') && ParseType(state)) { + return true; + } + state->parse_state = copy; + + // GNU vector extension Dv <expression> _ <type> + if (ParseTwoCharToken(state, "Dv") && ParseExpression(state) && + ParseOneCharToken(state, '_') && ParseType(state)) { return true; } state->parse_state = copy; diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 0b12234f..1d108c8b 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -671,6 +671,66 @@ TEST(Demangle, AbiTags) { EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp); } +TEST(Demangle, SimpleGnuVectorSize) { + char tmp[80]; + + // Source: + // + // #define VECTOR(size) __attribute__((vector_size(size))) + // void f(int x VECTOR(32)) {} + // + // The attribute's size is a number of bytes. The compiler verifies that this + // value corresponds to a whole number of elements and emits the number of + // elements as a <number> in the mangling. With sizeof(int) == 4, that yields + // 32/4 = 8. + // + // LLVM demangling: + // + // f(int vector[8]) + EXPECT_TRUE(Demangle("_Z1fDv8_i", tmp, sizeof(tmp))); + EXPECT_STREQ("f()", tmp); +} + +TEST(Demangle, GnuVectorSizeIsATemplateParameter) { + char tmp[80]; + + // Source: + // + // #define VECTOR(size) __attribute__((vector_size(size))) + // template <int n> void f(int x VECTOR(n)) {} + // template void f<32>(int x VECTOR(32)); + // + // LLVM demangling: + // + // void f<32>(int vector[32]) + // + // Because the size was dependent on a template parameter, it was encoded + // using the general expression encoding. Nothing in the mangling says how + // big the element type is, so the demangler is unable to show the element + // count 8 instead of the byte count 32. Arguably it would have been better + // to make the narrow production encode the byte count, so that nondependent + // and dependent versions of a 32-byte vector would both come out as + // vector[32]. + EXPECT_TRUE(Demangle("_Z1fILi32EEvDvT__i", tmp, sizeof(tmp))); + EXPECT_STREQ("f<>()", tmp); +} + +TEST(Demangle, GnuVectorSizeIsADependentOperatorExpression) { + char tmp[80]; + + // Source: + // + // #define VECTOR(size) __attribute__((vector_size(size))) + // template <int n> void f(int x VECTOR(2 * n)) {} + // template void f<32>(int x VECTOR(2 * 32)); + // + // LLVM demangling: + // + // void f<32>(int vector[2 * 32]) + EXPECT_TRUE(Demangle("_Z1fILi32EEvDvmlLi2ET__i", tmp, sizeof(tmp))); + EXPECT_STREQ("f<>()", tmp); +} + TEST(Demangle, EnableIfAttributeOnGlobalFunction) { char tmp[80]; |