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