mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
User-defined conversions, bug 222444.
This commit is contained in:
parent
6744e78d21
commit
36181bd862
6 changed files with 317 additions and 104 deletions
|
@ -7468,5 +7468,94 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
assertTrue(m.isInline());
|
assertTrue(m.isInline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class B {};
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// A() {};
|
||||||
|
// A(B c) {};
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class C : B {
|
||||||
|
// public:
|
||||||
|
// operator A() {}
|
||||||
|
// };
|
||||||
|
// void foo(A a) {}
|
||||||
|
// void test() {
|
||||||
|
// C c= *new C();
|
||||||
|
// foo(c);
|
||||||
|
// }
|
||||||
|
public void testUserdefinedConversion_222444a() throws Exception {
|
||||||
|
final String code = getAboveComment();
|
||||||
|
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class From {};
|
||||||
|
// class To1 {
|
||||||
|
// public:
|
||||||
|
// To1(...) {}
|
||||||
|
// };
|
||||||
|
// class To2 {
|
||||||
|
// public:
|
||||||
|
// To2(From f) {}
|
||||||
|
// };
|
||||||
|
// class To3 {
|
||||||
|
// public:
|
||||||
|
// To3(From f, int a=0) {}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void x1(To1 t) {}
|
||||||
|
// void x2(To2 t) {}
|
||||||
|
// void x3(To3 t) {}
|
||||||
|
// void test() {
|
||||||
|
// From f;
|
||||||
|
// x1(f);
|
||||||
|
// x2(f);
|
||||||
|
// x3(f);
|
||||||
|
// }
|
||||||
|
public void testUserdefinedConversion_222444b() throws Exception {
|
||||||
|
final String code = getAboveComment();
|
||||||
|
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {};
|
||||||
|
// class B : public A {};
|
||||||
|
//
|
||||||
|
// class C {
|
||||||
|
// public:
|
||||||
|
// operator const B() { return *new B();}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void foo(A a) {}
|
||||||
|
//
|
||||||
|
// void refs() {
|
||||||
|
// C c= *new C();
|
||||||
|
// const C cc= *new C();
|
||||||
|
// foo(c);
|
||||||
|
// foo(cc);
|
||||||
|
// }
|
||||||
|
public void testUserdefinedConversion_222444c() throws Exception {
|
||||||
|
final String code = getAboveComment();
|
||||||
|
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||||
|
bh.assertNonProblem("foo(c);", 3);
|
||||||
|
bh.assertProblem("foo(cc);", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class ULONGLONG {
|
||||||
|
// public :
|
||||||
|
// ULONGLONG ( unsigned long long val ) {}
|
||||||
|
// friend bool operator == ( const ULONGLONG & , const int ) { return true; }
|
||||||
|
// };
|
||||||
|
// enum E {A, B, C};
|
||||||
|
// int main() {
|
||||||
|
// return B == 23;
|
||||||
|
// }
|
||||||
|
public void testInvalidOverload_291409() throws Exception {
|
||||||
|
final String code = getAboveComment();
|
||||||
|
IASTTranslationUnit tu= parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||||
|
IASTFunctionDefinition fdef= getDeclaration(tu, 2);
|
||||||
|
IASTReturnStatement stmt= getStatement(fdef, 0);
|
||||||
|
IASTImplicitNameOwner no= (IASTImplicitNameOwner) stmt.getReturnValue();
|
||||||
|
assertEquals(0, no.getImplicitNames().length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4757,7 +4757,7 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
// foo(b);
|
// foo(b);
|
||||||
// foo(c);
|
// foo(c);
|
||||||
// }
|
// }
|
||||||
public void _testBug222444_a() throws Exception {
|
public void testBug222444_a() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
ICPPFunction foo1= ba.assertNonProblem("foo(b", 3, ICPPFunction.class);
|
ICPPFunction foo1= ba.assertNonProblem("foo(b", 3, ICPPFunction.class);
|
||||||
ICPPFunction foo2= ba.assertNonProblem("foo(c", 3, ICPPFunction.class);
|
ICPPFunction foo2= ba.assertNonProblem("foo(c", 3, ICPPFunction.class);
|
||||||
|
@ -4778,7 +4778,27 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
//
|
//
|
||||||
// foo(c);
|
// foo(c);
|
||||||
// }
|
// }
|
||||||
public void _testBug222444_b() throws Exception {
|
public void testBug222444_b() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ICPPFunction foo2= ba.assertNonProblem("foo(c", 3, ICPPFunction.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {};
|
||||||
|
// class B : public A {};
|
||||||
|
//
|
||||||
|
// class C {
|
||||||
|
// public:
|
||||||
|
// operator const B&() { return *new B();}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void foo(A a) {}
|
||||||
|
//
|
||||||
|
// void refs() {
|
||||||
|
// C c= *new C();
|
||||||
|
//
|
||||||
|
// foo(c);
|
||||||
|
// }
|
||||||
|
public void testBug222444_c() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
ICPPFunction foo2= ba.assertNonProblem("foo(c", 3, ICPPFunction.class);
|
ICPPFunction foo2= ba.assertNonProblem("foo(c", 3, ICPPFunction.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2075,7 +2075,9 @@ public class CPPSemantics {
|
||||||
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
|
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
|
||||||
if (data.firstArgIsImpliedMethodArg) {
|
if (data.firstArgIsImpliedMethodArg) {
|
||||||
argTypes = ArrayUtil.removeFirst(argTypes);
|
argTypes = ArrayUtil.removeFirst(argTypes);
|
||||||
args = ArrayUtil.removeFirst(args);
|
if (args != null) {
|
||||||
|
args = ArrayUtil.removeFirst(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2088,8 +2090,8 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
result= new FunctionCost(fn, sourceLen+1);
|
result= new FunctionCost(fn, sourceLen+1);
|
||||||
|
|
||||||
|
boolean sourceIsLValue= true;
|
||||||
final IType thisType = data.getImpliedObjectArgument();
|
final IType thisType = data.getImpliedObjectArgument();
|
||||||
|
|
||||||
if (fn instanceof ICPPMethod &&
|
if (fn instanceof ICPPMethod &&
|
||||||
(((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
|
(((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
|
||||||
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
|
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
|
||||||
|
@ -2101,12 +2103,12 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
if (CPPTemplates.isDependentType(implicitType))
|
if (CPPTemplates.isDependentType(implicitType))
|
||||||
return CONTAINS_DEPENDENT_TYPES;
|
return CONTAINS_DEPENDENT_TYPES;
|
||||||
cost = Conversions.checkImplicitConversionSequence(null, thisType, implicitType, UDCMode.noUDC, true);
|
cost = Conversions.checkImplicitConversionSequence(sourceIsLValue, thisType, implicitType, UDCMode.noUDC, true);
|
||||||
}
|
}
|
||||||
if (cost.getRank() == Rank.NO_MATCH)
|
if (cost.getRank() == Rank.NO_MATCH)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
result.setCost(k++, cost);
|
result.setCost(k++, cost, sourceIsLValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
|
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
|
||||||
|
@ -2116,6 +2118,7 @@ public class CPPSemantics {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final IASTExpression arg= args != null && j < args.length ? args[j] : null;
|
final IASTExpression arg= args != null && j < args.length ? args[j] : null;
|
||||||
|
final boolean sourceIsLValue = arg != null && !CPPVisitor.isRValue(arg);
|
||||||
|
|
||||||
IType paramType;
|
IType paramType;
|
||||||
if (j < paramTypes.length) {
|
if (j < paramTypes.length) {
|
||||||
|
@ -2124,7 +2127,7 @@ public class CPPSemantics {
|
||||||
paramType= VOID_TYPE;
|
paramType= VOID_TYPE;
|
||||||
} else {
|
} else {
|
||||||
cost = new Cost(argType, null, Rank.ELLIPSIS_CONVERSION);
|
cost = new Cost(argType, null, Rank.ELLIPSIS_CONVERSION);
|
||||||
result.setCost(k++, cost);
|
result.setCost(k++, cost, sourceIsLValue);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2133,17 +2136,17 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
if (CPPTemplates.isDependentType(paramType))
|
if (CPPTemplates.isDependentType(paramType))
|
||||||
return CONTAINS_DEPENDENT_TYPES;
|
return CONTAINS_DEPENDENT_TYPES;
|
||||||
cost = Conversions.checkImplicitConversionSequence(arg, argType, paramType, udc, false);
|
cost = Conversions.checkImplicitConversionSequence(sourceIsLValue, argType, paramType, udc, false);
|
||||||
}
|
}
|
||||||
if (cost.getRank() == Rank.NO_MATCH)
|
if (cost.getRank() == Rank.NO_MATCH)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
result.setCost(k++, cost);
|
result.setCost(k++, cost, sourceIsLValue);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IType getImplicitType(ICPPMethod m, final boolean isConst, final boolean isVolatile)
|
static IType getImplicitType(ICPPMethod m, final boolean isConst, final boolean isVolatile)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
IType implicitType;
|
IType implicitType;
|
||||||
ICPPClassType owner= m.getClassOwner();
|
ICPPClassType owner= m.getClassOwner();
|
||||||
|
@ -2495,7 +2498,7 @@ public class CPPSemantics {
|
||||||
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
||||||
innerFR.setParent(fieldReference); // connect to the AST
|
innerFR.setParent(fieldReference); // connect to the AST
|
||||||
|
|
||||||
ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, operatorName, false);
|
ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, operatorName, NonMemberMode.none);
|
||||||
if (op == null)
|
if (op == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2523,7 +2526,7 @@ public class CPPSemantics {
|
||||||
IASTExpression[] args = {exp.getArrayExpression(), exp.getSubscriptExpression()};
|
IASTExpression[] args = {exp.getArrayExpression(), exp.getSubscriptExpression()};
|
||||||
IType type1 = exp.getArrayExpression().getExpressionType();
|
IType type1 = exp.getArrayExpression().getExpressionType();
|
||||||
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
|
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
|
||||||
return findOverloadedOperator(exp, args, ultimateType1, name, false);
|
return findOverloadedOperator(exp, args, ultimateType1, name, NonMemberMode.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2545,7 +2548,7 @@ public class CPPSemantics {
|
||||||
args = new IASTExpression[] { exp.getFunctionNameExpression() };
|
args = new IASTExpression[] { exp.getFunctionNameExpression() };
|
||||||
}
|
}
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, name, false);
|
return findOverloadedOperator(exp, args, type, name, NonMemberMode.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
||||||
|
@ -2571,14 +2574,14 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTExpression[] argArray = args.toArray(new IASTExpression[args.size()]);
|
IASTExpression[] argArray = args.toArray(new IASTExpression[args.size()]);
|
||||||
return findOverloadedOperator(exp, argArray, type, op.toCharArray(), true);
|
return findOverloadedOperator(exp, argArray, type, op.toCharArray(), NonMemberMode.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
||||||
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
||||||
IASTExpression[] args = { exp.getOperand() };
|
IASTExpression[] args = { exp.getOperand() };
|
||||||
IType classType = getNestedClassType(exp);
|
IType classType = getNestedClassType(exp);
|
||||||
return findOverloadedOperator(exp, args, classType, op.toCharArray(), true);
|
return findOverloadedOperator(exp, args, classType, op.toCharArray(), NonMemberMode.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
||||||
|
@ -2645,7 +2648,7 @@ public class CPPSemantics {
|
||||||
if (!isUserDefined(type))
|
if (!isUserDefined(type))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, op.toCharArray(), true);
|
return findOverloadedOperator(exp, args, type, op.toCharArray(), NonMemberMode.limited);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
||||||
|
@ -2656,7 +2659,7 @@ public class CPPSemantics {
|
||||||
IType op1type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand1().getExpressionType());
|
IType op1type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand1().getExpressionType());
|
||||||
IASTExpression[] args = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() } ;
|
IASTExpression[] args = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() } ;
|
||||||
|
|
||||||
boolean lookupNonMember = false;
|
NonMemberMode lookupNonMember = NonMemberMode.none;
|
||||||
if (exp.getOperator() != IASTBinaryExpression.op_assign) {
|
if (exp.getOperator() != IASTBinaryExpression.op_assign) {
|
||||||
IType op2type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand2().getExpressionType());
|
IType op2type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand2().getExpressionType());
|
||||||
if (op2type instanceof IProblemBinding)
|
if (op2type instanceof IProblemBinding)
|
||||||
|
@ -2664,7 +2667,7 @@ public class CPPSemantics {
|
||||||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
lookupNonMember= true;
|
lookupNonMember= NonMemberMode.limited;
|
||||||
}
|
}
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, op1type, op.toCharArray(), lookupNonMember);
|
return findOverloadedOperator(exp, args, op1type, op.toCharArray(), lookupNonMember);
|
||||||
|
@ -2687,10 +2690,12 @@ public class CPPSemantics {
|
||||||
|
|
||||||
char[] name = OverloadableOperator.COMMA.toCharArray();
|
char[] name = OverloadableOperator.COMMA.toCharArray();
|
||||||
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
||||||
return findOverloadedOperator(dummy, args, lookupType, name, true);
|
return findOverloadedOperator(dummy, args, lookupType, name, NonMemberMode.limited);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTExpression[] args, IType methodLookupType, char[] operatorName, boolean lookupNonMember) {
|
enum NonMemberMode {none, limited, all}
|
||||||
|
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTExpression[] args, IType methodLookupType,
|
||||||
|
char[] operatorName, NonMemberMode mode) {
|
||||||
ICPPClassType callToObjectOfClassType= null;
|
ICPPClassType callToObjectOfClassType= null;
|
||||||
|
|
||||||
// Find a method
|
// Find a method
|
||||||
|
@ -2725,7 +2730,7 @@ public class CPPSemantics {
|
||||||
// Find a function
|
// Find a function
|
||||||
LookupData funcData = null;
|
LookupData funcData = null;
|
||||||
CPPASTName funcName = null;
|
CPPASTName funcName = null;
|
||||||
if (lookupNonMember || callToObjectOfClassType != null) {
|
if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
|
||||||
funcName = new CPPASTName(operatorName);
|
funcName = new CPPASTName(operatorName);
|
||||||
funcName.setParent(parent);
|
funcName.setParent(parent);
|
||||||
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
|
@ -2734,13 +2739,53 @@ public class CPPSemantics {
|
||||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (lookupNonMember) {
|
if (mode != NonMemberMode.none) {
|
||||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||||
if (scope == null)
|
if (scope == null)
|
||||||
return null;
|
return null;
|
||||||
lookup(funcData, scope);
|
lookup(funcData, scope);
|
||||||
}
|
}
|
||||||
if (callToObjectOfClassType != null) {
|
} catch (DOMException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.3.1.2.3
|
||||||
|
// However, if no operand type has class type, only those non-member functions ...
|
||||||
|
if (mode == NonMemberMode.limited) {
|
||||||
|
IType type2= args.length < 2 ? null : getUltimateTypeUptoPointers(args[1].getExpressionType());
|
||||||
|
if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
|
||||||
|
IEnumeration enum1= null;
|
||||||
|
IEnumeration enum2= null;
|
||||||
|
if (methodLookupType instanceof IEnumeration) {
|
||||||
|
enum1= (IEnumeration) methodLookupType;
|
||||||
|
}
|
||||||
|
if (type2 instanceof IEnumeration) {
|
||||||
|
enum2= (IEnumeration) type2;
|
||||||
|
}
|
||||||
|
Object[] items= (Object[]) funcData.foundItems;
|
||||||
|
int j= 0;
|
||||||
|
for (Object object : items) {
|
||||||
|
if (object instanceof ICPPFunction) {
|
||||||
|
ICPPFunction func= (ICPPFunction) object;
|
||||||
|
try {
|
||||||
|
ICPPFunctionType ft = func.getType();
|
||||||
|
IType[] pts= ft.getParameterTypes();
|
||||||
|
if ((enum1 != null && pts.length > 0 && enum1.isSameType(getUltimateTypeUptoPointers(pts[0]))) ||
|
||||||
|
(enum2 != null && pts.length > 1 && enum2.isSameType(getUltimateTypeUptoPointers(pts[1])))) {
|
||||||
|
items[j++]= object;
|
||||||
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(j < items.length) {
|
||||||
|
items[j++]= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callToObjectOfClassType != null) {
|
||||||
|
try {
|
||||||
// 13.3.1.1.2 call to object of class type
|
// 13.3.1.1.2 call to object of class type
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
|
||||||
for (ICPPMethod op : ops) {
|
for (ICPPMethod op : ops) {
|
||||||
|
@ -2757,9 +2802,9 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -672,7 +672,11 @@ public class CPPTemplates {
|
||||||
final int length = tmplParams.length;
|
final int length = tmplParams.length;
|
||||||
|
|
||||||
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
|
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
|
||||||
if (!deduceTemplateParameterMap(template.getType().getReturnType(), conversionType, map)) {
|
IType a= SemanticUtil.getSimplifiedType(conversionType);
|
||||||
|
final boolean isReferenceType = a instanceof ICPPReferenceType;
|
||||||
|
final IType p= getArgumentTypeForDeduction(template.getType().getReturnType(), isReferenceType);
|
||||||
|
a= getParameterTypeForDeduction(a, isReferenceType);
|
||||||
|
if (!deduceTemplateParameterMap(p, a, map)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,10 +1411,6 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType, IASTName name) {
|
|
||||||
instantiateConversionTemplates(functions, conversionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType) {
|
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType) {
|
||||||
boolean checkedForDependentType= false;
|
boolean checkedForDependentType= false;
|
||||||
for (int i = 0; i < functions.length; i++) {
|
for (int i = 0; i < functions.length; i++) {
|
||||||
|
@ -1546,6 +1546,8 @@ public class CPPTemplates {
|
||||||
/**
|
/**
|
||||||
* 14.8.2.1-2 If P is a cv-qualified type, the top level cv-qualifiers of P's type are ignored for type
|
* 14.8.2.1-2 If P is a cv-qualified type, the top level cv-qualifiers of P's type are ignored for type
|
||||||
* deduction. If P is a reference type, the type referred to by P is used for Type deduction.
|
* deduction. If P is a reference type, the type referred to by P is used for Type deduction.
|
||||||
|
*
|
||||||
|
* Also 14.8.2.3-2 where the same logics is used in reverse.
|
||||||
*/
|
*/
|
||||||
static private IType getParameterTypeForDeduction(IType pType, boolean isReferenceType) {
|
static private IType getParameterTypeForDeduction(IType pType, boolean isReferenceType) {
|
||||||
if (isReferenceType) {
|
if (isReferenceType) {
|
||||||
|
@ -1560,9 +1562,8 @@ public class CPPTemplates {
|
||||||
* - If A is an array type, the pointer type produced by the array-to-pointer conversion is used instead
|
* - If A is an array type, the pointer type produced by the array-to-pointer conversion is used instead
|
||||||
* - If A is a function type, the pointer type produced by the function-to-pointer conversion is used instead
|
* - If A is a function type, the pointer type produced by the function-to-pointer conversion is used instead
|
||||||
* - If A is a cv-qualified type, the top level cv-qualifiers are ignored for type deduction
|
* - If A is a cv-qualified type, the top level cv-qualifiers are ignored for type deduction
|
||||||
* @param type argument type
|
*
|
||||||
* @param parameterIsAReferenceType indicates whether template parameter is a reference type.
|
* Also 14.8.2.3-2 where the same logics is used in reverse.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
static private IType getArgumentTypeForDeduction(IType type, boolean parameterIsAReferenceType) {
|
static private IType getArgumentTypeForDeduction(IType type, boolean parameterIsAReferenceType) {
|
||||||
type = SemanticUtil.getSimplifiedType(type);
|
type = SemanticUtil.getSimplifiedType(type);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||||
|
@ -34,7 +35,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
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.ICPPSpecialization;
|
||||||
|
@ -58,7 +61,7 @@ public class Conversions {
|
||||||
/**
|
/**
|
||||||
* Computes the cost of an implicit conversion sequence
|
* Computes the cost of an implicit conversion sequence
|
||||||
* [over.best.ics] 13.3.3.1
|
* [over.best.ics] 13.3.3.1
|
||||||
* @param sourceExp the expression behind the source type
|
* @param sourceIsLValue whether the source type is an lvalue
|
||||||
* @param source the source (argument) type
|
* @param source the source (argument) type
|
||||||
* @param target the target (parameter) type
|
* @param target the target (parameter) type
|
||||||
* @param isImpliedObject
|
* @param isImpliedObject
|
||||||
|
@ -66,7 +69,7 @@ public class Conversions {
|
||||||
* @return the cost of converting from source to target
|
* @return the cost of converting from source to target
|
||||||
* @throws DOMException
|
* @throws DOMException
|
||||||
*/
|
*/
|
||||||
public static Cost checkImplicitConversionSequence(IASTExpression sourceExp, IType source,
|
public static Cost checkImplicitConversionSequence(boolean sourceIsLValue, IType source,
|
||||||
IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
||||||
if (isImpliedObject) {
|
if (isImpliedObject) {
|
||||||
udc= UDCMode.noUDC;
|
udc= UDCMode.noUDC;
|
||||||
|
@ -79,14 +82,15 @@ public class Conversions {
|
||||||
// [8.5.3-5] initialization of a reference
|
// [8.5.3-5] initialization of a reference
|
||||||
IType cv1T1= getNestedType(target, TDEF | REF);
|
IType cv1T1= getNestedType(target, TDEF | REF);
|
||||||
|
|
||||||
boolean lvalue= sourceExp == null || !CPPVisitor.isRValue(sourceExp);
|
if (source instanceof ICPPReferenceType) {
|
||||||
if (source instanceof ICPPReferenceType)
|
sourceIsLValue= true;
|
||||||
source= getNestedType(source, TDEF | REF);
|
source= getNestedType(source, TDEF | REF);
|
||||||
|
}
|
||||||
|
|
||||||
IType T2= getNestedType(source, TDEF | REF | CVQ | PTR_CVQ);
|
IType T2= getNestedType(source, TDEF | REF | CVQ | PTR_CVQ);
|
||||||
|
|
||||||
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
||||||
if (lvalue) {
|
if (sourceIsLValue) {
|
||||||
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
// [8.5.3-5] this is a direct reference binding
|
// [8.5.3-5] this is a direct reference binding
|
||||||
|
@ -135,7 +139,7 @@ public class Conversions {
|
||||||
// [8.5.3-5] Direct binding failed - Otherwise
|
// [8.5.3-5] Direct binding failed - Otherwise
|
||||||
boolean cv1isConst= getCVQualifier(cv1T1) == 1;
|
boolean cv1isConst= getCVQualifier(cv1T1) == 1;
|
||||||
if (cv1isConst) {
|
if (cv1isConst) {
|
||||||
if (!lvalue && T2 instanceof ICPPClassType) {
|
if (!sourceIsLValue && T2 instanceof ICPPClassType) {
|
||||||
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
||||||
if (cost != null)
|
if (cost != null)
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -156,7 +160,7 @@ public class Conversions {
|
||||||
|
|
||||||
// We must do a non-reference initialization
|
// We must do a non-reference initialization
|
||||||
if (!illformed) {
|
if (!illformed) {
|
||||||
return nonReferenceConversion(source, cv1T1, udc, isImpliedObject);
|
return nonReferenceConversion(sourceIsLValue, source, cv1T1, udc, isImpliedObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,31 +168,36 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-reference binding
|
// Non-reference binding
|
||||||
// [13.3.3.1-6] Subsume cv-qualifications
|
IType uqsource= getNestedType(source, TDEF | REF | CVQ);
|
||||||
source= getNestedType(source, TDEF | REF | CVQ | PTR_CVQ);
|
IType uqtarget= getNestedType(target, TDEF | REF | CVQ);
|
||||||
target= getNestedType(target, TDEF | REF | CVQ | PTR_CVQ);
|
|
||||||
|
|
||||||
// [13.3.3.1-6] Derived to base conversion
|
// [13.3.3.1-6] Derived to base conversion
|
||||||
if (source instanceof ICPPClassType && target instanceof ICPPClassType) {
|
if (uqsource instanceof ICPPClassType && uqtarget instanceof ICPPClassType) {
|
||||||
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, source, target);
|
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, uqsource, uqtarget);
|
||||||
if (depth > -1) {
|
if (depth > -1) {
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
return new Cost(source, target, Rank.IDENTITY);
|
return new Cost(uqsource, uqtarget, Rank.IDENTITY);
|
||||||
}
|
}
|
||||||
Cost cost= new Cost(source, target, Rank.CONVERSION);
|
Cost cost= new Cost(uqsource, uqtarget, Rank.CONVERSION);
|
||||||
cost.setInheritanceDistance(depth);
|
cost.setInheritanceDistance(depth);
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nonReferenceConversion(source, target, udc, isImpliedObject);
|
|
||||||
|
// [13.3.3.1-6] Subsume cv-qualifications
|
||||||
|
if (!(uqsource instanceof ICPPClassType) && !(uqtarget instanceof ICPPClassType)) {
|
||||||
|
source= uqsource;
|
||||||
|
target= uqtarget;
|
||||||
|
}
|
||||||
|
return nonReferenceConversion(sourceIsLValue, source, target, udc, isImpliedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cost nonReferenceConversion(IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
||||||
Cost cost= checkStandardConversionSequence(source, target, isImpliedObject);
|
Cost cost= checkStandardConversionSequence(source, target, isImpliedObject);
|
||||||
if (cost.getRank() != Rank.NO_MATCH || udc == UDCMode.noUDC)
|
if (cost.getRank() != Rank.NO_MATCH || udc == UDCMode.noUDC)
|
||||||
return cost;
|
return cost;
|
||||||
|
|
||||||
Cost temp = checkUserDefinedConversionSequence(source, target, udc == UDCMode.deferUDC);
|
Cost temp = checkUserDefinedConversionSequence(sourceIsLValue, source, target, udc == UDCMode.deferUDC);
|
||||||
if (temp != null) {
|
if (temp != null) {
|
||||||
cost = temp;
|
cost = temp;
|
||||||
}
|
}
|
||||||
|
@ -340,10 +349,7 @@ public class Conversions {
|
||||||
* @return
|
* @return
|
||||||
* @throws DOMException
|
* @throws DOMException
|
||||||
*/
|
*/
|
||||||
static final Cost checkUserDefinedConversionSequence(IType source, IType target, boolean deferUDC) throws DOMException {
|
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC) throws DOMException {
|
||||||
Cost constructorCost= null;
|
|
||||||
Cost operatorCost= null;
|
|
||||||
|
|
||||||
IType s= getNestedType(source, TDEF | CVQ | REF);
|
IType s= getNestedType(source, TDEF | CVQ | REF);
|
||||||
IType t= getNestedType(target, TDEF | CVQ | REF);
|
IType t= getNestedType(target, TDEF | CVQ | REF);
|
||||||
|
|
||||||
|
@ -352,69 +358,115 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deferUDC) {
|
if (deferUDC) {
|
||||||
Cost c= new Cost(s, t, Rank.USER_DEFINED_CONVERSION);
|
Cost c= new Cost(source, target, Rank.USER_DEFINED_CONVERSION);
|
||||||
c.setDeferredUDC(true);
|
c.setDeferredUDC(true);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructors
|
// 13.3.1.4 Copy initialization of class by user-defined conversion
|
||||||
if (t instanceof ICPPClassType) {
|
if (t instanceof ICPPClassType) {
|
||||||
|
Cost cost1= null;
|
||||||
|
Cost cost2= null;
|
||||||
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
|
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
|
||||||
// Select converting constructors
|
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, null);
|
||||||
int j= 0;
|
|
||||||
ICPPConstructor[] convertingCtors= new ICPPConstructor[ctors.length];
|
|
||||||
for (ICPPConstructor ctor : ctors) {
|
|
||||||
if (!(ctor instanceof IProblemBinding) && !ctor.isExplicit())
|
|
||||||
convertingCtors[j++]= ctor;
|
|
||||||
}
|
|
||||||
if (j > 0) {
|
|
||||||
LookupData data= new LookupData();
|
|
||||||
data.setFunctionArgumentTypes(new IType[] { source });
|
|
||||||
IBinding binding = CPPSemantics.resolveFunction(data, convertingCtors, false);
|
|
||||||
if (binding instanceof ICPPConstructor && !(binding instanceof IProblemBinding)) {
|
|
||||||
constructorCost = checkStandardConversionSequence(t, target, false);
|
|
||||||
if (constructorCost.getRank() == Rank.NO_MATCH) {
|
|
||||||
constructorCost= null;
|
|
||||||
} else {
|
|
||||||
constructorCost.setUserDefinedConversion((ICPPConstructor) binding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conversion operators
|
for (ICPPConstructor ctor : ctors) {
|
||||||
boolean ambiguousConversionOperator= false;
|
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||||
if (s instanceof ICPPClassType) {
|
final ICPPFunctionType ft = ctor.getType();
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
final IType[] ptypes = ft.getParameterTypes();
|
||||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
Cost c1;
|
||||||
for (final ICPPMethod op : ops) {
|
if (ptypes.length == 0) {
|
||||||
if (op != null && !(op instanceof IProblemBinding)) {
|
if (ctor.takesVarArgs()) {
|
||||||
Cost cost= checkStandardConversionSequence(op.getType().getReturnType(), target, false);
|
c1= new Cost(source, null, Rank.ELLIPSIS_CONVERSION);
|
||||||
if (cost.getRank() != Rank.NO_MATCH) {
|
} else {
|
||||||
int cmp= cost.compareTo(operatorCost);
|
continue;
|
||||||
if (cmp <= 0) {
|
}
|
||||||
cost.setUserDefinedConversion(op);
|
} else {
|
||||||
operatorCost= cost;
|
if (ptypes.length > 1) {
|
||||||
ambiguousConversionOperator= cmp == 0;
|
IParameter[] pars = ctor.getParameters();
|
||||||
|
if (pars.length < 2 || !((ICPPParameter) pars[1]).hasDefaultValue())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c1= checkImplicitConversionSequence(sourceIsLValue, source, ptypes[0], UDCMode.noUDC, false);
|
||||||
|
}
|
||||||
|
int cmp= c1.compareTo(cost1);
|
||||||
|
if (cmp <= 0) {
|
||||||
|
cost1= c1;
|
||||||
|
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||||
|
cost2.setUserDefinedConversion(ctor);
|
||||||
|
if (cmp == 0) {
|
||||||
|
cost2.setAmbiguousUDC(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (s instanceof ICPPClassType) {
|
||||||
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||||
if (constructorCost != null) {
|
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||||
if (operatorCost != null && !ambiguousConversionOperator) {
|
for (final ICPPMethod op : ops) {
|
||||||
// If both are valid, then the conversion is ambiguous
|
if (op != null && !(op instanceof IProblemBinding)) {
|
||||||
constructorCost.setAmbiguousUDC(true);
|
final IType returnType = op.getType().getReturnType();
|
||||||
|
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVQ);
|
||||||
|
final int dist = calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, uqReturnType, t);
|
||||||
|
if (dist >= 0) {
|
||||||
|
final ICPPFunctionType ft = op.getType();
|
||||||
|
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
|
||||||
|
Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false);
|
||||||
|
int cmp= c1.compareTo(cost1);
|
||||||
|
if (cmp <= 0) {
|
||||||
|
cost1= c1;
|
||||||
|
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||||
|
if (dist > 0) {
|
||||||
|
cost2.setInheritanceDistance(dist);
|
||||||
|
cost2.setRank(Rank.CONVERSION);
|
||||||
|
}
|
||||||
|
cost2.setUserDefinedConversion(op);
|
||||||
|
if (cmp == 0) {
|
||||||
|
cost2.setAmbiguousUDC(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return constructorCost;
|
if (cost1 == null || cost1.getRank() == Rank.NO_MATCH)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return cost2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operatorCost != null) {
|
// 13.3.1.5 Initialization by conversion function
|
||||||
operatorCost.setAmbiguousUDC(ambiguousConversionOperator);
|
if (s instanceof ICPPClassType) {
|
||||||
return operatorCost;
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||||
}
|
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||||
|
Cost cost1= null;
|
||||||
|
Cost cost2= null;
|
||||||
|
for (final ICPPMethod op : ops) {
|
||||||
|
if (op != null && !(op instanceof IProblemBinding)) {
|
||||||
|
final IType returnType = op.getType().getReturnType();
|
||||||
|
IType uqReturnType= getNestedType(returnType, TDEF | CVQ | PTR_CVQ);
|
||||||
|
Cost c2= checkImplicitConversionSequence(false, uqReturnType, target, UDCMode.noUDC, false);
|
||||||
|
if (c2.getRank() != Rank.NO_MATCH) {
|
||||||
|
ICPPFunctionType ftype = op.getType();
|
||||||
|
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
||||||
|
Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false);
|
||||||
|
int cmp= c1.compareTo(cost1);
|
||||||
|
if (cmp <= 0) {
|
||||||
|
cost1= c1;
|
||||||
|
cost2= c2;
|
||||||
|
cost2.setUserDefinedConversion(op);
|
||||||
|
if (cmp == 0) {
|
||||||
|
cost2.setAmbiguousUDC(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cost1 == null || cost1.getRank() == Rank.NO_MATCH)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return cost2;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,6 +596,7 @@ public class Conversions {
|
||||||
|
|
||||||
// This should actually be done in 'checkImplicitConversionSequence', see 13.3.3.1-6 and 8.5.14
|
// This should actually be done in 'checkImplicitConversionSequence', see 13.3.3.1-6 and 8.5.14
|
||||||
// 8.5.14 cv-qualifiers can be ignored for non-class types
|
// 8.5.14 cv-qualifiers can be ignored for non-class types
|
||||||
|
// mstodo
|
||||||
IType unqualifiedTarget= getNestedType(target, CVQ | PTR_CVQ | TDEF | REF);
|
IType unqualifiedTarget= getNestedType(target, CVQ | PTR_CVQ | TDEF | REF);
|
||||||
if (!(unqualifiedTarget instanceof ICPPClassType)) {
|
if (!(unqualifiedTarget instanceof ICPPClassType)) {
|
||||||
IType unqualifiedSource= getNestedType(source, CVQ | PTR_CVQ | TDEF | REF);
|
IType unqualifiedSource= getNestedType(source, CVQ | PTR_CVQ | TDEF | REF);
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
|
@ -23,10 +25,12 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
class FunctionCost {
|
class FunctionCost {
|
||||||
private final IFunction fFunction;
|
private final IFunction fFunction;
|
||||||
private final Cost[] fCosts;
|
private final Cost[] fCosts;
|
||||||
|
private final BitSet fSourceIsLValue;
|
||||||
|
|
||||||
public FunctionCost(IFunction fn, int paramCount) {
|
public FunctionCost(IFunction fn, int paramCount) {
|
||||||
fFunction= fn;
|
fFunction= fn;
|
||||||
fCosts= new Cost[paramCount];
|
fCosts= new Cost[paramCount];
|
||||||
|
fSourceIsLValue= new BitSet(paramCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
|
@ -37,8 +41,9 @@ class FunctionCost {
|
||||||
return fCosts[idx];
|
return fCosts[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(int idx, Cost cost) {
|
public void setCost(int idx, Cost cost, boolean sourceIsLValue) {
|
||||||
fCosts[idx]= cost;
|
fCosts[idx]= cost;
|
||||||
|
fSourceIsLValue.set(idx, sourceIsLValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFunction getFunction() {
|
public IFunction getFunction() {
|
||||||
|
@ -65,7 +70,7 @@ class FunctionCost {
|
||||||
for (int i = 0; i < fCosts.length; i++) {
|
for (int i = 0; i < fCosts.length; i++) {
|
||||||
Cost cost = fCosts[i];
|
Cost cost = fCosts[i];
|
||||||
if (cost.isDeferredUDC()) {
|
if (cost.isDeferredUDC()) {
|
||||||
Cost udcCost= Conversions.checkUserDefinedConversionSequence(cost.source, cost.target, false);
|
Cost udcCost= Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i), cost.source, cost.target, false);
|
||||||
if (udcCost == null) {
|
if (udcCost == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue