1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 09:46:02 +02:00

Instantiation of dependent values, bug 245027.

This commit is contained in:
Markus Schorn 2008-12-17 13:07:23 +00:00
parent 6e9e2be414
commit 3604a05aba
19 changed files with 794 additions and 200 deletions

View file

@ -3184,7 +3184,7 @@ public class AST2TemplateTests extends AST2BaseTest {
// cb.b = 6; // cb.b = 6;
// func(cb); // func(cb);
// } // }
public void _testTemplateMetaProgramming_245027() throws Exception { public void testTemplateMetaProgramming_245027() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ICPPMethod method= ba.assertNonProblem("method();", 6, ICPPMethod.class); ICPPMethod method= ba.assertNonProblem("method();", 6, ICPPMethod.class);
ICPPVariable a= ba.assertNonProblem("a =", 1, ICPPVariable.class); ICPPVariable a= ba.assertNonProblem("a =", 1, ICPPVariable.class);

View file

@ -139,8 +139,9 @@ public class ASTTypeUtil {
* @since 5.1 * @since 5.1
*/ */
public static String getArgumentString(ICPPTemplateArgument arg, boolean normalize) { public static String getArgumentString(ICPPTemplateArgument arg, boolean normalize) {
if (arg.isNonTypeValue()) IValue val= arg.getNonTypeValue();
return arg.getNonTypeValue().getCanonicalRepresentation(); if (val != null)
return new String(val.getSignature());
return getType(arg.getTypeValue(), normalize); return getType(arg.getTypeValue(), normalize);
} }

View file

@ -23,9 +23,22 @@ public interface IValue {
Long numericalValue(); Long numericalValue();
/** /**
* Returns a canonical representation that is suitable for distinguishing * Returns an internal representation of the expression that builds up the
* constant values for the purpose of template instantiation. * value. It is suitable for instantiating dependent values but may not be
* The representation may not be used to display the value. * used for the purpose of displaying values.
*/ */
String getCanonicalRepresentation(); char[] getInternalExpression();
/**
* A value may be dependent on template parameters, in which case a list
* of unknown bindings is maintained for later instantiation.
*/
IBinding[] getUnknownBindings();
/**
* Returns a signature containing both the internal representation and the
* unknown bindings. The representation is sufficient to distinguish values
* for the purpose of instantiation, it may not be used to display the value.
*/
char[] getSignature();
} }

View file

@ -14,14 +14,15 @@ package org.eclipse.cdt.core.dom.ast.cpp;
/** /**
* Models the mapping of template parameters to values. * Models the mapping of template parameters to values.
* @since 5.1 * @since 5.1
* @noimplement This interface is not intended to be implemented by clients.
*/ */
public interface ICPPTemplateParameterMap { public interface ICPPTemplateParameterMap {
/** /**
* Returns the value for the template parameter at the given position. * Returns the value for the template parameter with the given id.
* @see ICPPTemplateParameter#getParameterPosition() * @see ICPPTemplateParameter#getParameterID()
*/ */
public ICPPTemplateArgument getArgument(int paramPosition); public ICPPTemplateArgument getArgument(int paramID);
/** /**
* Returns the value for the template parameter in the map, or <code>null</code> if * Returns the value for the template parameter in the map, or <code>null</code> if

View file

@ -10,7 +10,12 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser; package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
@ -25,9 +30,10 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator; import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator;
@ -39,49 +45,135 @@ import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalExce
*/ */
public class Value implements IValue { public class Value implements IValue {
public static final int MAX_RECURSION_DEPTH = 25; public static final int MAX_RECURSION_DEPTH = 25;
public final static IValue UNKNOWN= new Value("<unknown>"); //$NON-NLS-1$ public final static IValue UNKNOWN= new Value("<unknown>".toCharArray(), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY); //$NON-NLS-1$
private final static IValue[] TYPICAL= {new Value(String.valueOf(0)), private static final String SCOPE_OP = "::"; //$NON-NLS-1$
new Value(String.valueOf(1)), new Value(String.valueOf(2)), new Value(String.valueOf(3)), private static final char UNIQUE_CHAR = '_';
new Value(String.valueOf(4)), new Value(String.valueOf(5)), new Value(String.valueOf(6))}; private static final char TEMPLATE_PARAM_CHAR = '#';
private static final char REFERENCE_CHAR = '&';
private static final char UNARY_OP_CHAR = '$';
private static final char BINARY_OP_CHAR = '@';
private static final char CONDITIONAL_CHAR= '?';
private static final char SEPARATOR = ',';
private final static IValue[] TYPICAL= {
new Value(new char[] {'0'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'1'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'2'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'3'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'4'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'5'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY),
new Value(new char[] {'6'}, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY)};
private static class Reevaluation {
public final char[] fExpression;
public int pos=0;
public final Map<String, Integer> fUnknownSigs;
public final List<ICPPUnknownBinding> fUnknowns;
public final IBinding[] fResolvedUnknown;
public final ICPPTemplateParameterMap fMap;
public Reevaluation(char[] expr, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map) {
fExpression= expr;
fUnknownSigs= unknownSigs;
fUnknowns= unknowns;
fResolvedUnknown= resolvedUnknowns;
fMap= map;
}
public void nextSeperator() throws UnknownValueException {
final char[] expression = fExpression;
final int len = expression.length;
int idx = pos;
while(idx < len) {
if (expression[idx++] == SEPARATOR)
break;
}
pos= idx;
}
}
private static class UnknownValueException extends Exception {} private static class UnknownValueException extends Exception {}
private static UnknownValueException UNKNOWN_EX= new UnknownValueException(); private static UnknownValueException UNKNOWN_EX= new UnknownValueException();
private static int sUnique=0; private static int sUnique=0;
private final String fValue; private final char[] fExpression;
private Value(String rep) { private final ICPPUnknownBinding[] fUnknownBindings;
private char[] fSignature;
private Value(char[] rep, ICPPUnknownBinding[] unknown) {
assert rep != null; assert rep != null;
fValue= rep; fExpression= rep;
fUnknownBindings= unknown;
} }
public String getCanonicalRepresentation() {
return fValue; public char[] getInternalExpression() {
return fExpression;
} }
public Long numericalValue() { public IBinding[] getUnknownBindings() {
try { return fUnknownBindings;
return Long.parseLong(fValue); }
} catch (NumberFormatException e) {
public char[] getSignature() {
if (fSignature == null) {
if (fUnknownBindings.length == 0) {
fSignature= fExpression;
} else {
StringBuilder buf= new StringBuilder();
buf.append(fExpression);
buf.append('[');
for (int i = 0; i < fUnknownBindings.length; i++) {
if (i>0)
buf.append(',');
buf.append(getSignatureForUnknown(fUnknownBindings[i]));
}
buf.append(']');
final int end= buf.length();
fSignature= new char[end];
buf.getChars(0, end, fSignature, 0);
}
} }
return null; return fSignature;
}
public Long numericalValue() {
return parseLong(fExpression);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return fValue.hashCode(); return CharArrayUtils.hash(fExpression);
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof IValue)) { if (!(obj instanceof IValue)) {
return false; return false;
} }
return fValue.equals(((IValue) obj).getCanonicalRepresentation()); final IValue rhs = (IValue) obj;
if (!CharArrayUtils.equals(fExpression, rhs.getInternalExpression()))
return false;
IBinding[] rhsUnknowns= rhs.getUnknownBindings();
if (fUnknownBindings.length != rhsUnknowns.length)
return false;
for (int i = 0; i < rhsUnknowns.length; i++) {
final IBinding rhsUnknown = rhsUnknowns[i];
if (rhsUnknown instanceof ICPPUnknownBinding) {
if (!getSignatureForUnknown((ICPPUnknownBinding) rhsUnknown).equals(getSignatureForUnknown(fUnknownBindings[i]))) {
return false;
}
} else {
return false;
}
}
return true;
} }
@Override @Override
public String toString() { public String toString() {
return fValue; return new String(getSignature());
} }
/** /**
@ -90,37 +182,68 @@ public class Value implements IValue {
public static IValue create(long value) { public static IValue create(long value) {
if (value >=0 && value < TYPICAL.length) if (value >=0 && value < TYPICAL.length)
return TYPICAL[(int) value]; return TYPICAL[(int) value];
return new Value(String.valueOf(value)); return new Value(toCharArray(value), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY);
} }
/** /**
* Creates a value representing the given template parameter. * Creates a value representing the given template parameter.
*/ */
public static IValue create(ICPPTemplateNonTypeParameter tntp) { public static IValue create(ICPPTemplateNonTypeParameter tntp) {
return new Value(evaluate(tntp)); final String expr = createTemplateParamExpression(tntp.getParameterID());
return new Value(expr.toCharArray(), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY);
}
private static String createTemplateParamExpression(int id) {
StringBuilder buf= new StringBuilder();
buf.append(TEMPLATE_PARAM_CHAR);
buf.append(Integer.toHexString(id));
return buf.toString();
} }
/** /**
* Tests whether the value is a template parameter, returns the parameter id of the * Tests whether the value is a template parameter, returns the parameter id of the
* parameter, or <code>null</code> if it is not a template parameter. * parameter, or <code>-1</code> if it is not a template parameter.
*/ */
public static int isTemplateParameter(IValue tval) { public static int isTemplateParameter(IValue tval) {
final String rep= tval.getCanonicalRepresentation(); final char[] rep= tval.getInternalExpression();
if (rep.indexOf('#') == 0 && rep.indexOf(',') == -1) { if (rep.length > 0) {
try { if (rep[0] == TEMPLATE_PARAM_CHAR) {
return Integer.parseInt(rep.substring(1), 16); for (int i = 1; i < rep.length; i++) {
} catch (NumberFormatException e) { if (rep[i] == SEPARATOR)
return -1;
}
try {
return parseHex(rep, 1);
} catch (UnknownValueException e) {
}
} }
} }
return -1; return -1;
} }
/**
* Tests whether the value directly references some template parameter.
*/
public static boolean referencesTemplateParameter(IValue tval) {
final char[] rep= tval.getInternalExpression();
for (int i = 0; i < rep.length; i++) {
if (rep[i] == TEMPLATE_PARAM_CHAR)
return true;
}
return false;
}
/** /**
* Tests whether the value depends on a template parameter. * Tests whether the value depends on a template parameter.
*/ */
public static boolean isDependentValue(IValue nonTypeValue) { public static boolean isDependentValue(IValue nonTypeValue) {
final String rep= nonTypeValue.getCanonicalRepresentation(); final char[] rep= nonTypeValue.getInternalExpression();
return rep.indexOf('#') >= 0; for (int i = 0; i < rep.length; i++) {
final char c = rep[i];
if (c == REFERENCE_CHAR || c == TEMPLATE_PARAM_CHAR)
return true;
}
return false;
} }
/** /**
@ -128,10 +251,19 @@ public class Value implements IValue {
*/ */
public static IValue create(IASTExpression expr, int maxRecursionDepth) { public static IValue create(IASTExpression expr, int maxRecursionDepth) {
try { try {
Object obj= evaluate(expr, maxRecursionDepth); Map<String, Integer> unknownSigs= new HashMap<String, Integer>();
if (obj instanceof Long) List<ICPPUnknownBinding> unknown= new ArrayList<ICPPUnknownBinding>();
return create(((Long) obj).longValue()); Object obj= evaluate(expr, unknownSigs, unknown, maxRecursionDepth);
return new Value(obj.toString()); if (obj instanceof Number)
return create(((Number) obj).longValue());
ICPPUnknownBinding[] ua;
if (unknown.isEmpty()) {
ua= ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY;
} else {
ua= unknown.toArray(new ICPPUnknownBinding[unknown.size()]);
}
return new Value(((String)obj).toCharArray(), ua);
} catch (UnknownValueException e) { } catch (UnknownValueException e) {
} }
return UNKNOWN; return UNKNOWN;
@ -140,104 +272,78 @@ public class Value implements IValue {
/** /**
* Creates a value off its canonical representation. * Creates a value off its canonical representation.
*/ */
public static IValue fromCanonicalRepresentation(String rep) { public static IValue fromInternalRepresentation(char[] rep, ICPPUnknownBinding[] unknown) {
if (rep.equals(UNKNOWN.getCanonicalRepresentation())) if (CharArrayUtils.equals(rep, UNKNOWN.getInternalExpression()))
return UNKNOWN; return UNKNOWN;
try { Long l= parseLong(rep);
return create(Long.parseLong(rep)); if (l != null)
} catch (NumberFormatException e) {} return create(l.longValue());
return new Value(rep); return new Value(rep, unknown);
} }
/** /**
* Creates a unique value needed during template instantiation. * Creates a unique value needed during template instantiation.
*/ */
public static IValue unique() { public static IValue unique() {
return new Value("@" + (++sUnique)); //$NON-NLS-1$ StringBuilder buf= new StringBuilder(10);
buf.append(UNIQUE_CHAR);
buf.append(++sUnique);
return new Value(extractChars(buf), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY);
} }
/** /**
* Computes the canonical representation of the value of the expression. Returns a {@code Long} for * Computes the canonical representation of the value of the expression.
* numerical values or a {@code String}, otherwise. * Returns a {@code Number} for numerical values or a {@code String}, otherwise.
* @throws UnknownValueException * @throws UnknownValueException
*/ */
@SuppressWarnings("nls") private static Object evaluate(IASTExpression e, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
private static Object evaluate(IASTExpression e, int maxdepth) throws UnknownValueException {
if (maxdepth < 0 || e == null) if (maxdepth < 0 || e == null)
throw UNKNOWN_EX; throw UNKNOWN_EX;
if (e instanceof IASTArraySubscriptExpression) { if (e instanceof IASTArraySubscriptExpression) {
IASTArraySubscriptExpression sub= (IASTArraySubscriptExpression) e; throw UNKNOWN_EX;
return evaluate(sub.getArrayExpression(), maxdepth) + "," +
evaluate(sub.getSubscriptExpression(), maxdepth) + ",[]";
} }
if (e instanceof IASTBinaryExpression) { if (e instanceof IASTBinaryExpression) {
return evaluateBinaryExpression((IASTBinaryExpression) e, maxdepth); return evaluateBinaryExpression((IASTBinaryExpression) e, unknownSigs, unknowns, maxdepth);
} }
if (e instanceof IASTCastExpression) { // must be ahead of unary if (e instanceof IASTCastExpression) { // must be ahead of unary
return evaluate(((IASTCastExpression) e).getOperand(), maxdepth); return evaluate(((IASTCastExpression) e).getOperand(), unknownSigs, unknowns, maxdepth);
} }
if (e instanceof IASTUnaryExpression) { if (e instanceof IASTUnaryExpression) {
return evaluateUnaryExpression((IASTUnaryExpression) e, maxdepth); return evaluateUnaryExpression((IASTUnaryExpression) e, unknownSigs, unknowns, maxdepth);
} }
if (e instanceof IASTConditionalExpression) { if (e instanceof IASTConditionalExpression) {
IASTConditionalExpression cexpr= (IASTConditionalExpression) e; IASTConditionalExpression cexpr= (IASTConditionalExpression) e;
Object o= evaluate(cexpr.getLogicalConditionExpression(), maxdepth); Object o= evaluate(cexpr.getLogicalConditionExpression(), unknownSigs, unknowns, maxdepth);
if (o instanceof Long) { if (o instanceof Long) {
Long v= (Long) o; Long v= (Long) o;
if (v.longValue() == 0) { if (v.longValue() == 0) {
return evaluate(cexpr.getNegativeResultExpression(), maxdepth); return evaluate(cexpr.getNegativeResultExpression(), unknownSigs, unknowns, maxdepth);
} }
final IASTExpression pe = cexpr.getPositiveResultExpression(); final IASTExpression pe = cexpr.getPositiveResultExpression();
if (pe == null) // gnu-extension allows to omit the positive expression. if (pe == null) // gnu-extension allows to omit the positive expression.
return o; return o;
return evaluate(pe, maxdepth); return evaluate(pe, unknownSigs, unknowns, maxdepth);
} }
final IASTExpression pe = cexpr.getPositiveResultExpression(); final IASTExpression pe = cexpr.getPositiveResultExpression();
Object po= pe == null ? o : evaluate(pe, maxdepth); Object po= pe == null ? o : evaluate(pe, unknownSigs, unknowns, maxdepth);
return o + "," + evaluate(cexpr.getNegativeResultExpression(), maxdepth) + "," + po + '?'; Object neg= evaluate(cexpr.getNegativeResultExpression(), unknownSigs, unknowns, maxdepth);
return CONDITIONAL_CHAR + SEPARATOR + o.toString() + SEPARATOR + po.toString() + SEPARATOR + neg.toString();
} }
if (e instanceof IASTIdExpression) { if (e instanceof IASTIdExpression) {
IBinding b= CPPASTNameBase.resolvePreBinding(((IASTIdExpression) e).getName()); IBinding b= CPPASTNameBase.resolvePreBinding(((IASTIdExpression) e).getName());
if (b instanceof ICPPTemplateParameter) { return evaluateBinding(b, unknownSigs, unknowns, maxdepth);
if (b instanceof ICPPTemplateNonTypeParameter) {
return evaluate((ICPPTemplateParameter) b);
}
throw UNKNOWN_EX;
}
IValue cv= null;
if (b instanceof IInternalVariable) {
cv= ((IInternalVariable) b).getInitialValue(maxdepth-1);
} else if (b instanceof IVariable) {
cv= ((IVariable) b).getInitialValue();
} else if (b instanceof IEnumerator) {
cv= ((IEnumerator) b).getValue();
} else if (b instanceof ICPPUnknownBinding && !(b instanceof IType)) {
return "#0x0fffffff";
// mstodo unknown bindings must be stored with the value, such that they can
// be instantiated lated on, bug 245027
}
if (cv != null)
return toObject(cv);
try {
if (b instanceof ICPPBinding)
return ((ICPPBinding) b).getQualifiedName();
return b.getName();
} catch (DOMException e1) {
throw UNKNOWN_EX;
}
} }
if (e instanceof IASTLiteralExpression) { if (e instanceof IASTLiteralExpression) {
IASTLiteralExpression litEx= (IASTLiteralExpression) e; IASTLiteralExpression litEx= (IASTLiteralExpression) e;
switch (litEx.getKind()) { switch (litEx.getKind()) {
case IASTLiteralExpression.lk_false: case IASTLiteralExpression.lk_false:
return "0"; return 0;
case IASTLiteralExpression.lk_true: case IASTLiteralExpression.lk_true:
return "1"; return 1;
case IASTLiteralExpression.lk_integer_constant: case IASTLiteralExpression.lk_integer_constant:
try { try {
return ExpressionEvaluator.getNumber(litEx.getValue()); return ExpressionEvaluator.getNumber(litEx.getValue());
@ -259,28 +365,104 @@ public class Value implements IValue {
throw UNKNOWN_EX; throw UNKNOWN_EX;
} }
private static Object toObject(IValue cv) throws UnknownValueException { /**
* Extract a value off a binding.
*/
private static Object evaluateBinding(IBinding b, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
if (b instanceof IType) {
throw UNKNOWN_EX;
}
if (b instanceof ICPPTemplateNonTypeParameter)
return createTemplateParamExpression(((ICPPTemplateNonTypeParameter) b).getParameterID());
if (b instanceof ICPPUnknownBinding) {
return createReference((ICPPUnknownBinding) b, unknownSigs, unknowns);
}
IValue value= null;
if (b instanceof IInternalVariable) {
value= ((IInternalVariable) b).getInitialValue(maxdepth-1);
} else if (b instanceof IVariable) {
value= ((IVariable) b).getInitialValue();
} else if (b instanceof IEnumerator) {
value= ((IEnumerator) b).getValue();
}
if (value != null)
return evaluateValue(value, unknownSigs, unknowns);
throw UNKNOWN_EX;
}
private static Object createReference(ICPPUnknownBinding unknown, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns) {
String sig= getSignatureForUnknown(unknown);
Integer idx= unknownSigs.get(sig);
if (idx == null) {
idx= unknownSigs.size();
unknownSigs.put(sig, idx);
unknowns.add(unknown);
}
return REFERENCE_CHAR + idx.toString();
}
private static Object evaluateValue(IValue cv, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns) throws UnknownValueException {
if (cv == Value.UNKNOWN) if (cv == Value.UNKNOWN)
throw UNKNOWN_EX; throw UNKNOWN_EX;
Long lv= cv.numericalValue(); Long lv= cv.numericalValue();
if (lv != null) if (lv != null)
return lv; return lv;
return cv.getCanonicalRepresentation();
final IBinding[] oldUnknowns = cv.getUnknownBindings();
final char[] expr= cv.getInternalExpression();
if (oldUnknowns.length == 0)
return new String(expr);
StringBuilder buf= new StringBuilder(expr.length);
boolean skipToSeparator= false;
for (int i = 0; i < expr.length; i++) {
final char c= expr[i];
switch(c) {
case REFERENCE_CHAR: {
int idx= parseNonNegative(expr, i+1);
if (idx >= oldUnknowns.length)
throw UNKNOWN_EX;
final IBinding old = oldUnknowns[idx];
if (!(old instanceof ICPPUnknownBinding))
throw UNKNOWN_EX;
buf.append(createReference((ICPPUnknownBinding) old, unknownSigs, unknowns));
skipToSeparator= true;
break;
}
case SEPARATOR:
skipToSeparator= false;
buf.append(c);
break;
default:
if (!skipToSeparator)
buf.append(c);
break;
}
}
return buf.toString();
} }
@SuppressWarnings("nls") private static Object evaluateUnaryExpression(IASTUnaryExpression ue, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
private static String evaluate(ICPPTemplateParameter param) {
return "#" + Integer.toHexString(param.getParameterID());
}
@SuppressWarnings("nls")
private static Object evaluateUnaryExpression(IASTUnaryExpression ue, int maxdepth) throws UnknownValueException {
final int unaryOp= ue.getOperator(); final int unaryOp= ue.getOperator();
if (unaryOp == IASTUnaryExpression.op_amper || unaryOp == IASTUnaryExpression.op_star) if (unaryOp == IASTUnaryExpression.op_amper || unaryOp == IASTUnaryExpression.op_star)
throw UNKNOWN_EX; throw UNKNOWN_EX;
final Object value= evaluate(ue.getOperand(), maxdepth); final Object value= evaluate(ue.getOperand(), unknownSigs, unknowns, maxdepth);
return combineUnary(unaryOp, value);
}
private static Object combineUnary(final int unaryOp, final Object value) throws UnknownValueException {
switch (unaryOp) {
case IASTUnaryExpression.op_bracketedPrimary:
case IASTUnaryExpression.op_plus:
return value;
}
if (value instanceof Long) { if (value instanceof Long) {
long v= (Long) value; long v= (Long) value;
switch(unaryOp) { switch(unaryOp) {
@ -290,9 +472,6 @@ public class Value implements IValue {
case IASTUnaryExpression.op_prefixDecr : case IASTUnaryExpression.op_prefixDecr :
case IASTUnaryExpression.op_postFixDecr: case IASTUnaryExpression.op_postFixDecr:
return --v; return --v;
case IASTUnaryExpression.op_bracketedPrimary:
case IASTUnaryExpression.op_plus:
return value;
case IASTUnaryExpression.op_minus: case IASTUnaryExpression.op_minus:
return -v; return -v;
case IASTUnaryExpression.op_tilde: case IASTUnaryExpression.op_tilde:
@ -300,22 +479,32 @@ public class Value implements IValue {
case IASTUnaryExpression.op_not: case IASTUnaryExpression.op_not:
return v == 0 ? 1 : 0; return v == 0 ? 1 : 0;
} }
} throw UNKNOWN_EX;
switch (unaryOp) { }
case IASTUnaryExpression.op_bracketedPrimary:
case IASTUnaryExpression.op_plus:
return value;
}
return value + "," + ASTSignatureUtil.getUnaryOperatorString(ue); switch (unaryOp) {
case IASTUnaryExpression.op_prefixIncr:
case IASTUnaryExpression.op_postFixIncr:
case IASTUnaryExpression.op_prefixDecr :
case IASTUnaryExpression.op_postFixDecr:
case IASTUnaryExpression.op_minus:
case IASTUnaryExpression.op_tilde:
case IASTUnaryExpression.op_not:
return UNARY_OP_CHAR + unaryOp + SEPARATOR + value.toString();
}
throw UNKNOWN_EX;
} }
@SuppressWarnings("nls") private static Object evaluateBinaryExpression(IASTBinaryExpression be,
private static Object evaluateBinaryExpression(IASTBinaryExpression be, int maxdepth) throws UnknownValueException { Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
final Object o1= evaluate(be.getOperand1(), maxdepth); final Object o1= evaluate(be.getOperand1(), unknownSigs, unknowns, maxdepth);
final Object o2= evaluate(be.getOperand2(), maxdepth); final Object o2= evaluate(be.getOperand2(), unknownSigs, unknowns, maxdepth);
final int op= be.getOperator(); final int op= be.getOperator();
return combineBinary(op, o1, o2);
}
private static Object combineBinary(final int op, final Object o1, final Object o2) throws UnknownValueException {
if (o1 instanceof Long && o2 instanceof Long) { if (o1 instanceof Long && o2 instanceof Long) {
long v1= (Long) o1; long v1= (Long) o1;
long v2= (Long) o2; long v2= (Long) o2;
@ -365,14 +554,274 @@ public class Value implements IValue {
case IASTBinaryExpression.op_min: case IASTBinaryExpression.op_min:
return Math.min(v1, v2); return Math.min(v1, v2);
} }
throw UNKNOWN_EX;
} }
switch (op) { switch (op) {
case IASTBinaryExpression.op_multiply:
case IASTBinaryExpression.op_divide:
case IASTBinaryExpression.op_modulo:
case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_minus:
case IASTBinaryExpression.op_shiftLeft:
case IASTBinaryExpression.op_shiftRight:
case IASTBinaryExpression.op_lessThan:
case IASTBinaryExpression.op_greaterThan:
case IASTBinaryExpression.op_lessEqual:
case IASTBinaryExpression.op_greaterEqual:
case IASTBinaryExpression.op_binaryAnd:
case IASTBinaryExpression.op_binaryXor:
case IASTBinaryExpression.op_binaryOr:
case IASTBinaryExpression.op_logicalAnd:
case IASTBinaryExpression.op_logicalOr:
case IASTBinaryExpression.op_max:
case IASTBinaryExpression.op_min:
break;
case IASTBinaryExpression.op_equals: case IASTBinaryExpression.op_equals:
return o1.equals(o2) ? 1 : 0; if (o1.equals(o2))
return 1;
break;
case IASTBinaryExpression.op_notequals: case IASTBinaryExpression.op_notequals:
return !o1.equals(o2) ? 1 : 0; if (o1.equals(o2))
return 0;
break;
default:
throw UNKNOWN_EX;
} }
return o1 + "," + o2 + "," + ASTSignatureUtil.getBinaryOperatorString(be); return BINARY_OP_CHAR + op + SEPARATOR + o1.toString() + SEPARATOR + o2.toString();
}
public static IValue reevaluate(IValue val, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map, int maxdepth) {
try {
Map<String, Integer> unknownSigs= new HashMap<String, Integer>();
List<ICPPUnknownBinding> unknown= new ArrayList<ICPPUnknownBinding>();
Reevaluation reeval= new Reevaluation(val.getInternalExpression(),
unknownSigs, unknown,
resolvedUnknowns, map);
Object obj= reevaluate(reeval, maxdepth);
if (reeval.pos != reeval.fExpression.length)
return UNKNOWN;
if (obj instanceof Long)
return create(((Long) obj).longValue());
ICPPUnknownBinding[] ua;
if (unknown.isEmpty()) {
ua= ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY;
} else {
ua= unknown.toArray(new ICPPUnknownBinding[unknown.size()]);
}
return new Value(((String)obj).toCharArray(), ua);
} catch (UnknownValueException e) {
}
return UNKNOWN;
}
private static Object reevaluate(Reevaluation reeval, int maxdepth)
throws UnknownValueException {
if (maxdepth < 0)
throw UNKNOWN_EX;
final int idx= reeval.pos;
final char[] buf= reeval.fExpression;
final int length = buf.length;
if (idx >= length)
throw UNKNOWN_EX;
final char c= buf[idx];
switch(c) {
case BINARY_OP_CHAR:
int op= parseNonNegative(buf, idx+1);
reeval.nextSeperator();
Object o1= reevaluate(reeval, maxdepth);
Object o2= reevaluate(reeval, maxdepth);
return combineBinary(op, o1, o2);
case UNARY_OP_CHAR:
op= parseNonNegative(buf, idx+1);
reeval.nextSeperator();
o1= reevaluate(reeval, maxdepth);
return combineUnary(op, o1);
case CONDITIONAL_CHAR:
reeval.nextSeperator();
Object cond= reevaluate(reeval, maxdepth);
Object po= reevaluate(reeval, maxdepth);
Object neg= reevaluate(reeval, maxdepth);
if (cond instanceof Long) {
Long v= (Long) cond;
if (v.longValue() == 0) {
return neg;
}
return po;
}
return CONDITIONAL_CHAR + SEPARATOR + cond.toString() + SEPARATOR + po.toString() + SEPARATOR + neg.toString();
case REFERENCE_CHAR:
int num= parseNonNegative(buf, idx+1);
final IBinding[] resolvedUnknowns= reeval.fResolvedUnknown;
if (num >= resolvedUnknowns.length)
throw UNKNOWN_EX;
reeval.nextSeperator();
return evaluateBinding(resolvedUnknowns[num], reeval.fUnknownSigs, reeval.fUnknowns, maxdepth);
case TEMPLATE_PARAM_CHAR:
num= parseHex(buf, idx+1);
reeval.nextSeperator();
ICPPTemplateArgument arg = reeval.fMap.getArgument(num);
if (arg != null) {
IValue val= arg.getNonTypeValue();
if (val == null)
throw UNKNOWN_EX;
return evaluateValue(val, reeval.fUnknownSigs, reeval.fUnknowns);
}
return createTemplateParamExpression(num);
default:
reeval.nextSeperator();
return parseLong(buf, idx);
}
}
/**
* Parses a non negative int.
*/
private static int parseNonNegative(char[] value, int offset) throws UnknownValueException {
final long maxvalue= Integer.MAX_VALUE/10;
final int len= value.length;
int result = 0;
boolean ok= false;
for(; offset< len; offset++) {
final int digit= (value[offset]- '0');
if (digit < 0 || digit > 9)
break;
if (result > maxvalue)
return -1;
result= result*10 + digit;
ok= true;
}
if (!ok)
throw UNKNOWN_EX;
return result;
}
/**
* Parses a a hex value.
*/
private static int parseHex(char[] value, int offset) throws UnknownValueException {
int result = 0;
boolean ok= false;
final int len= value.length;
for(; offset< len; offset++) {
int digit= (value[offset]- '0');
if (digit < 0 || digit > 9) {
digit += '0'-'a'+10;
if (digit < 10 || digit > 15) {
digit += 'a'-'A';
if (digit < 10 || digit > 15) {
break;
}
}
}
if ((result & 0xf0000000) != 0)
throw UNKNOWN_EX;
result= (result << 4) + digit;
ok= true;
}
if (!ok)
throw UNKNOWN_EX;
return result;
}
/**
* Parses a long.
*/
private static long parseLong(char[] value, int offset) throws UnknownValueException {
final long maxvalue= Long.MAX_VALUE/10;
final int len= value.length;
boolean negative= false;
long result = 0;
boolean ok= false;
if (offset < len && value[offset] == '-') {
negative = true;
offset++;
}
for(; offset < len; offset++) {
final int digit= (value[offset]- '0');
if (digit < 0 || digit > 9)
break;
if (result > maxvalue)
throw UNKNOWN_EX;
result= result*10 + digit;
ok= true;
}
if (!ok)
throw UNKNOWN_EX;
return negative ? -result : result;
}
/**
* Parses a long, returns <code>null</code> if not possible
*/
private static Long parseLong(char[] value) {
final long maxvalue= Long.MAX_VALUE/10;
final int len= value.length;
boolean negative= false;
long result = 0;
int i= 0;
if (len > 0 && value[0] == '-') {
negative = true;
i++;
}
if (i==len)
return null;
for(; i< len; i++) {
if (result > maxvalue)
return null;
final int digit= (value[i]- '0');
if (digit < 0 || digit > 9)
return null;
result= result*10 + digit;
}
return negative ? -result : result;
}
/**
* Computes a signature for an unknown binding.
*/
private static String getSignatureForUnknown(ICPPUnknownBinding binding) {
try {
IBinding owner= binding.getOwner();
if (owner instanceof IType) {
return ASTTypeUtil.getType((IType) owner, true) + SCOPE_OP + binding.getName();
}
} catch (DOMException e) {
// ignore qualification
}
return binding.getName();
}
/**
* Converts long to a char array
*/
private static char[] toCharArray(long value) {
StringBuilder buf= new StringBuilder();
buf.append(value);
return extractChars(buf);
}
private static char[] extractChars(StringBuilder buf) {
final int len = buf.length();
char[] result= new char[len];
buf.getChars(0, len, result, 0);
return result;
} }
} }

View file

@ -91,9 +91,9 @@ public class CPPFieldSpecialization extends CPPSpecialization implements ICPPFie
if (field instanceof IInternalVariable) { if (field instanceof IInternalVariable) {
v= ((IInternalVariable) field).getInitialValue(maxRecursionDepth); v= ((IInternalVariable) field).getInitialValue(maxRecursionDepth);
} else { } else {
v= specializeValue(getField().getInitialValue()); v= getField().getInitialValue();
} }
value= specializeValue(v); value= specializeValue(v, maxRecursionDepth);
} }
return value; return value;
} }

View file

@ -59,8 +59,12 @@ public abstract class CPPSpecialization extends PlatformObject implements ICPPSp
} }
} }
public IValue specializeValue(IValue value) { public IValue specializeValue(IValue value, int maxdepth) {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap()); if (owner instanceof ICPPClassSpecialization) {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), (ICPPClassSpecialization) owner, maxdepth);
} else {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), null, maxdepth);
}
} }
public IBinding getSpecializedBinding() { public IBinding getSpecializedBinding() {

View file

@ -19,7 +19,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
* Represents the binding for a dependent name within a template declaration. * Represents the binding for a dependent name within a template declaration.
*/ */
public interface ICPPUnknownBinding extends ICPPBinding { public interface ICPPUnknownBinding extends ICPPBinding {
ICPPUnknownBinding[] EMPTY_UNKNOWN_BINDING_ARRAY = {};
/** /**
* Returns the scope this binding represents. * Returns the scope this binding represents.
* @throws DOMException * @throws DOMException

View file

@ -122,6 +122,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTemplateParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedefSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedefSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
@ -712,19 +713,38 @@ public class CPPTemplates {
return spec; return spec;
} }
public static IValue instantiateValue(IValue value, ICPPTemplateParameterMap tpMap) { public static IValue instantiateValue(IValue value, ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within, int maxdepth) {
if (value == null) if (value == null)
return null; return null;
// mstodo- instantiate values correctly IBinding[] unknowns= value.getUnknownBindings();
int parPos= Value.isTemplateParameter(value); IBinding[] resolvedUnknowns= null;
if (parPos >= 0) { if (unknowns.length != 0) {
ICPPTemplateArgument arg = tpMap.getArgument(parPos); for (int i = 0; i < unknowns.length; i++) {
if (arg != null) { IBinding unknown= unknowns[i];
IValue mappedValue = arg.getNonTypeValue(); IBinding resolved= unknown;
if (mappedValue != null) if (unknown instanceof ICPPUnknownBinding) {
return mappedValue; try {
resolved= resolveUnknown((ICPPUnknownBinding) unknown, tpMap, within);
} catch (DOMException e) {
return Value.UNKNOWN;
}
}
if (resolvedUnknowns != null) {
resolvedUnknowns[i]= resolved;
} else if (resolved != unknown) {
resolvedUnknowns= new IBinding[unknowns.length];
System.arraycopy(unknowns, 0, resolvedUnknowns, 0, i);
resolvedUnknowns[i]= resolved;
}
} }
} }
if (resolvedUnknowns != null)
return Value.reevaluate(value, resolvedUnknowns, tpMap, maxdepth);
if (Value.referencesTemplateParameter(value))
return Value.reevaluate(value, unknowns, tpMap, maxdepth);
return value; return value;
} }
@ -867,7 +887,7 @@ public class CPPTemplates {
ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) { ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) {
if (arg.isNonTypeValue()) { if (arg.isNonTypeValue()) {
final IValue orig= arg.getNonTypeValue(); final IValue orig= arg.getNonTypeValue();
final IValue inst= instantiateValue(orig, tpMap); final IValue inst= instantiateValue(orig, tpMap, within, Value.MAX_RECURSION_DEPTH);
if (orig == inst) if (orig == inst)
return arg; return arg;
return new CPPTemplateArgument(inst, arg.getTypeOfNonTypeValue()); return new CPPTemplateArgument(inst, arg.getTypeOfNonTypeValue());
@ -1899,7 +1919,7 @@ public class CPPTemplates {
if (map != null && pType != null) { if (map != null && pType != null) {
pType= instantiateType(pType, map, null); pType= instantiateType(pType, map, null);
} }
if (isNonTypeArgumentConvertible(pType, argType)) { if (argType instanceof ICPPUnknownType || isNonTypeArgumentConvertible(pType, argType)) {
return new CPPTemplateArgument(arg.getNonTypeValue(), pType); return new CPPTemplateArgument(arg.getNonTypeValue(), pType);
} }
return null; return null;
@ -2047,11 +2067,15 @@ public class CPPTemplates {
if (!t.equals(owner) && newArgs != arguments) { if (!t.equals(owner) && newArgs != arguments) {
result= new CPPUnknownClassInstance((ICPPUnknownBinding) t, ucli.getUnknownName(), newArgs); result= new CPPUnknownClassInstance((ICPPUnknownBinding) t, ucli.getUnknownName(), newArgs);
} }
} else if (unknown instanceof ICPPUnknownClassType) { } else if (!t.equals(owner)) {
if (!t.equals(owner)) { if (unknown instanceof ICPPUnknownClassType) {
result= new CPPUnknownClass((ICPPUnknownBinding)t, ((ICPPUnknownClassType)unknown).getUnknownName()); result= new CPPUnknownClass((ICPPUnknownBinding)t, unknown.getUnknownName());
} else if (unknown instanceof IFunction) {
result= new CPPUnknownClass((ICPPUnknownBinding)t, unknown.getUnknownName());
} else {
result= new CPPUnknownBinding((ICPPUnknownBinding) t, unknown.getUnknownName());
} }
} }
} else if (t instanceof ICPPClassType) { } else if (t instanceof ICPPClassType) {
IScope s = ((ICPPClassType) t).getCompositeScope(); IScope s = ((ICPPClassType) t).getCompositeScope();
if (s != null && ASTInternal.isFullyCached(s)) { if (s != null && ASTInternal.isFullyCached(s)) {
@ -2081,7 +2105,7 @@ public class CPPTemplates {
return result; return result;
} }
private static IBinding resolveDeferredClassInstance(ICPPDeferredClassInstance dci, ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) { private static IBinding resolveDeferredClassInstance(ICPPDeferredClassInstance dci, ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) {
ICPPTemplateArgument[] arguments = dci.getTemplateArguments(); ICPPTemplateArgument[] arguments = dci.getTemplateArguments();
ICPPTemplateArgument[] newArgs = CPPTemplates.instantiateArguments(arguments, tpMap, within); ICPPTemplateArgument[] newArgs = CPPTemplates.instantiateArguments(arguments, tpMap, within);

View file

@ -168,11 +168,12 @@ public class PDOM extends PlatformObject implements IPDOM {
* 76.0 - support for exception specification, bug 252697 * 76.0 - support for exception specification, bug 252697
* 77.0 - support for parameter annotations, bug 254520 * 77.0 - support for parameter annotations, bug 254520
* 78.0 - support for updating class templates, bug 254520 * 78.0 - support for updating class templates, bug 254520
* 79.0 - instantiation of values, bug 245027
*/ */
private static int version(int major, int minor) { private static int version(int major, int minor) {
return major << 16 + minor; return major << 16 + minor;
} }
public static final int MAJOR_VERSION = 78; public static final int MAJOR_VERSION = 79;
public static final int MINOR_VERSION = 0; // minor versions must be compatible public static final int MINOR_VERSION = 0; // minor versions must be compatible
public static final int CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION); public static final int CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION);

View file

@ -383,6 +383,13 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
public String toString() { public String toString() {
return getLinkageName(); return getLinkageName();
} }
/**
* Usually bindings are added on behalf of a name, only. For unknown values we need to
* add further bindings.
* @throws CoreException
*/
public PDOMBinding addUnknownValue(IBinding binding) throws CoreException {
return null;
}
} }

