Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Ferguson2008-04-16 16:04:43 +0000
committerAndrew Ferguson2008-04-16 16:04:43 +0000
commite4f737f6b10eb8b0d912700b9918443f095e397e (patch)
treec807bd13b2b1667bb5b9d15a59c0a96a291b46ac /core/org.eclipse.cdt.core
parent2942d637ad8e9c98526cccf75b5bd33803b2948d (diff)
downloadorg.eclipse.cdt-e4f737f6b10eb8b0d912700b9918443f095e397e.tar.gz
org.eclipse.cdt-e4f737f6b10eb8b0d912700b9918443f095e397e.tar.xz
org.eclipse.cdt-e4f737f6b10eb8b0d912700b9918443f095e397e.zip
222418: apply fix
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/CPPSemantics.java20
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java33
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java698
3 files changed, 536 insertions, 215 deletions
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 aa09a2bc77..34dd6fc9df 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
@@ -313,7 +313,7 @@ public class CPPSemantics {
return binding;
}
- static private LookupData createLookupData( IASTName name, boolean considerAssociatedScopes ){
+ private static LookupData createLookupData( IASTName name, boolean considerAssociatedScopes ){
LookupData data = new LookupData( name );
IASTNode parent = name.getParent();
@@ -1895,6 +1895,7 @@ public class CPPSemantics {
Cost [] bestFnCost = null; //the cost of the best function
Cost [] currFnCost = null; //the cost for the current function
+ IASTExpression sourceExp;
IType source = null; //parameter we are called with
IType target = null; //function's parameter
@@ -1933,9 +1934,13 @@ public class CPPSemantics {
for (int j = 0; j < sourceLen; j++) {
if (useImplicitObj > 0) {
isImpliedObject= j==0;
- source = isImpliedObject ? impliedObjectType : sourceParameters[j - 1];
+ source= isImpliedObject ? impliedObjectType : sourceParameters[j - 1];
+ Object se= isImpliedObject || data.functionParameters.length==0 ? null : data.functionParameters[j - 1];
+ sourceExp= se instanceof IASTExpression ? (IASTExpression) se : null;
} else {
source = sourceParameters[j];
+ Object se= data.functionParameters.length==0 ? null : data.functionParameters[j];
+ sourceExp= se instanceof IASTExpression ? (IASTExpression) se : null;
}
if (j < numTargetParams) {
@@ -1960,16 +1965,7 @@ public class CPPSemantics {
cost = new Cost( source, target );
cost.rank = Cost.IDENTITY_RANK; //exact match, no cost
} else {
- cost = Conversions.checkStandardConversionSequence( source, target, isImpliedObject);
- //12.3-4 At most one user-defined conversion is implicitly applied to
- //a single value. (also prevents infinite loop)
- if (!data.forUserDefinedConversion && (cost.rank == Cost.NO_MATCH_RANK ||
- cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
- Cost udcCost= Conversions.checkUserDefinedConversionSequence( source, target );
- if( udcCost != null ){
- cost = udcCost;
- }
- }
+ cost= Conversions.checkImplicitConversionSequence(!data.forUserDefinedConversion, sourceExp, source, target, isImpliedObject);
}
currFnCost[ j ] = cost;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
index ec5f111c02..1d1b677183 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
@@ -2183,4 +2183,37 @@ public class CPPVisitor {
}
return false;
}
+
+ /**
+ * [3.10] Lvalues and Rvalues
+ * @param exp
+ * @return whether the specified expression is an rvalue
+ */
+ static boolean isRValue(IASTExpression exp) {
+ if(exp instanceof IASTUnaryExpression) {
+ IASTUnaryExpression ue= (IASTUnaryExpression) exp;
+ if(ue.getOperator() == IASTUnaryExpression.op_amper) {
+ return true;
+ }
+ }
+ if(exp instanceof IASTLiteralExpression)
+ return true;
+ if(exp instanceof IASTFunctionCallExpression) {
+ try {
+ IASTFunctionCallExpression fc= (IASTFunctionCallExpression) exp;
+ IASTExpression fne= fc.getFunctionNameExpression();
+ if(fne instanceof IASTIdExpression) {
+ IASTIdExpression ide= (IASTIdExpression) fne;
+ IBinding b= ide.getName().resolveBinding();
+ if(b instanceof IFunction) {
+ IFunctionType tp= ((IFunction)b).getType();
+ return !(tp.getReturnType() instanceof ICPPReferenceType);
+ }
+ }
+ } catch(DOMException de) {
+ // fall-through
+ }
+ }
+ return false;
+ }
}
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 0ca4ff9630..44fad0b4a7 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
@@ -16,6 +16,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeViaTypedefs;
+import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
@@ -46,24 +47,259 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
+import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
+import org.eclipse.core.runtime.CoreException;
/**
- * Routines for calculating the cost of conversions
- *
- * See
- * [conv] 4
- * [over.best.ics] 13.3.3.1.
+ * Routines for calculating the cost of conversions.
*/
-class Conversions {
+public class Conversions {
+ /**
+ * Computes the cost of an implicit conversion sequence
+ * [over.best.ics] 13.3.3.1
+ *
+ * @param allowUDC whether a user-defined conversion is allowed during the sequence
+ * @param sourceExp the expression behind the source type
+ * @param source the source (argument) type
+ * @param target the target (parameter) type
+ * @param isImpliedObject
+ * @return the cost of converting from source to target
+ * @throws DOMException
+ */
+ public static Cost checkImplicitConversionSequence(boolean allowUDC, IASTExpression sourceExp, IType source, IType target, boolean isImpliedObject) throws DOMException {
+ Cost cost;
+
+ if(!isImpliedObject && target instanceof ICPPReferenceType) {
+ // [13.3.3.3.1] Reference binding
+ IType cv1T1= ((ICPPReferenceType)target).getType();
+ cost= new Cost(source, cv1T1);
+ cost.targetHadReference= true;
+
+ boolean lvalue= sourceExp == null || !CPPVisitor.isRValue(sourceExp);
+ IType T2= source instanceof IQualifierType ? ((IQualifierType)source).getType() : source;
+
+ if(lvalue && isReferenceCompatible(cv1T1, source)) {
+ /* Direct reference binding */
+ // [13.3.3.1.4]
+
+ /*
+ * is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2,”
+ */
+ // [13.3.3.1.4-1] direct binding
+ // [8.5.3-5]
+ qualificationConversion(cost);
+
+ derivedToBaseConversion(cost);
+ } else if(T2 instanceof ICPPClassType && allowUDC) {
+ /*
+ * or has a class type (i.e., T2 is a class type) and can be implicitly converted to
+ * an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with “cv3 T3” 92)
+ * (this conversion is selected by enumerating the applicable conversion functions (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 == false ){
+ for (final ICPPMethod op : fcns) {
+ Cost cost2 = checkStandardConversionSequence( op.getType().getReturnType(), target, false );
+ if( cost2.rank != Cost.NO_MATCH_RANK ) {
+ if (operatorCost == null) {
+ operatorCost= cost2;
+ conv= op;
+ }
+ else {
+ int cmp= operatorCost.compare(cost2);
+ if (cmp >= 0) {
+ ambiguousConversionOperator= cmp == 0;
+ operatorCost= cost2;
+ conv= op;
+ }
+ }
+ }
+ }
+ }
+
+ if(conv!= null && !ambiguousConversionOperator) {
+ IType newSource= conv.getType().getReturnType();
+ boolean isNewSourceLValue= newSource instanceof ICPPReferenceType;
+ if(isNewSourceLValue && isReferenceCompatible(cv1T1, newSource)) {
+ cost= new Cost(cv1T1, newSource);
+ qualificationConversion(cost);
+ derivedToBaseConversion(cost);
+ }
+ }
+ }
+
+ /* Direct binding failed */
+
+ if(cost.rank == Cost.NO_MATCH_RANK) {
+ // 8.5.3-5 - Otherwise
+
+ boolean cv1isConst= false;
+ if(cv1T1 instanceof IQualifierType) {
+ cv1isConst= ((IQualifierType)cv1T1).isConst() && !((IQualifierType)cv1T1).isVolatile();
+ } else if(cv1T1 instanceof IPointerType) {
+ cv1isConst= ((IPointerType)cv1T1).isConst() && !((IPointerType)cv1T1).isVolatile();
+ }
+
+ if(cv1isConst) {
+ if(!lvalue && source instanceof ICPPClassType) {
+ cost= new Cost(source, target);
+ cost.rank= Cost.IDENTITY_RANK;
+ } else {
+ // 5 - Otherwise
+ // Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression
+ // using the rules for a non-reference copy initialization (8.5). The reference is then bound to the temporary.
+
+ // If T1 is reference-related to T2, cv1 must be the same cv-qualification as, or greater cvqualification
+ // than, cv2; otherwise, the program is ill-formed. [Example
+ boolean illformed= false;
+ if(isReferenceRelated(cv1T1, source)) {
+ Integer cmp= compareQualifications(cv1T1, source);
+ if(cmp == null || cmp < 0) {
+ illformed= true;
+ }
+ }
+
+ // we must do a non-reference initialization
+ if(!illformed) {
+ cost= checkStandardConversionSequence( source, cv1T1, isImpliedObject);
+ // 12.3-4 At most one user-defined conversion is implicitly applied to
+ // a single value. (also prevents infinite loop)
+ if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
+ cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
+ Cost temp = checkUserDefinedConversionSequence(source, cv1T1);
+ if( temp != null ){
+ cost = temp;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // Non-reference binding
+
+ cost= checkStandardConversionSequence( source, target, isImpliedObject);
+ if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
+ cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
+ Cost temp = checkUserDefinedConversionSequence(source, target);
+ if( temp != null ){
+ cost = temp;
+ }
+ }
+ }
+
+ return cost;
+ }
+
+ /**
+ * [3.9.3-4] Implements cv-ness (partial) comparison. There is a (partial)
+ * ordering on cv-qualifiers, so that a type can be said to be more
+ * cv-qualified than another.
+ * @param cv1
+ * @param cv2
+ * @return <ul>
+ * <li>GT 1 if cv1 is more qualified than cv2
+ * <li>EQ 0 if cv1 and cv2 are equally qualified
+ * <li>LT -1 if cv1 is less qualified than cv2
+ * <li>NC null if cv1 and cv2 are not comparable
+ * </ul>
+ * @throws DOMException
+ */
+ private static final Integer compareQualifications(IType cv1, IType cv2) throws DOMException {
+ boolean cv1Const= false, cv2Const= false, cv1Volatile= false, cv2Volatile= false;
+ if(cv1 instanceof IQualifierType) {
+ IQualifierType qt1= (IQualifierType) cv1;
+ cv1Const= qt1.isConst();
+ cv1Volatile= qt1.isVolatile();
+ } else if(cv1 instanceof IPointerType) {
+ IPointerType pt1= (IPointerType) cv1;
+ cv1Const= pt1.isConst();
+ cv1Volatile= pt1.isVolatile();
+ }
+ if(cv2 instanceof IQualifierType) {
+ IQualifierType qt2= (IQualifierType) cv2;
+ cv2Const= qt2.isConst();
+ cv2Volatile= qt2.isVolatile();
+ } else if(cv2 instanceof IPointerType) {
+ IPointerType pt2= (IPointerType) cv2;
+ cv1Const= pt2.isConst();
+ cv1Volatile= pt2.isVolatile();
+ }
+ int cmpConst= cv1Const ? (cv2Const ? 0 : 1) : (!cv2Const ? 0 : -1);
+ int cmpVolatile= cv1Volatile ? (cv2Volatile ? 0 : 1) : (!cv2Volatile ? 0 : -1);
+
+ if(cmpConst == cmpVolatile) {
+ return cmpConst;
+ } else if(cmpConst != 0 && cmpVolatile == 0) {
+ return cmpConst;
+ } else if(cmpConst == 0 && cmpVolatile != 0) {
+ return cmpVolatile;
+ }
+
+ return null;
+ }
+
+ /**
+ * [8.5.3] "cv1 T1" is reference-related to "cv2 T2" if T1 is the same type as T2, or T1 is a base class of T2.
+ * Note this is not a symmetric relation.
+ * @param cv1t1
+ * @param cv2t2
+ * @return whether <code>cv1t1</code> is reference-related to <code>cv2t2</code>
+ * @throws DOMException
+ */
+ private static final boolean isReferenceRelated(IType cv1t1, IType cv2t2) throws DOMException {
+ // I've not found anything in the spec to justify unrolling cv1t1 or cv1t2 so far
+ IType t1= SemanticUtil.getUltimateTypeUptoPointers(cv1t1);
+ IType t2= SemanticUtil.getUltimateTypeUptoPointers(cv2t2);
+
+ // The way cv-qualification is currently modeled means
+ // we must cope with IPointerType objects separately.
+ if(t1 instanceof IPointerType && t2 instanceof IPointerType) {
+ IType ptt1= ((IPointerType)t1).getType();
+ IType ptt2= ((IPointerType)t2).getType();
+ return ptt1 != null && ptt2 != null ? ptt1.isSameType(ptt2) : ptt1 == ptt2;
+ }
+
+ t1= t1 instanceof IQualifierType ? ((IQualifierType)t1).getType() : t1;
+ t2= t2 instanceof IQualifierType ? ((IQualifierType)t2).getType() : t2;
+
+ if(t1 instanceof ICPPClassType && t2 instanceof ICPPClassType) {
+ return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, (ICPPClassType) t2, (ICPPClassType) t1) >= 0;
+ }
+
+ return t1 != null && t2 != null ? t1.isSameType(t2) : t1 == t2;
+ }
/**
+ * [8.5.3] “cv1 T1” is reference-compatible with “cv2 T2” if T1 is reference-related
+ * to T2 and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2.
+ * Note this is not a symmetric relation.
+ * @param cv1t1
+ * @param cv2t2
+ * @return whether <code>cv1t1</code> is reference-compatible with <code>cv2t2</code>
+ * @throws DOMException
+ */
+ private static final boolean isReferenceCompatible(IType cv1t1, IType cv2t2) throws DOMException {
+ if(isReferenceRelated(cv1t1, cv2t2)) {
+ Integer cmp= compareQualifications(cv1t1, cv2t2);
+ return cmp != null && cmp >= 0;
+ }
+ return false;
+ }
+
+ /**
+ * [4] Standard Conversions
* Computes the cost of using the standard conversion sequence from source to target.
* @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
*/
- static protected Cost checkStandardConversionSequence( IType source, IType target, boolean isImplicitThis) throws DOMException {
+ protected static final Cost checkStandardConversionSequence( IType source, IType target, boolean isImplicitThis) throws DOMException {
Cost cost = lvalue_to_rvalue( source, target );
if( cost.source == null || cost.target == null ){
@@ -119,33 +355,38 @@ class Conversions {
return cost;
}
- static Cost checkUserDefinedConversionSequence( IType source, IType target ) throws DOMException {
- Cost constructorCost = null;
- Cost operatorCost = null;
+ /**
+ * [13.3.3.1.2] User-defined conversions
+ * @param source
+ * @param target
+ * @return
+ * @throws DOMException
+ */
+ private static final Cost checkUserDefinedConversionSequence(IType source, IType target) throws DOMException {
+ Cost constructorCost= null;
+ Cost operatorCost= null;
- IType s = getUltimateType( source, true );
- IType t = getUltimateType( target, true );
+ IType s= getUltimateType(source, true);
+ IType t= getUltimateType(target, true);
//constructors
- if( t instanceof ICPPClassType ){
- ICPPConstructor [] constructors = ((ICPPClassType)t).getConstructors();
- if( constructors.length > 0 ){
- 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 ) {
- ICPPConstructor constructor = (ICPPConstructor) binding;
- if(!constructor.isExplicit()){
- constructorCost = checkStandardConversionSequence( t, target, false );
- if (constructorCost.rank == Cost.NO_MATCH_RANK) {
- constructorCost= null;
- }
+ if (t instanceof ICPPClassType) {
+ ICPPConstructor [] constructors= ((ICPPClassType)t).getConstructors();
+ 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 ) {
+ ICPPConstructor constructor= (ICPPConstructor) binding;
+ if(!constructor.isExplicit()){
+ constructorCost = checkStandardConversionSequence( t, target, false );
+ if (constructorCost.rank == Cost.NO_MATCH_RANK) {
+ constructorCost= null;
}
+ }
}
}
- }
}
boolean checkConversionOperators=
@@ -156,12 +397,12 @@ class Conversions {
|| s instanceof CPPClassInstance);
//conversion operators
- boolean ambigousConversionOperator= false;
+ boolean ambiguousConversionOperator= false;
if (checkConversionOperators) {
ICPPMethod [] ops = SemanticUtil.getConversionOperators((ICPPClassType)s);
- if( ops.length > 0 && ops[0] instanceof IProblemBinding == false ){
+ if (ops.length > 0 && ops[0] instanceof IProblemBinding == false) {
for (final ICPPMethod op : ops) {
- Cost cost = checkStandardConversionSequence( op.getType().getReturnType(), target, false );
+ Cost cost= checkStandardConversionSequence(op.getType().getReturnType(), target, false);
if( cost.rank != Cost.NO_MATCH_RANK ) {
if (operatorCost == null) {
operatorCost= cost;
@@ -169,7 +410,7 @@ class Conversions {
else {
int cmp= operatorCost.compare(cost);
if (cmp >= 0) {
- ambigousConversionOperator= cmp == 0;
+ ambiguousConversionOperator= cmp == 0;
operatorCost= cost;
}
}
@@ -179,7 +420,7 @@ class Conversions {
}
if (constructorCost != null) {
- if (operatorCost == null || ambigousConversionOperator) {
+ if (operatorCost == null || ambiguousConversionOperator) {
constructorCost.userDefined = Cost.USERDEFINED_CONVERSION;
constructorCost.rank = Cost.USERDEFINED_CONVERSION_RANK;
}
@@ -192,7 +433,7 @@ class Conversions {
}
if (operatorCost != null) {
operatorCost.rank = Cost.USERDEFINED_CONVERSION_RANK;
- if (ambigousConversionOperator) {
+ if (ambiguousConversionOperator) {
operatorCost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION;
}
else {
@@ -212,14 +453,15 @@ class Conversions {
* no inheritance relation
* @throws DOMException
*/
- private static int calculateInheritanceDepth(int maxdepth, ICPPClassType clazz, ICPPClassType ancestorToFind) throws DOMException {
- if(clazz == ancestorToFind || clazz.isSameType(ancestorToFind))
+ private static final int calculateInheritanceDepth(int maxdepth, ICPPClassType clazz, ICPPClassType ancestorToFind) throws DOMException {
+ if (clazz == ancestorToFind || clazz.isSameType(ancestorToFind)) {
return 0;
+ }
- if(maxdepth>0) {
- ICPPBase [] bases = clazz.getBases();
+ if (maxdepth>0) {
+ ICPPBase[] bases= clazz.getBases();
for (ICPPBase cppBase : bases) {
- IBinding base = cppBase.getBaseClass();
+ IBinding base= cppBase.getBaseClass();
if(base instanceof IType) {
IType tbase= (IType) base;
if( tbase.isSameType(ancestorToFind) ||
@@ -242,137 +484,74 @@ class Conversions {
return -1;
}
- static private void conversion( Cost cost ) throws DOMException{
- IType src = cost.source;
- IType trg = cost.target;
+ /**
+ * [4.1] Lvalue-to-rvalue conversion
+ * [4.2] array-to-ptr
+ * [4.3] function-to-ptr
+ *
+ * @param source
+ * @param target
+ * @return
+ * @throws DOMException
+ */
+ private static final Cost lvalue_to_rvalue(IType source, IType target) throws DOMException {
+ Cost cost = new Cost(source, target);
- cost.conversion = 0;
- cost.detail = 0;
+ if (!isCompleteType(source)) {
+ cost.rank= Cost.NO_MATCH_RANK;
+ return cost;
+ }
- IType[] sHolder= new IType[1], tHolder= new IType[1];
- IType s = getUltimateType( src, sHolder, true );
- IType t = getUltimateType( trg, tHolder, true );
- IType sPrev= sHolder[0], tPrev= tHolder[0];
+ if (source instanceof ICPPReferenceType) {
+ source= ((ICPPReferenceType) source).getType();
+ }
+ if (target instanceof ICPPReferenceType) {
+ target= ((ICPPReferenceType) target).getType();
+ cost.targetHadReference = true;
+ }
- if( src instanceof IBasicType && trg instanceof IPointerType ){
- //4.10-1 an integral constant expression of integer type that evaluates to 0 can be converted to a pointer type
- IASTExpression exp = ((IBasicType)src).getValue();
- if( exp instanceof IASTLiteralExpression &&
- ((IASTLiteralExpression)exp).getKind() == IASTLiteralExpression.lk_integer_constant )
- {
- try {
- String val = exp.toString().toLowerCase().replace('u', '0');
- val.replace( 'l', '0' );
- if( Integer.decode( val ).intValue() == 0 ){
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- }
- } catch( NumberFormatException e ) {
- }
- }
- } else if( sPrev instanceof IPointerType ){
- //4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
- //converted to an rvalue of type "pointer to cv void"
- if( tPrev instanceof IPointerType && t instanceof IBasicType && ((IBasicType)t).getType() == IBasicType.t_void ){
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- cost.detail = 2;
- return;
- }
- //4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted
- //to an rvalue of type "pointer to cv B", where B is a base class of D.
- else if( s instanceof ICPPClassType && tPrev instanceof IPointerType && t instanceof ICPPClassType ){
- int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, (ICPPClassType)s, (ICPPClassType) t );
- cost.rank= ( depth > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
- cost.conversion= ( depth > -1 ) ? depth : 0;
- cost.detail= 1;
- return;
- }
- // 4.12 if the target is a bool, we can still convert
- else if(!(trg instanceof IBasicType && ((IBasicType)trg).getType() == ICPPBasicType.t_bool)) {
- return;
- }
+ //4.3 function to pointer conversion
+ if( target instanceof IPointerType && ((IPointerType)target).getType() instanceof IFunctionType &&
+ source instanceof IFunctionType )
+ {
+ source = new CPPPointerType( source );
+ }
+ //4.2 Array-To-Pointer conversion
+ else if( target instanceof IPointerType && source instanceof IArrayType ){
+ source = new CPPPointerType( ((IArrayType)source).getType() );
}
- if( t instanceof IBasicType && 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;
- } else if( trg instanceof IBasicType && ((IBasicType)trg).getType() == ICPPBasicType.t_bool && s instanceof IPointerType ){
- //4.12 pointer or pointer to member type can be converted to an rvalue of type bool
- cost.rank = Cost.CONVERSION_RANK;
- cost.conversion = 1;
- } else if( s instanceof ICPPPointerToMemberType && t instanceof ICPPPointerToMemberType ){
- //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type,
- //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a
- //derived class of B
- ICPPPointerToMemberType spm = (ICPPPointerToMemberType) s;
- ICPPPointerToMemberType tpm = (ICPPPointerToMemberType) t;
- IType st = spm.getType();
- IType tt = tpm.getType();
- if( st != null && tt != null && st.isSameType( tt ) ){
- int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, tpm.getMemberOfClass(), spm.getMemberOfClass());
- cost.rank= ( depth > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
- cost.conversion= ( depth > -1 ) ? depth : 0;
- cost.detail= 1;
+ //4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T
+ if( source instanceof IQualifierType ){
+ IType t = ((IQualifierType)source).getType();
+ while( t instanceof ITypedef )
+ t = ((ITypedef)t).getType();
+ if( !(t instanceof ICPPClassType) ){
+ source = t;
+ }
+ } else if( source instanceof IPointerType &&
+ ( ((IPointerType)source).isConst() || ((IPointerType)source).isVolatile() ) )
+ {
+ IType t= ((IPointerType) source).getType();
+ while (t instanceof ITypedef)
+ t= ((ITypedef) t).getType();
+ if (!(t instanceof ICPPClassType)) {
+ source= new CPPPointerType(t);
}
}
- }
- static private void derivedToBaseConversion( Cost cost ) throws DOMException {
- IType s = getUltimateType( cost.source, true );
- IType t = getUltimateType( cost.target, true );
+ cost.source = source;
+ cost.target = target;
- if( cost.targetHadReference && s instanceof ICPPClassType && t instanceof ICPPClassType ){
- int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, (ICPPClassType) s, (ICPPClassType) t);
- if(depth > -1){
- cost.rank= Cost.DERIVED_TO_BASE_CONVERSION;
- cost.conversion= depth;
- }
- }
+ return cost;
}
-
+
/**
- * 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.
- * 4.5-2 wchar_t or an enumeration can be converted to the first of the
- * following that can hold it: int, unsigned int, long unsigned long.
- * 4.5-4 bool can be promoted to int
- * 4.6 float can be promoted to double
+ * [4.4] Qualifications
+ * @param cost
* @throws DOMException
*/
- static private void promotion( Cost cost ) throws DOMException{
- IType src = cost.source;
- IType trg = cost.target;
-
- if( src.isSameType( trg ) )
- return;
-
- if( src instanceof IBasicType && trg instanceof IBasicType ){
- int sType = ((IBasicType)src).getType();
- int tType = ((IBasicType)trg).getType();
- if( ( tType == IBasicType.t_int && ( sType == IBasicType.t_int || //short, long , unsigned etc
- sType == IBasicType.t_char ||
- sType == ICPPBasicType.t_bool ||
- sType == ICPPBasicType.t_wchar_t ||
- sType == IBasicType.t_unspecified ) ) || //treat unspecified as int
- ( tType == IBasicType.t_double && sType == IBasicType.t_float ) )
- {
- cost.promotion = 1;
- }
- } else if( src instanceof IEnumeration && trg instanceof IBasicType &&
- ( ((IBasicType)trg).getType() == IBasicType.t_int ||
- ((IBasicType)trg).getType() == IBasicType.t_unspecified ) )
- {
- cost.promotion = 1;
- }
-
- cost.rank = (cost.promotion > 0 ) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK;
- }
-
- static private void qualificationConversion( Cost cost ) throws DOMException{
+ private static final void qualificationConversion( Cost cost ) throws DOMException{
boolean canConvert = true;
int requiredConversion = Cost.IDENTITY_RANK;
@@ -496,66 +675,179 @@ class Conversions {
}
}
- static private Cost lvalue_to_rvalue( IType source, IType target ) throws DOMException{
- Cost cost = new Cost( source, target );
-
- if( ! isCompleteType( source ) ){
- cost.rank = Cost.NO_MATCH_RANK;
- return cost;
- }
+ /**
+ * [4.5] [4.6] Promotion
+ *
+ * 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.
+ * 4.5-2 wchar_t or an enumeration can be converted to the first of the
+ * following that can hold it: int, unsigned int, long unsigned long.
+ * 4.5-4 bool can be promoted to int
+ * 4.6 float can be promoted to double
+ * @throws DOMException
+ */
+ private static final void promotion( Cost cost ) throws DOMException{
+ IType src = cost.source;
+ IType trg = cost.target;
- if( source instanceof ICPPReferenceType ){
- source = ((ICPPReferenceType) source).getType();
- }
- if( target instanceof ICPPReferenceType ){
- target = ((ICPPReferenceType) target).getType();
- cost.targetHadReference = true;
- }
+ if( src.isSameType( trg ) )
+ return;
- //4.3 function to pointer conversion
- if( target instanceof IPointerType && ((IPointerType)target).getType() instanceof IFunctionType &&
- source instanceof IFunctionType )
+ if( src instanceof IBasicType && trg instanceof IBasicType ){
+ int sType = ((IBasicType)src).getType();
+ int tType = ((IBasicType)trg).getType();
+ if( ( tType == IBasicType.t_int && ( sType == IBasicType.t_int || //short, long , unsigned etc
+ sType == IBasicType.t_char ||
+ sType == ICPPBasicType.t_bool ||
+ sType == ICPPBasicType.t_wchar_t ||
+ sType == IBasicType.t_unspecified ) ) || //treat unspecified as int
+ ( tType == IBasicType.t_double && sType == IBasicType.t_float ) )
+ {
+ cost.promotion = 1;
+ }
+ } else if( src instanceof IEnumeration && trg instanceof IBasicType &&
+ ( ((IBasicType)trg).getType() == IBasicType.t_int ||
+ ((IBasicType)trg).getType() == IBasicType.t_unspecified ) )
{
- source = new CPPPointerType( source );
- }
- //4.2 Array-To-Pointer conversion
- else if( target instanceof IPointerType && source instanceof IArrayType ){
- source = new CPPPointerType( ((IArrayType)source).getType() );
+ cost.promotion = 1;
}
- //4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T
- if( source instanceof IQualifierType ){
- IType t = ((IQualifierType)source).getType();
- while( t instanceof ITypedef )
- t = ((ITypedef)t).getType();
- if( !(t instanceof ICPPClassType) ){
- source = t;
+ cost.rank = (cost.promotion > 0 ) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK;
+ }
+
+ /**
+ * [4.7] Integral conversions
+ * [4.8] Floating point conversions
+ * [4.9] Floating-integral conversions
+ * [4.10] Pointer conversions
+ * [4.11] Pointer to member conversions
+ * @param cost
+ * @throws DOMException
+ */
+ private static final void conversion( Cost cost ) throws DOMException{
+ final IType src = cost.source;
+ final IType trg = cost.target;
+
+ cost.conversion = 0;
+ cost.detail = 0;
+
+ IType[] sHolder= new IType[1], tHolder= new IType[1];
+ IType s = getUltimateType( src, sHolder, true );
+ IType t = getUltimateType( trg, tHolder, true );
+ IType sPrev= sHolder[0], tPrev= tHolder[0];
+
+ if( src instanceof IBasicType && trg instanceof IPointerType ){
+ //4.10-1 an integral constant expression of integer type that evaluates to 0 can be converted to a pointer type
+ IASTExpression exp = ((IBasicType)src).getValue();
+ if( exp instanceof IASTLiteralExpression &&
+ ((IASTLiteralExpression)exp).getKind() == IASTLiteralExpression.lk_integer_constant )
+ {
+ try {
+ String val = exp.toString().toLowerCase().replace('u', '0');
+ val.replace( 'l', '0' );
+ if( Integer.decode( val ).intValue() == 0 ){
+ cost.rank = Cost.CONVERSION_RANK;
+ cost.conversion = 1;
+ }
+ } catch( NumberFormatException e ) {
+ }
}
- } else if( source instanceof IPointerType &&
- ( ((IPointerType)source).isConst() || ((IPointerType)source).isVolatile() ) )
- {
- IType t = ((IPointerType)source).getType();
- while( t instanceof ITypedef )
- t = ((ITypedef)t).getType();
- if( !(t instanceof ICPPClassType) ){
- source = new CPPPointerType( t );
+ } else if( sPrev instanceof IPointerType ){
+ //4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
+ //converted to an rvalue of type "pointer to cv void"
+ if( tPrev instanceof IPointerType && t instanceof IBasicType && ((IBasicType)t).getType() == IBasicType.t_void ){
+ cost.rank = Cost.CONVERSION_RANK;
+ cost.conversion = 1;
+ cost.detail = 2;
+ return;
+ }
+ //4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted
+ //to an rvalue of type "pointer to cv B", where B is a base class of D.
+ else if( s instanceof ICPPClassType && tPrev instanceof IPointerType && t instanceof ICPPClassType ){
+ int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, (ICPPClassType)s, (ICPPClassType) t );
+ cost.rank= ( depth > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
+ cost.conversion= ( depth > -1 ) ? depth : 0;
+ cost.detail= 1;
+ return;
+ }
+ // 4.12 if the target is a bool, we can still convert
+ else if(!(trg instanceof IBasicType && ((IBasicType)trg).getType() == ICPPBasicType.t_bool)) {
+ return;
}
}
- cost.source = source;
- cost.target = target;
-
- return cost;
+ if( t instanceof IBasicType && 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;
+ } else if( trg instanceof IBasicType && ((IBasicType)trg).getType() == ICPPBasicType.t_bool && s instanceof IPointerType ){
+ //4.12 pointer or pointer to member type can be converted to an rvalue of type bool
+ cost.rank = Cost.CONVERSION_RANK;
+ cost.conversion = 1;
+ } else if( s instanceof ICPPPointerToMemberType && t instanceof ICPPPointerToMemberType ){
+ //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type,
+ //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a
+ //derived class of B
+ ICPPPointerToMemberType spm = (ICPPPointerToMemberType) s;
+ ICPPPointerToMemberType tpm = (ICPPPointerToMemberType) t;
+ IType st = spm.getType();
+ IType tt = tpm.getType();
+ if( st != null && tt != null && st.isSameType( tt ) ){
+ int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, tpm.getMemberOfClass(), spm.getMemberOfClass());
+ cost.rank= ( depth > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
+ cost.conversion= ( depth > -1 ) ? depth : 0;
+ cost.detail= 1;
+ }
+ }
}
+
+ /**
+ * [13.3.3.1-6] Derived to base conversion
+ * @param cost
+ * @throws DOMException
+ */
+ private static final void derivedToBaseConversion(Cost cost) throws DOMException {
+ IType s = getUltimateType(cost.source, true);
+ IType t = getUltimateType(cost.target, true);
- static private boolean isCompleteType( IType type ){
- type = getUltimateType( type, false );
- if( type instanceof ICPPClassType && type instanceof ICPPInternalBinding )
- return (((ICPPInternalBinding)type).getDefinition() != null );
+ if (cost.targetHadReference && s instanceof ICPPClassType && t instanceof ICPPClassType) {
+ int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, (ICPPClassType) s, (ICPPClassType) t);
+ if (depth > -1) {
+ cost.rank = Cost.DERIVED_TO_BASE_CONVERSION;
+ cost.conversion = depth;
+ }
+ }
+ }
+
+ /**
+ * @param type
+ * @return whether the specified type has an associated definition
+ */
+ private static final boolean isCompleteType(IType type) {
+ type= getUltimateType(type, false);
+ if(type instanceof ICPPClassType) {
+ if(type instanceof ICPPInternalBinding) {
+ return (((ICPPInternalBinding)type).getDefinition() != null );
+ }
+ if(type instanceof IIndexFragmentBinding) {
+ try {
+ return ((IIndexFragmentBinding)type).hasDefinition();
+ } catch(CoreException ce) {
+ CCorePlugin.log(ce);
+ }
+ }
+ }
+
return true;
}
- static private void relaxTemplateParameters( Cost cost ){
+ /**
+ * Allows any very loose matching between template parameters.
+ * @param cost
+ */
+ private static final void relaxTemplateParameters( Cost cost ){
IType s = getUltimateType( cost.source, false );
IType t = getUltimateType( cost.target, false );

Back to the top