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:
parent
43a30d5d3d
commit
057fdbe4a5
5 changed files with 207 additions and 249 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 <code>null</code>, 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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue