diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
index 08dcdbe0ac5..9848c8cb804 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
@@ -7018,4 +7018,15 @@ public class AST2CPPTests extends AST2BaseTest {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
+
+ // void f(int volatile * const * ) {}
+ // void f(int const volatile * const *) {}
+ // void test() {
+ // int ** x;
+ // f(x); // problem binding here
+ // }
+ public void testRankingOfQualificationConversion_Bug269321() throws Exception {
+ final String code = getAboveComment();
+ parseAndCheckBindings(code, ParserLanguage.CPP);
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java
index e9f3599d3e8..53b3a9c0f40 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java
@@ -174,6 +174,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
import org.eclipse.cdt.internal.core.index.IIndexScope;
/**
@@ -2091,7 +2092,7 @@ public class CPPSemantics {
int len = Math.min(fnCost.length, bestFnCost.length);
for (int j = 1; j <= len; j++) {
Cost currCost = fnCost[fnCost.length - j];
- if (currCost.rank < 0) {
+ if (currCost.getRank() == Rank.NO_MATCH) {
hasWorse = true;
hasBetter = false;
break;
@@ -2099,13 +2100,13 @@ public class CPPSemantics {
// An ambiguity in the user defined conversion sequence is only a problem
// if this function turns out to be the best.
- if (currCost.userDefined == Cost.AMBIGUOUS_USERDEFINED_CONVERSION)
+ if (currCost.isAmbiguousUserdefinedConversion())
hasAmbiguousParam = true;
if (bestFnCost != null) {
int comparison = currCost.compare(bestFnCost[bestFnCost.length - j]);
- hasWorse |= (comparison < 0);
- hasBetter |= (comparison > 0);
+ hasWorse |= (comparison > 0);
+ hasBetter |= (comparison < 0);
} else {
hasBetter = true;
}
@@ -2186,20 +2187,18 @@ public class CPPSemantics {
} else {
result= new Cost[sourceLen+1];
if (ASTInternal.isStatic(fn, false)) {
- // 13.3.1-4 for static member functions, the implicit object parameter always matches
- cost = new Cost(thisType, implicitType);
- cost.rank = Cost.IDENTITY_RANK; // exact match, no cost
+ // 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
+ cost = new Cost(thisType, implicitType, Rank.IDENTITY);
} else if (thisType == null) {
return null;
} else if (thisType.isSameType(implicitType)) {
- cost = new Cost(thisType, implicitType);
- cost.rank = Cost.IDENTITY_RANK; // exact match, no cost
+ cost = new Cost(thisType, implicitType, Rank.IDENTITY);
} else {
if (CPPTemplates.isDependentType(implicitType))
return CONTAINS_DEPENDENT_TYPES;
cost = Conversions.checkImplicitConversionSequence(null, thisType, implicitType, false, true);
}
- if (cost.rank < 0)
+ if (cost.getRank() == Rank.NO_MATCH)
return null;
result[k++] = cost;
@@ -2218,21 +2217,19 @@ public class CPPSemantics {
} else if (!fn.takesVarArgs()) {
paramType= VOID_TYPE;
} else {
- cost = new Cost(argType, null);
- cost.rank = Cost.ELLIPSIS_CONVERSION;
+ cost = new Cost(argType, null, Rank.ELLIPSIS_CONVERSION);
result[k++]= cost;
continue;
}
if (argType.isSameType(paramType)) {
- cost = new Cost(argType, paramType);
- cost.rank = Cost.IDENTITY_RANK; // exact match, no cost
+ cost = new Cost(argType, paramType, Rank.IDENTITY);
} else {
if (CPPTemplates.isDependentType(paramType))
return CONTAINS_DEPENDENT_TYPES;
cost = Conversions.checkImplicitConversionSequence(arg, argType, paramType, allowUDC, false);
}
- if (cost.rank < 0)
+ if (cost.getRank() == Rank.NO_MATCH)
return null;
result[k++] = cost;
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 590bbd55e12..ef08d0bf9bb 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
@@ -138,6 +138,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
/**
* Collection of static methods to perform template instantiation, member specialization and
@@ -1962,7 +1963,7 @@ public class CPPTemplates {
}
}
Cost cost = Conversions.checkStandardConversionSequence(arg, paramType, false);
- return cost != null && cost.rank != Cost.NO_MATCH_RANK;
+ return cost != null && cost.getRank() != Rank.NO_MATCH;
}
static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
index 6f7c9f14581..b64899daa33 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
@@ -43,6 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.core.runtime.CoreException;
@@ -80,22 +81,13 @@ public class Conversions {
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
if (lvalue) {
- Cost cost= isReferenceCompatible(cv1T1, source);
+ Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
if (cost != null) {
// [8.5.3-5] this is a direct reference binding
- // [13.3.3.1.4-1] direct binding has either identity or conversion rank.
-
- // 7.3.3.13 for overload resolution the implicit this pointer is treated as if
- // it were a pointer to the derived class
- if (isImpliedObject)
- cost.conversion= 0;
-
- // [13.3.3.1.4]
- if (cost.conversion > 0) {
- cost.rank= Cost.DERIVED_TO_BASE_CONVERSION;
- } else {
- cost.rank = Cost.IDENTITY_RANK;
- }
+ // [13.3.3.1.4-1] direct binding has either identity or conversion rank.
+ if (cost.getInheritanceDistance() > 0) {
+ cost.setRank(Rank.CONVERSION);
+ }
return cost;
}
}
@@ -107,42 +99,30 @@ public class Conversions {
// (13.3.1.6) and choosing the best one through overload resolution (13.3)).
ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType) T2);
Cost operatorCost= null;
- ICPPMethod conv= null;
boolean ambiguousConversionOperator= false;
if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) {
for (final ICPPMethod op : fcns) {
- Cost cost2 = checkStandardConversionSequence(op.getType().getReturnType(), cv1T1,
- false);
- if (cost2.rank != Cost.NO_MATCH_RANK) {
- if (operatorCost == null) {
- operatorCost= cost2;
- conv= op;
- } else {
- int cmp= operatorCost.compare(cost2);
- if (cmp >= 0) {
+ IType newSource= op.getType().getReturnType();
+ if (newSource instanceof ICPPReferenceType) { // require an lvalue
+ IType cvT2= getNestedType(newSource, TDEF | REF);
+ Cost cost2= isReferenceCompatible(cv1T1, cvT2, false);
+ if (cost2 != null) {
+ int cmp= cost2.compare(operatorCost);
+ if (cmp <= 0) {
ambiguousConversionOperator= cmp == 0;
operatorCost= cost2;
- conv= op;
+ operatorCost.setUserDefinedConversion(op);
}
}
}
}
}
- if (conv!= null && !ambiguousConversionOperator) {
- IType newSource= conv.getType().getReturnType();
- if (newSource instanceof ICPPReferenceType) { // require an lvalue
- IType cvT2= getNestedType(newSource, TDEF | REF);
- Cost cost= isReferenceCompatible(cv1T1, cvT2);
- if (cost != null) {
- if (isImpliedObject) {
- cost.conversion= 0;
- }
- cost.rank= Cost.USERDEFINED_CONVERSION_RANK;
- cost.userDefined= Cost.USERDEFINED_CONVERSION;
- return cost;
- }
+ if (operatorCost != null && !ambiguousConversionOperator) {
+ if (isImpliedObject) {
+ operatorCost.setInheritanceDistance(0);
}
+ return operatorCost;
}
}
@@ -150,7 +130,7 @@ public class Conversions {
boolean cv1isConst= getCVQualifier(cv1T1) == 1;
if (cv1isConst) {
if (!lvalue && T2 instanceof ICPPClassType) {
- Cost cost= isReferenceCompatible(cv1T1, source);
+ Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
if (cost != null)
return cost;
}
@@ -162,15 +142,19 @@ public class Conversions {
// If T1 is reference-related to T2, cv1 must be the same cv-qualification as,
// or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
- IType T1= getNestedType(cv1T1, TDEF | REF | CVQ | PTR_CVQ);
- boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0;
+
+ // 13.3.3.1.7 no temporary object when converting the implicit object parameter
+ if (!isImpliedObject) {
+ IType T1= getNestedType(cv1T1, TDEF | REF | CVQ | PTR_CVQ);
+ boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0;
// We must do a non-reference initialization
- if (!illformed) {
- return nonReferenceConversion(source, cv1T1, allowUDC, isImpliedObject);
+ if (!illformed) {
+ return nonReferenceConversion(source, cv1T1, allowUDC, isImpliedObject);
+ }
}
}
- return new Cost(source, cv1T1);
+ return new Cost(source, cv1T1, Rank.NO_MATCH);
}
// Non-reference binding
@@ -180,7 +164,7 @@ public class Conversions {
private static Cost nonReferenceConversion(IType source, IType target, boolean allowUDC,
boolean isImpliedObject) throws DOMException {
Cost cost= checkStandardConversionSequence(source, target, isImpliedObject);
- if (allowUDC && cost.rank == Cost.NO_MATCH_RANK) {
+ if (allowUDC && cost.getRank() == Rank.NO_MATCH) {
Cost temp = checkUserDefinedConversionSequence(source, target);
if (temp != null) {
cost = temp;
@@ -280,18 +264,22 @@ public class Conversions {
* @return The cost for converting or null
if cv1t1
is not
* reference-compatible with cv2t2
*/
- private static final Cost isReferenceCompatible(IType cv1Target, IType cv2Source) throws DOMException {
- final int inheritanceDist= isReferenceRelated(cv1Target, cv2Source);
+ private static final Cost isReferenceCompatible(IType cv1Target, IType cv2Source, boolean isImpliedObject) throws DOMException {
+ int inheritanceDist= isReferenceRelated(cv1Target, cv2Source);
if (inheritanceDist < 0)
return null;
final int cmp= compareQualifications(cv1Target, cv2Source);
if (cmp < 0)
return null;
- Cost cost= new Cost(cv2Source, cv1Target);
- cost.qualification= cmp > 0 ? Cost.CONVERSION_RANK : Cost.IDENTITY_RANK;
- cost.conversion= inheritanceDist;
- cost.rank= Cost.IDENTITY_RANK;
+ // 7.3.3.13 for overload resolution the implicit this pointer is treated as if
+ // it were a pointer to the derived class
+ if (isImpliedObject)
+ inheritanceDist= 0;
+
+ Cost cost= new Cost(cv2Source, cv1Target, Rank.IDENTITY);
+ cost.setQualificationAdjustment(cmp);
+ cost.setInheritanceDistance(inheritanceDist);
return cost;
}
@@ -305,8 +293,7 @@ public class Conversions {
*/
protected static final Cost checkStandardConversionSequence(IType source, IType target,
boolean isImplicitThis) throws DOMException {
- final Cost cost= new Cost(source, target);
- cost.rank= Cost.IDENTITY_RANK;
+ final Cost cost= new Cost(source, target, Rank.IDENTITY);
if (lvalue_to_rvalue(cost))
return cost;
@@ -320,12 +307,8 @@ public class Conversions {
return cost;
// If we can't convert the qualifications, then we can't do anything
- cost.rank= Cost.NO_MATCH_RANK;
+ cost.setRank(Rank.NO_MATCH);
return cost;
-
-// if (cost.rank == -1) {
-// relaxTemplateParameters(cost);
-// }
}
/**
@@ -359,8 +342,10 @@ public class Conversions {
IBinding binding = CPPSemantics.resolveFunction(data, convertingCtors, false);
if (binding instanceof ICPPConstructor && !(binding instanceof IProblemBinding)) {
constructorCost = checkStandardConversionSequence(t, target, false);
- if (constructorCost.rank == Cost.NO_MATCH_RANK) {
+ if (constructorCost.getRank() == Rank.NO_MATCH) {
constructorCost= null;
+ } else {
+ constructorCost.setUserDefinedConversion((ICPPConstructor)binding);
}
}
}
@@ -373,15 +358,12 @@ public class Conversions {
if (ops.length > 0 && !(ops[0] instanceof IProblemBinding)) {
for (final ICPPMethod op : ops) {
Cost cost= checkStandardConversionSequence(op.getType().getReturnType(), target, false);
- if (cost.rank != Cost.NO_MATCH_RANK) {
- if (operatorCost == null) {
+ if (cost.getRank() != Rank.NO_MATCH) {
+ int cmp= cost.compare(operatorCost);
+ if (cmp <= 0) {
+ cost.setUserDefinedConversion(op);
operatorCost= cost;
- } else {
- int cmp= operatorCost.compare(cost);
- if (cmp >= 0) {
- ambiguousConversionOperator= cmp == 0;
- operatorCost= cost;
- }
+ ambiguousConversionOperator= cmp == 0;
}
}
}
@@ -389,25 +371,18 @@ public class Conversions {
}
if (constructorCost != null) {
- if (operatorCost == null || ambiguousConversionOperator) {
- constructorCost.userDefined = Cost.USERDEFINED_CONVERSION;
- constructorCost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- } else {
+ if (operatorCost != null && !ambiguousConversionOperator) {
// If both are valid, then the conversion is ambiguous
- constructorCost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION;
- constructorCost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- }
+ constructorCost.setAmbiguousUserdefinedConversion(true);
+ }
return constructorCost;
}
+
if (operatorCost != null) {
- operatorCost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- if (ambiguousConversionOperator) {
- operatorCost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION;
- } else {
- operatorCost.userDefined = Cost.USERDEFINED_CONVERSION;
- }
+ operatorCost.setAmbiguousUserdefinedConversion(ambiguousConversionOperator);
return operatorCost;
}
+
return null;
}
@@ -481,13 +456,13 @@ public class Conversions {
source= srcRValue;
} else {
// ill-formed
- cost.rank= Cost.NO_MATCH_RANK;
+ cost.setRank(Rank.NO_MATCH);
return true;
}
} else {
source= unqualifiedSrcRValue;
}
- cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
+ cost.setRank(Rank.LVALUE_TRANSFORMATION);
isConverted= true;
}
}
@@ -510,8 +485,8 @@ public class Conversions {
IASTLiteralExpression lit= (IASTLiteralExpression) val;
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
source= new CPPPointerType(tmp, false, false);
- cost.qualification= Cost.CONVERSION_RANK;
- cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
+ cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt) | 1);
+ cost.setRank(Rank.LVALUE_TRANSFORMATION);
isConverted= true;
}
}
@@ -521,7 +496,7 @@ public class Conversions {
}
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
- cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
+ cost.setRank(Rank.LVALUE_TRANSFORMATION);
isConverted= true;
}
}
@@ -531,7 +506,7 @@ public class Conversions {
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
if (targetPtrTgt instanceof IFunctionType && srcRValue instanceof IFunctionType) {
source = new CPPPointerType(source);
- cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
+ cost.setRank(Rank.LVALUE_TRANSFORMATION);
isConverted= true;
}
}
@@ -548,7 +523,7 @@ public class Conversions {
}
if (source == null || target == null) {
- cost.rank= Cost.NO_MATCH_RANK;
+ cost.setRank(Rank.NO_MATCH);
return true;
}
cost.source= source;
@@ -569,10 +544,12 @@ public class Conversions {
IType t = cost.target;
boolean constInEveryCV2k = true;
boolean firstPointer= true;
+ int adjustments= 0;
while (true) {
s= getNestedType(s, TDEF | REF);
t= getNestedType(t, TDEF | REF);
if (s instanceof IPointerType && t instanceof IPointerType) {
+ adjustments <<= 2;
final int cmp= compareQualifications(t, s); // is t more qualified than s?
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
return false;
@@ -590,31 +567,33 @@ public class Conversions {
}
}
- if (cmp != 0) {
- cost.qualification= Cost.CONVERSION_RANK;
- }
final IPointerType tPtr = (IPointerType) t;
final IPointerType sPtr = (IPointerType) s;
constInEveryCV2k &= (firstPointer || tPtr.isConst());
s= sPtr.getType();
t= tPtr.getType();
firstPointer= false;
+ adjustments |= cmp;
} else {
break;
}
}
if (s instanceof IQualifierType || t instanceof IQualifierType) {
+ adjustments <<= 2;
int cmp= compareQualifications(t, s); // is t more qualified than s?
- if (cmp == -1 || (cmp == 1 && !constInEveryCV2k)) {
+ if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
return false;
- } else if (cmp != 0) {
- cost.qualification= Cost.CONVERSION_RANK;
- }
+ }
+
+ adjustments |= cmp;
s= getNestedType(s, CVQ | TDEF | REF);
t= getNestedType(t, CVQ | TDEF | REF);
}
+ if (adjustments > 0) {
+ cost.setQualificationAdjustment(adjustments);
+ }
return s != null && t != null && s.isSameType(t);
}
@@ -668,8 +647,7 @@ public class Conversions {
}
}
if (canPromote) {
- cost.promotion = 1;
- cost.rank= Cost.PROMOTION_RANK;
+ cost.setRank(Rank.PROMOTION);
return true;
}
return false;
@@ -687,9 +665,6 @@ public class Conversions {
final IType s = cost.source;
final IType t = cost.target;
- cost.conversion = 0;
- cost.detail = 0;
-
if (t instanceof IBasicType) {
// 4.7 integral conversion
// 4.8 floating point conversion
@@ -697,15 +672,13 @@ public class Conversions {
if (s instanceof IBasicType || s instanceof IEnumeration) {
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
// An rvalue of an enumeration type can be converted to an rvalue of an integer type.
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
+ cost.setRank(Rank.CONVERSION);
return true;
}
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
final int tgtType = ((IBasicType) t).getType();
if (tgtType == ICPPBasicType.t_bool && s instanceof IPointerType) {
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
+ cost.setRank(Rank.CONVERSION_PTR_BOOL);
return true;
}
}
@@ -720,8 +693,7 @@ public class Conversions {
if (exp != null) {
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
if (val != null && val == 0) {
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
+ cost.setRank(Rank.CONVERSION);
return true;
}
}
@@ -733,9 +705,8 @@ public class Conversions {
// converted to an rvalue of type "pointer to cv void"
IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TDEF | CVQ | REF);
if (tgtPtrTgt instanceof IBasicType && ((IBasicType) tgtPtrTgt).getType() == IBasicType.t_void) {
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- cost.detail = 2;
+ cost.setRank(Rank.CONVERSION);
+ cost.setInheritanceDistance(Short.MAX_VALUE); // mstodo add distance to last base class
int cv= getCVQualifier(srcPtr.getType());
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, (cv&1) != 0, (cv&2) != 0));
return false;
@@ -750,15 +721,14 @@ public class Conversions {
if (tgtPtrTgt instanceof ICPPClassType && srcPtrTgt instanceof ICPPClassType) {
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, srcPtrTgt, tgtPtrTgt);
if (depth == -1) {
- cost.rank= Cost.NO_MATCH_RANK;
+ cost.setRank(Rank.NO_MATCH);
return true;
}
if (depth > 0) {
if (!forImplicitThis) {
- cost.rank= Cost.CONVERSION_RANK;
- cost.conversion= depth;
+ cost.setRank(Rank.CONVERSION);
+ cost.setInheritanceDistance(depth);
}
- cost.detail= 1;
int cv= getCVQualifier(srcPtr.getType());
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, (cv&1) != 0, (cv&2) != 0));
}
@@ -776,13 +746,12 @@ public class Conversions {
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH,
tpm.getMemberOfClass(), spm.getMemberOfClass());
if (depth == -1) {
- cost.rank= Cost.NO_MATCH_RANK;
+ cost.setRank(Rank.NO_MATCH);
return true;
}
if (depth > 0) {
- cost.rank= Cost.CONVERSION_RANK;
- cost.conversion= depth;
- cost.detail= 1;
+ cost.setRank(Rank.CONVERSION);
+ cost.setInheritanceDistance(depth);
cost.source = new CPPPointerToMemberType(spm.getType(),
tpm.getMemberOfClass(), spm.isConst(), spm.isVolatile());
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java
index 971c1a59ea6..cb049e0dd7f 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 IBM Corporation 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
@@ -14,138 +14,118 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ast.DOMException;
-import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType;
-import org.eclipse.cdt.core.dom.ast.ITypedef;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
/**
* The cost of an implicit conversion sequence.
*
* See [over.best.ics] 13.3.3.1.
*/
-class Cost {
- //Some constants to help clarify things
- public static final int NO_USERDEFINED_CONVERSION = 0;
- public static final int AMBIGUOUS_USERDEFINED_CONVERSION = 1;
- public static final int USERDEFINED_CONVERSION = 2;
+final class Cost {
+ enum Rank {
+ IDENTITY, LVALUE_TRANSFORMATION, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
+ USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
+ }
+
+ IType source;
+ IType target;
+
+ private Rank fRank;
+ private Rank fSecondStandardConversionRank;
+ private boolean fAmbiguousUserdefinedConversion;
+ private int fQualificationAdjustments;
+ private int fInheritanceDistance;
+ private ICPPFunction fUserDefinedConversion;
- public static final int NO_MATCH_RANK = -1;
- public static final int IDENTITY_RANK = 0;
- public static final int LVALUE_OR_QUALIFICATION_RANK = 0;
- public static final int PROMOTION_RANK = 1;
- public static final int CONVERSION_RANK = 2;
- public static final int DERIVED_TO_BASE_CONVERSION = 3;
- public static final int USERDEFINED_CONVERSION_RANK = 4;
- public static final int ELLIPSIS_CONVERSION = 5;
-
- public IType source;
- public IType target;
-
- public int lvalue;
- public int promotion;
- public int conversion;
- public int qualification;
- public int userDefined= NO_USERDEFINED_CONVERSION;
- public int rank = -1;
- public int detail;
-
- public Cost( IType s, IType t ){
+ public Cost(IType s, IType t, Rank rank) {
source = s;
target = t;
+ fRank= rank;
}
- public int compare( Cost cost ) throws DOMException{
- int result = 0;
-
- if( rank != cost.rank ){
- return cost.rank - rank;
+ public Rank getRank() {
+ return fRank;
+ }
+
+ public void setRank(Rank rank) {
+ fRank= rank;
+ }
+
+ public boolean isAmbiguousUserdefinedConversion() {
+ return fAmbiguousUserdefinedConversion;
+ }
+
+ public void setAmbiguousUserdefinedConversion(boolean val) {
+ fAmbiguousUserdefinedConversion= val;
+ }
+
+ public int getInheritanceDistance() {
+ return fInheritanceDistance;
+ }
+
+ public void setInheritanceDistance(int inheritanceDistance) {
+ fInheritanceDistance = inheritanceDistance;
+ }
+
+ public void setQualificationAdjustment(int adjustment) {
+ fQualificationAdjustments= adjustment;
+ if (adjustment != 0 && fRank == Rank.IDENTITY) {
+ fRank= Rank.LVALUE_TRANSFORMATION;
}
+ }
+
+ /**
+ * Converts the cost for the second standard conversion into the overall cost for the
+ * implicit conversion sequence.
+ */
+ public void setUserDefinedConversion(ICPPMethod conv) {
+ fUserDefinedConversion= conv;
+ if (conv != null) {
+ fSecondStandardConversionRank= fRank;
+ fRank= Rank.USER_DEFINED_CONVERSION;
+ }
+ }
+
+ /**
+ * Returns an integer < 0 if other cost is null
, or this cost is smaller than the other cost,
+ * 0 if this cost is equal to the other cost,
+ * an integer > 0 if this cost is larger than the other cost.
+ */
+ public int compare(Cost other) throws DOMException {
+ if (other == null)
+ return -1;
- if (userDefined == cost.userDefined) {
- if (userDefined == AMBIGUOUS_USERDEFINED_CONVERSION) {
+ int cmp= fRank.compareTo(other.fRank);
+ if (cmp != 0)
+ return cmp;
+
+ // rank is equal
+ if (fRank == Rank.USER_DEFINED_CONVERSION) {
+ // 13.3.3.1.10
+ if (isAmbiguousUserdefinedConversion() || other.isAmbiguousUserdefinedConversion())
return 0;
- }
- // same or no userconversion --> rank on standard conversion sequence.
- }
- else {
- if (userDefined == NO_USERDEFINED_CONVERSION || cost.userDefined == NO_USERDEFINED_CONVERSION) {
- return cost.userDefined - userDefined;
- }
- // one ambiguous, the other needs conversion --> can't use std conversion to rank
- return 0;
- }
-
- if( promotion > 0 || cost.promotion > 0 ){
- result = cost.promotion - promotion;
- }
- if( conversion > 0 || cost.conversion > 0 ){
- if( detail == cost.detail ){
- result = cost.conversion - conversion;
- } else {
- result = cost.detail - detail;
- }
- }
-
- if( result == 0 ){
- if( cost.qualification != qualification ){
- return cost.qualification - qualification;
- }
- if( qualification == 0 ){
- return 0;
- }
- // something is wrong below:
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=226877
-
- IPointerType op1, op2;
- IType t1 = cost.target, t2 = target;
- int subOrSuper = 0;
- while (true) {
- op1 = null;
- op2 = null;
- while (true) {
- if (t1 instanceof ITypedef) {
- t1 = ((ITypedef) t1).getType();
- } else {
- if (t1 instanceof IPointerType)
- op1 = (IPointerType) t1;
- break;
- }
- }
- while (true) {
- if (t2 instanceof ITypedef) {
- t2 = ((ITypedef) t2).getType();
- } else {
- if (t2 instanceof IPointerType)
- op2 = (IPointerType) t2;
- break;
- }
- }
- if (op1 == null || op2 == null)
- break;
-
- int cmp = (op1.isConst() ? 1 : 0) + (op1.isVolatile() ? 1 : 0)
- - (op2.isConst() ? 1 : 0) + (op2.isVolatile() ? 1 : 0);
-
- if (cmp != 0) {
- if (subOrSuper == 0) {
- subOrSuper = cmp;
- }
- else if ((subOrSuper > 0) != (cmp > 0)) {
- return 0;
- }
- }
- t1= op1.getType();
- t2= op2.getType();
- }
- if (op1 != null) {
- return 1;
- } else if (op2 != null) {
- return -1;
- }
- return 0;
+ if (!fUserDefinedConversion.equals(other.fUserDefinedConversion))
+ return 0;
+
+ cmp= fSecondStandardConversionRank.compareTo(other.fSecondStandardConversionRank);
+ if (cmp != 0)
+ return cmp;
}
-
- return result;
+
+ cmp= fInheritanceDistance - other.fInheritanceDistance;
+ if (cmp != 0)
+ return cmp;
+
+ int qdiff= fQualificationAdjustments ^ other.fQualificationAdjustments;
+ if (qdiff != 0) {
+ if ((fQualificationAdjustments & qdiff) == 0)
+ return -1;
+ if ((other.fQualificationAdjustments & qdiff) == 0)
+ return 1;
+ }
+ return 0;
}
}
\ No newline at end of file