diff options
author | Markus Schorn | 2008-04-14 14:53:24 +0000 |
---|---|---|
committer | Markus Schorn | 2008-04-14 14:53:24 +0000 |
commit | b9f428181ba0a374bb95b75c562654bb868fb17c (patch) | |
tree | 384fcf2b05e7f047a35aafc2ff7cd1aad27e89ff /core | |
parent | fb2df943e365314d49771013fdd90754b0e96556 (diff) | |
download | org.eclipse.cdt-b9f428181ba0a374bb95b75c562654bb868fb17c.tar.gz org.eclipse.cdt-b9f428181ba0a374bb95b75c562654bb868fb17c.tar.xz org.eclipse.cdt-b9f428181ba0a374bb95b75c562654bb868fb17c.zip |
Fixes user-defined conversions, comment 4 of bug 226308.
Diffstat (limited to 'core')
2 files changed, 78 insertions, 78 deletions
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 dfe31fb72c5..0ca4ff9630d 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 @@ -39,7 +39,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; -import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization; @@ -59,7 +58,7 @@ class Conversions { /** * Computes the cost of using the standard conversion sequence from source to target. - * @param ignoreDerivedToBaseConversion handles the special case when members of different + * @param isImplicitThis handles the special case when members of different * classes are nominated via using-declarations. In such a situation the derived to * base conversion does not cause any costs. * @throws DOMException @@ -121,33 +120,31 @@ class Conversions { } static Cost checkUserDefinedConversionSequence( IType source, IType target ) throws DOMException { - Cost cost = null; Cost constructorCost = null; - Cost conversionCost = null; + Cost operatorCost = null; IType s = getUltimateType( source, true ); IType t = getUltimateType( target, true ); - ICPPConstructor constructor = null; - ICPPMethod conversion = null; - //constructors if( t instanceof ICPPClassType ){ ICPPConstructor [] constructors = ((ICPPClassType)t).getConstructors(); if( constructors.length > 0 ){ - if( constructors.length == 1 && constructors[0] instanceof IProblemBinding ) - constructor = null; - else { + if( constructors.length > 0 && constructors[0] instanceof IProblemBinding == false ){ LookupData data = new LookupData(); data.forUserDefinedConversion = true; data.functionParameters = new IType [] { source }; IBinding binding = CPPSemantics.resolveFunction( data, constructors ); - if( binding instanceof ICPPConstructor ) - constructor = (ICPPConstructor) binding; + if( binding instanceof ICPPConstructor ) { + ICPPConstructor constructor = (ICPPConstructor) binding; + if(!constructor.isExplicit()){ + constructorCost = checkStandardConversionSequence( t, target, false ); + if (constructorCost.rank == Cost.NO_MATCH_RANK) { + constructorCost= null; + } + } } } - if( constructor != null && !constructor.isExplicit() ){ - constructorCost = checkStandardConversionSequence( t, target, false ); } } @@ -159,55 +156,51 @@ class Conversions { || s instanceof CPPClassInstance); //conversion operators + boolean ambigousConversionOperator= false; if (checkConversionOperators) { ICPPMethod [] ops = SemanticUtil.getConversionOperators((ICPPClassType)s); - if( ops.length > 0 && !(ops[0] instanceof IProblemBinding) ){ - Cost [] costs = null; - for (int i = 0; i < ops.length; i++) { - cost = checkStandardConversionSequence( ops[i].getType().getReturnType(), target, false ); - if( cost.rank != Cost.NO_MATCH_RANK ) - costs = (Cost[]) ArrayUtil.append( Cost.class, costs, cost ); - } - if( costs != null ){ - Cost best = costs[0]; - boolean bestIsBest = true; - int bestIdx = 0; - for (int i = 1; i < costs.length && costs[i] != null; i++) { - int comp = best.compare( costs[i] ); - if( comp == 0 ) - bestIsBest = false; - else if( comp > 0 ){ - best = costs[ bestIdx = i ]; - bestIsBest = true; + if( ops.length > 0 && ops[0] instanceof IProblemBinding == false ){ + for (final ICPPMethod op : ops) { + Cost cost = checkStandardConversionSequence( op.getType().getReturnType(), target, false ); + if( cost.rank != Cost.NO_MATCH_RANK ) { + if (operatorCost == null) { + operatorCost= cost; + } + else { + int cmp= operatorCost.compare(cost); + if (cmp >= 0) { + ambigousConversionOperator= cmp == 0; + operatorCost= cost; + } } - } - if( bestIsBest ){ - conversion = ops[ bestIdx ]; - conversionCost = best; } } } } - //if both are valid, then the conversion is ambiguous - if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK && - conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK ) - { - cost = constructorCost; - cost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION; - cost.rank = Cost.USERDEFINED_CONVERSION_RANK; - } else { - if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK ){ - cost = constructorCost; - cost.userDefined = constructor.hashCode(); - cost.rank = Cost.USERDEFINED_CONVERSION_RANK; - } else if( conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK ){ - cost = conversionCost; - cost.userDefined = conversion.hashCode(); - cost.rank = Cost.USERDEFINED_CONVERSION_RANK; + if (constructorCost != null) { + if (operatorCost == null || ambigousConversionOperator) { + constructorCost.userDefined = Cost.USERDEFINED_CONVERSION; + constructorCost.rank = Cost.USERDEFINED_CONVERSION_RANK; + } + else { + //if both are valid, then the conversion is ambiguous + constructorCost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION; + constructorCost.rank = Cost.USERDEFINED_CONVERSION_RANK; + } + return constructorCost; + } + if (operatorCost != null) { + operatorCost.rank = Cost.USERDEFINED_CONVERSION_RANK; + if (ambigousConversionOperator) { + operatorCost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION; + } + else { + operatorCost.userDefined = Cost.USERDEFINED_CONVERSION; } + return operatorCost; } - return cost; + return null; } /** @@ -225,8 +218,8 @@ class Conversions { if(maxdepth>0) { ICPPBase [] bases = clazz.getBases(); - for(int i=0; i<bases.length; i++) { - IBinding base = bases[i].getBaseClass(); + for (ICPPBase cppBase : bases) { + IBinding base = cppBase.getBaseClass(); if(base instanceof IType) { IType tbase= (IType) base; if( tbase.isSameType(ancestorToFind) || @@ -341,11 +334,6 @@ class Conversions { } /** - * - * @param source - * @param target - * @return int - * * 4.5-1 char, signed char, unsigned char, short int or unsigned short int * can be converted to int if int can represent all the values of the source * type, otherwise they can be converted to unsigned int. @@ -394,13 +382,12 @@ class Conversions { while( true ){ s= getUltimateTypeViaTypedefs(s); t= getUltimateTypeViaTypedefs(t); - IPointerType op1= s instanceof IPointerType ? (IPointerType) s : null; - IPointerType op2= t instanceof IPointerType ? (IPointerType) t : null; + final boolean sourceIsPointer= s instanceof IPointerType; + final boolean targetIsPointer= t instanceof IPointerType; - if( op1 == null && op2 == null ) - break; - else if( op1 == null ^ op2 == null) { - // 4.12 - pointer types can be converted to bool + if (!targetIsPointer) { + if (!sourceIsPointer) + break; if(t instanceof ICPPBasicType) { if(((ICPPBasicType)t).getType() == ICPPBasicType.t_bool) { canConvert= true; @@ -410,10 +397,17 @@ class Conversions { } canConvert = false; break; - } else if( op1 instanceof ICPPPointerToMemberType ^ op2 instanceof ICPPPointerToMemberType ){ + } else if (!sourceIsPointer) { + canConvert = false; + break; + } else if( s instanceof ICPPPointerToMemberType ^ t instanceof ICPPPointerToMemberType ){ canConvert = false; break; } + + // both are pointers + IPointerType op1= (IPointerType) s; + IPointerType op2= (IPointerType) t; //if const is in cv1,j then const is in cv2,j. Similary for volatile if( ( op1.isConst() && !op2.isConst() ) || ( op1.isVolatile() && !op2.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 d2d12892bda..33272640631 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 @@ -25,7 +25,9 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; */ 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; public static final int NO_MATCH_RANK = -1; public static final int IDENTITY_RANK = 0; @@ -46,7 +48,7 @@ class Cost { public int promotion; public int conversion; public int qualification; - public int userDefined; + public int userDefined= NO_USERDEFINED_CONVERSION; public int rank = -1; public int detail; @@ -62,17 +64,18 @@ class Cost { return cost.rank - rank; } - if( userDefined != 0 || cost.userDefined != 0 ){ - if( userDefined == 0 || cost.userDefined == 0 ){ + if (userDefined == cost.userDefined) { + if (userDefined == AMBIGUOUS_USERDEFINED_CONVERSION) { + 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; - } - if( (userDefined == AMBIGUOUS_USERDEFINED_CONVERSION || cost.userDefined == AMBIGUOUS_USERDEFINED_CONVERSION) || - (userDefined != cost.userDefined ) ) - return 0; - - // else they are the same constructor/conversion operator and are ranked - //on the standard conversion sequence - + } + // one ambiguous, the other needs conversion --> can't use std conversion to rank + return 0; } if( promotion > 0 || cost.promotion > 0 ){ @@ -92,6 +95,9 @@ class Cost { } else if( (cost.qualification == qualification) && qualification == 0 ){ return 0; } else { + // 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; |