Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Schorn2008-04-14 14:53:24 +0000
committerMarkus Schorn2008-04-14 14:53:24 +0000
commitb9f428181ba0a374bb95b75c562654bb868fb17c (patch)
tree384fcf2b05e7f047a35aafc2ff7cd1aad27e89ff /core/org.eclipse.cdt.core
parentfb2df943e365314d49771013fdd90754b0e96556 (diff)
downloadorg.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/org.eclipse.cdt.core')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java128
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java28
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 dfe31fb72c..0ca4ff9630 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 d2d12892bd..3327264063 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;

Back to the top