mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-30 21:55:31 +02:00
bug 265982, support for overloaded unary operators
This commit is contained in:
parent
b718c89802
commit
49891dac3a
5 changed files with 241 additions and 55 deletions
|
@ -6425,6 +6425,108 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
ba.assertProblem("a; //6", 1);
|
||||
}
|
||||
|
||||
|
||||
// struct A {
|
||||
// int x;
|
||||
// };
|
||||
//
|
||||
// struct B {
|
||||
// A& operator++(); // prefix
|
||||
// A operator++(int); // postfix
|
||||
// };
|
||||
//
|
||||
// void test(B p1, B p2) {
|
||||
// (p1++).x; //1
|
||||
// (++p1).x; //2
|
||||
// }
|
||||
public void testOverloadedUnaryOperator_259927_3() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
||||
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
||||
}
|
||||
|
||||
|
||||
// struct A {
|
||||
// int x;
|
||||
// };
|
||||
// struct B { };
|
||||
// A& operator++(B); // prefix
|
||||
// A operator++(B, int); // postfix
|
||||
//
|
||||
// void test(B p1, B p2) {
|
||||
// (p1++).x; //1
|
||||
// (++p1).x; //2
|
||||
// }
|
||||
public void testOverloadedUnaryOperator_259927_4() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
||||
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
||||
}
|
||||
|
||||
|
||||
// struct A {
|
||||
// int xx;
|
||||
// };
|
||||
//
|
||||
//
|
||||
// struct B {
|
||||
// A operator*();
|
||||
// A operator&();
|
||||
// A operator+();
|
||||
// A operator-();
|
||||
// A operator!();
|
||||
// A operator~();
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// B b;
|
||||
//
|
||||
// (*b).xx; // 1
|
||||
// (&b).xx; // 2
|
||||
// (+b).xx; // 3
|
||||
// (-b).xx; // 4
|
||||
// (!b).xx; // 5
|
||||
// (~b).xx; // 6
|
||||
// }
|
||||
public void testOverloadedUnaryOperator_259927_5() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
for(int i = 1; i <=6; i++)
|
||||
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// int xx;
|
||||
// };
|
||||
//
|
||||
//
|
||||
// struct B {
|
||||
// };
|
||||
//
|
||||
// A operator*(B);
|
||||
// A operator&(B);
|
||||
// A operator+(B);
|
||||
// A operator-(B);
|
||||
// A operator!(B);
|
||||
// A operator~(B);
|
||||
//
|
||||
// int main() {
|
||||
// B b;
|
||||
//
|
||||
// (*b).xx; // 1
|
||||
// (&b).xx; // 2
|
||||
// (+b).xx; // 3
|
||||
// (-b).xx; // 4
|
||||
// (!b).xx; // 5
|
||||
// (~b).xx; // 6
|
||||
//}
|
||||
public void testOverloadedUnaryOperator_259927_6() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
for(int i = 1; i <=6; i++)
|
||||
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// int a,b,c,d ;
|
||||
// class X {
|
||||
// void m() {
|
||||
|
|
|
@ -26,6 +26,9 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
|||
*/
|
||||
public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralExpression {
|
||||
|
||||
public static final CPPASTLiteralExpression INT_ZERO = new CPPASTLiteralExpression(lk_integer_constant, new char[] {'0'} );
|
||||
|
||||
|
||||
private int kind;
|
||||
private char[] value = CharArrayUtils.EMPTY;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2009 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* All rights reserved. This program and the accompanying masterials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
|
@ -8,12 +8,11 @@
|
|||
* Contributors:
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Sergey Prigogin (Google)
|
||||
* Mike Kucera (IBM)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVQ;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
|
@ -122,39 +121,14 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
return CPPVisitor.get_SIZE_T(this);
|
||||
case IASTUnaryExpression.op_typeid:
|
||||
return CPPVisitor.get_type_info(this);
|
||||
case IASTUnaryExpression.op_not:
|
||||
return new CPPBasicType(ICPPBasicType.t_bool, 0);
|
||||
}
|
||||
|
||||
final IASTExpression operand = getOperand();
|
||||
if (op == IASTUnaryExpression.op_star) {
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
|
||||
if (type instanceof IProblemBinding) {
|
||||
return type;
|
||||
}
|
||||
try {
|
||||
if (type instanceof ICPPClassType) {
|
||||
ICPPFunction operator= CPPSemantics.findOperator(this, (ICPPClassType) type);
|
||||
if (operator != null) {
|
||||
return operator.getType().getReturnType();
|
||||
}
|
||||
} else if (type instanceof IPointerType || type instanceof IArrayType) {
|
||||
return ((ITypeContainer) type).getType();
|
||||
} else if (type instanceof ICPPUnknownType) {
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
return new ProblemBinding(this, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
this.getRawSignature().toCharArray());
|
||||
}
|
||||
if (op == IASTUnaryExpression.op_amper) {
|
||||
|
||||
if (op == IASTUnaryExpression.op_amper) { // check for pointer to member
|
||||
IASTNode child= operand;
|
||||
boolean inParenthesis= false;
|
||||
while (child instanceof IASTUnaryExpression &&
|
||||
((IASTUnaryExpression) child).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
while (child instanceof IASTUnaryExpression && ((IASTUnaryExpression) child).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
child= ((IASTUnaryExpression) child).getOperand();
|
||||
inParenthesis= true;
|
||||
}
|
||||
|
@ -165,13 +139,11 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
ICPPMember member= (ICPPMember) b;
|
||||
try {
|
||||
if (name instanceof ICPPASTQualifiedName) {
|
||||
if (!member.isStatic()) {
|
||||
if (!member.isStatic()) { // so if the member is static it will fall through
|
||||
if (!inParenthesis) {
|
||||
return new CPPPointerToMemberType(member.getType(), member.getClassOwner(),
|
||||
false, false);
|
||||
return new CPPPointerToMemberType(member.getType(), member.getClassOwner(), false, false);
|
||||
} else if (member instanceof IFunction) {
|
||||
return new ProblemBinding(operand, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
operand.getRawSignature().toCharArray());
|
||||
return new ProblemBinding(operand, IProblemBinding.SEMANTIC_INVALID_TYPE, operand.getRawSignature().toCharArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,14 +155,75 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF);
|
||||
|
||||
IType operator = findOperatorReturnType(type);
|
||||
if(operator != null)
|
||||
return operator;
|
||||
|
||||
return new CPPPointerType(type);
|
||||
}
|
||||
|
||||
|
||||
if (op == IASTUnaryExpression.op_star) {
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
|
||||
if (type instanceof IProblemBinding) {
|
||||
return type;
|
||||
}
|
||||
try {
|
||||
IType operator = findOperatorReturnType(type);
|
||||
if(operator != null) {
|
||||
return operator;
|
||||
} else if (type instanceof IPointerType || type instanceof IArrayType) {
|
||||
return ((ITypeContainer) type).getType();
|
||||
} else if (type instanceof ICPPUnknownType) {
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
return new ProblemBinding(this, IProblemBinding.SEMANTIC_INVALID_TYPE, this.getRawSignature().toCharArray());
|
||||
}
|
||||
|
||||
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF);
|
||||
IType operator = findOperatorReturnType(type);
|
||||
if(operator != null) {
|
||||
return operator;
|
||||
}
|
||||
|
||||
if(op == IASTUnaryExpression.op_not) {
|
||||
return new CPPBasicType(ICPPBasicType.t_bool, 0);
|
||||
}
|
||||
if (type instanceof CPPBasicType) {
|
||||
((CPPBasicType) type).setFromExpression(this);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
private IType findOperatorReturnType(IType type) {
|
||||
ICPPFunction operatorFunction = findOperatorFunction(type);
|
||||
if(operatorFunction != null) {
|
||||
try {
|
||||
return operatorFunction.getType().getReturnType();
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private ICPPFunction findOperatorFunction(IType type) {
|
||||
if(type instanceof ICPPClassType) {
|
||||
ICPPFunction operator = CPPSemantics.findOperator(this, (ICPPClassType) type);
|
||||
if(operator != null)
|
||||
return operator;
|
||||
return CPPSemantics.findOverloadedOperator(this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Mike Kucera (IBM)
|
||||
* 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.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.parser.IToken;
|
||||
|
||||
/**
|
||||
|
@ -19,8 +21,6 @@ import org.eclipse.cdt.core.parser.IToken;
|
|||
*
|
||||
* Note: toString() has not been overridden, use toCharArray() to get
|
||||
* a character representation of the operator.
|
||||
*
|
||||
* @author Mike Kucera
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
public enum OverloadableOperator {
|
||||
|
@ -187,4 +187,20 @@ public enum OverloadableOperator {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static OverloadableOperator fromUnaryExpression(IASTUnaryExpression expression) {
|
||||
switch(expression.getOperator()) {
|
||||
case IASTUnaryExpression.op_prefixIncr: return INCR;
|
||||
case IASTUnaryExpression.op_prefixDecr: return DECR;
|
||||
case IASTUnaryExpression.op_plus: return PLUS;
|
||||
case IASTUnaryExpression.op_minus: return MINUS;
|
||||
case IASTUnaryExpression.op_star: return STAR;
|
||||
case IASTUnaryExpression.op_amper: return AMPER;
|
||||
case IASTUnaryExpression.op_tilde: return BITCOMPLEMENT;
|
||||
case IASTUnaryExpression.op_not: return NOT;
|
||||
case IASTUnaryExpression.op_postFixIncr: return INCR;
|
||||
case IASTUnaryExpression.op_postFixDecr: return DECR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,11 @@
|
|||
* Bryan Wilkinson (QNX)
|
||||
* Andrew Ferguson (Symbian)
|
||||
* Sergey Prigogin (Google)
|
||||
* Mike Kucera (IBM)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -142,6 +140,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||
|
@ -2493,12 +2492,7 @@ public class CPPSemantics {
|
|||
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||
LookupData data;
|
||||
|
||||
if (exp instanceof IASTUnaryExpression) {
|
||||
astName.setName(OverloadableOperator.STAR.toCharArray());
|
||||
data = new LookupData(astName);
|
||||
data.forceQualified = true;
|
||||
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
|
||||
} else if (exp instanceof IASTArraySubscriptExpression) {
|
||||
if (exp instanceof IASTArraySubscriptExpression) {
|
||||
astName.setName(OverloadableOperator.BRACKET.toCharArray());
|
||||
data = new LookupData(astName);
|
||||
data.forceQualified = true;
|
||||
|
@ -2523,6 +2517,20 @@ public class CPPSemantics {
|
|||
data = new LookupData(astName);
|
||||
data.forceQualified = true;
|
||||
data.setFunctionArguments(new IASTExpression[] { binary.getOperand2() });
|
||||
} else if (exp instanceof IASTUnaryExpression) {
|
||||
IASTUnaryExpression unary = (IASTUnaryExpression) exp;
|
||||
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(unary);
|
||||
if(operator == null) {
|
||||
return null;
|
||||
}
|
||||
astName.setName(operator.toCharArray());
|
||||
data = new LookupData(astName);
|
||||
data.forceQualified = true;
|
||||
int op = unary.getOperator();
|
||||
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr)
|
||||
data.setFunctionArguments(new IASTExpression[] { CPPASTLiteralExpression.INT_ZERO });
|
||||
else
|
||||
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -2545,6 +2553,30 @@ public class CPPSemantics {
|
|||
*/
|
||||
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
||||
OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(exp);
|
||||
IASTExpression[] args = { exp.getOperand1(), exp.getOperand2() };
|
||||
return findOverloadedOperator(exp, operator, args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the overloaded operator corresponding to a unary expression, or {@code null}
|
||||
* if no such operator is found.
|
||||
*/
|
||||
public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) {
|
||||
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(exp);
|
||||
|
||||
IASTExpression[] args = null;
|
||||
int op = exp.getOperator();
|
||||
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr)
|
||||
args = new IASTExpression[] { exp.getOperand(), CPPASTLiteralExpression.INT_ZERO };
|
||||
else
|
||||
args = new IASTExpression[] { exp.getOperand() };
|
||||
|
||||
return findOverloadedOperator(exp, operator, args);
|
||||
}
|
||||
|
||||
|
||||
private static ICPPFunction findOverloadedOperator(IASTExpression exp, OverloadableOperator operator, IASTExpression[] args) {
|
||||
if (operator == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -2558,18 +2590,18 @@ public class CPPSemantics {
|
|||
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||
astName.setName(operator.toCharArray());
|
||||
LookupData data = new LookupData(astName);
|
||||
data.setFunctionArguments(new IASTExpression[] {exp.getOperand1(), exp.getOperand2()});
|
||||
|
||||
data.setFunctionArguments(args);
|
||||
|
||||
try {
|
||||
lookup(data, scope);
|
||||
IBinding binding = resolveAmbiguities(data, astName);
|
||||
if (binding instanceof ICPPFunction)
|
||||
return (ICPPFunction) binding;
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
} catch (DOMException e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException {
|
||||
return findBindings(scope, name.toCharArray(), qualified, null);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue