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