[demangler][NFC] OperatorInfo table unit test

Placing a run-once test inside the operator lookup function caused
problems with the thread sanitizer. See D122975.

Break out the operator table into a member variable, and move the test
to the unit test machinery.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D123390
This commit is contained in:
Nathan Sidwell 2022-04-08 06:55:31 -07:00
parent 72904a990c
commit c47bcf9af6
3 changed files with 184 additions and 200 deletions

View File

@ -2658,6 +2658,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
bool getFlag() const { return Flag; }
Node::Prec getPrecedence() const { return Prec; }
};
static const OperatorInfo Ops[];
static const size_t NumOps;
const OperatorInfo *parseOperatorEncoding();
/// Parse the <unresolved-name> production.
@ -2955,35 +2957,30 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
return make<NameType>(Name);
}
// If the next 2 chars are an operator encoding, consume them and return their
// OperatorInfo. Otherwise return nullptr.
// Operator encodings
template <typename Derived, typename Alloc>
const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
static const OperatorInfo Ops[] = {
const typename AbstractManglingParser<
Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
Alloc>::Ops[] = {
// Keep ordered by encoding
{"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
{"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
{"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
{"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
{"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
{"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
"alignof "},
{"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
{"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
"operator co_await"},
{"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
"alignof "},
{"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
{"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
{"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
{"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
{"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
{"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
"operator"}, // C Cast
{"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
{"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
{"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
"operator delete[]"},
{"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
"dynamic_cast"},
{"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
{"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
{"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
"operator delete"},
@ -3013,8 +3010,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
{"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
{"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
{"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
{"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
"operator new"},
{"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
{"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
{"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
{"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
@ -3035,31 +3031,23 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
{"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
"operator%"},
{"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
{"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
"static_cast"},
{"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
{"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
{"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
{"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
"sizeof "},
{"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
{"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
"typeid "},
{"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
"typeid "},
};
const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
#ifndef NDEBUG
{
// Verify table order.
static bool Done;
if (!Done) {
Done = true;
for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
assert(Op[0] < Op[1] && "Operator table is not ordered");
}
}
#endif
{"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
};
template <typename Derived, typename Alloc>
const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
sizeof(Ops[0]);
// If the next 2 chars are an operator encoding, consume them and return their
// OperatorInfo. Otherwise return nullptr.
template <typename Derived, typename Alloc>
const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
if (numLeft() < 2)
return nullptr;

View File

@ -2658,6 +2658,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
bool getFlag() const { return Flag; }
Node::Prec getPrecedence() const { return Prec; }
};
static const OperatorInfo Ops[];
static const size_t NumOps;
const OperatorInfo *parseOperatorEncoding();
/// Parse the <unresolved-name> production.
@ -2955,35 +2957,30 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
return make<NameType>(Name);
}
// If the next 2 chars are an operator encoding, consume them and return their
// OperatorInfo. Otherwise return nullptr.
// Operator encodings
template <typename Derived, typename Alloc>
const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
static const OperatorInfo Ops[] = {
const typename AbstractManglingParser<
Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
Alloc>::Ops[] = {
// Keep ordered by encoding
{"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
{"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
{"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
{"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
{"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
{"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
"alignof "},
{"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
{"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
"operator co_await"},
{"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
"alignof "},
{"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
{"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
{"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
{"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
{"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
{"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
"operator"}, // C Cast
{"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
{"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
{"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
"operator delete[]"},
{"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
"dynamic_cast"},
{"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
{"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
{"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
"operator delete"},
@ -3013,8 +3010,7 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
{"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
{"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
{"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
{"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
"operator new"},
{"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
{"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
{"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
{"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
@ -3035,31 +3031,23 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
{"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
"operator%"},
{"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
{"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
"static_cast"},
{"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
{"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
{"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
{"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
"sizeof "},
{"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
{"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
"typeid "},
{"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
"typeid "},
};
const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
#ifndef NDEBUG
{
// Verify table order.
static bool Done;
if (!Done) {
Done = true;
for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
assert(Op[0] < Op[1] && "Operator table is not ordered");
}
}
#endif
{"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
};
template <typename Derived, typename Alloc>
const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
sizeof(Ops[0]);
// If the next 2 chars are an operator encoding, consume them and return their
// OperatorInfo. Otherwise return nullptr.
template <typename Derived, typename Alloc>
const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
if (numLeft() < 2)
return nullptr;

View File

@ -56,6 +56,14 @@ void Visitor() {
}
} // namespace NodeMatcher
// Verify Operator table is ordered
TEST(ItaniumDemangle, OperatorOrdering) {
struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {};
for (const auto *Op = &TestParser::Ops[0];
Op != &TestParser::Ops[TestParser::NumOps - 1]; Op++)
ASSERT_LT(Op[0], Op[1]);
}
TEST(ItaniumDemangle, MethodOverride) {
struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
std::vector<char> Types;