diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index d1a4e75a18e..6a844012c8f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java index 63b6b8e7d48..c7e84dad164 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java index aa3f02378a0..875312a19b6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPTemplateParameterMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPTemplateParameterMap.java index 59e21f693bf..68d022b0c58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPTemplateParameterMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPTemplateParameterMap.java @@ -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 null if diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index e2e81d9d495..8bb0dc0a2f2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -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(""); //$NON-NLS-1$ + public final static IValue UNKNOWN= new Value("".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 fUnknownSigs; + public final List fUnknowns; + public final IBinding[] fResolvedUnknown; + public final ICPPTemplateParameterMap fMap; + public Reevaluation(char[] expr, Map unknownSigs, List 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 null if it is not a template parameter. + * parameter, or -1 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 unknownSigs= new HashMap(); + List unknown= new ArrayList(); + 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 unknownSigs, List 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 unknownSigs, List 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 unknownSigs, List 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 unknownSigs, List 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 unknownSigs, List 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 unknownSigs, List 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 unknownSigs= new HashMap(); + List unknown= new ArrayList(); + 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 null 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; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java index 3dddadfac83..5afae0f97df 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java index 2238c39ff55..4be0e055518 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSpecialization.java @@ -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() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPUnknownBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPUnknownBinding.java index 205286015e0..f02f0b6820c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPUnknownBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPUnknownBinding.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index eb30b9d6da3..6ffd8c6e480 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 26a3057fb04..75621c6fdc7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 16b8faa9291..f2fea7cf248 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMValue.java new file mode 100644 index 00000000000..e6da5ee943f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMValue.java @@ -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); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java index 7786f24997a..d70c70bc41f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPArgumentList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPArgumentList.java index cb1a5681a93..b136f535f58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPArgumentList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPArgumentList.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java index 7909782c20d..87d0640a6ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 76dac097995..66576d7a299 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -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 fromName is not null * then an existing binding is updated with the properties of the name. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateNonTypeParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateNonTypeParameter.java index 2ea00dfcf62..2967de2e6e3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateNonTypeParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateNonTypeParameter.java @@ -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; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateParameterMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateParameterMap.java index 1c7b1d81eae..bbf6c4f8ec8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateParameterMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateParameterMap.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java index 825822f79f5..a7f1cc12b2b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java @@ -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;