mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 302412: List initialization with elements of the initializer list.
This commit is contained in:
parent
bd8092d830
commit
ce38a4facd
8 changed files with 274 additions and 57 deletions
|
@ -8140,5 +8140,78 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
bh.assertProblem("f( {1.0} )", 1);
|
||||
bh.assertNonProblem("g({ \"foo\", \"bar\" })", 1);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// struct str {
|
||||
// str(const char*) {
|
||||
// }
|
||||
// };
|
||||
// struct A {
|
||||
// A(std::initializer_list<int>);
|
||||
// };
|
||||
// struct B {
|
||||
// B(int, double);
|
||||
// };
|
||||
// struct C {
|
||||
// C(str);
|
||||
// };
|
||||
// struct D {
|
||||
// D(A, C);
|
||||
// };
|
||||
// struct X {
|
||||
// X();
|
||||
// X(X&);
|
||||
// };
|
||||
// void e(A);
|
||||
// void f(A);
|
||||
// void f(B);
|
||||
// void g(B);
|
||||
// void h(C);
|
||||
// void i(D);
|
||||
// void x(const X);
|
||||
//
|
||||
// void test() {
|
||||
// e( { 'a', 'b' }); // OK: f(A(std::initializer_list<int>)) user-defined conversion
|
||||
// g( { 'a', 'b' }); // OK: g(B(int,double)) user-defined conversion
|
||||
// g( { 1.0, 1.0 }); // error: narrowing
|
||||
// f( { 'a', 'b' }); // error: ambiguous f(A) or f(B)
|
||||
// h( { "foo" }); // OK: h(C(std::string("foo")))
|
||||
// i( { { 1, 2 }, { "bar" } }); // OK: i(D(A(std::initializer_list<int>{1,2}),C(std::string("bar"))))
|
||||
// X x1;
|
||||
// x({x1}); // no matching constructor
|
||||
// }
|
||||
public void testListInitialization_302412c() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("e( { 'a', 'b' })", 1);
|
||||
bh.assertNonProblem("g( { 'a', 'b' })", 1);
|
||||
bh.assertProblem("g( { 1.0, 1.0 })", 1);
|
||||
bh.assertProblem("f( { 'a', 'b' })", 1);
|
||||
bh.assertNonProblem("h( {", 1);
|
||||
bh.assertNonProblem("i( { { 1, 2 }, {", 1);
|
||||
bh.assertProblem("x({x1})", 1);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// struct A {
|
||||
// int m1;
|
||||
// double m2;
|
||||
// };
|
||||
// void f(A);
|
||||
// void test() {
|
||||
// f( {'a', 'b'} ); // OK: f(A(int,double)) user-defined conversion
|
||||
// f( {1.0} ); // narrowing not detected by cdt.
|
||||
// }
|
||||
public void testListInitialization_302412d() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("f( {'a', 'b'} )", 1);
|
||||
// not detected by CDT
|
||||
// bh.assertProblem("f( {1.0} )", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.eclipse.cdt.core.dom.ast.IBasicType;
|
|||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
|
||||
/**
|
||||
* Arithmetic conversions as required to compute the type of unary or binary expressions.
|
||||
|
@ -278,4 +279,43 @@ public abstract class ArithmeticConversion {
|
|||
return IBasicType.IS_UNSIGNED | IBasicType.IS_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean fitsIntoType(ICPPBasicType basicTarget, long n) {
|
||||
final Kind kind = basicTarget.getKind();
|
||||
switch (kind) {
|
||||
case eInt:
|
||||
if (!basicTarget.isUnsigned()) {
|
||||
if (basicTarget.isShort()) {
|
||||
return Short.MIN_VALUE <= n && n <= Short.MAX_VALUE;
|
||||
}
|
||||
// Can't represent long longs with java longs.
|
||||
if (basicTarget.isLong() || basicTarget.isLongLong()) {
|
||||
return true;
|
||||
}
|
||||
return Integer.MIN_VALUE <= n && n <= Integer.MAX_VALUE;
|
||||
}
|
||||
if (n < 0)
|
||||
return false;
|
||||
|
||||
if (basicTarget.isShort()) {
|
||||
return n < (Short.MAX_VALUE + 1L)*2;
|
||||
}
|
||||
// Can't represent long longs with java longs.
|
||||
if (basicTarget.isLong() || basicTarget.isLongLong()) {
|
||||
return true;
|
||||
}
|
||||
return n < (Integer.MAX_VALUE + 1L)*2;
|
||||
|
||||
case eFloat:
|
||||
float f= n;
|
||||
return (long)f == n;
|
||||
|
||||
case eDouble:
|
||||
double d= n;
|
||||
return (long)d == n;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2296,7 +2296,7 @@ public class CPPSemantics {
|
|||
cost = new Cost(thisType, implicitType, Rank.IDENTITY);
|
||||
} else {
|
||||
cost = Conversions.checkImplicitConversionSequence(implicitType, thisType, sourceIsLValue, UDCMode.noUDC, true);
|
||||
if (cost.getRank() == Rank.NO_MATCH) {
|
||||
if (!cost.converts()) {
|
||||
if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) {
|
||||
IType s= getNestedType(thisType, TDEF|REF|CVTYPE);
|
||||
IType t= getNestedType(implicitType, TDEF|REF|CVTYPE);
|
||||
|
@ -2307,7 +2307,7 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cost.getRank() == Rank.NO_MATCH)
|
||||
if (!cost.converts())
|
||||
return null;
|
||||
|
||||
result.setCost(k++, cost, sourceIsLValue);
|
||||
|
@ -2338,8 +2338,11 @@ public class CPPSemantics {
|
|||
if (CPPTemplates.isDependentType(paramType))
|
||||
return CONTAINS_DEPENDENT_TYPES;
|
||||
cost = Conversions.checkImplicitConversionSequence(paramType, argType, sourceIsLValue, udc, false);
|
||||
if (data.fNoNarrowing && cost.isNarrowingConversion()) {
|
||||
cost= Cost.NO_CONVERSION;
|
||||
}
|
||||
}
|
||||
if (cost.getRank() == Rank.NO_MATCH)
|
||||
if (!cost.converts())
|
||||
return null;
|
||||
|
||||
result.setCost(k++, cost, sourceIsLValue);
|
||||
|
|
|
@ -140,7 +140,6 @@ 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.Conversions.UDCMode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||
|
||||
/**
|
||||
* Collection of static methods to perform template instantiation, member specialization and
|
||||
|
@ -1966,7 +1965,7 @@ public class CPPTemplates {
|
|||
paramType = new CPPPointerType(((IArrayType) paramType).getType());
|
||||
}
|
||||
Cost cost = Conversions.checkImplicitConversionSequence(paramType, arg, true, UDCMode.noUDC, false);
|
||||
return cost != null && cost.getRank() != Rank.NO_MATCH;
|
||||
return cost != null && cost.converts();
|
||||
}
|
||||
|
||||
static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
|
||||
|
|
|
@ -21,7 +21,9 @@ import java.util.BitSet;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -33,6 +35,7 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
|
@ -47,6 +50,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
|||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||
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;
|
||||
|
@ -145,7 +149,7 @@ public class Conversions {
|
|||
ok= !exprIsLValue;
|
||||
}
|
||||
if (!ok) {
|
||||
return new Cost(exprType, cv1T1, Rank.NO_MATCH);
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
// If T1 and T2 are class types and ...
|
||||
|
@ -204,7 +208,7 @@ public class Conversions {
|
|||
return cost;
|
||||
}
|
||||
}
|
||||
return new Cost(exprType, cv1T1, Rank.NO_MATCH);
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
// Non-reference binding
|
||||
|
@ -274,14 +278,10 @@ public class Conversions {
|
|||
// [13.3.3.1-6] Subsume cv-qualifications
|
||||
IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ);
|
||||
Cost cost= checkStandardConversionSequence(uqSource, sourceIsLValue, target, isImpliedObject);
|
||||
if (cost.getRank() != Rank.NO_MATCH || udc == UDCMode.noUDC)
|
||||
if (cost.converts() || udc == UDCMode.noUDC)
|
||||
return cost;
|
||||
|
||||
Cost temp = checkUserDefinedConversionSequence(sourceIsLValue, source, target, udc == UDCMode.deferUDC);
|
||||
if (temp != null) {
|
||||
cost = temp;
|
||||
}
|
||||
return cost;
|
||||
return checkUserDefinedConversionSequence(sourceIsLValue, source, target, udc == UDCMode.deferUDC);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -296,7 +296,7 @@ public class Conversions {
|
|||
for (int i = 0; i < exprTypes.length; i++) {
|
||||
IType exprType = exprTypes[i];
|
||||
Cost cost= checkImplicitConversionSequence(listType, exprType, isLValue.get(i), UDCMode.allowUDC, false);
|
||||
if (cost.getRank() == Rank.NO_MATCH)
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
if (cost.isNarrowingConversion()) {
|
||||
cost.setRank(Rank.NO_MATCH);
|
||||
|
@ -312,17 +312,17 @@ public class Conversions {
|
|||
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
|
||||
if (noCVTarget instanceof ICPPClassType) {
|
||||
if (udc == UDCMode.noUDC)
|
||||
return new Cost(arg, target, Rank.NO_MATCH);
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
||||
if (ClassTypeHelper.isAggregateClass(classTarget)) {
|
||||
return new Cost(arg, target, Rank.USER_DEFINED_CONVERSION);
|
||||
}
|
||||
Cost cost= checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC);
|
||||
if (cost != null)
|
||||
Cost cost= new Cost(arg, target, Rank.IDENTITY);
|
||||
cost.setUserDefinedConversion(null);
|
||||
return cost;
|
||||
}
|
||||
return checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC);
|
||||
}
|
||||
return new Cost(arg, target, Rank.NO_MATCH);
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
private static IType getInitListType(IType target) throws DOMException {
|
||||
|
@ -492,18 +492,13 @@ public class Conversions {
|
|||
|
||||
/**
|
||||
* [13.3.3.1.2] User-defined conversions
|
||||
* @param source
|
||||
* @param target
|
||||
* @return
|
||||
* @throws DOMException
|
||||
*/
|
||||
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC) throws DOMException {
|
||||
// mstodo don't return null
|
||||
IType s= getNestedType(source, TDEF | CVTYPE | REF);
|
||||
IType t= getNestedType(target, TDEF | CVTYPE | REF);
|
||||
|
||||
if (!(s instanceof ICPPClassType || t instanceof ICPPClassType)) {
|
||||
return null;
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
if (deferUDC) {
|
||||
|
@ -525,26 +520,25 @@ public class Conversions {
|
|||
// 13.3.1.5 Initialization by conversion function
|
||||
return initializationByConversion(source, (ICPPClassType) s, target);
|
||||
}
|
||||
return null;
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
private static Cost listInitializationOfClass(InitializerListType s, ICPPClassType t, boolean isDirect) throws DOMException {
|
||||
private static Cost listInitializationOfClass(InitializerListType arg, ICPPClassType t, boolean isDirect) throws DOMException {
|
||||
// If T has an initializer-list constructor
|
||||
ICPPConstructor usedCtor= null;
|
||||
Cost bestCost= null;
|
||||
ICPPConstructor[] ctors= t.getConstructors();
|
||||
boolean hasInitListConstructor= false;
|
||||
final ICPPConstructor[] constructors = t.getConstructors();
|
||||
ICPPConstructor[] ctors= constructors;
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
if (ctor.getRequiredArgumentCount() <= 1) {
|
||||
IType[] parTypes= ctor.getType().getParameterTypes();
|
||||
if (parTypes.length > 0) {
|
||||
final IType target = parTypes[0];
|
||||
if (getInitListType(target) != null) {
|
||||
Cost cost= listInitializationSequence(s, target, UDCMode.noUDC);
|
||||
if (cost.getRank() == Rank.NO_MATCH) {
|
||||
if (bestCost == null) {
|
||||
bestCost= cost;
|
||||
}
|
||||
} else {
|
||||
hasInitListConstructor= true;
|
||||
Cost cost= listInitializationSequence(arg, target, UDCMode.noUDC);
|
||||
if (cost.converts()) {
|
||||
int cmp= cost.compareTo(bestCost);
|
||||
if (bestCost == null || cmp < 0) {
|
||||
usedCtor= ctor;
|
||||
|
@ -558,7 +552,10 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (bestCost != null) {
|
||||
if (hasInitListConstructor) {
|
||||
if (bestCost == null)
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
if (!bestCost.isAmbiguousUDC() && !isDirect) {
|
||||
if (usedCtor != null && usedCtor.isExplicit()) {
|
||||
bestCost.setRank(Rank.NO_MATCH);
|
||||
|
@ -566,10 +563,48 @@ public class Conversions {
|
|||
}
|
||||
return bestCost;
|
||||
}
|
||||
|
||||
// mstodo expanding the list for selecting the ctor.
|
||||
return new Cost(s, t, Rank.NO_MATCH);
|
||||
|
||||
|
||||
// No initializer-list constructor
|
||||
final ICPPASTInitializerList initializerList = arg.getInitializerList();
|
||||
|
||||
LookupData data= new LookupData();
|
||||
IASTName name = new CPPASTName(t.getNameCharArray());
|
||||
name.setParent(initializerList);
|
||||
name.setPropertyInParent(CPPSemantics.STRING_LOOKUP_PROPERTY);
|
||||
final IASTInitializerClause[] expandedArgs = initializerList.getClauses();
|
||||
data.setFunctionArguments(expandedArgs);
|
||||
data.fNoNarrowing= true;
|
||||
|
||||
// 13.3.3.1.4
|
||||
ICPPConstructor[] filteredConstructors = constructors;
|
||||
if (expandedArgs.length == 1) {
|
||||
filteredConstructors= new ICPPConstructor[constructors.length];
|
||||
int j=0;
|
||||
for (ICPPConstructor ctor : constructors) {
|
||||
if (ctor.getRequiredArgumentCount() < 2) {
|
||||
IType[] ptypes= ctor.getType().getParameterTypes();
|
||||
if (ptypes.length > 0) {
|
||||
IType ptype= getNestedType(ptypes[0], TDEF | REF | CVTYPE);
|
||||
if (!t.isSameType(ptype)) {
|
||||
filteredConstructors[j++]= ctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final IBinding result= CPPSemantics.resolveFunction(data, filteredConstructors, true);
|
||||
final Cost c;
|
||||
if (result instanceof ICPPMethod) {
|
||||
c= new Cost(arg, t, Rank.IDENTITY);
|
||||
c.setUserDefinedConversion((ICPPMethod) result);
|
||||
} else if (result instanceof IProblemBinding
|
||||
&& ((IProblemBinding) result).getID() == IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP) {
|
||||
c = new Cost(arg, t, Rank.USER_DEFINED_CONVERSION);
|
||||
c.setAmbiguousUDC(true);
|
||||
} else {
|
||||
c= Cost.NO_CONVERSION;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -646,8 +681,8 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
if (cost1 == null || !cost1.getCost(0).converts())
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
|
@ -667,7 +702,7 @@ public class Conversions {
|
|||
boolean isLValue = uqReturnType instanceof ICPPReferenceType
|
||||
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
|
||||
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
|
||||
if (c2.getRank() != Rank.NO_MATCH) {
|
||||
if (c2.converts()) {
|
||||
ICPPFunctionType ftype = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
|
@ -686,8 +721,8 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
if (cost1 == null || !cost1.getCost(0).converts())
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
|
|
|
@ -13,16 +13,23 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
|
||||
/**
|
||||
* The cost of an implicit conversion sequence.
|
||||
*
|
||||
* See [over.best.ics] 13.3.3.1.
|
||||
*/
|
||||
final class Cost {
|
||||
class Cost {
|
||||
enum Rank {
|
||||
IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
||||
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
||||
|
@ -31,6 +38,41 @@ final class Cost {
|
|||
RVALUE_REF_BINDS_RVALUE, LVALUE_REF, OTHER
|
||||
}
|
||||
|
||||
public static final Cost NO_CONVERSION = new Cost(null, null, Rank.NO_MATCH) {
|
||||
@Override
|
||||
public void setRank(Rank rank) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setReferenceBinding(ReferenceBinding binding) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setAmbiguousUDC(boolean val) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setDeferredUDC(boolean val) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setInheritanceDistance(int inheritanceDistance) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setQualificationAdjustment(int adjustment) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setUserDefinedConversion(ICPPMethod conv) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setCouldNarrow() {
|
||||
assert false;
|
||||
}
|
||||
};
|
||||
|
||||
IType source;
|
||||
IType target;
|
||||
|
||||
|
@ -52,10 +94,14 @@ final class Cost {
|
|||
fReferenceBinding= ReferenceBinding.OTHER;
|
||||
}
|
||||
|
||||
public Rank getRank() {
|
||||
public final Rank getRank() {
|
||||
return fRank;
|
||||
}
|
||||
|
||||
public final boolean converts() {
|
||||
return fRank != Rank.NO_MATCH;
|
||||
}
|
||||
|
||||
public void setRank(Rank rank) {
|
||||
fRank= rank;
|
||||
}
|
||||
|
@ -99,10 +145,9 @@ final class Cost {
|
|||
*/
|
||||
public void setUserDefinedConversion(ICPPMethod conv) {
|
||||
fUserDefinedConversion= conv;
|
||||
if (conv != null) {
|
||||
fSecondStandardConversionRank= fRank;
|
||||
fRank= Rank.USER_DEFINED_CONVERSION;
|
||||
}
|
||||
fSecondStandardConversionRank= fRank;
|
||||
fRank= Rank.USER_DEFINED_CONVERSION;
|
||||
fCouldNarrow= false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +234,26 @@ final class Cost {
|
|||
}
|
||||
|
||||
public boolean isNarrowingConversion() {
|
||||
return fCouldNarrow;
|
||||
if (fCouldNarrow) {
|
||||
if (source instanceof CPPBasicType && target instanceof ICPPBasicType) {
|
||||
ICPPBasicType basicTarget= (ICPPBasicType) target;
|
||||
final Kind targetKind = basicTarget.getKind();
|
||||
if (targetKind != Kind.eInt && targetKind != Kind.eFloat && targetKind != Kind.eDouble) {
|
||||
return true;
|
||||
}
|
||||
IASTExpression val = ((CPPBasicType) source).getCreatedFromExpression();
|
||||
if (val instanceof IASTLiteralExpression) {
|
||||
// mstodo extend to constant expressions
|
||||
Long l= Value.create(val, Value.MAX_RECURSION_DEPTH).numericalValue();
|
||||
if (l != null) {
|
||||
long n= l.longValue();
|
||||
return !ArithmeticConversion.fitsIntoType(basicTarget, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setCouldNarrow() {
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
|
|||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||
|
||||
/**
|
||||
* Cost for the entire function call
|
||||
|
@ -66,6 +65,8 @@ class FunctionCost {
|
|||
|
||||
public boolean hasDeferredUDC() {
|
||||
for (Cost cost : fCosts) {
|
||||
if (!cost.converts())
|
||||
return false;
|
||||
if (cost.isDeferredUDC())
|
||||
return true;
|
||||
}
|
||||
|
@ -77,10 +78,10 @@ class FunctionCost {
|
|||
Cost cost = fCosts[i];
|
||||
if (cost.isDeferredUDC()) {
|
||||
Cost udcCost= Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i), cost.source, cost.target, false);
|
||||
if (udcCost == null || udcCost.getRank() == Rank.NO_MATCH) {
|
||||
fCosts[i]= udcCost;
|
||||
if (!udcCost.converts()) {
|
||||
return false;
|
||||
}
|
||||
fCosts[i]= udcCost;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -102,7 +103,7 @@ class FunctionCost {
|
|||
int idxOther= other.getLength() - 1;
|
||||
for (; idx >= 0 && idxOther >= 0; idx--, idxOther--) {
|
||||
Cost cost= getCost(idx);
|
||||
if (cost.getRank() == Rank.NO_MATCH) {
|
||||
if (!cost.converts()) {
|
||||
haveWorse = true;
|
||||
haveBetter = false;
|
||||
break;
|
||||
|
@ -155,7 +156,7 @@ class FunctionCost {
|
|||
int idxOther= other.getLength() - 1;
|
||||
for (; idx >= 0 && idxOther >= 0; idx--, idxOther--) {
|
||||
Cost cost= getCost(idx);
|
||||
if (cost.getRank() == Rank.NO_MATCH)
|
||||
if (!cost.converts())
|
||||
return true;
|
||||
|
||||
Cost otherCost= other.getCost(idxOther);
|
||||
|
|
|
@ -101,6 +101,8 @@ public class LookupData {
|
|||
/** When computing the cost of a method call, treat the first argument as the implied method argument. */
|
||||
public boolean firstArgIsImpliedMethodArg = false;
|
||||
public boolean ignoreMembers = false;
|
||||
/** In list-initialization **/
|
||||
public boolean fNoNarrowing= false;
|
||||
|
||||
private ICPPASTParameterDeclaration[] functionParameters;
|
||||
private IASTInitializerClause[] functionArgs;
|
||||
|
|
Loading…
Add table
Reference in a new issue