forked from qt-creator/qt-creator
Debugger: Support rvalue references in functions args with gdb
Change-Id: I5383ffa38f07e3f191619555a9e735c211b3dd8b Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -120,7 +120,8 @@ TypeCodeMemberPointer, \
|
|||||||
TypeCodeFortranString, \
|
TypeCodeFortranString, \
|
||||||
TypeCodeUnresolvable, \
|
TypeCodeUnresolvable, \
|
||||||
TypeCodeBitfield, \
|
TypeCodeBitfield, \
|
||||||
= range(0, 15)
|
TypeCodeRValueReference, \
|
||||||
|
= range(0, 16)
|
||||||
|
|
||||||
def isIntegralTypeName(name):
|
def isIntegralTypeName(name):
|
||||||
return name in ('int', 'unsigned int', 'signed int',
|
return name in ('int', 'unsigned int', 'signed int',
|
||||||
@@ -2784,7 +2785,7 @@ class DumperBase:
|
|||||||
self.putType(typeobj.name)
|
self.putType(typeobj.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
if typeobj.code == TypeCodeReference:
|
if typeobj.code in (TypeCodeReference, TypeCodeRValueReference):
|
||||||
#warn('REFERENCE VALUE: %s' % value)
|
#warn('REFERENCE VALUE: %s' % value)
|
||||||
val = value.dereference()
|
val = value.dereference()
|
||||||
if val.laddress != 0:
|
if val.laddress != 0:
|
||||||
@@ -3040,7 +3041,7 @@ class DumperBase:
|
|||||||
self.check()
|
self.check()
|
||||||
if self.type.code == TypeCodeTypedef:
|
if self.type.code == TypeCodeTypedef:
|
||||||
return self.findMemberByName(self.detypedef())
|
return self.findMemberByName(self.detypedef())
|
||||||
if self.type.code in (TypeCodePointer, TypeCodeReference):
|
if self.type.code in (TypeCodePointer, TypeCodeReference, TypeCodeRValueReference):
|
||||||
res = self.dereference().findMemberByName(name)
|
res = self.dereference().findMemberByName(name)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
return res
|
return res
|
||||||
@@ -3114,7 +3115,7 @@ class DumperBase:
|
|||||||
|
|
||||||
if self.type.code == TypeCodeTypedef:
|
if self.type.code == TypeCodeTypedef:
|
||||||
return self.cast(self.type.ltarget).extractField(field)
|
return self.cast(self.type.ltarget).extractField(field)
|
||||||
if self.type.code == TypeCodeReference:
|
if self.type.code in (TypeCodeReference, TypeCodeRValueReference):
|
||||||
return self.dereference().extractField(field)
|
return self.dereference().extractField(field)
|
||||||
#warn('FIELD: %s ' % field)
|
#warn('FIELD: %s ' % field)
|
||||||
val = self.dumper.Value(self.dumper)
|
val = self.dumper.Value(self.dumper)
|
||||||
@@ -3159,7 +3160,7 @@ class DumperBase:
|
|||||||
else:
|
else:
|
||||||
self.dumper.check(False)
|
self.dumper.check(False)
|
||||||
|
|
||||||
if fieldType.code == TypeCodeReference:
|
if fieldType.code in (TypeCodeReference, TypeCodeRValueReference):
|
||||||
if val.laddress is not None:
|
if val.laddress is not None:
|
||||||
val = self.dumper.createReferenceValue(val.laddress, fieldType.ltarget)
|
val = self.dumper.createReferenceValue(val.laddress, fieldType.ltarget)
|
||||||
val.name = field.name
|
val.name = field.name
|
||||||
@@ -3228,7 +3229,7 @@ class DumperBase:
|
|||||||
if self.type.code == TypeCodeTypedef:
|
if self.type.code == TypeCodeTypedef:
|
||||||
return self.detypedef().dereference()
|
return self.detypedef().dereference()
|
||||||
val = self.dumper.Value(self.dumper)
|
val = self.dumper.Value(self.dumper)
|
||||||
if self.type.code == TypeCodeReference:
|
if self.type.code in (TypeCodeReference, TypeCodeRValueReference):
|
||||||
val.summary = self.summary
|
val.summary = self.summary
|
||||||
if self.nativeValue is None:
|
if self.nativeValue is None:
|
||||||
val.laddress = self.pointer()
|
val.laddress = self.pointer()
|
||||||
@@ -3586,7 +3587,7 @@ class DumperBase:
|
|||||||
# Crude approximation.
|
# Crude approximation.
|
||||||
return 8 if self.dumper.isWindowsTarget() else self.dumper.ptrSize()
|
return 8 if self.dumper.isWindowsTarget() else self.dumper.ptrSize()
|
||||||
return self.size()
|
return self.size()
|
||||||
if tdata.code in (TypeCodePointer, TypeCodeReference):
|
if tdata.code in (TypeCodePointer, TypeCodeReference, TypeCodeRValueReference):
|
||||||
return self.dumper.ptrSize()
|
return self.dumper.ptrSize()
|
||||||
if tdata.lalignment is not None:
|
if tdata.lalignment is not None:
|
||||||
#if isinstance(tdata.lalignment, function): # Does not work that way.
|
#if isinstance(tdata.lalignment, function): # Does not work that way.
|
||||||
@@ -3743,6 +3744,20 @@ class DumperBase:
|
|||||||
self.registerType(typeId, tdata)
|
self.registerType(typeId, tdata)
|
||||||
return self.Type(self, typeId)
|
return self.Type(self, typeId)
|
||||||
|
|
||||||
|
def createRValueReferenceType(self, targetType):
|
||||||
|
if not isinstance(targetType, self.Type):
|
||||||
|
error('Expected type in createRValueReferenceType(), got %s'
|
||||||
|
% type(targetType))
|
||||||
|
typeId = targetType.typeId + ' &&'
|
||||||
|
tdata = self.TypeData(self)
|
||||||
|
tdata.name = targetType.name + ' &&'
|
||||||
|
tdata.typeId = typeId
|
||||||
|
tdata.code = TypeCodeRValueReference
|
||||||
|
tdata.ltarget = targetType
|
||||||
|
tdata.lbitsize = None
|
||||||
|
self.registerType(typeId, tdata)
|
||||||
|
return self.Type(self, typeId)
|
||||||
|
|
||||||
def createArrayType(self, targetType, count):
|
def createArrayType(self, targetType, count):
|
||||||
if not isinstance(targetType, self.Type):
|
if not isinstance(targetType, self.Type):
|
||||||
error('Expected type in createArrayType(), got %s'
|
error('Expected type in createArrayType(), got %s'
|
||||||
|
@@ -309,6 +309,11 @@ class Dumper(DumperBase):
|
|||||||
targetType = self.fromNativeType(nativeType.target().unqualified())
|
targetType = self.fromNativeType(nativeType.target().unqualified())
|
||||||
return self.createReferenceType(targetType)
|
return self.createReferenceType(targetType)
|
||||||
|
|
||||||
|
if code == gdb.TYPE_CODE_RVALUE_REF:
|
||||||
|
#warn('RVALUEREF')
|
||||||
|
targetType = self.fromNativeType(nativeType.target())
|
||||||
|
return self.createRValueReferenceType(targetType)
|
||||||
|
|
||||||
if code == gdb.TYPE_CODE_ARRAY:
|
if code == gdb.TYPE_CODE_ARRAY:
|
||||||
#warn('ARRAY')
|
#warn('ARRAY')
|
||||||
nativeTargetType = nativeType.target().unqualified()
|
nativeTargetType = nativeType.target().unqualified()
|
||||||
|
@@ -59,7 +59,9 @@ enum TypeCodes {
|
|||||||
TypeCodeFunction,
|
TypeCodeFunction,
|
||||||
TypeCodeMemberPointer,
|
TypeCodeMemberPointer,
|
||||||
TypeCodeFortranString,
|
TypeCodeFortranString,
|
||||||
TypeCodeUnresolvable
|
TypeCodeUnresolvable,
|
||||||
|
TypeCodeBitField,
|
||||||
|
TypeCodeRValueReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool isType(const std::string &typeName, const std::vector<std::string> &types)
|
static bool isType(const std::string &typeName, const std::vector<std::string> &types)
|
||||||
|
@@ -5976,6 +5976,17 @@ void tst_Dumpers::dumper_data()
|
|||||||
+ Check("x2", "", "X &")
|
+ Check("x2", "", "X &")
|
||||||
+ Check("x3", "", "X &");
|
+ Check("x3", "", "X &");
|
||||||
|
|
||||||
|
QTest::newRow("RValueReference")
|
||||||
|
<< Data("",
|
||||||
|
"struct S { int a = 32; };\n"
|
||||||
|
"auto foo = [](int && i, S && s) { BREAK; return i + s.a; };\n"
|
||||||
|
"foo(int(1), S());\n")
|
||||||
|
+ Cxx11Profile()
|
||||||
|
+ GdbVersion(80200)
|
||||||
|
+ Check("i", "1", "int &&")
|
||||||
|
+ CheckType("s", "S &&")
|
||||||
|
+ Check("s.a", "32", "int");
|
||||||
|
|
||||||
QTest::newRow("SSE")
|
QTest::newRow("SSE")
|
||||||
<< Data("#include <xmmintrin.h>\n"
|
<< Data("#include <xmmintrin.h>\n"
|
||||||
"#include <stddef.h>\n",
|
"#include <stddef.h>\n",
|
||||||
|
Reference in New Issue
Block a user