View file

@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.core.runtime.CoreException;
/**
* Helper class for storing values in the index.
*/
public class PDOMValue {
/**
* Stores a value and returns the offset of where it was stored.
* @throws CoreException
*/
public static int store(Database db, PDOMLinkage linkage, IValue val) throws CoreException {
if (val == null)
return 0;
final IBinding[] unknown= val.getUnknownBindings();
int[] unknownRecs= {};
if (unknown.length != 0) {
unknownRecs= new int[unknown.length];
for (int i = 0; i < unknown.length; i++) {
PDOMNode node= linkage.addUnknownValue(unknown[i]);
if (node == null) {
return store(db, linkage, Value.UNKNOWN);
}
unknownRecs[i]= node.getRecord();
}
}
final short len= (short) Math.min(unknown.length, (Database.MAX_MALLOC_SIZE-6)/4);
final int block= db.malloc(6+4*len);
final int repRec= db.newString(val.getInternalExpression()).getRecord();
db.putShort(block, len);
db.putInt(block+2, repRec);
int p= block+6;
for (int i = 0; i < len; i++) {
db.putInt(p, unknownRecs[i]);
p+= 4;
}
return block;
}
/**
* Restores a value from the given record
* @throws CoreException
*/
public static IValue restore(Database db, PDOMLinkage linkage, int valRec) throws CoreException {
if (valRec == 0)
return null;
final int len= db.getShort(valRec);
final int repRec = db.getInt(valRec+2);
final char[] rep= db.getString(repRec).getChars();
if (len == 0)
return Value.fromInternalRepresentation(rep, ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY);
ICPPUnknownBinding[] unknown= new ICPPUnknownBinding[len];
int p= valRec+6;
for (int i = 0; i < unknown.length; i++) {
int rec= db.getInt(p);
PDOMNode node= linkage.getNode(rec);
if (node instanceof ICPPUnknownBinding) {
unknown[i]= (ICPPUnknownBinding) node;
} else {
return Value.UNKNOWN;
}
p+= 4;
}
return Value.fromInternalRepresentation(rep, unknown);
}
/**
* Deletes a value stored at the given record.
*/
public static void delete(Database db, int valueRec) throws CoreException {
if (valueRec == 0)
return;
final int repRec = db.getInt(valueRec+2);
db.getString(repRec).delete();
db.free(valueRec);
}
}

