1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Ranking by qualification adjustments + cleanup of cost comparison, bug 269321.

This commit is contained in:
Markus Schorn 2009-03-19 17:18:09 +00:00
parent 43a30d5d3d
commit 057fdbe4a5
5 changed files with 207 additions and 249 deletions

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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) {

View file

@ -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 <code>null</code> if <code>cv1t1</code> is not
* reference-compatible with <code>cv2t2</code>
*/
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());
}

View file

@ -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 &lt 0 if other cost is <code>null</code>, or this cost is smaller than the other cost,
* 0 if this cost is equal to the other cost,
* an integer &gt 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;
}
}