forked from qt-creator/qt-creator
Debugger: Name demangler improvements.
- Fix assertion macro. - Make parse tree smaller by getting rid of nodes that serve no purpose. - Add all examples from the ABI spec to the auto test. Change-Id: Id63d8330e6380bfb7d56acd1d445f7b70a1f6e70 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
@@ -61,7 +61,7 @@ public:
|
|||||||
|
|
||||||
#define DEMANGLER_ASSERT(cond) \
|
#define DEMANGLER_ASSERT(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (!cond) { \
|
if (!(cond)) { \
|
||||||
throw InternalDemanglerException(Q_FUNC_INFO, __FILE__, __LINE__); \
|
throw InternalDemanglerException(Q_FUNC_INFO, __FILE__, __LINE__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ QByteArray GlobalParseState::readAhead(int charCount) const
|
|||||||
|
|
||||||
void GlobalParseState::addSubstitution(const ParseTreeNode *node)
|
void GlobalParseState::addSubstitution(const ParseTreeNode *node)
|
||||||
{
|
{
|
||||||
const QByteArray symbol = node->toByteArray();
|
addSubstitution(node->toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalParseState::addSubstitution(const QByteArray &symbol)
|
||||||
|
{
|
||||||
if (!symbol.isEmpty() && !m_substitutions.contains(symbol))
|
if (!symbol.isEmpty() && !m_substitutions.contains(symbol))
|
||||||
m_substitutions.append(symbol);
|
m_substitutions.append(symbol);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
int substitutionCount() const { return m_substitutions.count(); }
|
int substitutionCount() const { return m_substitutions.count(); }
|
||||||
QByteArray substitutionAt(int index) const { return m_substitutions.at(index); }
|
QByteArray substitutionAt(int index) const { return m_substitutions.at(index); }
|
||||||
void addSubstitution(const ParseTreeNode *node);
|
void addSubstitution(const ParseTreeNode *node);
|
||||||
|
void addSubstitution(const QByteArray &symbol);
|
||||||
|
|
||||||
int templateParamCount() const { return m_templateParams.count(); }
|
int templateParamCount() const { return m_templateParams.count(); }
|
||||||
ParseTreeNode *templateParamAt(int index) const { return m_templateParams.at(index); }
|
ParseTreeNode *templateParamAt(int index) const { return m_templateParams.at(index); }
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ bool NameDemanglerPrivate::demangle(const QString &mangledName)
|
|||||||
m_parseState.m_isConversionOperator = false;
|
m_parseState.m_isConversionOperator = false;
|
||||||
m_demangledName.clear();
|
m_demangledName.clear();
|
||||||
|
|
||||||
if (!MangledNameNode::mangledRepresentationStartsWith(m_parseState.peek())) {
|
if (!MangledNameRule::mangledRepresentationStartsWith(m_parseState.peek())) {
|
||||||
m_demangledName = m_parseState.m_mangledName;
|
m_demangledName = m_parseState.m_mangledName;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseTreeNode::parseRule<MangledNameNode>(&m_parseState);
|
MangledNameRule::parse(&m_parseState, 0);
|
||||||
if (m_parseState.m_pos != m_parseState.m_mangledName.size())
|
if (m_parseState.m_pos != m_parseState.m_mangledName.size())
|
||||||
throw ParseException(QLatin1String("Unconsumed input"));
|
throw ParseException(QLatin1String("Unconsumed input"));
|
||||||
if (m_parseState.m_parseStack.count() != 1) {
|
if (m_parseState.m_parseStack.count() != 1) {
|
||||||
|
|||||||
@@ -39,14 +39,19 @@
|
|||||||
#define PEEK() (parseState()->peek())
|
#define PEEK() (parseState()->peek())
|
||||||
#define ADVANCE() (parseState()->advance())
|
#define ADVANCE() (parseState()->advance())
|
||||||
|
|
||||||
#define PARSE_RULE_AND_ADD_RESULT_AS_CHILD(nodeType) \
|
#define PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(nodeType, parseState, parentNode) \
|
||||||
do { \
|
do { \
|
||||||
parseRule<nodeType>(parseState()); \
|
ParseTreeNode::parseRule<nodeType>(parseState); \
|
||||||
DEMANGLER_ASSERT(parseState()->stackElementCount() > 0); \
|
DEMANGLER_ASSERT(parseState->stackElementCount() > 0); \
|
||||||
DEMANGLER_ASSERT(dynamic_cast<nodeType *>(parseState()->stackTop())); \
|
DEMANGLER_ASSERT(dynamic_cast<nodeType *>(parseState->stackTop())); \
|
||||||
addChild(parseState()->popFromStack()); \
|
if (parentNode) \
|
||||||
|
(parentNode)->addChild(parseState->popFromStack()); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#define PARSE_RULE_AND_ADD_RESULT_AS_CHILD(nodeType) \
|
||||||
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(nodeType, parseState(), this)
|
||||||
|
|
||||||
#define CHILD_AT(obj, index) obj->childAt(index, Q_FUNC_INFO, __FILE__, __LINE__)
|
#define CHILD_AT(obj, index) obj->childAt(index, Q_FUNC_INFO, __FILE__, __LINE__)
|
||||||
#define MY_CHILD_AT(index) CHILD_AT(this, index)
|
#define MY_CHILD_AT(index) CHILD_AT(this, index)
|
||||||
#define CHILD_TO_BYTEARRAY(index) MY_CHILD_AT(index)->toByteArray()
|
#define CHILD_TO_BYTEARRAY(index) MY_CHILD_AT(index)->toByteArray()
|
||||||
@@ -211,66 +216,95 @@ void BuiltinTypeNode::parse()
|
|||||||
{
|
{
|
||||||
const char next = ADVANCE();
|
const char next = ADVANCE();
|
||||||
if (next == 'u') {
|
if (next == 'u') {
|
||||||
|
m_type = VendorType;
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SourceNameNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SourceNameNode);
|
||||||
} else {
|
return;
|
||||||
// TODO: This seems silly. Why not integrate the type into this node and have
|
}
|
||||||
// an additional one "VendorType" that indicates that there's a child node?
|
|
||||||
PredefinedBuiltinTypeNode * const fixedTypeNode = new PredefinedBuiltinTypeNode;
|
|
||||||
addChild(fixedTypeNode);
|
|
||||||
|
|
||||||
switch (next) {
|
switch (next) {
|
||||||
case 'v': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::VoidType; break;
|
case 'v': m_type = VoidType; break;
|
||||||
case 'w': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::WCharType; break;
|
case 'w': m_type = WCharType; break;
|
||||||
case 'b': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::BoolType; break;
|
case 'b': m_type = BoolType; break;
|
||||||
case 'c': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::PlainCharType; break;
|
case 'c': m_type = PlainCharType; break;
|
||||||
case 'a': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedCharType; break;
|
case 'a': m_type = SignedCharType; break;
|
||||||
case 'h': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedCharType; break;
|
case 'h': m_type = UnsignedCharType; break;
|
||||||
case 's': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedShortType; break;
|
case 's': m_type = SignedShortType; break;
|
||||||
case 't': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedShortType; break;
|
case 't': m_type = UnsignedShortType; break;
|
||||||
case 'i': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedIntType; break;
|
case 'i': m_type = SignedIntType; break;
|
||||||
case 'j': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedIntType; break;
|
case 'j': m_type = UnsignedIntType; break;
|
||||||
case 'l': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedLongType; break;
|
case 'l': m_type = SignedLongType; break;
|
||||||
case 'm': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedLongType; break;
|
case 'm': m_type = UnsignedLongType; break;
|
||||||
case 'x': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedLongLongType; break;
|
case 'x': m_type = SignedLongLongType; break;
|
||||||
case 'y': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedLongLongType; break;
|
case 'y': m_type = UnsignedLongLongType; break;
|
||||||
case 'n': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedInt128Type; break;
|
case 'n': m_type = SignedInt128Type; break;
|
||||||
case 'o': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedInt128Type; break;
|
case 'o': m_type = UnsignedInt128Type; break;
|
||||||
case 'f': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::FloatType; break;
|
case 'f': m_type = FloatType; break;
|
||||||
case 'd': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DoubleType; break;
|
case 'd': m_type = DoubleType; break;
|
||||||
case 'e': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::LongDoubleType; break;
|
case 'e': m_type = LongDoubleType; break;
|
||||||
case 'g': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::Float128Type; break;
|
case 'g': m_type = Float128Type; break;
|
||||||
case 'z': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::EllipsisType; break;
|
case 'z': m_type = EllipsisType; break;
|
||||||
case 'D':
|
case 'D':
|
||||||
switch (ADVANCE()) {
|
switch (ADVANCE()) {
|
||||||
case 'd':
|
case 'd':
|
||||||
fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DecimalFloatingType64;
|
m_type = DecimalFloatingType64;
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DecimalFloatingType128;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DecimalFloatingType32;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DecimalFloatingType16; break;
|
|
||||||
case 'i': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::Char32Type; break;
|
|
||||||
case 's': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::Char16Type; break;
|
|
||||||
default: throw ParseException(QString::fromLatin1("Invalid built-in type"));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 'e':
|
||||||
DEMANGLER_ASSERT(false);
|
m_type = DecimalFloatingType128;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
m_type = DecimalFloatingType32;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
m_type = DecimalFloatingType16; break;
|
||||||
|
case 'i': m_type = Char32Type; break;
|
||||||
|
case 's': m_type = Char16Type; break;
|
||||||
|
default: throw ParseException(QString::fromLatin1("Invalid built-in type"));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEMANGLER_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray BuiltinTypeNode::toByteArray() const
|
QByteArray BuiltinTypeNode::toByteArray() const
|
||||||
{
|
{
|
||||||
return CHILD_TO_BYTEARRAY(0);
|
switch (m_type) {
|
||||||
|
case VoidType: return "void";
|
||||||
|
case WCharType: return "wchar_t";
|
||||||
|
case BoolType: return "bool";
|
||||||
|
case PlainCharType: return "char";
|
||||||
|
case SignedCharType: return "signed char";
|
||||||
|
case UnsignedCharType: return "unsigned char";
|
||||||
|
case SignedShortType: return "signed short";
|
||||||
|
case UnsignedShortType: return "unsigned short";
|
||||||
|
case SignedIntType: return "int";
|
||||||
|
case UnsignedIntType: return "unsigned int";
|
||||||
|
case SignedLongType: return "long";
|
||||||
|
case UnsignedLongType: return "unsigned long";
|
||||||
|
case SignedLongLongType: return "long long";
|
||||||
|
case UnsignedLongLongType: return "unsigned long long";
|
||||||
|
case SignedInt128Type: return "__int128";
|
||||||
|
case UnsignedInt128Type: return "unsigned __int128";
|
||||||
|
case FloatType: return "float";
|
||||||
|
case DoubleType: return "double";
|
||||||
|
case LongDoubleType: return "long double";
|
||||||
|
case Float128Type: return "__float128";
|
||||||
|
case EllipsisType: return "...";
|
||||||
|
case DecimalFloatingType16: return "[IEEE 754r half-precision floating point]";
|
||||||
|
case DecimalFloatingType32: return "[IEEE 754r decimal floating point (32 bits)]";
|
||||||
|
case DecimalFloatingType64: return "[IEEE 754r decimal floating point (64 bits)]";
|
||||||
|
case DecimalFloatingType128: return "[IEEE 754r decimal floating point (128 bits)]";
|
||||||
|
case Char32Type: return "char32_t";
|
||||||
|
case Char16Type: return "char16_t";
|
||||||
|
case VendorType: return CHILD_TO_BYTEARRAY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEMANGLER_ASSERT(false);
|
||||||
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CallOffsetNode::mangledRepresentationStartsWith(char c)
|
bool CallOffsetRule::mangledRepresentationStartsWith(char c)
|
||||||
{
|
{
|
||||||
return c == 'h' || c == 'v';
|
return c == 'h' || c == 'v';
|
||||||
}
|
}
|
||||||
@@ -279,24 +313,18 @@ bool CallOffsetNode::mangledRepresentationStartsWith(char c)
|
|||||||
* <call-offset> ::= h <nv-offset> _
|
* <call-offset> ::= h <nv-offset> _
|
||||||
* ::= v <v-offset> _
|
* ::= v <v-offset> _
|
||||||
*/
|
*/
|
||||||
void CallOffsetNode::parse()
|
void CallOffsetRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode)
|
||||||
{
|
{
|
||||||
switch (ADVANCE()) {
|
switch (parseState->advance()) {
|
||||||
case 'h': PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NvOffsetNode); break;
|
case 'h': PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NvOffsetNode, parseState, parentNode); break;
|
||||||
case 'v': PARSE_RULE_AND_ADD_RESULT_AS_CHILD(VOffsetNode); break;
|
case 'v': PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(VOffsetNode, parseState, parentNode); break;
|
||||||
default: DEMANGLER_ASSERT(false);
|
default: DEMANGLER_ASSERT(false);
|
||||||
}
|
}
|
||||||
if (ADVANCE() != '_')
|
if (parseState->advance() != '_')
|
||||||
throw ParseException(QString::fromLatin1("Invalid call-offset"));
|
throw ParseException(QString::fromLatin1("Invalid call-offset"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray CallOffsetNode::toByteArray() const
|
bool ClassEnumTypeRule::mangledRepresentationStartsWith(char c)
|
||||||
{
|
|
||||||
return CHILD_TO_BYTEARRAY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ClassEnumTypeNode::mangledRepresentationStartsWith(char c)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The first set of <class-enum-type> is much smaller than
|
* The first set of <class-enum-type> is much smaller than
|
||||||
@@ -308,33 +336,23 @@ bool ClassEnumTypeNode::mangledRepresentationStartsWith(char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* <class-enum-type> ::= <name> */
|
/* <class-enum-type> ::= <name> */
|
||||||
void ClassEnumTypeNode::parse()
|
void ClassEnumTypeRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode)
|
||||||
{
|
{
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NameNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NameNode, parseState, parentNode);
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ClassEnumTypeNode::toByteArray() const
|
|
||||||
{
|
|
||||||
return CHILD_TO_BYTEARRAY(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DiscriminatorNode::mangledRepresentationStartsWith(char c)
|
bool DiscriminatorRule::mangledRepresentationStartsWith(char c)
|
||||||
{
|
{
|
||||||
return c == '_';
|
return c == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <discriminator> := _ <non-negative-number> */
|
/* <discriminator> := _ <non-negative-number> */
|
||||||
void DiscriminatorNode::parse()
|
void DiscriminatorRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode)
|
||||||
{
|
{
|
||||||
if (ADVANCE() != '_')
|
if (parseState->advance() != '_')
|
||||||
throw ParseException(QString::fromLatin1("Invalid discriminator"));
|
throw ParseException(QString::fromLatin1("Invalid discriminator"));
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NonNegativeNumberNode<10>);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NonNegativeNumberNode<10>, parseState, parentNode);
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray DiscriminatorNode::toByteArray() const
|
|
||||||
{
|
|
||||||
return CHILD_TO_BYTEARRAY(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -960,44 +978,6 @@ QByteArray OperatorNameNode::toByteArray() const
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QByteArray PredefinedBuiltinTypeNode::toByteArray() const
|
|
||||||
{
|
|
||||||
switch (m_type) {
|
|
||||||
case VoidType: return "void";
|
|
||||||
case WCharType: return "wchar_t";
|
|
||||||
case BoolType: return "bool";
|
|
||||||
case PlainCharType: return "char";
|
|
||||||
case SignedCharType: return "signed char";
|
|
||||||
case UnsignedCharType: return "unsigned char";
|
|
||||||
case SignedShortType: return "signed short";
|
|
||||||
case UnsignedShortType: return "unsigned short";
|
|
||||||
case SignedIntType: return "int";
|
|
||||||
case UnsignedIntType: return "unsigned int";
|
|
||||||
case SignedLongType: return "long";
|
|
||||||
case UnsignedLongType: return "unsigned long";
|
|
||||||
case SignedLongLongType: return "long long";
|
|
||||||
case UnsignedLongLongType: return "unsigned long long";
|
|
||||||
case SignedInt128Type: return "__int128";
|
|
||||||
case UnsignedInt128Type: return "unsigned __int128";
|
|
||||||
case FloatType: return "float";
|
|
||||||
case DoubleType: return "double";
|
|
||||||
case LongDoubleType: return "long double";
|
|
||||||
case Float128Type: return "__float128";
|
|
||||||
case EllipsisType: return "...";
|
|
||||||
case DecimalFloatingType16: return "[IEEE 754r half-precision floating point]";
|
|
||||||
case DecimalFloatingType32: return "[IEEE 754r decimal floating point (32 bits)]";
|
|
||||||
case DecimalFloatingType64: return "[IEEE 754r decimal floating point (64 bits)]";
|
|
||||||
case DecimalFloatingType128: return "[IEEE 754r decimal floating point (128 bits)]";
|
|
||||||
case Char32Type: return "char32_t";
|
|
||||||
case Char16Type: return "char16_t";
|
|
||||||
}
|
|
||||||
|
|
||||||
DEMANGLER_ASSERT(false);
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ExprPrimaryNode::mangledRepresentationStartsWith(char c)
|
bool ExprPrimaryNode::mangledRepresentationStartsWith(char c)
|
||||||
{
|
{
|
||||||
return c == 'L';
|
return c == 'L';
|
||||||
@@ -1020,27 +1000,23 @@ void ExprPrimaryNode::parse()
|
|||||||
? 0 : dynamic_cast<BuiltinTypeNode * >(CHILD_AT(topLevelTypeNode, 0));
|
? 0 : dynamic_cast<BuiltinTypeNode * >(CHILD_AT(topLevelTypeNode, 0));
|
||||||
if (!typeNode)
|
if (!typeNode)
|
||||||
throw ParseException(QLatin1String("Invalid type in expr-primary"));
|
throw ParseException(QLatin1String("Invalid type in expr-primary"));
|
||||||
PredefinedBuiltinTypeNode * const predefTypeNode
|
|
||||||
= dynamic_cast<PredefinedBuiltinTypeNode *>(CHILD_AT(typeNode, 0));
|
|
||||||
if (!predefTypeNode)
|
|
||||||
throw ParseException(QLatin1String("Invalid type in expr-primary"));
|
|
||||||
|
|
||||||
// TODO: Of which type can a literal actually be?
|
// TODO: Of which type can a literal actually be?
|
||||||
switch (predefTypeNode->m_type) {
|
switch (typeNode->type()) {
|
||||||
case PredefinedBuiltinTypeNode::SignedIntType:
|
case BuiltinTypeNode::SignedIntType:
|
||||||
case PredefinedBuiltinTypeNode::UnsignedIntType:
|
case BuiltinTypeNode::UnsignedIntType:
|
||||||
case PredefinedBuiltinTypeNode::UnsignedLongType:
|
case BuiltinTypeNode::UnsignedLongType:
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NumberNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NumberNode);
|
||||||
break;
|
break;
|
||||||
case PredefinedBuiltinTypeNode::FloatType: case PredefinedBuiltinTypeNode::DoubleType:
|
case BuiltinTypeNode::FloatType: case BuiltinTypeNode::DoubleType:
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FloatValueNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FloatValueNode);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw ParseException(QString::fromLatin1("Invalid type in expr-primary"));
|
throw ParseException(QString::fromLatin1("Invalid type in expr-primary"));
|
||||||
}
|
}
|
||||||
delete parseState()->popFromStack(); // No need to keep the type node in the tree.
|
delete parseState()->popFromStack(); // No need to keep the type node in the tree.
|
||||||
} else if (MangledNameNode::mangledRepresentationStartsWith(next)) {
|
} else if (MangledNameRule::mangledRepresentationStartsWith(next)) {
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(MangledNameNode);
|
MangledNameRule::parse(parseState(), this);
|
||||||
} else {
|
} else {
|
||||||
throw ParseException(QString::fromLatin1("Invalid expr-primary"));
|
throw ParseException(QString::fromLatin1("Invalid expr-primary"));
|
||||||
}
|
}
|
||||||
@@ -1115,8 +1091,8 @@ void LocalNameNode::parse()
|
|||||||
} else {
|
} else {
|
||||||
throw ParseException(QString::fromLatin1("Invalid local-name"));
|
throw ParseException(QString::fromLatin1("Invalid local-name"));
|
||||||
}
|
}
|
||||||
if (DiscriminatorNode::mangledRepresentationStartsWith(PEEK()))
|
if (DiscriminatorRule::mangledRepresentationStartsWith(PEEK()))
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(DiscriminatorNode);
|
DiscriminatorRule::parse(parseState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray LocalNameNode::toByteArray() const
|
QByteArray LocalNameNode::toByteArray() const
|
||||||
@@ -1131,15 +1107,16 @@ QByteArray LocalNameNode::toByteArray() const
|
|||||||
hasDiscriminator = childCount() == 3;
|
hasDiscriminator = childCount() == 3;
|
||||||
}
|
}
|
||||||
if (hasDiscriminator) {
|
if (hasDiscriminator) {
|
||||||
const QByteArray discriminator = MY_CHILD_AT(childCount() - 1)->toByteArray();
|
// TODO: Does this information serve any purpose? Names seem to demangle fine without printing anything here.
|
||||||
const int rawDiscriminatorValue = discriminator.toInt();
|
// const QByteArray discriminator = MY_CHILD_AT(childCount() - 1)->toByteArray();
|
||||||
name += " (occurrence number " + QByteArray::number(rawDiscriminatorValue - 2) + ')';
|
// const int rawDiscriminatorValue = discriminator.toInt();
|
||||||
|
// name += " (occurrence number " + QByteArray::number(rawDiscriminatorValue - 2) + ')';
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MangledNameNode::mangledRepresentationStartsWith(char c)
|
bool MangledNameRule::mangledRepresentationStartsWith(char c)
|
||||||
{
|
{
|
||||||
return c == '_';
|
return c == '_';
|
||||||
}
|
}
|
||||||
@@ -1150,15 +1127,10 @@ bool MangledNameNode::mangledRepresentationStartsWith(char c)
|
|||||||
* were necessary, which we will document at the respective parsing function.
|
* were necessary, which we will document at the respective parsing function.
|
||||||
* <mangled-name> ::= _Z <encoding>
|
* <mangled-name> ::= _Z <encoding>
|
||||||
*/
|
*/
|
||||||
void MangledNameNode::parse()
|
void MangledNameRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode)
|
||||||
{
|
{
|
||||||
parseState()->advance(2);
|
parseState->advance(2);
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(EncodingNode, parseState, parentNode);
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray MangledNameNode::toByteArray() const
|
|
||||||
{
|
|
||||||
return pasteAllChildren();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1573,11 +1545,12 @@ void SpecialNameNode::parse()
|
|||||||
} else if (str == "Tc") {
|
} else if (str == "Tc") {
|
||||||
m_type = DoubleCallOffsetType;
|
m_type = DoubleCallOffsetType;
|
||||||
parseState()->advance(2);
|
parseState()->advance(2);
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(CallOffsetNode);
|
CallOffsetRule::parse(parseState(), this);
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(CallOffsetNode);
|
CallOffsetRule::parse(parseState(), this);
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode);
|
||||||
} else if (ADVANCE() == 'T') {
|
} else if (ADVANCE() == 'T') {
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(CallOffsetNode);
|
m_type = SingleCallOffsetType;
|
||||||
|
CallOffsetRule::parse(parseState(), this);
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode);
|
||||||
} else {
|
} else {
|
||||||
throw ParseException(QString::fromLatin1("Invalid special-name"));
|
throw ParseException(QString::fromLatin1("Invalid special-name"));
|
||||||
@@ -1820,7 +1793,7 @@ QByteArray Prefix2Node::toByteArray() const
|
|||||||
|
|
||||||
bool Prefix2Node::isTemplate() const
|
bool Prefix2Node::isTemplate() const
|
||||||
{
|
{
|
||||||
return dynamic_cast<TemplateArgsNode *>(MY_CHILD_AT(childCount() - 1));
|
return childCount() > 0 && dynamic_cast<TemplateArgsNode *>(MY_CHILD_AT(childCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Prefix2Node::isConstructorOrDestructorOrConversionOperator() const
|
bool Prefix2Node::isConstructorOrDestructorOrConversionOperator() const
|
||||||
@@ -1839,22 +1812,16 @@ bool Prefix2Node::isConstructorOrDestructorOrConversionOperator() const
|
|||||||
*/
|
*/
|
||||||
void Prefix2Node::parse()
|
void Prefix2Node::parse()
|
||||||
{
|
{
|
||||||
// We need to do this so we can correctly add all substitutions, which always start
|
|
||||||
// with the representation of the prefix node.
|
|
||||||
// Note that this breaks the invariant that a node is on the stack while it is being parsed;
|
|
||||||
// it does not seem that this matters in practice for this particular node.
|
|
||||||
ParseTreeNode * const prefixNode
|
ParseTreeNode * const prefixNode
|
||||||
= parseState()->stackElementAt(parseState()->stackElementCount() - 2);
|
= parseState()->stackElementAt(parseState()->stackElementCount() - 2);
|
||||||
prefixNode->addChild(this);
|
|
||||||
parseState()->popFromStack();
|
|
||||||
|
|
||||||
bool firstRun = true;
|
bool firstRun = true;
|
||||||
while (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) {
|
while (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) {
|
||||||
if (!firstRun)
|
if (!firstRun)
|
||||||
parseState()->addSubstitution(prefixNode);
|
parseState()->addSubstitution(prefixNode->toByteArray() + toByteArray());
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(UnqualifiedNameNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(UnqualifiedNameNode);
|
||||||
if (TemplateArgsNode::mangledRepresentationStartsWith(PEEK())) {
|
if (TemplateArgsNode::mangledRepresentationStartsWith(PEEK())) {
|
||||||
parseState()->addSubstitution(prefixNode);
|
parseState()->addSubstitution(prefixNode->toByteArray() + toByteArray());
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(TemplateArgsNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(TemplateArgsNode);
|
||||||
}
|
}
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
@@ -1871,6 +1838,8 @@ bool PrefixNode::mangledRepresentationStartsWith(char c)
|
|||||||
|
|
||||||
QByteArray PrefixNode::toByteArray() const
|
QByteArray PrefixNode::toByteArray() const
|
||||||
{
|
{
|
||||||
|
if (childCount() == 0) // Can only happen when inserting a substitution from Prefix2Node::parse().
|
||||||
|
return QByteArray();
|
||||||
if (childCount() == 1)
|
if (childCount() == 1)
|
||||||
return CHILD_TO_BYTEARRAY(0);
|
return CHILD_TO_BYTEARRAY(0);
|
||||||
if (MY_CHILD_AT(childCount() - 1)->childCount() == 0) // Empty prefix2, i.e. no symbol follows.
|
if (MY_CHILD_AT(childCount() - 1)->childCount() == 0) // Empty prefix2, i.e. no symbol follows.
|
||||||
@@ -1920,7 +1889,7 @@ void PrefixNode::parse()
|
|||||||
}
|
}
|
||||||
if (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) {
|
if (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) {
|
||||||
parseState()->addSubstitution(this);
|
parseState()->addSubstitution(this);
|
||||||
parseRule<Prefix2Node>(parseState()); // Pops itself to child list.
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(Prefix2Node);
|
||||||
}
|
}
|
||||||
} else if (SubstitutionNode::mangledRepresentationStartsWith(next)) {
|
} else if (SubstitutionNode::mangledRepresentationStartsWith(next)) {
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SubstitutionNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SubstitutionNode);
|
||||||
@@ -1929,9 +1898,9 @@ void PrefixNode::parse()
|
|||||||
if (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK()))
|
if (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK()))
|
||||||
parseState()->addSubstitution(this);
|
parseState()->addSubstitution(this);
|
||||||
}
|
}
|
||||||
parseRule<Prefix2Node>(parseState()); // Pops itself to child list.
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(Prefix2Node);
|
||||||
} else {
|
} else {
|
||||||
parseRule<Prefix2Node>(parseState()); // Pops itself to child list.
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(Prefix2Node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1940,7 +1909,7 @@ bool TypeNode::mangledRepresentationStartsWith(char c)
|
|||||||
{
|
{
|
||||||
return BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
return BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| FunctionTypeNode::mangledRepresentationStartsWith(c)
|
|| FunctionTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
|| ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| ArrayTypeNode::mangledRepresentationStartsWith(c)
|
|| ArrayTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| PointerToMemberTypeNode::mangledRepresentationStartsWith(c)
|
|| PointerToMemberTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| TemplateParamNode::mangledRepresentationStartsWith(c)
|
|| TemplateParamNode::mangledRepresentationStartsWith(c)
|
||||||
@@ -2011,9 +1980,9 @@ void TypeNode::parse()
|
|||||||
m_type = OtherType;
|
m_type = OtherType;
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FunctionTypeNode);
|
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FunctionTypeNode);
|
||||||
parseState()->addSubstitution(this);
|
parseState()->addSubstitution(this);
|
||||||
} else if (ClassEnumTypeNode::mangledRepresentationStartsWith(next)) {
|
} else if (ClassEnumTypeRule::mangledRepresentationStartsWith(next)) {
|
||||||
m_type = OtherType;
|
m_type = OtherType;
|
||||||
PARSE_RULE_AND_ADD_RESULT_AS_CHILD(ClassEnumTypeNode);
|
ClassEnumTypeRule::parse(parseState(), this);
|
||||||
parseState()->addSubstitution(this);
|
parseState()->addSubstitution(this);
|
||||||
} else if (ArrayTypeNode::mangledRepresentationStartsWith(next)) {
|
} else if (ArrayTypeNode::mangledRepresentationStartsWith(next)) {
|
||||||
m_type = OtherType;
|
m_type = OtherType;
|
||||||
|
|||||||
@@ -38,10 +38,6 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
// TODO: Get the number of node objects in a tree down by only creating sub-nodes if there is really a need
|
|
||||||
// or things would get more complicated without them.
|
|
||||||
// Example for an unnecessary object: The parent type node of a function type node -- it holds zero information!
|
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -110,18 +106,6 @@ public:
|
|||||||
|
|
||||||
QByteArray toByteArray() const;
|
QByteArray toByteArray() const;
|
||||||
|
|
||||||
private:
|
|
||||||
void parse();
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: DIE!!!
|
|
||||||
class PredefinedBuiltinTypeNode : public ParseTreeNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QByteArray toByteArray() const;
|
|
||||||
|
|
||||||
void parse() {}
|
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
VoidType, WCharType, BoolType,
|
VoidType, WCharType, BoolType,
|
||||||
PlainCharType, SignedCharType, UnsignedCharType, SignedShortType, UnsignedShortType,
|
PlainCharType, SignedCharType, UnsignedCharType, SignedShortType, UnsignedShortType,
|
||||||
@@ -129,19 +113,21 @@ public:
|
|||||||
SignedLongLongType, UnsignedLongLongType, SignedInt128Type, UnsignedInt128Type,
|
SignedLongLongType, UnsignedLongLongType, SignedInt128Type, UnsignedInt128Type,
|
||||||
FloatType, DoubleType, LongDoubleType, Float128Type, EllipsisType,
|
FloatType, DoubleType, LongDoubleType, Float128Type, EllipsisType,
|
||||||
DecimalFloatingType64, DecimalFloatingType128, DecimalFloatingType32,
|
DecimalFloatingType64, DecimalFloatingType128, DecimalFloatingType32,
|
||||||
DecimalFloatingType16, Char32Type, Char16Type
|
DecimalFloatingType16, Char32Type, Char16Type, VendorType
|
||||||
} m_type;
|
};
|
||||||
};
|
Type type() const { return m_type; }
|
||||||
|
|
||||||
class CallOffsetNode : public ParseTreeNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static bool mangledRepresentationStartsWith(char c);
|
|
||||||
|
|
||||||
QByteArray toByteArray() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parse();
|
void parse();
|
||||||
|
|
||||||
|
Type m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallOffsetRule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool mangledRepresentationStartsWith(char c);
|
||||||
|
static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NvOffsetNode : public ParseTreeNode
|
class NvOffsetNode : public ParseTreeNode
|
||||||
@@ -162,26 +148,18 @@ private:
|
|||||||
void parse();
|
void parse();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClassEnumTypeNode : public ParseTreeNode
|
class ClassEnumTypeRule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool mangledRepresentationStartsWith(char c);
|
static bool mangledRepresentationStartsWith(char c);
|
||||||
|
static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode);
|
||||||
QByteArray toByteArray() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void parse();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DiscriminatorNode : public ParseTreeNode
|
class DiscriminatorRule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool mangledRepresentationStartsWith(char c);
|
static bool mangledRepresentationStartsWith(char c);
|
||||||
|
static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode);
|
||||||
QByteArray toByteArray() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void parse();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CtorDtorNameNode : public ParseTreeNode
|
class CtorDtorNameNode : public ParseTreeNode
|
||||||
@@ -305,15 +283,11 @@ private:
|
|||||||
bool m_isStringLiteral;
|
bool m_isStringLiteral;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MangledNameNode : public ParseTreeNode
|
class MangledNameRule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool mangledRepresentationStartsWith(char c);
|
static bool mangledRepresentationStartsWith(char c);
|
||||||
|
static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode);
|
||||||
QByteArray toByteArray() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void parse();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NumberNode : public ParseTreeNode
|
class NumberNode : public ParseTreeNode
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames()
|
|||||||
TEST_CORRECTLY_MANGLED_NAME("_ZplR1XS0_", "operator+(X &, X &)");
|
TEST_CORRECTLY_MANGLED_NAME("_ZplR1XS0_", "operator+(X &, X &)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZlsRK1XS1_", "operator<<(X const &, X const &)");
|
TEST_CORRECTLY_MANGLED_NAME("_ZlsRK1XS1_", "operator<<(X const &, X const &)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZN3FooIA4_iE3barE", "Foo<int[4]>::bar");
|
TEST_CORRECTLY_MANGLED_NAME("_ZN3FooIA4_iE3barE", "Foo<int[4]>::bar");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z1fIiEvi", "void f<int>(int)");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z5firstI3DuoEvS0_", "void first<Duo>(Duo)");
|
TEST_CORRECTLY_MANGLED_NAME("_Z5firstI3DuoEvS0_", "void first<Duo>(Duo)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z5firstI3DuoEvT_", "void first<Duo>(Duo)");
|
TEST_CORRECTLY_MANGLED_NAME("_Z5firstI3DuoEvT_", "void first<Duo>(Duo)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z3fooIiPFidEiEvv",
|
TEST_CORRECTLY_MANGLED_NAME("_Z3fooIiPFidEiEvv",
|
||||||
@@ -101,13 +100,6 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames()
|
|||||||
"foo()::C::bar()::E::baz()");
|
"foo()::C::bar()::E::baz()");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZZN1N1fEiE1p", "N::f(int)::p");
|
TEST_CORRECTLY_MANGLED_NAME("_ZZN1N1fEiE1p", "N::f(int)::p");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZZN1N1fEiEs", "N::f(int)::[string literal]");
|
TEST_CORRECTLY_MANGLED_NAME("_ZZN1N1fEiEs", "N::f(int)::[string literal]");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z3fooc", "foo(char)");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z2CBIL_Z3foocEE", "CB<foo(char)>");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z2CBIL_Z7IsEmptyEE", "CB<IsEmpty>");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZN1N1TIiiE2mfES0_IddE",
|
|
||||||
"N::T<int, int>::mf(N::T<double, double>)");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZSt5state", "std::state");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZNSt3_In4wardE", "std::_In::ward");
|
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_Z41__static_initialization_and_destruction_0ii",
|
TEST_CORRECTLY_MANGLED_NAME("_Z41__static_initialization_and_destruction_0ii",
|
||||||
"__static_initialization_and_destruction_0(int, int)");
|
"__static_initialization_and_destruction_0(int, int)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZN20NameDemanglerPrivate3eoiE",
|
TEST_CORRECTLY_MANGLED_NAME("_ZN20NameDemanglerPrivate3eoiE",
|
||||||
@@ -176,6 +168,40 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames()
|
|||||||
TEST_CORRECTLY_MANGLED_NAME("_ZN1CppEi", "C::operator++(int)");
|
TEST_CORRECTLY_MANGLED_NAME("_ZN1CppEi", "C::operator++(int)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZN1CmmEi", "C::operator--(int)");
|
TEST_CORRECTLY_MANGLED_NAME("_ZN1CmmEi", "C::operator--(int)");
|
||||||
TEST_CORRECTLY_MANGLED_NAME("_ZNK1CcvT_IPKcEEv", "C::operator char const *<char const *>() const");
|
TEST_CORRECTLY_MANGLED_NAME("_ZNK1CcvT_IPKcEEv", "C::operator char const *<char const *>() const");
|
||||||
|
|
||||||
|
// All examples from the ABI spec.
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZN1S1xE", "S::x");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z1fM1AKFvvE", "f(void (A::*)() const)");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z1fIiEvT_", "void f<int>(int)");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z3fooc", "foo(char)");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z2CBIL_Z3foocEE", "CB<foo(char)>");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z2CBIL_Z7IsEmptyEE", "CB<IsEmpty>");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1giEN1S1fE_2i", "g(int)::S::f(int)");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1gvEN1SC1Ev", "g()::S::S()");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZZ1gvEN1SC1EvEs", "g()::S::S()::[string literal]");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1gvE5str4a", "g()::str4a");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1gvEs_1", "g()::[string literal]");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1gvE5str4b", "g()::str4b");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z1fPFvvEM1SFvvE", "f(void (*)(), void (S::*)())");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZN1N1TIiiE2mfES0_IddE", "N::T<int, int>::mf(N::T<double, double>)");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZSt5state", "std::state");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZNSt3_In4wardE", "std::_In::ward");
|
||||||
|
|
||||||
|
/* ABI examples that do not work yet. Partly due to unimplemented C++11 features and missing ABI updates.
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z1fIiEvT_PDtfL0pK_E", "??");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z1fN1SUt_E", "f(S::{unnamed type#1})");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_Z3fooILi2EEvRAplT_Li1E_i", "template void foo<2> (int (&)[3])");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZDTpldtfp_1xdtL_Z1qE1xE", "??");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZDTplfp_dtL_Z1dEsr1B1XIT_EE1xE", "??");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZZ1giEN1S1fE_2iEUt1_", "g(int)::S::f(int)::{unnamed type#3}");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZZ1giEN1S1fE_2iENUt1_2fxEv", "g(int)::S::f(int)::{unnamed type#3}::fx()");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1giENKUlvE_clEv", "g(int)::{lambda()#1}::operator()() const");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZ1giENKUlvE0_clEv", "g(int)::{lambda()#2}::operator()() const");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZN1S1fEiiEd0_NKUlvE_clEv", "S::f(int, int)::{default arg#2}::{lambda()#1}::operator()() const");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZN1S1fEiiEd0_NKUlvE0_clEv", "S::f(int, int)::{default arg#2}::{lambda()#2}::operator()() const");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZZN1S1fEiiEd_NKUlvE_clEv", "S::f(int, int)::{default arg#1}::{lambda()#1}::operator()() const");
|
||||||
|
TEST_CORRECTLY_MANGLED_NAME("_ZNK1SIiE1xMUlvE_clEv", "S<int>::x::{lambda()#1}::operator()() const");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void NameDemanglerAutoTest::testIncorrectlyMangledNames()
|
void NameDemanglerAutoTest::testIncorrectlyMangledNames()
|
||||||
@@ -243,14 +269,14 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
|
|||||||
|
|
||||||
// <expr-primary>
|
// <expr-primary>
|
||||||
QVERIFY(!TypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!TypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !MangledNameNode::mangledRepresentationStartsWith(c));
|
|| !MangledNameRule::mangledRepresentationStartsWith(c));
|
||||||
|
|
||||||
// <type>
|
// <type>
|
||||||
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !FunctionTypeNode::mangledRepresentationStartsWith(c));
|
|| !FunctionTypeNode::mangledRepresentationStartsWith(c));
|
||||||
|
|
||||||
QVERIFY2(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY2(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !ClassEnumTypeNode::mangledRepresentationStartsWith(c) || c == 'D', &c);
|
|| !ClassEnumTypeRule::mangledRepresentationStartsWith(c) || c == 'D', &c);
|
||||||
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
@@ -262,7 +288,7 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
|
|||||||
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !ClassEnumTypeNode::mangledRepresentationStartsWith(c));
|
|| !ClassEnumTypeRule::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
||||||
@@ -273,15 +299,15 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
|
|||||||
|| !SubstitutionNode::mangledRepresentationStartsWith(c));
|
|| !SubstitutionNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
|| !ArrayTypeNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| !PointerToMemberTypeNode::mangledRepresentationStartsWith(c));
|
|| !PointerToMemberTypeNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| !TemplateParamNode::mangledRepresentationStartsWith(c));
|
|| !TemplateParamNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| !SubstitutionNode::mangledRepresentationStartsWith(c));
|
|| !SubstitutionNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c)
|
||||||
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
|| !CvQualifiersNode::mangledRepresentationStartsWith(c));
|
||||||
QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith(c)
|
QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith(c)
|
||||||
|| !PointerToMemberTypeNode::mangledRepresentationStartsWith(c));
|
|| !PointerToMemberTypeNode::mangledRepresentationStartsWith(c));
|
||||||
@@ -355,12 +381,12 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
|
|||||||
&& !FunctionTypeNode::mangledRepresentationStartsWith('G')
|
&& !FunctionTypeNode::mangledRepresentationStartsWith('G')
|
||||||
&& !FunctionTypeNode::mangledRepresentationStartsWith('U')
|
&& !FunctionTypeNode::mangledRepresentationStartsWith('U')
|
||||||
&& !FunctionTypeNode::mangledRepresentationStartsWith('D'));
|
&& !FunctionTypeNode::mangledRepresentationStartsWith('D'));
|
||||||
QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith('P')
|
QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith('P')
|
||||||
&& !ClassEnumTypeNode::mangledRepresentationStartsWith('R')
|
&& !ClassEnumTypeRule::mangledRepresentationStartsWith('R')
|
||||||
&& !ClassEnumTypeNode::mangledRepresentationStartsWith('O')
|
&& !ClassEnumTypeRule::mangledRepresentationStartsWith('O')
|
||||||
&& !ClassEnumTypeNode::mangledRepresentationStartsWith('C')
|
&& !ClassEnumTypeRule::mangledRepresentationStartsWith('C')
|
||||||
&& !ClassEnumTypeNode::mangledRepresentationStartsWith('G')
|
&& !ClassEnumTypeRule::mangledRepresentationStartsWith('G')
|
||||||
&& !ClassEnumTypeNode::mangledRepresentationStartsWith('U')
|
&& !ClassEnumTypeRule::mangledRepresentationStartsWith('U')
|
||||||
/* && !firstSetClassEnumType.contains('D') */);
|
/* && !firstSetClassEnumType.contains('D') */);
|
||||||
QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith('P')
|
QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith('P')
|
||||||
&& !ArrayTypeNode::mangledRepresentationStartsWith('R')
|
&& !ArrayTypeNode::mangledRepresentationStartsWith('R')
|
||||||
@@ -413,11 +439,11 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
|
|||||||
&& !NonNegativeNumberNode<36>::mangledRepresentationStartsWith('d'));
|
&& !NonNegativeNumberNode<36>::mangledRepresentationStartsWith('d'));
|
||||||
|
|
||||||
// <special-name>
|
// <special-name>
|
||||||
QVERIFY(!CallOffsetNode::mangledRepresentationStartsWith('V')
|
QVERIFY(!CallOffsetRule::mangledRepresentationStartsWith('V')
|
||||||
&& !CallOffsetNode::mangledRepresentationStartsWith('T')
|
&& !CallOffsetRule::mangledRepresentationStartsWith('T')
|
||||||
&& !CallOffsetNode::mangledRepresentationStartsWith('I')
|
&& !CallOffsetRule::mangledRepresentationStartsWith('I')
|
||||||
&& !CallOffsetNode::mangledRepresentationStartsWith('S')
|
&& !CallOffsetRule::mangledRepresentationStartsWith('S')
|
||||||
&& !CallOffsetNode::mangledRepresentationStartsWith('c'));
|
&& !CallOffsetRule::mangledRepresentationStartsWith('c'));
|
||||||
|
|
||||||
// <unscoped-name>
|
// <unscoped-name>
|
||||||
QVERIFY(!UnqualifiedNameNode::mangledRepresentationStartsWith('S'));
|
QVERIFY(!UnqualifiedNameNode::mangledRepresentationStartsWith('S'));
|
||||||
|
|||||||
Reference in New Issue
Block a user