forked from qt-creator/qt-creator
Debugger: Add a workaround for bad gcc debug info generation
Gcc does not write out full type names with 'using template ...', see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80466 This is in most cases harmless for Creator as dumpers are triggered independently of template arguments. However, if the dumper takes different code path based on the template argument type, as is e.g. needed for std::vector<bool>, wrong results are produced, as the type cache only used the template base name as type id. Work around by mangling the id of the un-typedef-ed type into the type id of a typedef, which, in case of templates contain the full parameter list. Change-Id: I63c59cccdc186b09ff780e9dfd57b0ad668ae98f Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -3637,7 +3637,9 @@ class DumperBase:
|
||||
self.registerType(typeId, tdata)
|
||||
return self.Type(self, typeId)
|
||||
|
||||
def createTypedefedType(self, targetType, typeId):
|
||||
def createTypedefedType(self, targetType, typeName, typeId = None):
|
||||
if typeId is None:
|
||||
typeId = typeName
|
||||
if not isinstance(targetType, self.Type):
|
||||
error('Expected type in createTypedefType(), got %s'
|
||||
% type(targetType))
|
||||
@@ -3645,12 +3647,13 @@ class DumperBase:
|
||||
if targetType.typeId == typeId:
|
||||
return targetType
|
||||
tdata = self.TypeData(self)
|
||||
tdata.name = typeId
|
||||
tdata.name = typeName
|
||||
tdata.typeId = typeId
|
||||
tdata.code = TypeCodeTypedef
|
||||
tdata.ltarget = targetType
|
||||
tdata.lbitsize = targetType.lbitsize
|
||||
#tdata.lfields = targetType.lfields
|
||||
tdata.lbitsize = targetType.lbitsize
|
||||
self.registerType(typeId, tdata)
|
||||
return self.Type(self, typeId)
|
||||
|
||||
|
||||
@@ -315,7 +315,8 @@ class Dumper(DumperBase):
|
||||
while nativeTargetType.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
nativeTargetType = nativeTargetType.strip_typedefs().unqualified()
|
||||
targetType = self.fromNativeType(nativeTargetType)
|
||||
return self.createTypedefedType(targetType, str(nativeType))
|
||||
return self.createTypedefedType(targetType, str(nativeType),
|
||||
self.nativeTypeId(nativeType))
|
||||
|
||||
if code == gdb.TYPE_CODE_ERROR:
|
||||
warn('Type error: %s' % nativeType)
|
||||
@@ -408,6 +409,8 @@ class Dumper(DumperBase):
|
||||
return '%d' % intval
|
||||
|
||||
def nativeTypeId(self, nativeType):
|
||||
if nativeType.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
return '%s{%s}' % (nativeType, nativeType.strip_typedefs())
|
||||
name = str(nativeType)
|
||||
if len(name) == 0:
|
||||
c = '0'
|
||||
|
||||
@@ -526,7 +526,7 @@ struct Check
|
||||
|
||||
const Check &operator%(GccVersion version) const
|
||||
{
|
||||
enginesForCheck = GdbEngine;
|
||||
enginesForCheck = NoCdbEngine;
|
||||
gccVersionForCheck = version;
|
||||
return *this;
|
||||
}
|
||||
@@ -1330,6 +1330,7 @@ void tst_Dumpers::dumper()
|
||||
"\n#endif"
|
||||
"\n#ifdef __clang__"
|
||||
"\n int clangversion = 10000 * __clang_major__ + 100 * __clang_minor__; unused(&clangversion);"
|
||||
"\n gccversion = 0;"
|
||||
"\n#else"
|
||||
"\n int clangversion = 0; unused(&clangversion);"
|
||||
"\n#endif"
|
||||
@@ -5451,6 +5452,30 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("t2", "0", "myType2");
|
||||
|
||||
|
||||
QTest::newRow("Typedef2")
|
||||
<< Data("#include <vector>\n"
|
||||
"template<typename T> using TVector = std::vector<T>;\n",
|
||||
"std::vector<bool> b1(10); unused(&b1);\n"
|
||||
"std::vector<int> b2(10); unused(&b2);\n"
|
||||
"TVector<bool> b3(10); unused(&b3);\n"
|
||||
"TVector<int> b4(10); unused(&b4);\n"
|
||||
"TVector<bool> b5(10); unused(&b5);\n"
|
||||
"TVector<int> b6(10); unused(&b6);\n")
|
||||
|
||||
+ NoCdbEngine
|
||||
|
||||
// The test is for a gcc bug
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80466,
|
||||
// so check for any gcc version vs any other compiler
|
||||
// (identified by gccversion == 0).
|
||||
+ Check("b1", "<10 items>", "std::vector<bool>")
|
||||
+ Check("b2", "<10 items>", "std::vector<int>")
|
||||
+ Check("b3", "<10 items>", "TVector") % GccVersion(1)
|
||||
+ Check("b4", "<10 items>", "TVector") % GccVersion(1)
|
||||
+ Check("b5", "<10 items>", "TVector<bool>") % GccVersion(0, 0)
|
||||
+ Check("b6", "<10 items>", "TVector<int>") % GccVersion(0, 0);
|
||||
|
||||
|
||||
QTest::newRow("Struct")
|
||||
<< Data(fooData,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user