mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 03:53:21 +02:00
Bug 376901 - DSF-GDB should properly handle variable type change (based
on RTTI) Change-Id: I9869900530792ec102f39950c0dbf23d0c4ca160 Reviewed-on: https://git.eclipse.org/r/5602 Reviewed-by: Jens Elmenthaler <jens.elmenthaler@me.com> Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
parent
5d74bf2eaf
commit
a5fd3894d1
3 changed files with 113 additions and 13 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2011 Monta Vista and others.
|
* Copyright (c) 2008, 2012 Monta Vista and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* Axel Mueller - Bug 306555 - Add support for cast to type / view as array (IExpressions2)
|
* Axel Mueller - Bug 306555 - Add support for cast to type / view as array (IExpressions2)
|
||||||
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
||||||
* Axel Mueller - Workaround for GDB bug where -var-info-path-expression gives invalid result (Bug 320277)
|
* Axel Mueller - Workaround for GDB bug where -var-info-path-expression gives invalid result (Bug 320277)
|
||||||
|
* Anton Gorenkov - DSF-GDB should properly handle variable type change (based on RTTI) (Bug 376901)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.mi.service;
|
package org.eclipse.cdt.dsf.mi.service;
|
||||||
|
|
||||||
|
@ -367,6 +368,8 @@ public class MIVariableManager implements ICommandControl {
|
||||||
// The children of this variable, if any.
|
// The children of this variable, if any.
|
||||||
// Null means we didn't fetch them yet, while an empty array means no children
|
// Null means we didn't fetch them yet, while an empty array means no children
|
||||||
private ExpressionInfo[] children = null;
|
private ExpressionInfo[] children = null;
|
||||||
|
// we need to keep track of fake children because they are in the LRU and need to be removed in some cases.
|
||||||
|
private List<ExpressionInfo> fakeChildren = new ArrayList<ExpressionInfo>(3);
|
||||||
private boolean hasMore = false;
|
private boolean hasMore = false;
|
||||||
private MIDisplayHint displayHint = MIDisplayHint.NONE;
|
private MIDisplayHint displayHint = MIDisplayHint.NONE;
|
||||||
|
|
||||||
|
@ -504,11 +507,14 @@ public class MIVariableManager implements ICommandControl {
|
||||||
public boolean isPointer() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.POINTER; }
|
public boolean isPointer() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.POINTER; }
|
||||||
public boolean isMethod() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.FUNCTION; }
|
public boolean isMethod() { return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.FUNCTION; }
|
||||||
// A complex variable is one with children. However, it must not be a pointer since a pointer
|
// A complex variable is one with children. However, it must not be a pointer since a pointer
|
||||||
// does have children, but is still a 'simple' variable, as it can be modifed.
|
// does have children, but is still a 'simple' variable, as it can be modified.
|
||||||
|
// A reference can be modified too, because it can be a reference to the base class before initialization
|
||||||
|
// and after initialization it can become a reference to the derived class (if gdb shows the value type and
|
||||||
|
// children taking into account RTTI ("set print object on")).
|
||||||
// Note that the numChildrenHint can be trusted when asking if the number of children is 0 or not
|
// Note that the numChildrenHint can be trusted when asking if the number of children is 0 or not
|
||||||
public boolean isComplex() {
|
public boolean isComplex() {
|
||||||
return (getGDBType() == null) ? false
|
return (getGDBType() == null) ? false
|
||||||
: getGDBType().getType() != GDBType.POINTER
|
: getGDBType().getType() != GDBType.POINTER && getGDBType().getType() != GDBType.REFERENCE
|
||||||
&& (getNumChildrenHint() > 0
|
&& (getNumChildrenHint() > 0
|
||||||
|| hasMore() || getDisplayHint().isCollectionHint());
|
|| hasMore() || getDisplayHint().isCollectionHint());
|
||||||
}
|
}
|
||||||
|
@ -559,7 +565,7 @@ public class MIVariableManager implements ICommandControl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param info
|
* @param info
|
||||||
* @param t
|
* @param typeName
|
||||||
* @param num
|
* @param num
|
||||||
* If the correspinding MI variable is dynamic, the number of
|
* If the correspinding MI variable is dynamic, the number of
|
||||||
* children currently fetched by gdb.
|
* children currently fetched by gdb.
|
||||||
|
@ -568,14 +574,21 @@ public class MIVariableManager implements ICommandControl {
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public void setExpressionData(ExpressionInfo info, String t, int num, boolean hasMore) {
|
public void setExpressionData(ExpressionInfo info, String typeName, int num, boolean hasMore) {
|
||||||
exprInfo = info;
|
exprInfo = info;
|
||||||
type = t;
|
setType(typeName);
|
||||||
gdbType = fGDBTypeParser.parse(t);
|
|
||||||
numChildrenHint = num;
|
numChildrenHint = num;
|
||||||
this.hasMore = hasMore;
|
this.hasMore = hasMore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public void setType(String newTypeName) {
|
||||||
|
type = newTypeName;
|
||||||
|
gdbType = fGDBTypeParser.parse(newTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
public void setValue(String format, String val) { valueMap.put(format, val); }
|
public void setValue(String format, String val) { valueMap.put(format, val); }
|
||||||
|
|
||||||
public void resetValues(String valueInCurrentFormat) {
|
public void resetValues(String valueInCurrentFormat) {
|
||||||
|
@ -681,6 +694,47 @@ public class MIVariableManager implements ICommandControl {
|
||||||
numChildrenHint = newNumChildren;
|
numChildrenHint = newNumChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified child from LRU and makes the cleanup on its
|
||||||
|
* children (if any).
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
private void cleanupChild(ExpressionInfo child) {
|
||||||
|
String childFullExpression = child.getFullExpr();
|
||||||
|
VariableObjectId childId = new VariableObjectId();
|
||||||
|
childId.generateId(childFullExpression, getInternalId());
|
||||||
|
MIVariableObject varobjOfChild = lruVariableList.remove(childId);
|
||||||
|
if (varobjOfChild != null) {
|
||||||
|
// Remove it from the list of modifiable descendants
|
||||||
|
getRootToUpdate().removeModifiableDescendant(varobjOfChild.getGdbName());
|
||||||
|
// Remove children recursively
|
||||||
|
varobjOfChild.cleanupChildren();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all the children (real and fake) of the variable object from
|
||||||
|
* LRU cache and from variable object itself. It is used when the type
|
||||||
|
* of variable was changed.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public void cleanupChildren() {
|
||||||
|
hasMore = false;
|
||||||
|
if (children != null) {
|
||||||
|
for (ExpressionInfo child : children) {
|
||||||
|
cleanupChild(child);
|
||||||
|
}
|
||||||
|
children = null;
|
||||||
|
numChildrenHint = 0;
|
||||||
|
}
|
||||||
|
for (ExpressionInfo fakeChild : fakeChildren) {
|
||||||
|
cleanupChild(fakeChild);
|
||||||
|
}
|
||||||
|
fakeChildren.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void setParent(MIVariableObject p) {
|
public void setParent(MIVariableObject p) {
|
||||||
parent = p;
|
parent = p;
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
|
@ -799,6 +853,19 @@ public class MIVariableManager implements ICommandControl {
|
||||||
*/
|
*/
|
||||||
protected void processChange(final MIVarChange update, final RequestMonitor rm) {
|
protected void processChange(final MIVarChange update, final RequestMonitor rm) {
|
||||||
|
|
||||||
|
// Handle the variable type change properly
|
||||||
|
if (update.isChanged()) {
|
||||||
|
setType(update.getNewType());
|
||||||
|
cleanupChildren();
|
||||||
|
editable = null;
|
||||||
|
updateLimit(IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These properties of the variable will probably not change,
|
||||||
|
// but if they are - we should handle it properly.
|
||||||
|
setDisplayHint(update.getDisplayHint());
|
||||||
|
exprInfo.setDynamic(update.isDynamic());
|
||||||
|
|
||||||
MIVar[] newChildren = update.getNewChildren();
|
MIVar[] newChildren = update.getNewChildren();
|
||||||
|
|
||||||
// children == null means fetchChildren will happen later, so
|
// children == null means fetchChildren will happen later, so
|
||||||
|
@ -1441,7 +1508,9 @@ public class MIVariableManager implements ICommandControl {
|
||||||
var.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
|
var.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
|
||||||
|
|
||||||
if (fakeChild) {
|
if (fakeChild) {
|
||||||
|
if (! isSuccess()) {
|
||||||
|
fakeChildren.add(var.exprInfo);
|
||||||
|
}
|
||||||
addRealChildrenOfFake(var, exprDmc, realChildren,
|
addRealChildrenOfFake(var, exprDmc, realChildren,
|
||||||
arrayPosition, countingRm);
|
arrayPosition, countingRm);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1451,7 +1520,6 @@ public class MIVariableManager implements ICommandControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (childVar.currentState == STATE_CREATION_FAILED) {
|
} else if (childVar.currentState == STATE_CREATION_FAILED) {
|
||||||
// There has been an attempt the create a MIRootVariableObject for a full
|
// There has been an attempt the create a MIRootVariableObject for a full
|
||||||
// expression representing a child of a dynamic varobj. Such an attempt always
|
// expression representing a child of a dynamic varobj. Such an attempt always
|
||||||
|
@ -1473,7 +1541,7 @@ public class MIVariableManager implements ICommandControl {
|
||||||
childVar.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
|
childVar.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
|
||||||
|
|
||||||
if (fakeChild) {
|
if (fakeChild) {
|
||||||
|
fakeChildren.add(childVar.exprInfo);
|
||||||
addRealChildrenOfFake(childVar, exprDmc, realChildren,
|
addRealChildrenOfFake(childVar, exprDmc, realChildren,
|
||||||
arrayPosition, countingRm);
|
arrayPosition, countingRm);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2021,6 +2089,17 @@ public class MIVariableManager implements ICommandControl {
|
||||||
modifiableDescendants.put(gdbName, descendant);
|
modifiableDescendants.put(gdbName, descendant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the descendant with the specified name from the collection of
|
||||||
|
* modifiable descendants. Does nothing if there is no child with such
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public void removeModifiableDescendant(String gdbName) {
|
||||||
|
modifiableDescendants.remove(gdbName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000, 2010 QNX Software Systems and others.
|
* Copyright (c) 2000, 2012 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* QNX Software Systems - Initial API and implementation
|
* QNX Software Systems - Initial API and implementation
|
||||||
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
||||||
|
* Anton Gorenkov - DSF-GDB should properly handle variable type change (based on RTTI) (Bug 376901)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.mi.service.command.output;
|
package org.eclipse.cdt.dsf.mi.service.command.output;
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ public class MIVarChange {
|
||||||
String value;
|
String value;
|
||||||
boolean inScope;
|
boolean inScope;
|
||||||
boolean changed;
|
boolean changed;
|
||||||
|
private String newType;
|
||||||
private boolean isDynamic = false;
|
private boolean isDynamic = false;
|
||||||
private int newNumChildren = -1;
|
private int newNumChildren = -1;
|
||||||
private boolean hasMore = false;
|
private boolean hasMore = false;
|
||||||
|
@ -47,6 +49,13 @@ public class MIVarChange {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public String getNewType() {
|
||||||
|
return newType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether the associated variable's value and children are provided
|
* @return Whether the associated variable's value and children are provided
|
||||||
* by a pretty printer.
|
* by a pretty printer.
|
||||||
|
@ -117,6 +126,13 @@ public class MIVarChange {
|
||||||
changed = c;
|
changed = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public void setNewType(String newType) {
|
||||||
|
this.newType = newType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000, 2010 QNX Software Systems and others.
|
* Copyright (c) 2000, 2012 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* QNX Software Systems - Initial API and implementation
|
* QNX Software Systems - Initial API and implementation
|
||||||
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
||||||
|
* Anton Gorenkov - DSF-GDB should properly handle variable type change (based on RTTI) (Bug 376901)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.mi.service.command.output;
|
package org.eclipse.cdt.dsf.mi.service.command.output;
|
||||||
|
|
||||||
|
@ -99,6 +100,10 @@ public class MIVarUpdateInfo extends MIInfo {
|
||||||
if (change != null) {
|
if (change != null) {
|
||||||
change.setChanged("true".equals(str)); //$NON-NLS-1$
|
change.setChanged("true".equals(str)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
} else if (var.equals("new_type")) { //$NON-NLS-1$
|
||||||
|
if (change != null) {
|
||||||
|
change.setNewType(str);
|
||||||
|
}
|
||||||
} else if (var.equals("new_num_children")) { //$NON-NLS-1$
|
} else if (var.equals("new_num_children")) { //$NON-NLS-1$
|
||||||
if (change != null) {
|
if (change != null) {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Reference in a new issue