diff options
author | Christian Kandeler <christian.kandeler@nokia.com> | 2012-07-06 20:03:58 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@nokia.com> | 2012-07-09 12:14:46 +0200 |
commit | 889409f2cd7ad9a02bf5b2ae2f4e541a7ae791f7 (patch) | |
tree | fbb3dadb1a6924b2734d9ecf53764496ddd44dbb | |
parent | d77d8fba437f9a17ae6fe59241b6e45a24a353cd (diff) | |
download | qt-creator-889409f2cd7ad9a02bf5b2ae2f4e541a7ae791f7.tar.gz |
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>
7 files changed, 210 insertions, 236 deletions
diff --git a/src/plugins/debugger/namedemangler/demanglerexceptions.h b/src/plugins/debugger/namedemangler/demanglerexceptions.h index 2410e95ed2..5132995d02 100644 --- a/src/plugins/debugger/namedemangler/demanglerexceptions.h +++ b/src/plugins/debugger/namedemangler/demanglerexceptions.h @@ -61,7 +61,7 @@ public: #define DEMANGLER_ASSERT(cond) \ do { \ - if (!cond) { \ + if (!(cond)) { \ throw InternalDemanglerException(Q_FUNC_INFO, __FILE__, __LINE__); \ } \ } while (0) diff --git a/src/plugins/debugger/namedemangler/globalparsestate.cpp b/src/plugins/debugger/namedemangler/globalparsestate.cpp index 0c11239622..9a47348522 100644 --- a/src/plugins/debugger/namedemangler/globalparsestate.cpp +++ b/src/plugins/debugger/namedemangler/globalparsestate.cpp @@ -68,7 +68,11 @@ QByteArray GlobalParseState::readAhead(int charCount) const 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)) m_substitutions.append(symbol); } diff --git a/src/plugins/debugger/namedemangler/globalparsestate.h b/src/plugins/debugger/namedemangler/globalparsestate.h index 796681c22a..0037eaa349 100644 --- a/src/plugins/debugger/namedemangler/globalparsestate.h +++ b/src/plugins/debugger/namedemangler/globalparsestate.h @@ -57,6 +57,7 @@ public: int substitutionCount() const { return m_substitutions.count(); } QByteArray substitutionAt(int index) const { return m_substitutions.at(index); } void addSubstitution(const ParseTreeNode *node); + void addSubstitution(const QByteArray &symbol); int templateParamCount() const { return m_templateParams.count(); } ParseTreeNode *templateParamAt(int index) const { return m_templateParams.at(index); } diff --git a/src/plugins/debugger/namedemangler/namedemangler.cpp b/src/plugins/debugger/namedemangler/namedemangler.cpp index b0c41886a1..0ddbcf588a 100644 --- a/src/plugins/debugger/namedemangler/namedemangler.cpp +++ b/src/plugins/debugger/namedemangler/namedemangler.cpp @@ -63,12 +63,12 @@ bool NameDemanglerPrivate::demangle(const QString &mangledName) m_parseState.m_isConversionOperator = false; m_demangledName.clear(); - if (!MangledNameNode::mangledRepresentationStartsWith(m_parseState.peek())) { + if (!MangledNameRule::mangledRepresentationStartsWith(m_parseState.peek())) { m_demangledName = m_parseState.m_mangledName; return true; } - ParseTreeNode::parseRule<MangledNameNode>(&m_parseState); + MangledNameRule::parse(&m_parseState, 0); if (m_parseState.m_pos != m_parseState.m_mangledName.size()) throw ParseException(QLatin1String("Unconsumed input")); if (m_parseState.m_parseStack.count() != 1) { diff --git a/src/plugins/debugger/namedemangler/parsetreenodes.cpp b/src/plugins/debugger/namedemangler/parsetreenodes.cpp index 6855f19699..e197b531e6 100644 --- a/src/plugins/debugger/namedemangler/parsetreenodes.cpp +++ b/src/plugins/debugger/namedemangler/parsetreenodes.cpp @@ -39,14 +39,19 @@ #define PEEK() (parseState()->peek()) #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 { \ - parseRule<nodeType>(parseState()); \ - DEMANGLER_ASSERT(parseState()->stackElementCount() > 0); \ - DEMANGLER_ASSERT(dynamic_cast<nodeType *>(parseState()->stackTop())); \ - addChild(parseState()->popFromStack()); \ + ParseTreeNode::parseRule<nodeType>(parseState); \ + DEMANGLER_ASSERT(parseState->stackElementCount() > 0); \ + DEMANGLER_ASSERT(dynamic_cast<nodeType *>(parseState->stackTop())); \ + if (parentNode) \ + (parentNode)->addChild(parseState->popFromStack()); \ } 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 MY_CHILD_AT(index) CHILD_AT(this, index) #define CHILD_TO_BYTEARRAY(index) MY_CHILD_AT(index)->toByteArray() @@ -211,66 +216,95 @@ void BuiltinTypeNode::parse() { const char next = ADVANCE(); if (next == 'u') { + m_type = VendorType; PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SourceNameNode); - } else { - // 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) { - case 'v': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::VoidType; break; - case 'w': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::WCharType; break; - case 'b': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::BoolType; break; - case 'c': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::PlainCharType; break; - case 'a': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedCharType; break; - case 'h': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedCharType; break; - case 's': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedShortType; break; - case 't': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedShortType; break; - case 'i': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedIntType; break; - case 'j': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedIntType; break; - case 'l': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedLongType; break; - case 'm': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedLongType; break; - case 'x': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedLongLongType; break; - case 'y': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedLongLongType; break; - case 'n': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::SignedInt128Type; break; - case 'o': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::UnsignedInt128Type; break; - case 'f': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::FloatType; break; - case 'd': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::DoubleType; break; - case 'e': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::LongDoubleType; break; - case 'g': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::Float128Type; break; - case 'z': fixedTypeNode->m_type = PredefinedBuiltinTypeNode::EllipsisType; break; - case 'D': - switch (ADVANCE()) { - case 'd': - fixedTypeNode->m_type = PredefinedBuiltinTypeNode::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")); - } + return; + } + + switch (next) { + case 'v': m_type = VoidType; break; + case 'w': m_type = WCharType; break; + case 'b': m_type = BoolType; break; + case 'c': m_type = PlainCharType; break; + case 'a': m_type = SignedCharType; break; + case 'h': m_type = UnsignedCharType; break; + case 's': m_type = SignedShortType; break; + case 't': m_type = UnsignedShortType; break; + case 'i': m_type = SignedIntType; break; + case 'j': m_type = UnsignedIntType; break; + case 'l': m_type = SignedLongType; break; + case 'm': m_type = UnsignedLongType; break; + case 'x': m_type = SignedLongLongType; break; + case 'y': m_type = UnsignedLongLongType; break; + case 'n': m_type = SignedInt128Type; break; + case 'o': m_type = UnsignedInt128Type; break; + case 'f': m_type = FloatType; break; + case 'd': m_type = DoubleType; break; + case 'e': m_type = LongDoubleType; break; + case 'g': m_type = Float128Type; break; + case 'z': m_type = EllipsisType; break; + case 'D': + switch (ADVANCE()) { + case 'd': + m_type = DecimalFloatingType64; break; - default: - DEMANGLER_ASSERT(false); + case 'e': + 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 { - 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'; } @@ -279,24 +313,18 @@ bool CallOffsetNode::mangledRepresentationStartsWith(char c) * <call-offset> ::= h <nv-offset> _ * ::= v <v-offset> _ */ -void CallOffsetNode::parse() +void CallOffsetRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode) { - switch (ADVANCE()) { - case 'h': PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NvOffsetNode); break; - case 'v': PARSE_RULE_AND_ADD_RESULT_AS_CHILD(VOffsetNode); break; + switch (parseState->advance()) { + case 'h': PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NvOffsetNode, parseState, parentNode); break; + case 'v': PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(VOffsetNode, parseState, parentNode); break; default: DEMANGLER_ASSERT(false); } - if (ADVANCE() != '_') + if (parseState->advance() != '_') throw ParseException(QString::fromLatin1("Invalid call-offset")); } -QByteArray CallOffsetNode::toByteArray() const -{ - return CHILD_TO_BYTEARRAY(0); -} - - -bool ClassEnumTypeNode::mangledRepresentationStartsWith(char c) +bool ClassEnumTypeRule::mangledRepresentationStartsWith(char c) { /* * The first set of <class-enum-type> is much smaller than @@ -308,33 +336,23 @@ bool ClassEnumTypeNode::mangledRepresentationStartsWith(char c) } /* <class-enum-type> ::= <name> */ -void ClassEnumTypeNode::parse() +void ClassEnumTypeRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode) { - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NameNode); -} - -QByteArray ClassEnumTypeNode::toByteArray() const -{ - return CHILD_TO_BYTEARRAY(0); + PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NameNode, parseState, parentNode); } -bool DiscriminatorNode::mangledRepresentationStartsWith(char c) +bool DiscriminatorRule::mangledRepresentationStartsWith(char c) { return c == '_'; } /* <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")); - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NonNegativeNumberNode<10>); -} - -QByteArray DiscriminatorNode::toByteArray() const -{ - return CHILD_TO_BYTEARRAY(0); + PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(NonNegativeNumberNode<10>, parseState, parentNode); } @@ -960,44 +978,6 @@ QByteArray OperatorNameNode::toByteArray() const 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) { return c == 'L'; @@ -1020,27 +1000,23 @@ void ExprPrimaryNode::parse() ? 0 : dynamic_cast<BuiltinTypeNode * >(CHILD_AT(topLevelTypeNode, 0)); if (!typeNode) 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? - switch (predefTypeNode->m_type) { - case PredefinedBuiltinTypeNode::SignedIntType: - case PredefinedBuiltinTypeNode::UnsignedIntType: - case PredefinedBuiltinTypeNode::UnsignedLongType: + switch (typeNode->type()) { + case BuiltinTypeNode::SignedIntType: + case BuiltinTypeNode::UnsignedIntType: + case BuiltinTypeNode::UnsignedLongType: PARSE_RULE_AND_ADD_RESULT_AS_CHILD(NumberNode); break; - case PredefinedBuiltinTypeNode::FloatType: case PredefinedBuiltinTypeNode::DoubleType: + case BuiltinTypeNode::FloatType: case BuiltinTypeNode::DoubleType: PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FloatValueNode); break; default: throw ParseException(QString::fromLatin1("Invalid type in expr-primary")); } delete parseState()->popFromStack(); // No need to keep the type node in the tree. - } else if (MangledNameNode::mangledRepresentationStartsWith(next)) { - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(MangledNameNode); + } else if (MangledNameRule::mangledRepresentationStartsWith(next)) { + MangledNameRule::parse(parseState(), this); } else { throw ParseException(QString::fromLatin1("Invalid expr-primary")); } @@ -1115,8 +1091,8 @@ void LocalNameNode::parse() } else { throw ParseException(QString::fromLatin1("Invalid local-name")); } - if (DiscriminatorNode::mangledRepresentationStartsWith(PEEK())) - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(DiscriminatorNode); + if (DiscriminatorRule::mangledRepresentationStartsWith(PEEK())) + DiscriminatorRule::parse(parseState(), this); } QByteArray LocalNameNode::toByteArray() const @@ -1131,15 +1107,16 @@ QByteArray LocalNameNode::toByteArray() const hasDiscriminator = childCount() == 3; } if (hasDiscriminator) { - const QByteArray discriminator = MY_CHILD_AT(childCount() - 1)->toByteArray(); - const int rawDiscriminatorValue = discriminator.toInt(); - name += " (occurrence number " + QByteArray::number(rawDiscriminatorValue - 2) + ')'; + // TODO: Does this information serve any purpose? Names seem to demangle fine without printing anything here. +// const QByteArray discriminator = MY_CHILD_AT(childCount() - 1)->toByteArray(); +// const int rawDiscriminatorValue = discriminator.toInt(); +// name += " (occurrence number " + QByteArray::number(rawDiscriminatorValue - 2) + ')'; } return name; } -bool MangledNameNode::mangledRepresentationStartsWith(char c) +bool MangledNameRule::mangledRepresentationStartsWith(char c) { return c == '_'; } @@ -1150,15 +1127,10 @@ bool MangledNameNode::mangledRepresentationStartsWith(char c) * were necessary, which we will document at the respective parsing function. * <mangled-name> ::= _Z <encoding> */ -void MangledNameNode::parse() +void MangledNameRule::parse(GlobalParseState *parseState, ParseTreeNode *parentNode) { - parseState()->advance(2); - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode); -} - -QByteArray MangledNameNode::toByteArray() const -{ - return pasteAllChildren(); + parseState->advance(2); + PARSE_RULE_AND_ADD_RESULT_AS_CHILD_TO_NODE(EncodingNode, parseState, parentNode); } @@ -1573,11 +1545,12 @@ void SpecialNameNode::parse() } else if (str == "Tc") { m_type = DoubleCallOffsetType; parseState()->advance(2); - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(CallOffsetNode); - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(CallOffsetNode); + CallOffsetRule::parse(parseState(), this); + CallOffsetRule::parse(parseState(), this); PARSE_RULE_AND_ADD_RESULT_AS_CHILD(EncodingNode); } 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); } else { throw ParseException(QString::fromLatin1("Invalid special-name")); @@ -1820,7 +1793,7 @@ QByteArray Prefix2Node::toByteArray() 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 @@ -1839,22 +1812,16 @@ bool Prefix2Node::isConstructorOrDestructorOrConversionOperator() const */ 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 = parseState()->stackElementAt(parseState()->stackElementCount() - 2); - prefixNode->addChild(this); - parseState()->popFromStack(); bool firstRun = true; while (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) { if (!firstRun) - parseState()->addSubstitution(prefixNode); + parseState()->addSubstitution(prefixNode->toByteArray() + toByteArray()); PARSE_RULE_AND_ADD_RESULT_AS_CHILD(UnqualifiedNameNode); if (TemplateArgsNode::mangledRepresentationStartsWith(PEEK())) { - parseState()->addSubstitution(prefixNode); + parseState()->addSubstitution(prefixNode->toByteArray() + toByteArray()); PARSE_RULE_AND_ADD_RESULT_AS_CHILD(TemplateArgsNode); } firstRun = false; @@ -1871,6 +1838,8 @@ bool PrefixNode::mangledRepresentationStartsWith(char c) QByteArray PrefixNode::toByteArray() const { + if (childCount() == 0) // Can only happen when inserting a substitution from Prefix2Node::parse(). + return QByteArray(); if (childCount() == 1) return CHILD_TO_BYTEARRAY(0); 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())) { parseState()->addSubstitution(this); - parseRule<Prefix2Node>(parseState()); // Pops itself to child list. + PARSE_RULE_AND_ADD_RESULT_AS_CHILD(Prefix2Node); } } else if (SubstitutionNode::mangledRepresentationStartsWith(next)) { PARSE_RULE_AND_ADD_RESULT_AS_CHILD(SubstitutionNode); @@ -1929,9 +1898,9 @@ void PrefixNode::parse() if (UnqualifiedNameNode::mangledRepresentationStartsWith(PEEK())) parseState()->addSubstitution(this); } - parseRule<Prefix2Node>(parseState()); // Pops itself to child list. + PARSE_RULE_AND_ADD_RESULT_AS_CHILD(Prefix2Node); } 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) || FunctionTypeNode::mangledRepresentationStartsWith(c) - || ClassEnumTypeNode::mangledRepresentationStartsWith(c) + || ClassEnumTypeRule::mangledRepresentationStartsWith(c) || ArrayTypeNode::mangledRepresentationStartsWith(c) || PointerToMemberTypeNode::mangledRepresentationStartsWith(c) || TemplateParamNode::mangledRepresentationStartsWith(c) @@ -2011,9 +1980,9 @@ void TypeNode::parse() m_type = OtherType; PARSE_RULE_AND_ADD_RESULT_AS_CHILD(FunctionTypeNode); parseState()->addSubstitution(this); - } else if (ClassEnumTypeNode::mangledRepresentationStartsWith(next)) { + } else if (ClassEnumTypeRule::mangledRepresentationStartsWith(next)) { m_type = OtherType; - PARSE_RULE_AND_ADD_RESULT_AS_CHILD(ClassEnumTypeNode); + ClassEnumTypeRule::parse(parseState(), this); parseState()->addSubstitution(this); } else if (ArrayTypeNode::mangledRepresentationStartsWith(next)) { m_type = OtherType; diff --git a/src/plugins/debugger/namedemangler/parsetreenodes.h b/src/plugins/debugger/namedemangler/parsetreenodes.h index 3ac415a9b3..b0b7e6cc8a 100644 --- a/src/plugins/debugger/namedemangler/parsetreenodes.h +++ b/src/plugins/debugger/namedemangler/parsetreenodes.h @@ -38,10 +38,6 @@ #include <QList> #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 Internal { @@ -110,18 +106,6 @@ public: QByteArray toByteArray() const; -private: - void parse(); -}; - -// TODO: DIE!!! -class PredefinedBuiltinTypeNode : public ParseTreeNode -{ -public: - QByteArray toByteArray() const; - - void parse() {} - enum Type { VoidType, WCharType, BoolType, PlainCharType, SignedCharType, UnsignedCharType, SignedShortType, UnsignedShortType, @@ -129,19 +113,21 @@ public: SignedLongLongType, UnsignedLongLongType, SignedInt128Type, UnsignedInt128Type, FloatType, DoubleType, LongDoubleType, Float128Type, EllipsisType, DecimalFloatingType64, DecimalFloatingType128, DecimalFloatingType32, - DecimalFloatingType16, Char32Type, Char16Type - } m_type; + DecimalFloatingType16, Char32Type, Char16Type, VendorType + }; + Type type() const { return m_type; } + +private: + void parse(); + + Type m_type; }; -class CallOffsetNode : public ParseTreeNode +class CallOffsetRule { public: static bool mangledRepresentationStartsWith(char c); - - QByteArray toByteArray() const; - -private: - void parse(); + static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode); }; class NvOffsetNode : public ParseTreeNode @@ -162,26 +148,18 @@ private: void parse(); }; -class ClassEnumTypeNode : public ParseTreeNode +class ClassEnumTypeRule { public: static bool mangledRepresentationStartsWith(char c); - - QByteArray toByteArray() const; - -private: - void parse(); + static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode); }; -class DiscriminatorNode : public ParseTreeNode +class DiscriminatorRule { public: static bool mangledRepresentationStartsWith(char c); - - QByteArray toByteArray() const; - -private: - void parse(); + static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode); }; class CtorDtorNameNode : public ParseTreeNode @@ -305,15 +283,11 @@ private: bool m_isStringLiteral; }; -class MangledNameNode : public ParseTreeNode +class MangledNameRule { public: static bool mangledRepresentationStartsWith(char c); - - QByteArray toByteArray() const; - -private: - void parse(); + static void parse(GlobalParseState *parseState, ParseTreeNode *parentNode); }; class NumberNode : public ParseTreeNode diff --git a/tests/auto/debugger/tst_namedemangler.cpp b/tests/auto/debugger/tst_namedemangler.cpp index 7cdb5a0823..1e7cd9a16c 100644 --- a/tests/auto/debugger/tst_namedemangler.cpp +++ b/tests/auto/debugger/tst_namedemangler.cpp @@ -71,7 +71,6 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames() TEST_CORRECTLY_MANGLED_NAME("_ZplR1XS0_", "operator+(X &, X &)"); TEST_CORRECTLY_MANGLED_NAME("_ZlsRK1XS1_", "operator<<(X const &, X const &)"); 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("_Z5firstI3DuoEvT_", "void first<Duo>(Duo)"); TEST_CORRECTLY_MANGLED_NAME("_Z3fooIiPFidEiEvv", @@ -101,13 +100,6 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames() "foo()::C::bar()::E::baz()"); TEST_CORRECTLY_MANGLED_NAME("_ZZN1N1fEiE1p", "N::f(int)::p"); 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", "__static_initialization_and_destruction_0(int, int)"); TEST_CORRECTLY_MANGLED_NAME("_ZN20NameDemanglerPrivate3eoiE", @@ -176,6 +168,40 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames() TEST_CORRECTLY_MANGLED_NAME("_ZN1CppEi", "C::operator++(int)"); TEST_CORRECTLY_MANGLED_NAME("_ZN1CmmEi", "C::operator--(int)"); 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() @@ -243,14 +269,14 @@ void NameDemanglerAutoTest::testDisjunctFirstSets() // <expr-primary> QVERIFY(!TypeNode::mangledRepresentationStartsWith(c) - || !MangledNameNode::mangledRepresentationStartsWith(c)); + || !MangledNameRule::mangledRepresentationStartsWith(c)); // <type> QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c) || !FunctionTypeNode::mangledRepresentationStartsWith(c)); QVERIFY2(!BuiltinTypeNode::mangledRepresentationStartsWith(c) - || !ClassEnumTypeNode::mangledRepresentationStartsWith(c) || c == 'D', &c); + || !ClassEnumTypeRule::mangledRepresentationStartsWith(c) || c == 'D', &c); QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c) || !ArrayTypeNode::mangledRepresentationStartsWith(c)); QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c) @@ -262,7 +288,7 @@ void NameDemanglerAutoTest::testDisjunctFirstSets() QVERIFY(!BuiltinTypeNode::mangledRepresentationStartsWith(c) || !CvQualifiersNode::mangledRepresentationStartsWith(c)); QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c) - || !ClassEnumTypeNode::mangledRepresentationStartsWith(c)); + || !ClassEnumTypeRule::mangledRepresentationStartsWith(c)); QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c) || !ArrayTypeNode::mangledRepresentationStartsWith(c)); QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c) @@ -273,15 +299,15 @@ void NameDemanglerAutoTest::testDisjunctFirstSets() || !SubstitutionNode::mangledRepresentationStartsWith(c)); QVERIFY(!FunctionTypeNode::mangledRepresentationStartsWith(c) || !CvQualifiersNode::mangledRepresentationStartsWith(c)); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c) + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c) || !ArrayTypeNode::mangledRepresentationStartsWith(c)); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c) + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c) || !PointerToMemberTypeNode::mangledRepresentationStartsWith(c)); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c) + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c) || !TemplateParamNode::mangledRepresentationStartsWith(c)); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c) + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c) || !SubstitutionNode::mangledRepresentationStartsWith(c)); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith(c) + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith(c) || !CvQualifiersNode::mangledRepresentationStartsWith(c)); QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith(c) || !PointerToMemberTypeNode::mangledRepresentationStartsWith(c)); @@ -355,12 +381,12 @@ void NameDemanglerAutoTest::testDisjunctFirstSets() && !FunctionTypeNode::mangledRepresentationStartsWith('G') && !FunctionTypeNode::mangledRepresentationStartsWith('U') && !FunctionTypeNode::mangledRepresentationStartsWith('D')); - QVERIFY(!ClassEnumTypeNode::mangledRepresentationStartsWith('P') - && !ClassEnumTypeNode::mangledRepresentationStartsWith('R') - && !ClassEnumTypeNode::mangledRepresentationStartsWith('O') - && !ClassEnumTypeNode::mangledRepresentationStartsWith('C') - && !ClassEnumTypeNode::mangledRepresentationStartsWith('G') - && !ClassEnumTypeNode::mangledRepresentationStartsWith('U') + QVERIFY(!ClassEnumTypeRule::mangledRepresentationStartsWith('P') + && !ClassEnumTypeRule::mangledRepresentationStartsWith('R') + && !ClassEnumTypeRule::mangledRepresentationStartsWith('O') + && !ClassEnumTypeRule::mangledRepresentationStartsWith('C') + && !ClassEnumTypeRule::mangledRepresentationStartsWith('G') + && !ClassEnumTypeRule::mangledRepresentationStartsWith('U') /* && !firstSetClassEnumType.contains('D') */); QVERIFY(!ArrayTypeNode::mangledRepresentationStartsWith('P') && !ArrayTypeNode::mangledRepresentationStartsWith('R') @@ -413,11 +439,11 @@ void NameDemanglerAutoTest::testDisjunctFirstSets() && !NonNegativeNumberNode<36>::mangledRepresentationStartsWith('d')); // <special-name> - QVERIFY(!CallOffsetNode::mangledRepresentationStartsWith('V') - && !CallOffsetNode::mangledRepresentationStartsWith('T') - && !CallOffsetNode::mangledRepresentationStartsWith('I') - && !CallOffsetNode::mangledRepresentationStartsWith('S') - && !CallOffsetNode::mangledRepresentationStartsWith('c')); + QVERIFY(!CallOffsetRule::mangledRepresentationStartsWith('V') + && !CallOffsetRule::mangledRepresentationStartsWith('T') + && !CallOffsetRule::mangledRepresentationStartsWith('I') + && !CallOffsetRule::mangledRepresentationStartsWith('S') + && !CallOffsetRule::mangledRepresentationStartsWith('c')); // <unscoped-name> QVERIFY(!UnqualifiedNameNode::mangledRepresentationStartsWith('S')); |