1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 09:46:02 +02:00

Bug 259927. Fix and test case.

This commit is contained in:
Sergey Prigogin 2009-01-18 00:24:17 +00:00
parent ff95da70c2
commit 07fe9a9e75
3 changed files with 114 additions and 53 deletions

View file

@ -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 {

View file

@ -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);
}

View file

@ -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) {