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 a298da40e4e..a3c6228f048 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 @@ -6352,11 +6352,11 @@ public class AST2CPPTests extends AST2BaseTest { // }; // // struct B { - // A operator-(B b2); - // A operator+(B& b2); - // A operator*(const B& b2); - // A operator/(B b2) const; - // A operator%(const B& b2) const; + // A operator-(B b); + // A operator+(B& b); + // A operator*(const B& b); + // A operator/(B b) const; + // A operator%(const B& b) const; // }; // // void test(B p1, B p2) { @@ -6366,7 +6366,7 @@ public class AST2CPPTests extends AST2BaseTest { // (p1 / p2).a; //4 // (p1 % p2).a; //5 // } - public void testOverloadedBinaryOperator_259927() throws Exception { + public void testOverloadedBinaryOperator_259927_1() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); ba.assertNonProblem("a; //1", 1, ICPPField.class); ba.assertNonProblem("a; //2", 1, ICPPField.class); @@ -6374,6 +6374,36 @@ public class AST2CPPTests extends AST2BaseTest { ba.assertNonProblem("a; //4", 1, ICPPField.class); ba.assertNonProblem("a; //5", 1, ICPPField.class); } + + // struct A { + // int a; + // }; + // struct B {}; + // enum E { zero }; + // + // A operator-(B p1, int p2); + // A operator+(int p1, const B& p2); + // A operator*(E p1, int p2); + // A operator/(int p1, const E& p2); + // A operator%(const B& p1, const B& p2); + // + // void test(B b, E e, int i) { + // (b - i).a; //1 + // (i + b).a; //2 + // (e * i).a; //3 + // (i / e).a; //4 + // (b % b).a; //5 + // (b + i).a; //6 + // } + public void testOverloadedBinaryOperator_259927_2() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ba.assertNonProblem("a; //1", 1, ICPPField.class); + ba.assertNonProblem("a; //2", 1, ICPPField.class); + ba.assertNonProblem("a; //3", 1, ICPPField.class); + ba.assertNonProblem("a; //4", 1, ICPPField.class); + ba.assertNonProblem("a; //5", 1, ICPPField.class); + ba.assertProblem("a; //6", 1); + } // int a,b,c,d ; // class X { 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 08fc2e124ca..4e238e1e034 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 @@ -2480,7 +2480,7 @@ public class CPPSemantics { CPPASTName astName = new CPPASTName(); astName.setParent(exp); astName.setPropertyInParent(STRING_LOOKUP_PROPERTY); - LookupData data = null; + LookupData data; if (exp instanceof IASTUnaryExpression) { astName.setName(OverloadableOperator.STAR.toCharArray()); @@ -2532,8 +2532,41 @@ public class CPPSemantics { } return null; } - - public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException{ + + /** + * Returns the overloaded operator corresponding to a binary expression, or {@code null} + * if no such operator is found. + * @param exp a binary expression + * @return the overloaded operator, or {@code null}. + */ + public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) { + OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(exp); + if (operator == null) { + return null; + } + + IScope scope = CPPVisitor.getContainingScope(exp); + if (scope == null) + return null; + + CPPASTName astName = new CPPASTName(); + astName.setParent(exp); + astName.setPropertyInParent(STRING_LOOKUP_PROPERTY); + astName.setName(operator.toCharArray()); + LookupData data = new LookupData(astName); + data.functionParameters = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() }; + + try { + lookup(data, scope); + IBinding binding = resolveAmbiguities(data, astName); + if (binding instanceof ICPPFunction) + return (ICPPFunction) binding; + } catch (DOMException e) { + } + return null; + } + + public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException{ return findBindings(scope, name.toCharArray(), qualified, null); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index cabe31709fc..53c92d60ddd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -1865,28 +1865,36 @@ public class CPPVisitor extends ASTQueries { // Check for overloaded operator. IType type1 = getExpressionType(binary.getOperand1()); - while (type1 instanceof ITypedef) { - try { - type1 = ((ITypedef) type1).getType(); - } catch (DOMException e) { - break; - } + IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1); + if (ultimateType1 instanceof IProblemBinding) { + return type1; } - try { - if (type1 instanceof ICPPReferenceType) { - type1 = ((ICPPReferenceType) type1).getType(); - } - if (type1 instanceof IQualifierType) { - type1 = ((IQualifierType) type1).getType(); - } - if (type1 instanceof ICPPClassType) { - ICPPFunction operator= CPPSemantics.findOperator(expression, (ICPPClassType) type1); - if (operator != null) { + if (ultimateType1 instanceof ICPPClassType) { + ICPPFunction operator= CPPSemantics.findOperator(expression, (ICPPClassType) ultimateType1); + if (operator != null) { + try { return operator.getType().getReturnType(); + } catch (DOMException e) { + return e.getProblem(); + } + } + } + IType type2 = getExpressionType(binary.getOperand2()); + IType ultimateType2 = SemanticUtil.getUltimateTypeUptoPointers(type2); + if (ultimateType2 instanceof IProblemBinding) { + return type2; + } + if (ultimateType1 instanceof ICPPClassType || ultimateType1 instanceof IEnumeration || + ultimateType2 instanceof ICPPClassType || ultimateType2 instanceof IEnumeration) { + // If at least one of the types is user defined, the operator can be overloaded. + ICPPFunction operator = CPPSemantics.findOverloadedOperator(binary); + if (operator != null) { + try { + return operator.getType().getReturnType(); + } catch (DOMException e) { + return e.getProblem(); } } - } catch (DOMException e) { - return e.getProblem(); } final int op = binary.getOperator(); @@ -1903,16 +1911,13 @@ public class CPPVisitor extends ASTQueries { basicType.setFromExpression(expression); return basicType; case IASTBinaryExpression.op_plus: - IType t2 = getExpressionType(binary.getOperand2()); - if (SemanticUtil.getUltimateTypeViaTypedefs(t2) instanceof IPointerType) { - return t2; + if (ultimateType2 instanceof IPointerType) { + return ultimateType2; } break; case IASTBinaryExpression.op_minus: - t2= getExpressionType(binary.getOperand2()); - if (SemanticUtil.getUltimateTypeViaTypedefs(t2) instanceof IPointerType) { - IType t1 = getExpressionType(binary.getOperand1()); - if (SemanticUtil.getUltimateTypeViaTypedefs(t1) instanceof IPointerType) { + if (ultimateType2 instanceof IPointerType) { + if (ultimateType1 instanceof IPointerType) { IScope scope = getContainingScope(expression); try { IBinding[] bs= CPPSemantics.findBindings(scope, PTRDIFF_T, false, expression); @@ -1929,22 +1934,22 @@ public class CPPVisitor extends ASTQueries { basicType.setFromExpression(expression); return basicType; } - return t1; + return ultimateType1; } break; case ICPPASTBinaryExpression.op_pmarrow: case ICPPASTBinaryExpression.op_pmdot: - IType type = getExpressionType(((IASTBinaryExpression) expression).getOperand2()); - if (type instanceof ICPPPointerToMemberType) { + if (type2 instanceof ICPPPointerToMemberType) { try { - return ((ICPPPointerToMemberType) type).getType(); + return ((ICPPPointerToMemberType) type2).getType(); } catch (DOMException e) { return e.getProblem(); } } - return new ProblemBinding(binary, IProblemBinding.SEMANTIC_INVALID_TYPE, new char[0]); + return new ProblemBinding(binary, IProblemBinding.SEMANTIC_INVALID_TYPE, + expression.getRawSignature().toCharArray()); } - return getExpressionType(((IASTBinaryExpression) expression).getOperand1()); + return type1; } else if (expression instanceof IASTUnaryExpression) { final int op= ((IASTUnaryExpression) expression).getOperator(); switch (op) { @@ -1955,21 +1960,14 @@ public class CPPVisitor extends ASTQueries { } IType type = getExpressionType(((IASTUnaryExpression) expression).getOperand()); - while (type instanceof ITypedef) { - try { - type = ((ITypedef) type).getType(); - } catch (DOMException e) { - break; - } - } + type = SemanticUtil.getUltimateTypeViaTypedefs(type); + if (op == IASTUnaryExpression.op_star) { try { - if (type instanceof ICPPReferenceType) { - type = ((ICPPReferenceType) type).getType(); - } - if (type instanceof IQualifierType) { - type = ((IQualifierType) type).getType(); - } + type = SemanticUtil.getUltimateTypeUptoPointers(type); + if (type instanceof IProblemBinding) { + return type; + } if (type instanceof ICPPClassType) { ICPPFunction operator= CPPSemantics.findOperator(expression, (ICPPClassType) type); if (operator != null) {