View file

@ -20,7 +20,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.c.CVariableReadWriteFlags; import org.eclipse.cdt.internal.core.dom.parser.c.CVariableReadWriteFlags;
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -29,6 +28,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
/** /**
@ -76,7 +76,8 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
private void setValue(final Database db, IVariable variable) throws CoreException { private void setValue(final Database db, IVariable variable) throws CoreException {
IValue val= variable.getInitialValue(); IValue val= variable.getInitialValue();
db.putInt(record + VALUE_OFFSET, val == null ? 0 : db.newString(val.getCanonicalRepresentation()).getRecord()); int valrec= PDOMValue.store(db, getLinkage(), val);
db.putInt(record + VALUE_OFFSET, valrec);
} }
@Override @Override
@ -94,8 +95,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
if (mytype != null) if (mytype != null)
linkage.deleteType(mytype, record); linkage.deleteType(mytype, record);
if (valueRec != 0) PDOMValue.delete(db, valueRec);
db.getString(valueRec).delete();
} catch (DOMException e) { } catch (DOMException e) {
throw new CoreException(Util.createStatus(e)); throw new CoreException(Util.createStatus(e));
} }
@ -135,9 +135,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
try { try {
final Database db = pdom.getDB(); final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET); int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0) return PDOMValue.restore(db, getLinkage(), valRec);
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).getString());
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return null; return null;

View file

@ -11,14 +11,14 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp; package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -45,8 +45,8 @@ public class PDOMCPPArgumentList {
final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue()); final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue());
// type can be null, if it is a local type // type can be null, if it is a local type
db.putInt(p, type == null ? 0 : type.getRecord()); db.putInt(p, type == null ? 0 : type.getRecord());
final IString s= db.newString(arg.getNonTypeValue().getCanonicalRepresentation()); int valueRec= PDOMValue.store(db, linkage, arg.getNonTypeValue());
db.putInt(p+4, s.getRecord()); db.putInt(p+4, valueRec);
} else { } else {
final PDOMNode type= linkage.addType(parent, arg.getTypeValue()); final PDOMNode type= linkage.addType(parent, arg.getTypeValue());
// type can be null, if it is a local type. // type can be null, if it is a local type.
@ -74,9 +74,7 @@ public class PDOMCPPArgumentList {
linkage.deleteType(t, parent.getRecord()); linkage.deleteType(t, parent.getRecord());
} }
final int nonTypeValueRec= db.getInt(p+4); final int nonTypeValueRec= db.getInt(p+4);
if (nonTypeValueRec != 0) { PDOMValue.delete(db, nonTypeValueRec);
db.getString(nonTypeValueRec).delete();
}
p+= 8; p+= 8;
} }
db.free(record); db.free(record);
@ -102,8 +100,8 @@ public class PDOMCPPArgumentList {
final IType type= typeRec == 0 ? new CPPBasicType(-1,0) : (IType) linkage.getNode(typeRec); final IType type= typeRec == 0 ? new CPPBasicType(-1,0) : (IType) linkage.getNode(typeRec);
final int nonTypeValRec= db.getInt(rec+4); final int nonTypeValRec= db.getInt(rec+4);
if (nonTypeValRec != 0) { if (nonTypeValRec != 0) {
final IString s= db.getString(nonTypeValRec); final IValue val= PDOMValue.restore(db, linkage, nonTypeValRec);
result[i]= new CPPTemplateArgument(Value.fromCanonicalRepresentation(s.getString()), type); result[i]= new CPPTemplateArgument(val, type);
} else { } else {
result[i]= new CPPTemplateArgument(type); result[i]= new CPPTemplateArgument(type);
} }

View file

@ -20,12 +20,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
/** /**
@ -56,15 +57,14 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements
try { try {
final Database db = pdom.getDB(); final Database db = pdom.getDB();
IType type = field.getType(); IType type = field.getType();
PDOMNode typeNode = getLinkageImpl().addType(this, type); final PDOMLinkage linkage = getLinkage();
PDOMNode typeNode = linkage.addType(this, type);
if (typeNode != null) { if (typeNode != null) {
db.putInt(record + TYPE, typeNode.getRecord()); db.putInt(record + TYPE, typeNode.getRecord());
} }
IValue val= field.getInitialValue(); IValue val= field.getInitialValue();
if (val != null) { int rec= PDOMValue.store(db, linkage, val);
db.putInt(record + VALUE_OFFSET, db.newString(val.getCanonicalRepresentation()).getRecord()); db.putInt(record + VALUE_OFFSET, rec);
}
} catch (DOMException e) { } catch (DOMException e) {
throw new CoreException(Util.createStatus(e)); throw new CoreException(Util.createStatus(e));
} }
@ -108,9 +108,7 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements
try { try {
final Database db = pdom.getDB(); final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET); int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0) return PDOMValue.restore(db, getLinkage(), valRec);
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).toString());
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return null; return null;

View file

@ -222,6 +222,11 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
return pdomBinding; return pdomBinding;
} }
@Override
public PDOMBinding addUnknownValue(IBinding binding) throws CoreException {
return addBinding(binding, null);
}
/** /**
* Adds or returns existing binding for the given one. If <code>fromName</code> is not <code>null</code> * Adds or returns existing binding for the given one. If <code>fromName</code> is not <code>null</code>
* then an existing binding is updated with the properties of the name. * then an existing binding is updated with the properties of the name.

View file

@ -23,15 +23,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
/** /**
@ -77,12 +76,10 @@ class PDOMCPPTemplateNonTypeParameter extends PDOMCPPBinding implements IPDOMMem
try { try {
final Database db = pdom.getDB(); final Database db = pdom.getDB();
int rec= db.getInt(record + DEFAULTVAL); int rec= db.getInt(record + DEFAULTVAL);
if (rec == 0) IValue val= PDOMValue.restore(db, getLinkage(), rec);
return null;
String val= db.getString(rec).getString();
if (val == null) if (val == null)
return null; return null;
return new CPPTemplateArgument(Value.fromCanonicalRepresentation(val), getType()); return new CPPTemplateArgument(val, getType());
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return null; return null;
@ -102,8 +99,8 @@ class PDOMCPPTemplateNonTypeParameter extends PDOMCPPBinding implements IPDOMMem
setType(linkage, newType); setType(linkage, newType);
if (mytype != null) if (mytype != null)
linkage.deleteType(mytype, record); linkage.deleteType(mytype, record);
if (setDefaultValue(db, ntp) && valueRec != 0) { if (setDefaultValue(db, ntp)) {
db.getString(valueRec).delete(); PDOMValue.delete(db, valueRec);
} }
} catch (DOMException e) { } catch (DOMException e) {
throw new CoreException(Util.createStatus(e)); throw new CoreException(Util.createStatus(e));
@ -119,8 +116,7 @@ class PDOMCPPTemplateNonTypeParameter extends PDOMCPPBinding implements IPDOMMem
} }
Database db= pdom.getDB(); Database db= pdom.getDB();
int valueRec= db.getInt(record + DEFAULTVAL); int valueRec= db.getInt(record + DEFAULTVAL);
if (valueRec != 0) PDOMValue.delete(db, valueRec);
db.getString(valueRec).delete();
} }
public short getParameterPosition() { public short getParameterPosition() {
@ -175,8 +171,8 @@ class PDOMCPPTemplateNonTypeParameter extends PDOMCPPBinding implements IPDOMMem
if (val != null) { if (val != null) {
IValue sval= val.getNonTypeValue(); IValue sval= val.getNonTypeValue();
if (sval != null) { if (sval != null) {
IString s= db.newString(sval.getCanonicalRepresentation()); int valueRec= PDOMValue.store(db, getLinkage(), sval);
db.putInt(record + DEFAULTVAL, s.getRecord()); db.putInt(record + DEFAULTVAL, valueRec);
return true; return true;
} }
} }

View file

@ -11,16 +11,16 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp; package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -50,8 +50,8 @@ public class PDOMCPPTemplateParameterMap {
final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue()); final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue());
// type can be null, if it is local // type can be null, if it is local
db.putInt(p, type == null ? 0 : type.getRecord()); db.putInt(p, type == null ? 0 : type.getRecord());
final IString s= db.newString(arg.getNonTypeValue().getCanonicalRepresentation()); int valueRec= PDOMValue.store(db, linkage, arg.getNonTypeValue());
db.putInt(p+4, s.getRecord()); db.putInt(p+4, valueRec);
} else { } else {
final PDOMNode type= linkage.addType(parent, arg.getTypeValue()); final PDOMNode type= linkage.addType(parent, arg.getTypeValue());
// type can be null, if it is local // type can be null, if it is local
@ -81,9 +81,7 @@ public class PDOMCPPTemplateParameterMap {
linkage.deleteType(t, parent.getRecord()); linkage.deleteType(t, parent.getRecord());
} }
final int nonTypeValueRec= db.getInt(rec+4); final int nonTypeValueRec= db.getInt(rec+4);
if (nonTypeValueRec != 0) { PDOMValue.delete(db, nonTypeValueRec);
db.getString(nonTypeValueRec).delete();
}
rec+= 8; rec+= 8;
} }
db.free(rec); db.free(rec);
@ -111,8 +109,8 @@ public class PDOMCPPTemplateParameterMap {
final int nonTypeValRec= db.getInt(rec+8); final int nonTypeValRec= db.getInt(rec+8);
ICPPTemplateArgument arg; ICPPTemplateArgument arg;
if (nonTypeValRec != 0) { if (nonTypeValRec != 0) {
final IString s= db.getString(nonTypeValRec); IValue val= PDOMValue.restore(db, linkage, nonTypeValRec);
arg= new CPPTemplateArgument(Value.fromCanonicalRepresentation(s.getString()), type); arg= new CPPTemplateArgument(val, type);
} else { } else {
arg= new CPPTemplateArgument(type); arg= new CPPTemplateArgument(type);
} }

View file

@ -21,7 +21,6 @@ import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -30,6 +29,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation; import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -78,7 +78,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
private void setValue(Database db, IVariable variable) throws CoreException { private void setValue(Database db, IVariable variable) throws CoreException {
IValue val= variable.getInitialValue(); IValue val= variable.getInitialValue();
int valueRec= val == null ? 0 : db.newString(val.getCanonicalRepresentation()).getRecord(); int valueRec= PDOMValue.store(db, getLinkage(), val);
db.putInt(record + VALUE_OFFSET, valueRec); db.putInt(record + VALUE_OFFSET, valueRec);
} }
@ -96,8 +96,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
setValue(db, var); setValue(db, var);
if (mytype != null) if (mytype != null)
linkage.deleteType(mytype, record); linkage.deleteType(mytype, record);
if (valueRec != 0) PDOMValue.delete(db, valueRec);
db.getString(valueRec).delete();
} catch (DOMException e) { } catch (DOMException e) {
throw new CoreException(Util.createStatus(e)); throw new CoreException(Util.createStatus(e));
@ -148,9 +147,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
try { try {
final Database db = pdom.getDB(); final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET); int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0) return PDOMValue.restore(db, getLinkage(), valRec);
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).getString());
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
return null; return null;