1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +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;
// func(cb);
// }
public void _testTemplateMetaProgramming_245027() throws Exception {
public void testTemplateMetaProgramming_245027() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ICPPMethod method= ba.assertNonProblem("method();", 6, ICPPMethod.class);
ICPPVariable a= ba.assertNonProblem("a =", 1, ICPPVariable.class);

View file

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

View file

@ -23,9 +23,22 @@ public interface IValue {
Long numericalValue();
/**
* Returns a canonical representation that is suitable for distinguishing
* constant values for the purpose of template instantiation.
* The representation may not be used to display the value.
* Returns an internal representation of the expression that builds up the
* value. It is suitable for instantiating dependent values but may not be
* 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.
* @since 5.1
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPTemplateParameterMap {
/**
* Returns the value for the template parameter at the given position.
* @see ICPPTemplateParameter#getParameterPosition()
* Returns the value for the template parameter with the given id.
* @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

View file

@ -10,7 +10,12 @@
*******************************************************************************/
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.IASTArraySubscriptExpression;
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.IValue;
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.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.ICPPUnknownBinding;
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 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)),
new Value(String.valueOf(1)), new Value(String.valueOf(2)), new Value(String.valueOf(3)),
new Value(String.valueOf(4)), new Value(String.valueOf(5)), new Value(String.valueOf(6))};
private static final String SCOPE_OP = "::"; //$NON-NLS-1$
private static final char UNIQUE_CHAR = '_';
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 UnknownValueException UNKNOWN_EX= new UnknownValueException();
private static int sUnique=0;
private final String fValue;
private Value(String rep) {
private final char[] fExpression;
private final ICPPUnknownBinding[] fUnknownBindings;
private char[] fSignature;
private Value(char[] rep, ICPPUnknownBinding[] unknown) {
assert rep != null;
fValue= rep;
fExpression= rep;
fUnknownBindings= unknown;
}
public String getCanonicalRepresentation() {
return fValue;
public char[] getInternalExpression() {
return fExpression;
}
public Long numericalValue() {
try {
return Long.parseLong(fValue);
} catch (NumberFormatException e) {
public IBinding[] getUnknownBindings() {
return fUnknownBindings;
}
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
public int hashCode() {
return fValue.hashCode();
return CharArrayUtils.hash(fExpression);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof IValue)) {
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
public String toString() {
return fValue;
return new String(getSignature());
}
/**
@ -90,37 +182,68 @@ public class Value implements IValue {
public static IValue create(long value) {
if (value >=0 && value < TYPICAL.length)
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.
*/
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
* 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) {
final String rep= tval.getCanonicalRepresentation();
if (rep.indexOf('#') == 0 && rep.indexOf(',') == -1) {
try {
return Integer.parseInt(rep.substring(1), 16);
} catch (NumberFormatException e) {
final char[] rep= tval.getInternalExpression();
if (rep.length > 0) {
if (rep[0] == TEMPLATE_PARAM_CHAR) {
for (int i = 1; i < rep.length; i++) {
if (rep[i] == SEPARATOR)
return -1;
}
try {
return parseHex(rep, 1);
} catch (UnknownValueException e) {
}
}
}
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.
*/
public static boolean isDependentValue(IValue nonTypeValue) {
final String rep= nonTypeValue.getCanonicalRepresentation();
return rep.indexOf('#') >= 0;
final char[] rep= nonTypeValue.getInternalExpression();
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) {
try {
Object obj= evaluate(expr, maxRecursionDepth);
if (obj instanceof Long)
return create(((Long) obj).longValue());
return new Value(obj.toString());
Map<String, Integer> unknownSigs= new HashMap<String, Integer>();
List<ICPPUnknownBinding> unknown= new ArrayList<ICPPUnknownBinding>();
Object obj= evaluate(expr, unknownSigs, unknown, maxRecursionDepth);
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) {
}
return UNKNOWN;
@ -140,104 +272,78 @@ public class Value implements IValue {
/**
* Creates a value off its canonical representation.
*/
public static IValue fromCanonicalRepresentation(String rep) {
if (rep.equals(UNKNOWN.getCanonicalRepresentation()))
public static IValue fromInternalRepresentation(char[] rep, ICPPUnknownBinding[] unknown) {
if (CharArrayUtils.equals(rep, UNKNOWN.getInternalExpression()))
return UNKNOWN;
try {
return create(Long.parseLong(rep));
} catch (NumberFormatException e) {}
Long l= parseLong(rep);
if (l != null)
return create(l.longValue());
return new Value(rep);
return new Value(rep, unknown);
}
/**
* Creates a unique value needed during template instantiation.
*/
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
* numerical values or a {@code String}, otherwise.
* Computes the canonical representation of the value of the expression.
* Returns a {@code Number} for numerical values or a {@code String}, otherwise.
* @throws UnknownValueException
*/
@SuppressWarnings("nls")
private static Object evaluate(IASTExpression e, int maxdepth) throws UnknownValueException {
private static Object evaluate(IASTExpression e, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
if (maxdepth < 0 || e == null)
throw UNKNOWN_EX;
if (e instanceof IASTArraySubscriptExpression) {
IASTArraySubscriptExpression sub= (IASTArraySubscriptExpression) e;
return evaluate(sub.getArrayExpression(), maxdepth) + "," +
evaluate(sub.getSubscriptExpression(), maxdepth) + ",[]";
throw UNKNOWN_EX;
}
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
return evaluate(((IASTCastExpression) e).getOperand(), maxdepth);
return evaluate(((IASTCastExpression) e).getOperand(), unknownSigs, unknowns, maxdepth);
}
if (e instanceof IASTUnaryExpression) {
return evaluateUnaryExpression((IASTUnaryExpression) e, maxdepth);
return evaluateUnaryExpression((IASTUnaryExpression) e, unknownSigs, unknowns, maxdepth);
}
if (e instanceof IASTConditionalExpression) {
IASTConditionalExpression cexpr= (IASTConditionalExpression) e;
Object o= evaluate(cexpr.getLogicalConditionExpression(), maxdepth);
Object o= evaluate(cexpr.getLogicalConditionExpression(), unknownSigs, unknowns, maxdepth);
if (o instanceof Long) {
Long v= (Long) o;
if (v.longValue() == 0) {
return evaluate(cexpr.getNegativeResultExpression(), maxdepth);
return evaluate(cexpr.getNegativeResultExpression(), unknownSigs, unknowns, maxdepth);
}
final IASTExpression pe = cexpr.getPositiveResultExpression();
if (pe == null) // gnu-extension allows to omit the positive expression.
return o;
return evaluate(pe, maxdepth);
return evaluate(pe, unknownSigs, unknowns, maxdepth);
}
final IASTExpression pe = cexpr.getPositiveResultExpression();
Object po= pe == null ? o : evaluate(pe, maxdepth);
return o + "," + evaluate(cexpr.getNegativeResultExpression(), maxdepth) + "," + po + '?';
Object po= pe == null ? o : evaluate(pe, unknownSigs, unknowns, maxdepth);
Object neg= evaluate(cexpr.getNegativeResultExpression(), unknownSigs, unknowns, maxdepth);
return CONDITIONAL_CHAR + SEPARATOR + o.toString() + SEPARATOR + po.toString() + SEPARATOR + neg.toString();
}
if (e instanceof IASTIdExpression) {
IBinding b= CPPASTNameBase.resolvePreBinding(((IASTIdExpression) e).getName());
if (b instanceof ICPPTemplateParameter) {
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;
}
return evaluateBinding(b, unknownSigs, unknowns, maxdepth);
}
if (e instanceof IASTLiteralExpression) {
IASTLiteralExpression litEx= (IASTLiteralExpression) e;
switch (litEx.getKind()) {
case IASTLiteralExpression.lk_false:
return "0";
return 0;
case IASTLiteralExpression.lk_true:
return "1";
return 1;
case IASTLiteralExpression.lk_integer_constant:
try {
return ExpressionEvaluator.getNumber(litEx.getValue());
@ -259,28 +365,104 @@ public class Value implements IValue {
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)
throw UNKNOWN_EX;
Long lv= cv.numericalValue();
if (lv != null)
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 String evaluate(ICPPTemplateParameter param) {
return "#" + Integer.toHexString(param.getParameterID());
}
@SuppressWarnings("nls")
private static Object evaluateUnaryExpression(IASTUnaryExpression ue, int maxdepth) throws UnknownValueException {
private static Object evaluateUnaryExpression(IASTUnaryExpression ue, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
final int unaryOp= ue.getOperator();
if (unaryOp == IASTUnaryExpression.op_amper || unaryOp == IASTUnaryExpression.op_star)
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) {
long v= (Long) value;
switch(unaryOp) {
@ -290,9 +472,6 @@ public class Value implements IValue {
case IASTUnaryExpression.op_prefixDecr :
case IASTUnaryExpression.op_postFixDecr:
return --v;
case IASTUnaryExpression.op_bracketedPrimary:
case IASTUnaryExpression.op_plus:
return value;
case IASTUnaryExpression.op_minus:
return -v;
case IASTUnaryExpression.op_tilde:
@ -300,22 +479,32 @@ public class Value implements IValue {
case IASTUnaryExpression.op_not:
return v == 0 ? 1 : 0;
}
}
switch (unaryOp) {
case IASTUnaryExpression.op_bracketedPrimary:
case IASTUnaryExpression.op_plus:
return value;
}
throw UNKNOWN_EX;
}
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, int maxdepth) throws UnknownValueException {
final Object o1= evaluate(be.getOperand1(), maxdepth);
final Object o2= evaluate(be.getOperand2(), maxdepth);
private static Object evaluateBinaryExpression(IASTBinaryExpression be,
Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, int maxdepth) throws UnknownValueException {
final Object o1= evaluate(be.getOperand1(), unknownSigs, unknowns, maxdepth);
final Object o2= evaluate(be.getOperand2(), unknownSigs, unknowns, maxdepth);
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) {
long v1= (Long) o1;
long v2= (Long) o2;
@ -365,14 +554,274 @@ public class Value implements IValue {
case IASTBinaryExpression.op_min:
return Math.min(v1, v2);
}
throw UNKNOWN_EX;
}
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:
return o1.equals(o2) ? 1 : 0;
if (o1.equals(o2))
return 1;
break;
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) {
v= ((IInternalVariable) field).getInitialValue(maxRecursionDepth);
} else {
v= specializeValue(getField().getInitialValue());
v= getField().getInitialValue();
}
value= specializeValue(v);
value= specializeValue(v, maxRecursionDepth);
}
return value;
}

View file

@ -59,8 +59,12 @@ public abstract class CPPSpecialization extends PlatformObject implements ICPPSp
}
}
public IValue specializeValue(IValue value) {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap());
public IValue specializeValue(IValue value, int maxdepth) {
if (owner instanceof ICPPClassSpecialization) {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), (ICPPClassSpecialization) owner, maxdepth);
} else {
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), null, maxdepth);
}
}
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.
*/
public interface ICPPUnknownBinding extends ICPPBinding {
ICPPUnknownBinding[] EMPTY_UNKNOWN_BINDING_ARRAY = {};
/**
* Returns the scope this binding represents.
* @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.CPPTemplateTypeParameter;
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.CPPUnknownClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
@ -712,19 +713,38 @@ public class CPPTemplates {
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)
return null;
// mstodo- instantiate values correctly
int parPos= Value.isTemplateParameter(value);
if (parPos >= 0) {
ICPPTemplateArgument arg = tpMap.getArgument(parPos);
if (arg != null) {
IValue mappedValue = arg.getNonTypeValue();
if (mappedValue != null)
return mappedValue;
IBinding[] unknowns= value.getUnknownBindings();
IBinding[] resolvedUnknowns= null;
if (unknowns.length != 0) {
for (int i = 0; i < unknowns.length; i++) {
IBinding unknown= unknowns[i];
IBinding resolved= unknown;
if (unknown instanceof ICPPUnknownBinding) {
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;
}
@ -867,7 +887,7 @@ public class CPPTemplates {
ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) {
if (arg.isNonTypeValue()) {
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)
return arg;
return new CPPTemplateArgument(inst, arg.getTypeOfNonTypeValue());
@ -1899,7 +1919,7 @@ public class CPPTemplates {
if (map != null && pType != null) {
pType= instantiateType(pType, map, null);
}
if (isNonTypeArgumentConvertible(pType, argType)) {
if (argType instanceof ICPPUnknownType || isNonTypeArgumentConvertible(pType, argType)) {
return new CPPTemplateArgument(arg.getNonTypeValue(), pType);
}
return null;
@ -2047,11 +2067,15 @@ public class CPPTemplates {
if (!t.equals(owner) && newArgs != arguments) {
result= new CPPUnknownClassInstance((ICPPUnknownBinding) t, ucli.getUnknownName(), newArgs);
}
} else if (unknown instanceof ICPPUnknownClassType) {
if (!t.equals(owner)) {
result= new CPPUnknownClass((ICPPUnknownBinding)t, ((ICPPUnknownClassType)unknown).getUnknownName());
} else if (!t.equals(owner)) {
if (unknown instanceof ICPPUnknownClassType) {
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) {
IScope s = ((ICPPClassType) t).getCompositeScope();
if (s != null && ASTInternal.isFullyCached(s)) {
@ -2081,7 +2105,7 @@ public class CPPTemplates {
return result;
}
private static IBinding resolveDeferredClassInstance(ICPPDeferredClassInstance dci, ICPPTemplateParameterMap tpMap, ICPPClassSpecialization within) {
ICPPTemplateArgument[] arguments = dci.getTemplateArguments();
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
* 77.0 - support for parameter annotations, 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) {
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 CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION);

View file

@ -383,6 +383,13 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
public String toString() {
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.IVariable;
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.index.IIndexCBindingConstants;
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.PDOMName;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
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 {
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
@ -94,8 +95,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
if (mytype != null)
linkage.deleteType(mytype, record);
if (valueRec != 0)
db.getString(valueRec).delete();
PDOMValue.delete(db, valueRec);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
@ -135,9 +135,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable {
try {
final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0)
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).getString());
return PDOMValue.restore(db, getLinkage(), valRec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;

View file

@ -11,14 +11,14 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
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.internal.core.dom.parser.Value;
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.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.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
@ -45,8 +45,8 @@ public class PDOMCPPArgumentList {
final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue());
// type can be null, if it is a local type
db.putInt(p, type == null ? 0 : type.getRecord());
final IString s= db.newString(arg.getNonTypeValue().getCanonicalRepresentation());
db.putInt(p+4, s.getRecord());
int valueRec= PDOMValue.store(db, linkage, arg.getNonTypeValue());
db.putInt(p+4, valueRec);
} else {
final PDOMNode type= linkage.addType(parent, arg.getTypeValue());
// type can be null, if it is a local type.
@ -74,9 +74,7 @@ public class PDOMCPPArgumentList {
linkage.deleteType(t, parent.getRecord());
}
final int nonTypeValueRec= db.getInt(p+4);
if (nonTypeValueRec != 0) {
db.getString(nonTypeValueRec).delete();
}
PDOMValue.delete(db, nonTypeValueRec);
p+= 8;
}
db.free(record);
@ -102,8 +100,8 @@ public class PDOMCPPArgumentList {
final IType type= typeRec == 0 ? new CPPBasicType(-1,0) : (IType) linkage.getNode(typeRec);
final int nonTypeValRec= db.getInt(rec+4);
if (nonTypeValRec != 0) {
final IString s= db.getString(nonTypeValRec);
result[i]= new CPPTemplateArgument(Value.fromCanonicalRepresentation(s.getString()), type);
final IValue val= PDOMValue.restore(db, linkage, nonTypeValRec);
result[i]= new CPPTemplateArgument(val, type);
} else {
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.ICPPSpecialization;
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.pdom.PDOM;
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.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
import org.eclipse.core.runtime.CoreException;
/**
@ -56,15 +57,14 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements
try {
final Database db = pdom.getDB();
IType type = field.getType();
PDOMNode typeNode = getLinkageImpl().addType(this, type);
final PDOMLinkage linkage = getLinkage();
PDOMNode typeNode = linkage.addType(this, type);
if (typeNode != null) {
db.putInt(record + TYPE, typeNode.getRecord());
}
IValue val= field.getInitialValue();
if (val != null) {
db.putInt(record + VALUE_OFFSET, db.newString(val.getCanonicalRepresentation()).getRecord());
}
int rec= PDOMValue.store(db, linkage, val);
db.putInt(record + VALUE_OFFSET, rec);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
@ -108,9 +108,7 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements
try {
final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0)
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).toString());
return PDOMValue.restore(db, getLinkage(), valRec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;

View file

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

View file

@ -11,16 +11,16 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
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.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.CPPTemplateArgument;
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.IString;
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.PDOMValue;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
@ -50,8 +50,8 @@ public class PDOMCPPTemplateParameterMap {
final PDOMNode type= linkage.addType(parent, arg.getTypeOfNonTypeValue());
// type can be null, if it is local
db.putInt(p, type == null ? 0 : type.getRecord());
final IString s= db.newString(arg.getNonTypeValue().getCanonicalRepresentation());
db.putInt(p+4, s.getRecord());
int valueRec= PDOMValue.store(db, linkage, arg.getNonTypeValue());
db.putInt(p+4, valueRec);
} else {
final PDOMNode type= linkage.addType(parent, arg.getTypeValue());
// type can be null, if it is local
@ -81,9 +81,7 @@ public class PDOMCPPTemplateParameterMap {
linkage.deleteType(t, parent.getRecord());
}
final int nonTypeValueRec= db.getInt(rec+4);
if (nonTypeValueRec != 0) {
db.getString(nonTypeValueRec).delete();
}
PDOMValue.delete(db, nonTypeValueRec);
rec+= 8;
}
db.free(rec);
@ -111,8 +109,8 @@ public class PDOMCPPTemplateParameterMap {
final int nonTypeValRec= db.getInt(rec+8);
ICPPTemplateArgument arg;
if (nonTypeValRec != 0) {
final IString s= db.getString(nonTypeValRec);
arg= new CPPTemplateArgument(Value.fromCanonicalRepresentation(s.getString()), type);
IValue val= PDOMValue.restore(db, linkage, nonTypeValRec);
arg= new CPPTemplateArgument(val, type);
} else {
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.cpp.ICPPVariable;
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.index.IIndexCPPBindingConstants;
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.PDOMName;
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.core.runtime.CoreException;
@ -78,7 +78,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
private void setValue(Database db, IVariable variable) throws CoreException {
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);
}
@ -96,8 +96,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
setValue(db, var);
if (mytype != null)
linkage.deleteType(mytype, record);
if (valueRec != 0)
db.getString(valueRec).delete();
PDOMValue.delete(db, valueRec);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
@ -148,9 +147,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable {
try {
final Database db = pdom.getDB();
int valRec = db.getInt(record + VALUE_OFFSET);
if (valRec == 0)
return null;
return Value.fromCanonicalRepresentation(db.getString(valRec).getString());
return PDOMValue.restore(db, getLinkage(), valRec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;