mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Bug 294543: Built-in candidates for overloaded operators: Additional testcases and corrections.
This commit is contained in:
parent
c39daa9ca9
commit
7ed4f94f50
6 changed files with 95 additions and 54 deletions
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Mike Kucera (IBM)
|
* Mike Kucera (IBM)
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||||
|
|
||||||
|
@ -495,4 +496,21 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
|
||||||
IASTImplicitName v = ba.assertImplicitName("v(p)", 1, ICPPConstructor.class);
|
IASTImplicitName v = ba.assertImplicitName("v(p)", 1, ICPPConstructor.class);
|
||||||
assertSame(ctor1, v.resolveBinding());
|
assertSame(ctor1, v.resolveBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enum A {aa};
|
||||||
|
// struct B{ operator A();};
|
||||||
|
// bool operator==(A, A); // overrides the built-in operator.
|
||||||
|
//
|
||||||
|
// void test() {
|
||||||
|
// B b;
|
||||||
|
// if (aa==b) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void testBuiltinOperators_294543() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
IASTTranslationUnit tu = ba.getTranslationUnit();
|
||||||
|
ICPPFunction op = ba.assertNonProblem("operator==", 0);
|
||||||
|
IASTImplicitName a = ba.assertImplicitName("==b", 2, ICPPFunction.class);
|
||||||
|
assertSame(op, a.resolveBinding());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8575,7 +8575,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// C c;
|
// C c;
|
||||||
// f(c+1); // converts c to a char and calls operator+(int, int)
|
// f(c+1); // converts c to a char and calls operator+(int, int)
|
||||||
// }
|
// }
|
||||||
public void testBuiltinOperators_294543() throws Exception {
|
public void testBuiltinOperators_294543a() throws Exception {
|
||||||
String code= getAboveComment();
|
String code= getAboveComment();
|
||||||
parseAndCheckBindings(code);
|
parseAndCheckBindings(code);
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||||
|
@ -8583,4 +8583,22 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
IFunction f= bh.assertNonProblem("f(c+1)", 1);
|
IFunction f= bh.assertNonProblem("f(c+1)", 1);
|
||||||
assertSame(fint, f);
|
assertSame(fint, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// operator long& ();
|
||||||
|
// };
|
||||||
|
// void f(long);
|
||||||
|
// void f(A);
|
||||||
|
// void test() {
|
||||||
|
// A a;
|
||||||
|
// f(a= 1); // A cannot be converted to long& here
|
||||||
|
// }
|
||||||
|
public void testBuiltinOperators_294543b() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
parseAndCheckBindings(code);
|
||||||
|
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||||
|
IFunction fA= bh.assertNonProblem("f(A)", 1);
|
||||||
|
IFunction f= bh.assertNonProblem("f(a= 1)", 1);
|
||||||
|
assertSame(fA, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5872,7 +5872,7 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
IASTTranslationUnit tu= parse(code, lang, false, true, true);
|
IASTTranslationUnit tu= parse(code, lang, false, true, true);
|
||||||
long diff= memoryUsed()-mem;
|
long diff= memoryUsed()-mem;
|
||||||
// allow a copy of the buffer + not even 1 byte per initializer
|
// allow a copy of the buffer + not even 1 byte per initializer
|
||||||
final int expected = code.length()*2 + AMOUNT/2;
|
final int expected = code.length()*2 + AMOUNT-1;
|
||||||
assertTrue(String.valueOf(diff) + " expected < " + expected, diff < expected);
|
assertTrue(String.valueOf(diff) + " expected < " + expected, diff < expected);
|
||||||
assertTrue(tu.isFrozen());
|
assertTrue(tu.isFrozen());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ Export-Package: org.eclipse.cdt.core,
|
||||||
org.eclipse.cdt.internal.core;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.debug.core",
|
org.eclipse.cdt.internal.core;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.debug.core",
|
||||||
org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true,
|
org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.dom;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.dom;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.dom.parser;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.dom.parser;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.dom.parser.c;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.dom.parser.c;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.dom.parser.cpp;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.dom.parser.cpp;x-friends:="org.eclipse.cdt.ui",
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
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;
|
||||||
|
@ -56,11 +57,11 @@ class BuiltinOperators {
|
||||||
private static final IType BOOL = new CPPBasicType(Kind.eBoolean, 0);
|
private static final IType BOOL = new CPPBasicType(Kind.eBoolean, 0);
|
||||||
private static final IType PTR_DIFF = new CPPBasicType(Kind.eInt, 0);
|
private static final IType PTR_DIFF = new CPPBasicType(Kind.eInt, 0);
|
||||||
|
|
||||||
public static ICPPFunction[] create(OverloadableOperator operator, IASTInitializerClause[] args, IASTTranslationUnit tu) {
|
public static ICPPFunction[] create(OverloadableOperator operator, IASTInitializerClause[] args, IASTTranslationUnit tu, Object[] globCandidates) {
|
||||||
if (operator == null || args == null || args.length == 0)
|
if (operator == null || args == null || args.length == 0)
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
|
|
||||||
return new BuiltinOperators(operator, args, tu.getScope()).create();
|
return new BuiltinOperators(operator, args, tu.getScope(), globCandidates).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OverloadableOperator fOperator;
|
private final OverloadableOperator fOperator;
|
||||||
|
@ -72,11 +73,13 @@ class BuiltinOperators {
|
||||||
private IScope fFileScope;
|
private IScope fFileScope;
|
||||||
private List<ICPPFunction> fResult;
|
private List<ICPPFunction> fResult;
|
||||||
private Set<String> fSignatures;
|
private Set<String> fSignatures;
|
||||||
|
private Object[] fGlobalCandidates;
|
||||||
|
|
||||||
BuiltinOperators(OverloadableOperator operator, IASTInitializerClause[] args, IScope fileScope) {
|
BuiltinOperators(OverloadableOperator operator, IASTInitializerClause[] args, IScope fileScope, Object[] globCandidates) {
|
||||||
fFileScope= fileScope;
|
fFileScope= fileScope;
|
||||||
fOperator= operator;
|
fOperator= operator;
|
||||||
fUnary= args.length<2;
|
fUnary= args.length<2;
|
||||||
|
fGlobalCandidates= globCandidates;
|
||||||
if (args.length > 0 && args[0] instanceof IASTExpression) {
|
if (args.length > 0 && args[0] instanceof IASTExpression) {
|
||||||
IType type= ((IASTExpression) args[0]).getExpressionType();
|
IType type= ((IASTExpression) args[0]).getExpressionType();
|
||||||
if (!(type instanceof IProblemBinding))
|
if (!(type instanceof IProblemBinding))
|
||||||
|
@ -183,17 +186,17 @@ class BuiltinOperators {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASSIGN:
|
case ASSIGN:
|
||||||
arithmeticAssignement(true, true, false);
|
arithmeticAssignement(true, Assignment.WITHOUT_OPERATION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINUSASSIGN:
|
case MINUSASSIGN:
|
||||||
case PLUSASSIGN:
|
case PLUSASSIGN:
|
||||||
arithmeticAssignement(true, false, true);
|
arithmeticAssignement(true, Assignment.WITH_POINTER_OPERATION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIVASSIGN:
|
case DIVASSIGN:
|
||||||
case STARASSIGN:
|
case STARASSIGN:
|
||||||
arithmeticAssignement(true, false, false);
|
arithmeticAssignement(true, Assignment.WITH_OPERATION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AMPERASSIGN:
|
case AMPERASSIGN:
|
||||||
|
@ -202,7 +205,7 @@ class BuiltinOperators {
|
||||||
case SHIFTLASSIGN:
|
case SHIFTLASSIGN:
|
||||||
case SHIFTRASSIGN:
|
case SHIFTRASSIGN:
|
||||||
case XORASSIGN:
|
case XORASSIGN:
|
||||||
arithmeticAssignement(false, false, false);
|
arithmeticAssignement(false, Assignment.WITH_OPERATION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AND:
|
case AND:
|
||||||
|
@ -474,53 +477,45 @@ class BuiltinOperators {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13.6-18, 13.6-29, 13.6-20, 13.6-22
|
// 13.6-18, 13.6-29, 13.6-20, 13.6-22
|
||||||
private void arithmeticAssignement(boolean fltPt, boolean self, boolean ptr) {
|
private static enum Assignment {WITHOUT_OPERATION, WITH_POINTER_OPERATION, WITH_OPERATION}
|
||||||
List<IType> p1= null, p2= null;
|
private void arithmeticAssignement(boolean fltPt, Assignment assign) {
|
||||||
|
|
||||||
IType[] types1= getClassConversionTypes(FIRST);
|
|
||||||
IType[] types2= getClassConversionTypes(SECOND);
|
IType[] types2= getClassConversionTypes(SECOND);
|
||||||
if (types1.length == 0 && types2.length == 0)
|
if (types2.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (IType t : types1) {
|
IType refType= SemanticUtil.getNestedType(fType1, TDEF);
|
||||||
p1 = addArithmeticRef(t, fltPt, p1, self, ptr);
|
if (refType instanceof ICPPReferenceType) {
|
||||||
}
|
IType t= SemanticUtil.getNestedType(((ICPPReferenceType) refType).getType(), TDEF);
|
||||||
p1= addArithmeticRef(fType1, fltPt, p1, false, false);
|
|
||||||
for (IType t : types2) {
|
|
||||||
p2 = addPromotedArithmetic(t, fltPt, p2);
|
|
||||||
}
|
|
||||||
p2= addPromotedArithmetic(fType2, fltPt, p2);
|
|
||||||
if (p1 == null || p2 == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (IType t1 : p1) {
|
|
||||||
for (IType t2 : p2) {
|
|
||||||
addFunction(t1, t1, t2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<IType> addArithmeticRef(IType t, boolean fltPt, List<IType> p1, boolean self, boolean ptr) {
|
|
||||||
final IType type= t= SemanticUtil.getNestedType(t, TDEF);
|
|
||||||
if (type instanceof ICPPReferenceType) {
|
|
||||||
t= SemanticUtil.getNestedType(((ICPPReferenceType) t).getType(), TDEF);
|
|
||||||
if (!SemanticUtil.getCVQualifier(t).isConst()) {
|
if (!SemanticUtil.getCVQualifier(t).isConst()) {
|
||||||
t = SemanticUtil.getNestedType(t, TDEF|CVTYPE);
|
switch(assign) {
|
||||||
|
case WITHOUT_OPERATION:
|
||||||
|
if (isEnumeration(t) || isPointerToMember(t) || isPointer(t)) {
|
||||||
|
addFunction(refType, refType, SemanticUtil.getNestedType(t, TDEF|ALLCVQ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WITH_POINTER_OPERATION:
|
||||||
|
if (isPointer(t)) {
|
||||||
|
addFunction(refType, refType, PTR_DIFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fltPt ? isArithmetic(t) : isIntegral(t)) {
|
if (fltPt ? isArithmetic(t) : isIntegral(t)) {
|
||||||
if (p1 == null) {
|
List<IType> p2= null;
|
||||||
p1= new ArrayList<IType>();
|
for (IType t2 : types2) {
|
||||||
|
p2 = addPromotedArithmetic(t2, fltPt, p2);
|
||||||
|
}
|
||||||
|
if (p2 != null) {
|
||||||
|
for (IType t2 : p2) {
|
||||||
|
addFunction(refType, refType, t2);
|
||||||
}
|
}
|
||||||
p1.add(type);
|
|
||||||
}
|
|
||||||
if (self && (isEnumeration(t) || isPointerToMember(t) || isPointer(t))) {
|
|
||||||
addFunction(type, type, SemanticUtil.getNestedType(t, TDEF|ALLCVQ));
|
|
||||||
}
|
|
||||||
if (ptr && isPointer(t)) {
|
|
||||||
addFunction(type, type, PTR_DIFF);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFunction(IType returnType, IType p1) {
|
private void addFunction(IType returnType, IType p1) {
|
||||||
|
@ -537,6 +532,16 @@ class BuiltinOperators {
|
||||||
String sig= ASTTypeUtil.getType(functionType, true);
|
String sig= ASTTypeUtil.getType(functionType, true);
|
||||||
if (fSignatures == null) {
|
if (fSignatures == null) {
|
||||||
fSignatures= new HashSet<String>();
|
fSignatures= new HashSet<String>();
|
||||||
|
if (fGlobalCandidates != null) {
|
||||||
|
for (Object cand : fGlobalCandidates) {
|
||||||
|
if (cand instanceof IFunction && !(cand instanceof ICPPMethod)) {
|
||||||
|
try {
|
||||||
|
fSignatures.add(ASTTypeUtil.getType(((IFunction)cand).getType(), true));
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fSignatures.add(sig)) {
|
if (fSignatures.add(sig)) {
|
||||||
for (int i = 0; i < parameterTypes.length; i++) {
|
for (int i = 0; i < parameterTypes.length; i++) {
|
||||||
|
|
|
@ -3090,7 +3090,7 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
||||||
ICPPFunction[] builtins= BuiltinOperators.create(operator, args, parent.getTranslationUnit());
|
ICPPFunction[] builtins= BuiltinOperators.create(operator, args, parent.getTranslationUnit(), (Object[]) funcData.foundItems);
|
||||||
mergeResults(funcData, builtins, false);
|
mergeResults(funcData, builtins, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue