Commit 889409f2 authored by Christian Kandeler's avatar Christian Kandeler
Browse files

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: default avatarFriedemann Kleint <Friedemann.Kleint@nokia.com>
parent d77d8fba
......@@ -61,7 +61,7 @@ public:
#define DEMANGLER_ASSERT(cond) \
do { \
if (!cond) { \
if (!(cond)) { \
throw InternalDemanglerException(Q_FUNC_INFO, __FILE__, __LINE__); \
} \
} while (0)
......
......@@ -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);
}
......
......@@ -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); }
......
......@@ -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) {
......
......@@ -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
......
......@@ -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'));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment