diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java index 0ca7cea5bd4..70f6b939bcf 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java @@ -8,6 +8,7 @@ * Contributors: * Mike Kucera (IBM) * Sergey Prigogin (Google) + * Markus Schorn (Wind River Systems) *******************************************************************************/ 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); 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()); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index a11985d0718..78a01fe8cdd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -8575,7 +8575,7 @@ public class AST2CPPTests extends AST2BaseTest { // C c; // 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(); parseAndCheckBindings(code); BindingAssertionHelper bh= new BindingAssertionHelper(code, true); @@ -8583,4 +8583,22 @@ public class AST2CPPTests extends AST2BaseTest { IFunction f= bh.assertNonProblem("f(c+1)", 1); 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); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index b3c6b69fd7f..a328197b8ee 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -5872,7 +5872,7 @@ public class AST2Tests extends AST2BaseTest { IASTTranslationUnit tu= parse(code, lang, false, true, true); long diff= memoryUsed()-mem; // 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(tu.isFrozen()); } diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 324595efe70..c20d23180e4 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -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.browser;x-friends:="org.eclipse.cdt.ui", 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.c;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.dom.parser.cpp;x-friends:="org.eclipse.cdt.ui", diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java index b4f097574f2..56a38ea8290 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java @@ -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.Kind; 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.IPointerType; 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 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) return EMPTY; - return new BuiltinOperators(operator, args, tu.getScope()).create(); + return new BuiltinOperators(operator, args, tu.getScope(), globCandidates).create(); } private final OverloadableOperator fOperator; @@ -72,11 +73,13 @@ class BuiltinOperators { private IScope fFileScope; private List fResult; private Set fSignatures; + private Object[] fGlobalCandidates; - BuiltinOperators(OverloadableOperator operator, IASTInitializerClause[] args, IScope fileScope) { + BuiltinOperators(OverloadableOperator operator, IASTInitializerClause[] args, IScope fileScope, Object[] globCandidates) { fFileScope= fileScope; fOperator= operator; fUnary= args.length<2; + fGlobalCandidates= globCandidates; if (args.length > 0 && args[0] instanceof IASTExpression) { IType type= ((IASTExpression) args[0]).getExpressionType(); if (!(type instanceof IProblemBinding)) @@ -183,17 +186,17 @@ class BuiltinOperators { break; case ASSIGN: - arithmeticAssignement(true, true, false); + arithmeticAssignement(true, Assignment.WITHOUT_OPERATION); break; case MINUSASSIGN: case PLUSASSIGN: - arithmeticAssignement(true, false, true); + arithmeticAssignement(true, Assignment.WITH_POINTER_OPERATION); break; case DIVASSIGN: case STARASSIGN: - arithmeticAssignement(true, false, false); + arithmeticAssignement(true, Assignment.WITH_OPERATION); break; case AMPERASSIGN: @@ -202,7 +205,7 @@ class BuiltinOperators { case SHIFTLASSIGN: case SHIFTRASSIGN: case XORASSIGN: - arithmeticAssignement(false, false, false); + arithmeticAssignement(false, Assignment.WITH_OPERATION); break; case AND: @@ -474,55 +477,47 @@ class BuiltinOperators { } // 13.6-18, 13.6-29, 13.6-20, 13.6-22 - private void arithmeticAssignement(boolean fltPt, boolean self, boolean ptr) { - List p1= null, p2= null; - - IType[] types1= getClassConversionTypes(FIRST); + private static enum Assignment {WITHOUT_OPERATION, WITH_POINTER_OPERATION, WITH_OPERATION} + private void arithmeticAssignement(boolean fltPt, Assignment assign) { IType[] types2= getClassConversionTypes(SECOND); - if (types1.length == 0 && types2.length == 0) + if (types2.length == 0) return; - for (IType t : types1) { - p1 = addArithmeticRef(t, fltPt, p1, self, ptr); - } - 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); + IType refType= SemanticUtil.getNestedType(fType1, TDEF); + if (refType instanceof ICPPReferenceType) { + IType t= SemanticUtil.getNestedType(((ICPPReferenceType) refType).getType(), TDEF); + if (!SemanticUtil.getCVQualifier(t).isConst()) { + 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)) { + List p2= null; + for (IType t2 : types2) { + p2 = addPromotedArithmetic(t2, fltPt, p2); + } + if (p2 != null) { + for (IType t2 : p2) { + addFunction(refType, refType, t2); + } + } + } + } } - private List addArithmeticRef(IType t, boolean fltPt, List 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()) { - t = SemanticUtil.getNestedType(t, TDEF|CVTYPE); - if (fltPt ? isArithmetic(t) : isIntegral(t)) { - if (p1 == null) { - p1= new ArrayList(); - } - 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) { addFunction(returnType, new IType[] {p1}); } @@ -537,6 +532,16 @@ class BuiltinOperators { String sig= ASTTypeUtil.getType(functionType, true); if (fSignatures == null) { fSignatures= new HashSet(); + 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)) { for (int i = 0; i < parameterTypes.length; i++) { 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 76ce81c9c0d..700be8c0413 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 @@ -3090,7 +3090,7 @@ public class CPPSemantics { } 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); }