mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 259927. Fix and test case.
This commit is contained in:
parent
89b260739c
commit
00d8f03ce2
5 changed files with 172 additions and 71 deletions
|
@ -6331,7 +6331,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
ICPPFunction f2= ba.assertNonProblem("func(*b)", 4, ICPPFunction.class);
|
||||
assertNotSame(f1, f2);
|
||||
}
|
||||
|
||||
|
||||
// struct C {int a;};
|
||||
// void myfunc(C c) {
|
||||
// return c < c.a ||
|
||||
|
@ -6346,4 +6346,32 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code);
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// int a;
|
||||
// };
|
||||
//
|
||||
// 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;
|
||||
// };
|
||||
//
|
||||
// void test(B p1, B p2) {
|
||||
// (p1 - p2).a; //1
|
||||
// (p1 + p2).a; //2
|
||||
// (p1 * p2).a; //3
|
||||
// (p1 / p2).a; //4
|
||||
// (p1 % p2).a; //5
|
||||
// }
|
||||
public void testOverloadedBinaryOperator_259927() 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.parser.IToken;
|
||||
|
||||
/**
|
||||
|
@ -66,7 +68,6 @@ public enum OverloadableOperator {
|
|||
DELETE("delete"),
|
||||
NEW_ARRAY("new[]");
|
||||
|
||||
|
||||
private final char[] rep;
|
||||
|
||||
private OverloadableOperator(String rep) {
|
||||
|
@ -78,59 +79,110 @@ public enum OverloadableOperator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the OverloadableOperator constant that corresponds to the
|
||||
* given token. Only works for operators that consist of one token.
|
||||
* Returns the OverloadableOperator constant that corresponds to
|
||||
* the given token. Only works for operators that consist of one token.
|
||||
*
|
||||
* @throws NullPointerException if token is null
|
||||
* @throws NullPointerException if {@code token} is {@code null}.
|
||||
*/
|
||||
public static OverloadableOperator valueOf(IToken token) {
|
||||
switch(token.getType()) {
|
||||
case IToken.t_delete: return DELETE;
|
||||
case IToken.t_new: return NEW;
|
||||
case IToken.tAMPER: return AMPER;
|
||||
case IToken.tAMPERASSIGN: return AMPERASSIGN;
|
||||
case IToken.tARROW: return ARROW;
|
||||
case IToken.tARROWSTAR: return ARROWSTAR;
|
||||
case IToken.tBITOR: return BITOR;
|
||||
case IToken.tBITORASSIGN: return BITORASSIGN;
|
||||
case IToken.tBITCOMPLEMENT: return BITCOMPLEMENT;
|
||||
case IToken.tSHIFTL: return SHIFTL;
|
||||
case IToken.tSHIFTLASSIGN: return SHIFTLASSIGN;
|
||||
case IToken.tSHIFTR: return SHIFTR;
|
||||
case IToken.tSHIFTRASSIGN: return SHIFTRASSIGN;
|
||||
case IToken.tXOR: return XOR;
|
||||
case IToken.tXORASSIGN: return XORASSIGN;
|
||||
|
||||
// logical operations
|
||||
case IToken.tNOT: return NOT;
|
||||
case IToken.tAND: return AND;
|
||||
case IToken.tOR: return OR;
|
||||
switch (token.getType()) {
|
||||
case IToken.t_delete: return DELETE;
|
||||
case IToken.t_new: return NEW;
|
||||
case IToken.tAMPER: return AMPER;
|
||||
case IToken.tAMPERASSIGN: return AMPERASSIGN;
|
||||
case IToken.tARROW: return ARROW;
|
||||
case IToken.tARROWSTAR: return ARROWSTAR;
|
||||
case IToken.tBITOR: return BITOR;
|
||||
case IToken.tBITORASSIGN: return BITORASSIGN;
|
||||
case IToken.tBITCOMPLEMENT: return BITCOMPLEMENT;
|
||||
case IToken.tSHIFTL: return SHIFTL;
|
||||
case IToken.tSHIFTLASSIGN: return SHIFTLASSIGN;
|
||||
case IToken.tSHIFTR: return SHIFTR;
|
||||
case IToken.tSHIFTRASSIGN: return SHIFTRASSIGN;
|
||||
case IToken.tXOR: return XOR;
|
||||
case IToken.tXORASSIGN: return XORASSIGN;
|
||||
|
||||
// logical operations
|
||||
case IToken.tNOT: return NOT;
|
||||
case IToken.tAND: return AND;
|
||||
case IToken.tOR: return OR;
|
||||
|
||||
// arithmetic
|
||||
case IToken.tDECR: return DECR;
|
||||
case IToken.tINCR: return INCR;
|
||||
case IToken.tDIV: return DIV;
|
||||
case IToken.tDIVASSIGN: return DIVASSIGN;
|
||||
case IToken.tMINUS: return MINUS;
|
||||
case IToken.tMINUSASSIGN: return MINUSASSIGN;
|
||||
case IToken.tMOD: return MOD;
|
||||
case IToken.tMODASSIGN: return MODASSIGN;
|
||||
case IToken.tPLUS: return PLUS;
|
||||
case IToken.tPLUSASSIGN: return PLUSASSIGN;
|
||||
case IToken.tSTAR: return STAR;
|
||||
case IToken.tSTARASSIGN: return STARASSIGN;
|
||||
|
||||
// comparison
|
||||
case IToken.tEQUAL: return EQUAL;
|
||||
case IToken.tNOTEQUAL: return NOTEQUAL;
|
||||
case IToken.tGT: return GT;
|
||||
case IToken.tGTEQUAL: return GTEQUAL;
|
||||
case IToken.tLT: return LT;
|
||||
case IToken.tLTEQUAL: return LTEQUAL;
|
||||
|
||||
// other
|
||||
case IToken.tASSIGN: return ASSIGN;
|
||||
case IToken.tCOMMA: return COMMA;
|
||||
// arithmetic
|
||||
case IToken.tDECR: return DECR;
|
||||
case IToken.tINCR: return INCR;
|
||||
case IToken.tDIV: return DIV;
|
||||
case IToken.tDIVASSIGN: return DIVASSIGN;
|
||||
case IToken.tMINUS: return MINUS;
|
||||
case IToken.tMINUSASSIGN: return MINUSASSIGN;
|
||||
case IToken.tMOD: return MOD;
|
||||
case IToken.tMODASSIGN: return MODASSIGN;
|
||||
case IToken.tPLUS: return PLUS;
|
||||
case IToken.tPLUSASSIGN: return PLUSASSIGN;
|
||||
case IToken.tSTAR: return STAR;
|
||||
case IToken.tSTARASSIGN: return STARASSIGN;
|
||||
|
||||
// comparison
|
||||
case IToken.tEQUAL: return EQUAL;
|
||||
case IToken.tNOTEQUAL: return NOTEQUAL;
|
||||
case IToken.tGT: return GT;
|
||||
case IToken.tGTEQUAL: return GTEQUAL;
|
||||
case IToken.tLT: return LT;
|
||||
case IToken.tLTEQUAL: return LTEQUAL;
|
||||
|
||||
// other
|
||||
case IToken.tASSIGN: return ASSIGN;
|
||||
case IToken.tCOMMA: return COMMA;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the OverloadableOperator constant that corresponds to
|
||||
* the given binary expression.
|
||||
*
|
||||
* @throws NullPointerException if {@code expression} is {@code null}.
|
||||
*/
|
||||
public static OverloadableOperator fromBinaryExpression(IASTBinaryExpression expression) {
|
||||
switch (expression.getOperator()) {
|
||||
case IASTBinaryExpression.op_binaryAnd: return AMPER;
|
||||
case IASTBinaryExpression.op_binaryAndAssign: return AMPERASSIGN;
|
||||
case IASTBinaryExpression.op_pmarrow: return ARROW;
|
||||
case IASTBinaryExpression.op_binaryOr: return BITOR;
|
||||
case IASTBinaryExpression.op_binaryOrAssign: return BITORASSIGN;
|
||||
case IASTBinaryExpression.op_shiftLeft: return SHIFTL;
|
||||
case IASTBinaryExpression.op_shiftLeftAssign: return SHIFTLASSIGN;
|
||||
case IASTBinaryExpression.op_shiftRight: return SHIFTR;
|
||||
case IASTBinaryExpression.op_shiftRightAssign: return SHIFTRASSIGN;
|
||||
case IASTBinaryExpression.op_binaryXor: return XOR;
|
||||
case IASTBinaryExpression.op_binaryXorAssign: return XORASSIGN;
|
||||
|
||||
// logical operations
|
||||
case IASTBinaryExpression.op_logicalAnd: return AND;
|
||||
case IASTBinaryExpression.op_logicalOr: return OR;
|
||||
|
||||
// arithmetic
|
||||
case IASTBinaryExpression.op_divide: return DIV;
|
||||
case IASTBinaryExpression.op_divideAssign: return DIVASSIGN;
|
||||
case IASTBinaryExpression.op_minus: return MINUS;
|
||||
case IASTBinaryExpression.op_minusAssign: return MINUSASSIGN;
|
||||
case IASTBinaryExpression.op_modulo: return MOD;
|
||||
case IASTBinaryExpression.op_moduloAssign: return MODASSIGN;
|
||||
case IASTBinaryExpression.op_plus: return PLUS;
|
||||
case IASTBinaryExpression.op_plusAssign: return PLUSASSIGN;
|
||||
case IASTBinaryExpression.op_multiply: return STAR;
|
||||
case IASTBinaryExpression.op_multiplyAssign: return STARASSIGN;
|
||||
|
||||
// comparison
|
||||
case IASTBinaryExpression.op_equals: return EQUAL;
|
||||
case IASTBinaryExpression.op_notequals: return NOTEQUAL;
|
||||
case IASTBinaryExpression.op_greaterThan: return GT;
|
||||
case IASTBinaryExpression.op_greaterEqual: return GTEQUAL;
|
||||
case IASTBinaryExpression.op_lessThan: return LT;
|
||||
case IASTBinaryExpression.op_lessEqual: return LTEQUAL;
|
||||
|
||||
// other
|
||||
case IASTBinaryExpression.op_assign: return ASSIGN;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -2574,6 +2574,16 @@ public class CPPSemantics {
|
|||
} else {
|
||||
data.functionParameters = new IASTExpression[] {paramExpression};
|
||||
}
|
||||
} else if (exp instanceof IASTBinaryExpression) {
|
||||
final IASTBinaryExpression binary = (IASTBinaryExpression) exp;
|
||||
OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(binary);
|
||||
if (operator == null) {
|
||||
return null;
|
||||
}
|
||||
astName.setName(operator.toCharArray());
|
||||
data = new LookupData(astName);
|
||||
data.forceQualified = true;
|
||||
data.functionParameters = new IASTExpression[] { binary.getOperand2() };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1876,6 +1876,33 @@ public class CPPVisitor extends ASTQueries {
|
|||
}
|
||||
} else if (expression instanceof IASTBinaryExpression) {
|
||||
final IASTBinaryExpression binary = (IASTBinaryExpression) expression;
|
||||
|
||||
// Check for overloaded operator.
|
||||
IType type1 = getExpressionType(binary.getOperand1());
|
||||
while (type1 instanceof ITypedef) {
|
||||
try {
|
||||
type1 = ((ITypedef) type1).getType();
|
||||
} catch (DOMException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
return operator.getType().getReturnType();
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
|
||||
final int op = binary.getOperator();
|
||||
switch (op) {
|
||||
case IASTBinaryExpression.op_lessEqual:
|
||||
|
|
|
@ -18,26 +18,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.*;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||
|
@ -372,6 +353,9 @@ class LookupData {
|
|||
if (tempNameParent instanceof IASTFunctionCallExpression) {
|
||||
return CPPVisitor.getExpressionType(((IASTFunctionCallExpression) tempNameParent).getFunctionNameExpression());
|
||||
}
|
||||
if (tempNameParent instanceof IASTBinaryExpression) {
|
||||
return CPPVisitor.getExpressionType(((IASTBinaryExpression) tempNameParent).getOperand1());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (prop == IASTFieldReference.FIELD_NAME) {
|
||||
|
|
Loading…
Add table
Reference in a new issue