Commit 26c4329f authored by Christian Kandeler's avatar Christian Kandeler
Browse files

Name demangler: Fix reference collapsing.



Change-Id: I7bcf1ace346ffcb5e05242f6cedfc5439c97fff9
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent 2dc005ca
......@@ -31,6 +31,7 @@
#define DEMANGLEREXCEPTIONS_H
#include <QtGlobal>
#include <QSharedPointer>
#include <QString>
namespace Debugger {
......@@ -64,10 +65,10 @@ public:
} \
} while (0)
template <typename T> T *demanglerCast(ParseTreeNode *node, const QString &func,
const QString &file, int line)
template <typename T> QSharedPointer<T> demanglerCast(const QSharedPointer<ParseTreeNode> &node,
const QString &func, const QString &file, int line)
{
T * const out = dynamic_cast<T *>(node);
const QSharedPointer<T> out = node.dynamicCast<T>();
if (!out)
throw InternalDemanglerException(func, file, line);
return out;
......
......@@ -64,15 +64,9 @@ QByteArray GlobalParseState::readAhead(int charCount) const
return str;
}
void GlobalParseState::addSubstitution(const ParseTreeNode *node)
void GlobalParseState::addSubstitution(const QSharedPointer<ParseTreeNode> &node)
{
addSubstitution(node->toByteArray());
}
void GlobalParseState::addSubstitution(const QByteArray &symbol)
{
if (!symbol.isEmpty())
m_substitutions.append(symbol);
m_substitutions << node->clone();
}
} // namespace Internal
......
......@@ -31,6 +31,7 @@
#define GLOBAL_PARSE_STATE_H
#include <QByteArray>
#include <QSharedPointer>
#include <QStack>
namespace Debugger {
......@@ -47,25 +48,24 @@ public:
QByteArray readAhead(int charCount) const;
int stackElementCount() const { return m_parseStack.count(); }
ParseTreeNode *stackTop() const { return m_parseStack.top(); }
ParseTreeNode *stackElementAt(int index) const { return m_parseStack.at(index); }
void pushToStack(ParseTreeNode *node) { m_parseStack.push(node); }
ParseTreeNode *popFromStack() { return m_parseStack.pop(); }
QSharedPointer<ParseTreeNode> stackTop() const { return m_parseStack.top(); }
QSharedPointer<ParseTreeNode> stackElementAt(int index) const { return m_parseStack.at(index); }
void pushToStack(const QSharedPointer<ParseTreeNode> &node) { m_parseStack.push(node); }
QSharedPointer<ParseTreeNode> popFromStack() { return m_parseStack.pop(); }
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);
QSharedPointer<ParseTreeNode> substitutionAt(int index) const { return m_substitutions.at(index); }
void addSubstitution(const QSharedPointer<ParseTreeNode> &node);
int templateParamCount() const { return m_templateParams.count(); }
ParseTreeNode *templateParamAt(int index) const { return m_templateParams.at(index); }
void addTemplateParam(ParseTreeNode *node) { m_templateParams << node; }
QSharedPointer<ParseTreeNode> templateParamAt(int index) const { return m_templateParams.at(index); }
void addTemplateParam(const QSharedPointer<ParseTreeNode> &node) { m_templateParams << node; }
private:
int m_pos;
QByteArray m_mangledName;
QList<QByteArray> m_substitutions;
QList<ParseTreeNode *> m_templateParams;
QStack<ParseTreeNode *> m_parseStack;
QList<QSharedPointer<ParseTreeNode> > m_substitutions;
QList<QSharedPointer<ParseTreeNode> > m_templateParams;
QStack<QSharedPointer<ParseTreeNode> > m_parseStack;
static const char eoi = '$';
};
......
......@@ -65,29 +65,18 @@ bool NameDemanglerPrivate::demangle(const QString &mangledName)
return true;
}
MangledNameRule::parse(&m_parseState, 0);
MangledNameRule::parse(&m_parseState, ParseTreeNode::Ptr());
if (m_parseState.m_pos != m_parseState.m_mangledName.size())
throw ParseException(QLatin1String("Unconsumed input"));
if (m_parseState.m_parseStack.count() != 1) {
throw ParseException(QString::fromLocal8Bit("There are %1 elements on the parse stack; "
"expected one.").arg(m_parseState.m_parseStack.count()));
}
m_demangledName = m_parseState.m_parseStack.top()->toByteArray();
/*
* FIXME: This is a hack we do because TypeNode::toByteArray() cannot catch all
* all nested reference due to the way substitutions are currently implented.
* Note that even with this hack, we do not catch things like
* "reference to reference to array", because the operators do not follow each other
* in the string.
* For a correct solution, we'll probably have to clone substitution nodes instead of
* just dumping their strings (which means adding a copy constructor and a clone function
* to every node).
*/
m_demangledName.replace("&& &&", "&&");
m_demangledName.replace("&& &", "&");
m_demangledName.replace(" & &", "&");
// Uncomment for debugging.
//m_parseState.stackTop()->print(0);
m_demangledName = m_parseState.stackTop()->toByteArray();
success = true;
} catch (const ParseException &p) {
m_errorString = QString::fromLocal8Bit("Parse error at index %1 of mangled name '%2': %3.")
......@@ -99,7 +88,6 @@ bool NameDemanglerPrivate::demangle(const QString &mangledName)
success = false;
}
qDeleteAll(m_parseState.m_parseStack);
m_parseState.m_parseStack.clear();
m_parseState.m_substitutions.clear();
m_parseState.m_templateParams.clear();
......
......@@ -177,10 +177,9 @@ void NameDemanglerAutoTest::testCorrectlyMangledNames()
TEST_CORRECTLY_MANGLED_NAME("_Z8toStringIiESsT_",
"std::basic_string<char, std::char_traits<char>, std::allocator<char> > toString<int>(int)");
// TODO: The rvalue reference at the end has to actually collapse. Remove it once collapsing
// is properly implemented.
TEST_CORRECTLY_MANGLED_NAME("_Z4funcIRA5_iEvOT_", "void func<int (&)[5]>(int (&)[5])");
TEST_CORRECTLY_MANGLED_NAME("_ZSt9make_pairIiRA5_KcESt4pairINSt17__decay_and_stripIT_E6__typeENS4_IT0_E6__typeEEOS5_OS8_",
"std::pair<std::__decay_and_strip<int>::__type, std::__decay_and_strip<char const (&)[5]>::__type> std::make_pair<int, char const (&)[5]>(int &&, char const (&)[5] &&)");
"std::pair<std::__decay_and_strip<int>::__type, std::__decay_and_strip<char const (&)[5]>::__type> std::make_pair<int, char const (&)[5]>(int &&, char const (&)[5])");
// All examples from the ABI spec.
TEST_CORRECTLY_MANGLED_NAME("_ZN1S1xE", "S::x");
......@@ -257,15 +256,11 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
QVERIFY(!TemplateParamNode::mangledRepresentationStartsWith(c)
|| !SubstitutionNode::mangledRepresentationStartsWith(c));
QVERIFY(!TemplateArgsNode::mangledRepresentationStartsWith(c)
|| !Prefix2Node::mangledRepresentationStartsWith(c));
|| !UnqualifiedNameNode::mangledRepresentationStartsWith(c));
QVERIFY(!TemplateParamNode::mangledRepresentationStartsWith(c)
|| !Prefix2Node::mangledRepresentationStartsWith(c));
|| !UnqualifiedNameNode::mangledRepresentationStartsWith(c));
QVERIFY(!SubstitutionNode::mangledRepresentationStartsWith(c)
|| !Prefix2Node::mangledRepresentationStartsWith(c));
// <prefix2>
QVERIFY(!TemplateArgsNode::mangledRepresentationStartsWith(c)
|| !Prefix2Node::mangledRepresentationStartsWith(c));
|| !UnqualifiedNameNode::mangledRepresentationStartsWith(c));
// <template-arg>
QVERIFY(!TypeNode::mangledRepresentationStartsWith(c)
......@@ -515,9 +510,9 @@ void NameDemanglerAutoTest::testDisjunctFirstSets()
// <unscoped-name>
QVERIFY(!UnqualifiedNameNode::mangledRepresentationStartsWith('S'));
// <prefix2>
// <prefix>
QVERIFY(!TemplateArgsNode::mangledRepresentationStartsWith('M'));
QVERIFY(!Prefix2Node::mangledRepresentationStartsWith('M'));
QVERIFY(!UnqualifiedNameNode::mangledRepresentationStartsWith('M'));
// <base-unresolved-name>
QVERIFY(!SimpleIdNode::mangledRepresentationStartsWith('o'));
......
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