1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +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:
xgsa 2012-05-02 22:12:11 +03:00 committed by Marc Khouzam
parent 5d74bf2eaf
commit a5fd3894d1
3 changed files with 113 additions and 13 deletions

View file

@ -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
* are made available under the terms of the Eclipse Public License v1.0
* 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)
* 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)
* Anton Gorenkov - DSF-GDB should properly handle variable type change (based on RTTI) (Bug 376901)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@ -367,6 +368,8 @@ public class MIVariableManager implements ICommandControl {
// The children of this variable, if any.
// Null means we didn't fetch them yet, while an empty array means no children
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 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 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
// 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
public boolean isComplex() {
return (getGDBType() == null) ? false
: getGDBType().getType() != GDBType.POINTER
: getGDBType().getType() != GDBType.POINTER && getGDBType().getType() != GDBType.REFERENCE
&& (getNumChildrenHint() > 0
|| hasMore() || getDisplayHint().isCollectionHint());
}
@ -559,7 +565,7 @@ public class MIVariableManager implements ICommandControl {
/**
* @param info
* @param t
* @param typeName
* @param num
* If the correspinding MI variable is dynamic, the number of
* children currently fetched by gdb.
@ -568,13 +574,20 @@ public class MIVariableManager implements ICommandControl {
*
* @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;
type = t;
gdbType = fGDBTypeParser.parse(t);
setType(typeName);
numChildrenHint = num;
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); }
@ -680,6 +693,47 @@ public class MIVariableManager implements ICommandControl {
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) {
parent = p;
@ -799,6 +853,19 @@ public class MIVariableManager implements ICommandControl {
*/
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();
// children == null means fetchChildren will happen later, so
@ -850,7 +917,7 @@ public class MIVariableManager implements ICommandControl {
rm.done();
}
};
// Process all the child MIVariableObjects.
int pendingVariableCreationCount = 0;
if (newChildren != null && newChildren.length != 0) {
@ -1441,7 +1508,9 @@ public class MIVariableManager implements ICommandControl {
var.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
if (fakeChild) {
if (! isSuccess()) {
fakeChildren.add(var.exprInfo);
}
addRealChildrenOfFake(var, exprDmc, realChildren,
arrayPosition, countingRm);
} else {
@ -1451,7 +1520,6 @@ public class MIVariableManager implements ICommandControl {
}
}
});
} else if (childVar.currentState == STATE_CREATION_FAILED) {
// There has been an attempt the create a MIRootVariableObject for a full
// expression representing a child of a dynamic varobj. Such an attempt always
@ -1473,7 +1541,7 @@ public class MIVariableManager implements ICommandControl {
childVar.hasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
if (fakeChild) {
fakeChildren.add(childVar.exprInfo);
addRealChildrenOfFake(childVar, exprDmc, realChildren,
arrayPosition, countingRm);
} else {
@ -2021,6 +2089,17 @@ public class MIVariableManager implements ICommandControl {
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
*/

View file

@ -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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* 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;
@ -21,6 +22,7 @@ public class MIVarChange {
String value;
boolean inScope;
boolean changed;
private String newType;
private boolean isDynamic = false;
private int newNumChildren = -1;
private boolean hasMore = false;
@ -47,6 +49,13 @@ public class MIVarChange {
return changed;
}
/**
* @since 4.1
*/
public String getNewType() {
return newType;
}
/**
* @return Whether the associated variable's value and children are provided
* by a pretty printer.
@ -117,6 +126,13 @@ public class MIVarChange {
changed = c;
}
/**
* @since 4.1
*/
public void setNewType(String newType) {
this.newType = newType;
}
/**
* @since 4.0
*/

View file

@ -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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* 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;
@ -99,6 +100,10 @@ public class MIVarUpdateInfo extends MIInfo {
if (change != null) {
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$
if (change != null) {
try {