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:
hjk
2017-04-20 08:47:34 +02:00
parent e2be021cba
commit 53ff0e1ca1
3 changed files with 35 additions and 4 deletions
+5 -2
View File
@@ -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)
+4 -1
View File
@@ -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'
+26 -1
View File
@@ -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,