1
0
Fork 0
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:
Mike Kucera 2009-02-24 17:49:37 +00:00
parent b718c89802
commit 49891dac3a
5 changed files with 241 additions and 55 deletions

View file

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

View file

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

View file

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

View file

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

View file

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