Debugger: Make rvalue dumper pass

Depending on whether DWARF-2 or DWARF-4 is used, compilers encode
rvalue references as lvalue reference or rvalue references.

GDB doesn't understand rvalues, and there's no workaround, so restrict
the test to compiler version that use DWARF-2 by default.
(see https://sourceware.org/bugzilla/show_bug.cgi?id=14441)

Change-Id: I98ed73844571a07e81003cf99c6d7e0be37722b5
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
hjk
2016-11-01 14:26:30 +01:00
parent 0eb52e1929
commit 8c9856d3d1

View File

@@ -192,6 +192,13 @@ struct QtVersion : VersionBase
{} {}
}; };
struct DwarfVersion : VersionBase
{
DwarfVersion(int minimum = 0, int maximum = INT_MAX)
: VersionBase(minimum, maximum)
{}
};
struct GccVersion : VersionBase struct GccVersion : VersionBase
{ {
GccVersion(int minimum = 0, int maximum = INT_MAX) GccVersion(int minimum = 0, int maximum = INT_MAX)
@@ -291,12 +298,6 @@ struct Value
} }
} }
} }
if (minimalGccVersion && context.gccVersion) {
if (minimalGccVersion >= context.gccVersion) {
//QWARN("Current GCC is too old for this test.")
return true;
}
}
QString actualValue = actualValue0; QString actualValue = actualValue0;
if (actualValue == " ") if (actualValue == " ")
actualValue.clear(); // FIXME: Remove later. actualValue.clear(); // FIXME: Remove later.
@@ -332,15 +333,12 @@ struct Value
return actualValue == expectedValue; return actualValue == expectedValue;
} }
void setMinimalGccVersion(int version) { minimalGccVersion = version; }
QString value; QString value;
bool hasPtrSuffix = false; bool hasPtrSuffix = false;
bool isFloatValue = false; bool isFloatValue = false;
bool substituteNamespace = true; bool substituteNamespace = true;
bool isPattern = false; bool isPattern = false;
int qtVersion = 0; int qtVersion = 0;
int minimalGccVersion = 0;
}; };
struct ValuePattern : Value struct ValuePattern : Value
@@ -443,9 +441,9 @@ struct Type5 : Type
Type5(const QString &ba) : Type(ba) { qtVersion = 5; } Type5(const QString &ba) : Type(ba) { qtVersion = 5; }
}; };
struct Pattern : Type struct TypePattern : Type
{ {
Pattern(const QString &ba) : Type(ba) { isPattern = true; } TypePattern(const QString &ba) : Type(ba) { isPattern = true; }
}; };
enum DebuggerEngine enum DebuggerEngine
@@ -637,6 +635,7 @@ struct MacLibCppProfile : public Profile
struct ForceC {}; struct ForceC {};
struct EigenProfile {}; struct EigenProfile {};
struct UseDebugImage {}; struct UseDebugImage {};
struct DwarfProfile { explicit DwarfProfile(int v) : version(v) {} int version; };
struct CoreProfile {}; struct CoreProfile {};
struct CorePrivateProfile {}; struct CorePrivateProfile {};
@@ -708,6 +707,12 @@ public:
return *this; return *this;
} }
const Data &operator+(const DwarfVersion &dwarfVersion) const
{
neededDwarfVersion = dwarfVersion;
return *this;
}
const Data &operator+(const DebuggerEngine &enginesForTest) const const Data &operator+(const DebuggerEngine &enginesForTest) const
{ {
engines = enginesForTest; engines = enginesForTest;
@@ -738,6 +743,14 @@ public:
return *this; return *this;
} }
const Data &operator+(const DwarfProfile &p)
{
profileExtra +=
"QMAKE_CXXFLAGS -= -g\n"
"QMAKE_CXXFLAGS += -gdwarf-" + QString::number(p.version) + "\n";
return *this;
}
const Data &operator+(const UseDebugImage &) const const Data &operator+(const UseDebugImage &) const
{ {
useDebugImage = true; useDebugImage = true;
@@ -850,6 +863,7 @@ public:
mutable GccVersion neededGccVersion; // DEC. 40702 for 4.7.2 mutable GccVersion neededGccVersion; // DEC. 40702 for 4.7.2
mutable ClangVersion neededClangVersion; // DEC. mutable ClangVersion neededClangVersion; // DEC.
mutable BoostVersion neededBoostVersion; // DEC. 105400 for 1.54.0 mutable BoostVersion neededBoostVersion; // DEC. 105400 for 1.54.0
mutable DwarfVersion neededDwarfVersion; // DEC. 105400 for 1.54.0
mutable QString configTest; mutable QString configTest;
@@ -889,19 +903,7 @@ class tst_Dumpers : public QObject
Q_OBJECT Q_OBJECT
public: public:
tst_Dumpers() tst_Dumpers() {}
{
t = 0;
m_keepTemp = true;
m_forceKeepTemp = false;
m_debuggerVersion = 0;
m_gdbBuildVersion = 0;
m_qtVersion = 0;
m_gccVersion = 0;
m_isMacGdb = false;
m_isQnxGdb = false;
m_useGLibCxxDebug = false;
}
private slots: private slots:
void initTestCase(); void initTestCase();
@@ -913,21 +915,21 @@ private slots:
private: private:
void disarm() { t->buildTemp.setAutoRemove(!keepTemp()); } void disarm() { t->buildTemp.setAutoRemove(!keepTemp()); }
bool keepTemp() const { return m_keepTemp || m_forceKeepTemp; } bool keepTemp() const { return m_keepTemp || m_forceKeepTemp; }
TempStuff *t; TempStuff *t = 0;
QString m_debuggerBinary; QString m_debuggerBinary;
QString m_qmakeBinary; QString m_qmakeBinary;
QProcessEnvironment m_env; QProcessEnvironment m_env;
DebuggerEngine m_debuggerEngine; DebuggerEngine m_debuggerEngine;
QString m_makeBinary; QString m_makeBinary;
bool m_keepTemp; bool m_keepTemp = true;
bool m_forceKeepTemp; bool m_forceKeepTemp = false;
int m_debuggerVersion; // GDB: 7.5.1 -> 70501 int m_debuggerVersion = 0; // GDB: 7.5.1 -> 70501
int m_gdbBuildVersion; int m_gdbBuildVersion = 0;
int m_qtVersion; // 5.2.0 -> 50200 int m_qtVersion = 0; // 5.2.0 -> 50200
int m_gccVersion; int m_gccVersion = 0;
bool m_isMacGdb; bool m_isMacGdb = false;
bool m_isQnxGdb; bool m_isQnxGdb = false;
bool m_useGLibCxxDebug; bool m_useGLibCxxDebug = false;
}; };
void tst_Dumpers::initTestCase() void tst_Dumpers::initTestCase()
@@ -1295,6 +1297,28 @@ void tst_Dumpers::dumper()
qDebug() << "Project file: " << proFile.fileName(); qDebug() << "Project file: " << proFile.fileName();
} }
if (data.neededDwarfVersion.isRestricted) {
QProcess readelf;
readelf.setWorkingDirectory(t->buildPath);
readelf.start("readelf", { "-wi", "doit" });
QVERIFY(readelf.waitForFinished());
output = readelf.readAllStandardOutput();
error = readelf.readAllStandardError();
int pos1 = output.indexOf("Version:") + 8;
int pos2 = output.indexOf("\n", pos1);
int dwarfVersion = output.mid(pos1, pos2 - pos1).toInt();
//qDebug() << "OUT: " << output;
//qDebug() << "ERR: " << error;
qDebug() << "DWARF Version : " << dwarfVersion;
if (data.neededDwarfVersion.min > dwarfVersion)
MSKIP_SINGLE("Need minimum DWARF version "
+ QByteArray::number(data.neededDwarfVersion.min));
if (data.neededDwarfVersion.max < dwarfVersion)
MSKIP_SINGLE("Need maximum DWARF version "
+ QByteArray::number(data.neededDwarfVersion.max));
}
QByteArray dumperDir = DUMPERDIR; QByteArray dumperDir = DUMPERDIR;
QSet<QString> expandedINames; QSet<QString> expandedINames;
@@ -2293,7 +2317,7 @@ void tst_Dumpers::dumper_data()
+ Check("loc1.groupSeparator", "44", "@QChar") // , + Check("loc1.groupSeparator", "44", "@QChar") // ,
+ Check("loc1.negativeSign", "45", "@QChar") // - + Check("loc1.negativeSign", "45", "@QChar") // -
+ Check("loc1.positiveSign", "43", "@QChar") // + + Check("loc1.positiveSign", "43", "@QChar") // +
+ Check("m1", ValuePattern(".*Imperial.*System (1)"), Pattern(".*MeasurementSystem")); + Check("m1", ValuePattern(".*Imperial.*System (1)"), TypePattern(".*MeasurementSystem"));
QTest::newRow("QMap") QTest::newRow("QMap")
@@ -3359,7 +3383,7 @@ void tst_Dumpers::dumper_data()
+ Check("list.1", "[1]", "2", "int") + Check("list.1", "[1]", "2", "int")
+ Check("list.2", "[2]", "3", "int") + Check("list.2", "[2]", "3", "int")
//+ Check("v3", "", "@QVariant (@QList<int>)") //+ Check("v3", "", "@QVariant (@QList<int>)")
+ Check("v3.data", "<3 items>", Pattern(".*QList<int>")) + Check("v3.data", "<3 items>", TypePattern(".*QList<int>"))
+ Check("v3.data.0", "[0]", "1", "int") + Check("v3.data.0", "[0]", "1", "int")
+ Check("v3.data.1", "[1]", "2", "int") + Check("v3.data.1", "[1]", "2", "int")
+ Check("v3.data.2", "[2]", "3", "int"); + Check("v3.data.2", "[2]", "3", "int");
@@ -3869,9 +3893,9 @@ void tst_Dumpers::dumper_data()
+ Cxx11Profile() + Cxx11Profile()
+ MacLibCppProfile() + MacLibCppProfile()
+ Check("a", "<4 items>", Pattern("std::array<int, 4.*>")) + Check("a", "<4 items>", TypePattern("std::array<int, 4.*>"))
+ Check("a.0", "[0]", "1", "int") + Check("a.0", "[0]", "1", "int")
+ Check("b", "<4 items>", Pattern("std::array<@QString, 4.*>")) + Check("b", "<4 items>", TypePattern("std::array<@QString, 4.*>"))
+ Check("b.0", "[0]", "\"1\"", "@QString"); + Check("b.0", "[0]", "\"1\"", "@QString");
@@ -5197,7 +5221,7 @@ void tst_Dumpers::dumper_data()
+ Check("d1", "43", "Ref1") + Check("d1", "43", "Ref1")
+ Check("a2", "\"hello\"", "std::string") + Check("a2", "\"hello\"", "std::string")
+ Check("b2", "\"bababa\"", Pattern("(std::)?string &")) // Clang... + Check("b2", "\"bababa\"", TypePattern("(std::)?string &")) // Clang...
+ Check("c2", "\"world\"", "std::string") + Check("c2", "\"world\"", "std::string")
+ Check("d2", "\"hello\"", "Ref2") % NoLldbEngine + Check("d2", "\"hello\"", "Ref2") % NoLldbEngine
@@ -5352,8 +5376,23 @@ void tst_Dumpers::dumper_data()
+ Check("y2", "", "X") + Check("y2", "", "X")
+ Check("y3", "", "X"); + Check("y3", "", "X");
QTest::newRow("RValueReference") QTest::newRow("RValueReference2")
<< Data(rvalueData) << Data(rvalueData)
+ DwarfProfile(2)
+ Check("x1", "", "X &")
+ Check("x2", "", "X &")
+ Check("x3", "", "X &");
// GCC emits rvalue references with DWARF-4, i.e. after 4.7.4.
// GDB doesn't understand them,
// https://sourceware.org/bugzilla/show_bug.cgi?id=14441
// and produces: 'x1 = <unknown type in [...]/doit, CU 0x0, DIE 0x355>'
// LLdb reports plain references.
QTest::newRow("RValueReference4")
<< Data(rvalueData)
+ DwarfProfile(4)
+ LldbEngine
+ Check("x1", "", "X &") + Check("x1", "", "X &")
+ Check("x2", "", "X &") + Check("x2", "", "X &")
+ Check("x3", "", "X &"); + Check("x3", "", "X &");
@@ -5502,7 +5541,7 @@ void tst_Dumpers::dumper_data()
"l.push_back(p(15, 65));\n" "l.push_back(p(15, 65));\n"
"l.push_back(p(16, 66));\n") "l.push_back(p(16, 66));\n")
+ BoostProfile() + BoostProfile()
+ Check("l", "<4 items>", Pattern("boost::container::list<std::pair<int,double>.*>")) + Check("l", "<4 items>", TypePattern("boost::container::list<std::pair<int,double>.*>"))
+ Check("l.2.second", FloatValue("65"), "double"); + Check("l.2.second", FloatValue("65"), "double");
@@ -6014,7 +6053,7 @@ void tst_Dumpers::dumper_data()
"unused(&v, &n);\n") "unused(&v, &n);\n")
+ Check("v", "", "{...}") % GdbEngine + Check("v", "", "{...}") % GdbEngine
+ Check("v", "", Pattern(".*anonymous .*")) % LldbEngine + Check("v", "", TypePattern(".*anonymous .*")) % LldbEngine
+ Check("n", "", "S") + Check("n", "", "S")
//+ Check("v.a", "2", "int") % GdbVersion(0, 70699) //+ Check("v.a", "2", "int") % GdbVersion(0, 70699)
//+ Check("v.0.a", "2", "int") % GdbVersion(70700) //+ Check("v.0.a", "2", "int") % GdbVersion(70700)
@@ -6240,7 +6279,7 @@ void tst_Dumpers::dumper_data()
<< nimData << nimData
+ GdbEngine + GdbEngine
+ Check("name", "\"Hello World\"", "NimStringDesc") + Check("name", "\"Hello World\"", "NimStringDesc")
+ Check("x", "<6 items>", Pattern("TY.*NI.6..")) // Something like "TY95019 (NI[6])" + Check("x", "<6 items>", TypePattern("TY.*NI.6..")) // Something like "TY95019 (NI[6])"
+ Check("x.2", "[2]", "3", "NI"); + Check("x.2", "[2]", "3", "NI");
#endif #endif
#endif #endif