mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-08 08:45:44 +02:00
Bug 294543: Built-in candidates for overloaded operators.
This commit is contained in:
parent
59ab06fad1
commit
a7397911f1
14 changed files with 738 additions and 113 deletions
|
@ -402,10 +402,10 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
|
||||||
// X* xs = new X[5];
|
// X* xs = new X[5];
|
||||||
// delete[] x;
|
// delete[] x;
|
||||||
// }
|
// }
|
||||||
public void _testImplicitNewAndDelete() throws Exception {
|
public void testImplicitNewAndDelete() throws Exception {
|
||||||
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
|
||||||
ba.assertNoImplicitName("new X", 3);
|
ba.assertNoImplicitName("new X", 3);
|
||||||
ba.assertNoImplicitName("delete[]", 6); // fails because its picking up the implicit global delete[]
|
ba.assertNoImplicitName("delete[]", 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// typedef long unsigned int size_t
|
// typedef long unsigned int size_t
|
||||||
|
|
|
@ -8562,4 +8562,25 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
String code= getAboveComment();
|
String code= getAboveComment();
|
||||||
parseAndCheckBindings(code);
|
parseAndCheckBindings(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct D {};
|
||||||
|
// struct C {
|
||||||
|
// operator D();
|
||||||
|
// operator char();
|
||||||
|
// };
|
||||||
|
// long operator+(D d, char a);
|
||||||
|
// void f(long);
|
||||||
|
// void f(int);
|
||||||
|
// void xx() {
|
||||||
|
// C c;
|
||||||
|
// f(c+1); // converts c to a char and calls operator+(int, int)
|
||||||
|
// }
|
||||||
|
public void testBuiltinOperators_294543() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
parseAndCheckBindings(code);
|
||||||
|
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||||
|
IFunction fint= bh.assertNonProblem("f(int)", 1);
|
||||||
|
IFunction f= bh.assertNonProblem("f(c+1)", 1);
|
||||||
|
assertSame(fint, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<component id="org.eclipse.cdt.core" version="2">
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/dom/ast/IASTImplicitName.java" type="org.eclipse.cdt.core.dom.ast.IASTImplicitName">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTImplicitName"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/dom/ast/IASTImplicitNameOwner.java" type="org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTArraySubscriptExpression.java" type="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTExpressionList.java" type="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionCallExpression.java" type="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
<resource path="parser/org/eclipse/cdt/core/parser/IInactiveCodeToken.java" type="org.eclipse.cdt.core.parser.IInactiveCodeToken">
|
|
||||||
<filter id="403853384">
|
|
||||||
<message_arguments>
|
|
||||||
<message_argument value="org.eclipse.cdt.core.parser.IInactiveCodeToken"/>
|
|
||||||
</message_arguments>
|
|
||||||
</filter>
|
|
||||||
</resource>
|
|
||||||
</component>
|
|
|
@ -96,7 +96,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (implicitNames == null) {
|
if (implicitNames == null) {
|
||||||
ICPPFunction overload = getOverload();
|
ICPPFunction overload = getOverload();
|
||||||
if (overload == null)
|
if (overload == null || overload instanceof CPPImplicitFunction)
|
||||||
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
|
|
||||||
// create separate implicit names for the two brackets
|
// create separate implicit names for the two brackets
|
||||||
|
|
|
@ -21,12 +21,13 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
|
@ -113,7 +114,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (implicitNames == null) {
|
if (implicitNames == null) {
|
||||||
ICPPFunction overload = getOverload();
|
ICPPFunction overload = getOverload();
|
||||||
if (overload == null) {
|
if (overload == null || (overload instanceof CPPImplicitFunction && !(overload instanceof ICPPMethod))) {
|
||||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
} else {
|
} else {
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
|
||||||
|
|
||||||
if (!isGlobal) {
|
if (!isGlobal) {
|
||||||
ICPPFunction deleteOperator = CPPSemantics.findOverloadedOperator(this);
|
ICPPFunction deleteOperator = CPPSemantics.findOverloadedOperator(this);
|
||||||
if (deleteOperator != null) {
|
if (deleteOperator != null && !(deleteOperator instanceof CPPImplicitFunction)) {
|
||||||
CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this);
|
CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this);
|
||||||
deleteName.setOperator(true);
|
deleteName.setOperator(true);
|
||||||
deleteName.setBinding(deleteOperator);
|
deleteName.setBinding(deleteOperator);
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
|
||||||
ICPPFunction[] overloads = getOverloads();
|
ICPPFunction[] overloads = getOverloads();
|
||||||
for(int i = 0; i < overloads.length; i++) {
|
for(int i = 0; i < overloads.length; i++) {
|
||||||
ICPPFunction overload = overloads[i];
|
ICPPFunction overload = overloads[i];
|
||||||
if(overload != null) {
|
if(overload != null && !(overload instanceof CPPImplicitFunction)) {
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.COMMA, this);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.COMMA, this);
|
||||||
operatorName.setBinding(overload);
|
operatorName.setBinding(overload);
|
||||||
operatorName.computeOperatorOffsets(exprs[i], true);
|
operatorName.computeOperatorOffsets(exprs[i], true);
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
@ -133,12 +134,16 @@ public class CPPASTFieldReference extends ASTNode implements ICPPASTFieldReferen
|
||||||
|
|
||||||
// create a name to wrap each binding
|
// create a name to wrap each binding
|
||||||
implicitNames = new IASTImplicitName[functionBindings.size()];
|
implicitNames = new IASTImplicitName[functionBindings.size()];
|
||||||
for(int i = 0, n = functionBindings.size(); i < n; i++) {
|
int i=-1;
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.ARROW, this);
|
for (ICPPFunction op : functionBindings) {
|
||||||
operatorName.setBinding(functionBindings.get(i));
|
if (op != null && !(op instanceof CPPImplicitFunction)) {
|
||||||
operatorName.computeOperatorOffsets(owner, true);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.ARROW, this);
|
||||||
implicitNames[i] = operatorName;
|
operatorName.setBinding(op);
|
||||||
|
operatorName.computeOperatorOffsets(owner, true);
|
||||||
|
implicitNames[++i] = operatorName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
implicitNames= ArrayUtil.trimAt(IASTImplicitName.class, implicitNames, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return implicitNames;
|
return implicitNames;
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (implicitNames == null) {
|
if (implicitNames == null) {
|
||||||
ICPPFunction overload = getOperator();
|
ICPPFunction overload = getOperator();
|
||||||
if (overload == null)
|
if (overload == null || overload instanceof CPPImplicitFunction)
|
||||||
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
|
|
||||||
// create separate implicit names for the two brackets
|
// create separate implicit names for the two brackets
|
||||||
|
@ -246,13 +246,9 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
||||||
if (t instanceof IFunctionType) {
|
if (t instanceof IFunctionType) {
|
||||||
return ((IFunctionType) t).getReturnType();
|
return ((IFunctionType) t).getReturnType();
|
||||||
} else if (t instanceof ICPPClassType) {
|
} else if (t instanceof ICPPClassType) {
|
||||||
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
|
overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
|
||||||
if (op != null) {
|
if (overload != null) {
|
||||||
// overload can be a surrogate function call, which consists of a conversion and a call to
|
return overload.getType().getReturnType();
|
||||||
// a dynamically computed function pointer.
|
|
||||||
if (!(op instanceof CPPImplicitFunction))
|
|
||||||
overload = op;
|
|
||||||
return op.getType().getReturnType();
|
|
||||||
}
|
}
|
||||||
} else if (t instanceof IPointerType) {
|
} else if (t instanceof IPointerType) {
|
||||||
t= SemanticUtil.getUltimateTypeUptoPointers(((IPointerType) t).getType());
|
t= SemanticUtil.getUltimateTypeUptoPointers(((IPointerType) t).getType());
|
||||||
|
|
|
@ -139,7 +139,7 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (implicitNames == null) {
|
if (implicitNames == null) {
|
||||||
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
|
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
|
||||||
if (operatorFunction == null) {
|
if (operatorFunction == null || operatorFunction instanceof CPPImplicitFunction) {
|
||||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
} else {
|
} else {
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
|
||||||
|
|
|
@ -26,12 +26,12 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
|
@ -100,7 +100,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (implicitNames == null) {
|
if (implicitNames == null) {
|
||||||
ICPPFunction overload = getOverload();
|
ICPPFunction overload = getOverload();
|
||||||
if (overload == null) {
|
if (overload == null || overload instanceof CPPImplicitFunction) {
|
||||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
} else {
|
} else {
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
|
||||||
|
|
|
@ -0,0 +1,658 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2010 Wind River Systems, Inc. and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates built-in operators according to 13.6
|
||||||
|
*/
|
||||||
|
class BuiltinOperators {
|
||||||
|
private static final ICPPFunction[] EMPTY = {};
|
||||||
|
private static final int FIRST = 0;
|
||||||
|
private static final int SECOND = 1;
|
||||||
|
private static final IType BOOL = new CPPBasicType(Kind.eBoolean, 0);
|
||||||
|
private static final IType PTR_DIFF = new CPPBasicType(Kind.eInt, 0);
|
||||||
|
|
||||||
|
public static ICPPFunction[] create(OverloadableOperator operator, IASTInitializerClause[] args, IASTTranslationUnit tu) {
|
||||||
|
if (operator == null || args == null || args.length == 0)
|
||||||
|
return EMPTY;
|
||||||
|
|
||||||
|
return new BuiltinOperators(operator, args, tu.getScope()).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final OverloadableOperator fOperator;
|
||||||
|
private final boolean fUnary;
|
||||||
|
private IType fType1;
|
||||||
|
private IType fType2;
|
||||||
|
private IType[][] fClassConversionTypes= {null, null};
|
||||||
|
private boolean[] fIsClass= {false,false};
|
||||||
|
private IScope fFileScope;
|
||||||
|
private List<ICPPFunction> fResult;
|
||||||
|
private Set<String> fSignatures;
|
||||||
|
|
||||||
|
BuiltinOperators(OverloadableOperator operator, IASTInitializerClause[] args, IScope fileScope) {
|
||||||
|
fFileScope= fileScope;
|
||||||
|
fOperator= operator;
|
||||||
|
fUnary= args.length<2;
|
||||||
|
if (args.length > 0 && args[0] instanceof IASTExpression) {
|
||||||
|
IType type= ((IASTExpression) args[0]).getExpressionType();
|
||||||
|
if (!(type instanceof IProblemBinding))
|
||||||
|
fType1= type;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (args.length > 1 && args[1] instanceof IASTExpression) {
|
||||||
|
IType type= ((IASTExpression) args[1]).getExpressionType();
|
||||||
|
if (!(type instanceof IProblemBinding))
|
||||||
|
fType2= type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ICPPFunction[] create() {
|
||||||
|
switch(fOperator) {
|
||||||
|
case ARROW:
|
||||||
|
case COMMA:
|
||||||
|
case DELETE:
|
||||||
|
case DELETE_ARRAY:
|
||||||
|
case NEW:
|
||||||
|
case NEW_ARRAY:
|
||||||
|
case PAREN:
|
||||||
|
return EMPTY;
|
||||||
|
|
||||||
|
case INCR:
|
||||||
|
case DECR:
|
||||||
|
opIncOrDec();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STAR:
|
||||||
|
if (fUnary) {
|
||||||
|
opDeref();
|
||||||
|
} else {
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIV:
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PLUS:
|
||||||
|
if (fUnary) {
|
||||||
|
unaryPointer();
|
||||||
|
unaryPromotedArithmetic(true);
|
||||||
|
} else {
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||||
|
pointerArithmetic(false, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BRACKET:
|
||||||
|
pointerArithmetic(true, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MINUS:
|
||||||
|
if (fUnary) {
|
||||||
|
unaryPromotedArithmetic(true);
|
||||||
|
} else {
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||||
|
pointerArithmetic(false, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BITCOMPLEMENT:
|
||||||
|
unaryPromotedArithmetic(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARROWSTAR:
|
||||||
|
opArrowStar();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EQUAL:
|
||||||
|
case NOTEQUAL:
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.USE_BOOL);
|
||||||
|
comparison(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GT:
|
||||||
|
case GTEQUAL:
|
||||||
|
case LT:
|
||||||
|
case LTEQUAL:
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.USE_BOOL);
|
||||||
|
comparison(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AMPER:
|
||||||
|
if (fUnary)
|
||||||
|
return EMPTY;
|
||||||
|
|
||||||
|
binaryPromotedArithmetic(false, ReturnType.CONVERT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BITOR:
|
||||||
|
case XOR:
|
||||||
|
case MOD:
|
||||||
|
binaryPromotedArithmetic(false, ReturnType.CONVERT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHIFTL:
|
||||||
|
case SHIFTR:
|
||||||
|
binaryPromotedArithmetic(false, ReturnType.USE_FIRST);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSIGN:
|
||||||
|
arithmeticAssignement(true, true, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MINUSASSIGN:
|
||||||
|
case PLUSASSIGN:
|
||||||
|
arithmeticAssignement(true, false, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIVASSIGN:
|
||||||
|
case STARASSIGN:
|
||||||
|
arithmeticAssignement(true, false, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AMPERASSIGN:
|
||||||
|
case BITORASSIGN:
|
||||||
|
case MODASSIGN:
|
||||||
|
case SHIFTLASSIGN:
|
||||||
|
case SHIFTRASSIGN:
|
||||||
|
case XORASSIGN:
|
||||||
|
arithmeticAssignement(false, false, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AND:
|
||||||
|
case OR:
|
||||||
|
addFunction(BOOL, BOOL, BOOL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NOT:
|
||||||
|
addFunction(BOOL, BOOL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fResult == null)
|
||||||
|
return EMPTY;
|
||||||
|
|
||||||
|
return fResult.toArray(new ICPPFunction[fResult.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 13.6-3, 13.6-4, 13.6-5
|
||||||
|
private void opIncOrDec() {
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF);
|
||||||
|
if (type instanceof ICPPReferenceType) {
|
||||||
|
IType nested= ((ICPPReferenceType) type).getType();
|
||||||
|
CVQualifier cvq= SemanticUtil.getCVQualifier(nested);
|
||||||
|
if (!cvq.isConst()) {
|
||||||
|
nested= SemanticUtil.getNestedType(nested, TDEF | CVTYPE);
|
||||||
|
boolean ok= false;
|
||||||
|
if (isArithmetic(nested)) {
|
||||||
|
// 13.6-3 and 1.3.6-4
|
||||||
|
if (fOperator == OverloadableOperator.INCR || !isBoolean(type)) {
|
||||||
|
ok= true;
|
||||||
|
}
|
||||||
|
} else if (isPointer(nested)) {
|
||||||
|
// 13.6-5
|
||||||
|
nested= ((IPointerType) nested).getType();
|
||||||
|
if (!(SemanticUtil.getNestedType(nested, TDEF) instanceof IFunctionType)) {
|
||||||
|
ok= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
if (fType2 != null) {
|
||||||
|
addFunction(type, type, fType2);
|
||||||
|
} else {
|
||||||
|
addFunction(type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-6, 13.6-7
|
||||||
|
private void opDeref() {
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF);
|
||||||
|
if (isPointer(type)) {
|
||||||
|
IType nested= SemanticUtil.getNestedType(((IPointerType) type).getType(), TDEF);
|
||||||
|
if (nested instanceof ICPPFunctionType) {
|
||||||
|
ICPPFunctionType ft= (ICPPFunctionType) nested;
|
||||||
|
if (ft.isConst() || ft.isVolatile())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addFunction(new CPPReferenceType(nested, false), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-8
|
||||||
|
private void unaryPointer() {
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF);
|
||||||
|
if (isPointer(type)) {
|
||||||
|
addFunction(type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-9, 13.6-10
|
||||||
|
private void unaryPromotedArithmetic(boolean includeFloatingPoint) {
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF|CVTYPE);
|
||||||
|
if (isFloatingPoint(type)) {
|
||||||
|
if (includeFloatingPoint) {
|
||||||
|
addFunction(type, type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type= CPPArithmeticConversion.promoteCppType(type);
|
||||||
|
if (type != null) {
|
||||||
|
addFunction(type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-11
|
||||||
|
private void opArrowStar() {
|
||||||
|
List<IPointerType> classPointers= null;
|
||||||
|
List<ICPPPointerToMemberType> memberPointers= null;
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF | REF);
|
||||||
|
if (isPointer(type)) {
|
||||||
|
final IPointerType ptrType = (IPointerType) type;
|
||||||
|
if (SemanticUtil.getNestedType(ptrType.getType(), TDEF | CVTYPE) instanceof ICPPClassType) {
|
||||||
|
if (classPointers == null) {
|
||||||
|
classPointers= new ArrayList<IPointerType>();
|
||||||
|
}
|
||||||
|
classPointers.add(ptrType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (classPointers == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
types= getClassConversionTypes(SECOND);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF | REF);
|
||||||
|
if (type instanceof ICPPPointerToMemberType) {
|
||||||
|
if (memberPointers == null) {
|
||||||
|
memberPointers= new ArrayList<ICPPPointerToMemberType>();
|
||||||
|
}
|
||||||
|
memberPointers.add((ICPPPointerToMemberType) type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (memberPointers == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IPointerType clsPtr : classPointers) {
|
||||||
|
IType cvClass= SemanticUtil.getNestedType(clsPtr.getType(), TDEF);
|
||||||
|
CVQualifier cv1= SemanticUtil.getCVQualifier(cvClass);
|
||||||
|
ICPPClassType c1= (ICPPClassType) SemanticUtil.getNestedType(cvClass, TDEF | CVTYPE);
|
||||||
|
for (ICPPPointerToMemberType memPtr : memberPointers) {
|
||||||
|
IType t2= SemanticUtil.getNestedType(memPtr.getMemberOfClass(), TDEF);
|
||||||
|
if (t2 instanceof ICPPClassType) {
|
||||||
|
ICPPClassType c2= (ICPPClassType) t2;
|
||||||
|
try {
|
||||||
|
if (SemanticUtil.calculateInheritanceDepth(c1, c2) >= 0) {
|
||||||
|
IType cvt= SemanticUtil.getNestedType(memPtr.getType(), TDEF);
|
||||||
|
IType rt= new CPPReferenceType(
|
||||||
|
SemanticUtil.addQualifiers(cvt, cv1.isConst(), cv1.isVolatile()), false);
|
||||||
|
addFunction(rt, clsPtr, memPtr);
|
||||||
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-12, 13.6-17
|
||||||
|
private static enum ReturnType {CONVERT, USE_FIRST, USE_BOOL}
|
||||||
|
private void binaryPromotedArithmetic(boolean fltPt, ReturnType rstrat) {
|
||||||
|
List<IType> p1= null, p2= null;
|
||||||
|
|
||||||
|
IType[] types1= getClassConversionTypes(FIRST);
|
||||||
|
IType[] types2= getClassConversionTypes(SECOND);
|
||||||
|
if (types1.length == 0 && types2.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IType t : types1) {
|
||||||
|
p1 = addPromotedArithmetic(t, fltPt, p1);
|
||||||
|
}
|
||||||
|
for (IType t : types2) {
|
||||||
|
p2 = addPromotedArithmetic(t, fltPt, p2);
|
||||||
|
}
|
||||||
|
p1= addPromotedArithmetic(fType1, fltPt, p1);
|
||||||
|
p2= addPromotedArithmetic(fType2, fltPt, p2);
|
||||||
|
if (p1 == null || p2 == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IType t1 : p1) {
|
||||||
|
for (IType t2 : p2) {
|
||||||
|
IType rt= null;
|
||||||
|
switch(rstrat) {
|
||||||
|
case USE_BOOL:
|
||||||
|
rt= BOOL;
|
||||||
|
break;
|
||||||
|
case USE_FIRST:
|
||||||
|
rt= t1;
|
||||||
|
break;
|
||||||
|
case CONVERT:
|
||||||
|
rt= CPPArithmeticConversion.convertCppOperandTypes(IASTBinaryExpression.op_plus, t1, t2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addFunction(rt, t1, t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IType> addPromotedArithmetic(IType t, boolean fltPt, List<IType> p1) {
|
||||||
|
IType type= SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
|
||||||
|
if (isFloatingPoint(type)) {
|
||||||
|
if (!fltPt) {
|
||||||
|
type= null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type= CPPArithmeticConversion.promoteCppType(type);
|
||||||
|
}
|
||||||
|
if (type != null) {
|
||||||
|
if (p1 == null) {
|
||||||
|
p1= new ArrayList<IType>();
|
||||||
|
}
|
||||||
|
p1.add(type);
|
||||||
|
}
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 13.6-13, 13.6.14
|
||||||
|
private void pointerArithmetic(boolean useRef, boolean isDiff) {
|
||||||
|
IType[] types= getClassConversionTypes(FIRST);
|
||||||
|
if (types.length == 0 && !fIsClass[FIRST]) {
|
||||||
|
types= new IType[] {fType1};
|
||||||
|
}
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF);
|
||||||
|
if (isPointer(type)) {
|
||||||
|
final IType ptrTarget = ((IPointerType) type).getType();
|
||||||
|
final IType uqPtrTarget = SemanticUtil.getNestedType(ptrTarget, TDEF|CVTYPE);
|
||||||
|
if (!(uqPtrTarget instanceof IFunctionType)) {
|
||||||
|
final IType retType= useRef ? new CPPReferenceType(ptrTarget, false) : type;
|
||||||
|
addFunction(retType, type, PTR_DIFF);
|
||||||
|
if (isDiff) {
|
||||||
|
addFunction(PTR_DIFF, type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
types= getClassConversionTypes(SECOND);
|
||||||
|
if (types.length == 0 && !fIsClass[SECOND]) {
|
||||||
|
types= new IType[] {fType2};
|
||||||
|
}
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF);
|
||||||
|
if (isPointer(type)) {
|
||||||
|
final IType ptrTarget = ((IPointerType) type).getType();
|
||||||
|
final IType uqPtrTarget = SemanticUtil.getNestedType(ptrTarget, TDEF|CVTYPE);
|
||||||
|
if (!(uqPtrTarget instanceof IFunctionType)) {
|
||||||
|
if (isDiff) {
|
||||||
|
addFunction(PTR_DIFF, type, type);
|
||||||
|
} else {
|
||||||
|
final IType retType= useRef ? new CPPReferenceType(ptrTarget, false) : type;
|
||||||
|
addFunction(retType, PTR_DIFF, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-15, 13.6.16
|
||||||
|
private void comparison(boolean ordered) {
|
||||||
|
for (int i = FIRST; i <= SECOND; i++) {
|
||||||
|
IType[] types= getClassConversionTypes(i);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF|CVTYPE);
|
||||||
|
if (isPointer(type) || isEnumeration(type) || (!ordered && isPointerToMember(type))) {
|
||||||
|
addFunction(BOOL, type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13.6-18, 13.6-29, 13.6-20, 13.6-22
|
||||||
|
private void arithmeticAssignement(boolean fltPt, boolean self, boolean ptr) {
|
||||||
|
List<IType> p1= null, p2= null;
|
||||||
|
|
||||||
|
IType[] types1= getClassConversionTypes(FIRST);
|
||||||
|
IType[] types2= getClassConversionTypes(SECOND);
|
||||||
|
if (types1.length == 0 && types2.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IType t : types1) {
|
||||||
|
p1 = addArithmeticRef(t, fltPt, p1, self, ptr);
|
||||||
|
}
|
||||||
|
p1= addArithmeticRef(fType1, fltPt, p1, false, false);
|
||||||
|
for (IType t : types2) {
|
||||||
|
p2 = addPromotedArithmetic(t, fltPt, p2);
|
||||||
|
}
|
||||||
|
p2= addPromotedArithmetic(fType2, fltPt, p2);
|
||||||
|
if (p1 == null || p2 == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IType t1 : p1) {
|
||||||
|
for (IType t2 : p2) {
|
||||||
|
addFunction(t1, t1, t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IType> addArithmeticRef(IType t, boolean fltPt, List<IType> p1, boolean self, boolean ptr) {
|
||||||
|
final IType type= t= SemanticUtil.getNestedType(t, TDEF);
|
||||||
|
if (type instanceof ICPPReferenceType) {
|
||||||
|
t= SemanticUtil.getNestedType(((ICPPReferenceType) t).getType(), TDEF);
|
||||||
|
if (!SemanticUtil.getCVQualifier(t).isConst()) {
|
||||||
|
t = SemanticUtil.getNestedType(t, TDEF|CVTYPE);
|
||||||
|
if (fltPt ? isArithmetic(t) : isIntegral(t)) {
|
||||||
|
if (p1 == null) {
|
||||||
|
p1= new ArrayList<IType>();
|
||||||
|
}
|
||||||
|
p1.add(type);
|
||||||
|
}
|
||||||
|
if (self && (isEnumeration(t) || isPointerToMember(t) || isPointer(t))) {
|
||||||
|
addFunction(type, type, SemanticUtil.getNestedType(t, TDEF|ALLCVQ));
|
||||||
|
}
|
||||||
|
if (ptr && isPointer(t)) {
|
||||||
|
addFunction(type, type, PTR_DIFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFunction(IType returnType, IType p1) {
|
||||||
|
addFunction(returnType, new IType[] {p1});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFunction(IType returnType, IType p1, IType p2) {
|
||||||
|
addFunction(returnType, new IType[] {p1, p2});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFunction(IType returnType, IType[] parameterTypes) {
|
||||||
|
ICPPParameter[] parameter = new ICPPParameter[parameterTypes.length];
|
||||||
|
ICPPFunctionType functionType = new CPPFunctionType(returnType, parameterTypes);
|
||||||
|
String sig= ASTTypeUtil.getType(functionType, true);
|
||||||
|
if (fSignatures == null) {
|
||||||
|
fSignatures= new HashSet<String>();
|
||||||
|
}
|
||||||
|
if (fSignatures.add(sig)) {
|
||||||
|
for (int i = 0; i < parameterTypes.length; i++) {
|
||||||
|
IType t = parameterTypes[i];
|
||||||
|
parameter[i]= new CPPBuiltinParameter(t);
|
||||||
|
}
|
||||||
|
if (fResult == null) {
|
||||||
|
fResult= new ArrayList<ICPPFunction>();
|
||||||
|
}
|
||||||
|
fResult.add(new CPPImplicitFunction(fOperator.toCharArray(), fFileScope, functionType, parameter, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEnumeration(IType type) {
|
||||||
|
return type instanceof IEnumeration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPointer(IType type) {
|
||||||
|
return type instanceof IPointerType && !(type instanceof ICPPPointerToMemberType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPointerToMember(IType type) {
|
||||||
|
return type instanceof ICPPPointerToMemberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBoolean(IType type) {
|
||||||
|
return type instanceof IBasicType && ((IBasicType) type).getKind() == Kind.eBoolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFloatingPoint(IType type) {
|
||||||
|
if (type instanceof IBasicType) {
|
||||||
|
IBasicType.Kind kind= ((IBasicType) type).getKind();
|
||||||
|
switch(kind) {
|
||||||
|
case eDouble:
|
||||||
|
case eFloat:
|
||||||
|
return true;
|
||||||
|
case eBoolean:
|
||||||
|
case eChar:
|
||||||
|
case eChar16:
|
||||||
|
case eChar32:
|
||||||
|
case eInt:
|
||||||
|
case eWChar:
|
||||||
|
case eUnspecified:
|
||||||
|
case eVoid:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isArithmetic(IType type) {
|
||||||
|
if (type instanceof IBasicType) {
|
||||||
|
IBasicType.Kind kind= ((IBasicType) type).getKind();
|
||||||
|
switch(kind) {
|
||||||
|
case eBoolean:
|
||||||
|
case eChar:
|
||||||
|
case eChar16:
|
||||||
|
case eChar32:
|
||||||
|
case eDouble:
|
||||||
|
case eFloat:
|
||||||
|
case eInt:
|
||||||
|
case eWChar:
|
||||||
|
return true;
|
||||||
|
case eUnspecified:
|
||||||
|
case eVoid:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIntegral(IType type) {
|
||||||
|
if (type instanceof IBasicType) {
|
||||||
|
IBasicType.Kind kind= ((IBasicType) type).getKind();
|
||||||
|
switch(kind) {
|
||||||
|
case eBoolean:
|
||||||
|
case eChar:
|
||||||
|
case eChar16:
|
||||||
|
case eChar32:
|
||||||
|
case eInt:
|
||||||
|
case eWChar:
|
||||||
|
return true;
|
||||||
|
case eDouble:
|
||||||
|
case eFloat:
|
||||||
|
case eUnspecified:
|
||||||
|
case eVoid:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IType[] getClassConversionTypes(int idx) {
|
||||||
|
IType[] result = fClassConversionTypes[idx];
|
||||||
|
if (result == null) {
|
||||||
|
result= IType.EMPTY_TYPE_ARRAY;
|
||||||
|
IType type= idx == 0 ? fType1 : fType2;
|
||||||
|
if (type != null) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||||
|
if (type instanceof ICPPClassType) {
|
||||||
|
fIsClass[idx]= true;
|
||||||
|
try {
|
||||||
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) type);
|
||||||
|
result= new IType[ops.length];
|
||||||
|
for (int i = 0; i < result.length; i++) {
|
||||||
|
final ICPPFunctionType functionType = ops[i].getType();
|
||||||
|
if (functionType != null) {
|
||||||
|
result[i]= functionType.getReturnType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fClassConversionTypes[idx]= result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2662,7 +2662,6 @@ public class CPPSemantics {
|
||||||
if (!fieldReference.isPointerDereference())
|
if (!fieldReference.isPointerDereference())
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
|
|
||||||
IASTExpression[] args = {owner};
|
IASTExpression[] args = {owner};
|
||||||
|
|
||||||
// bug 205964: as long as the type is a class type, recurse.
|
// bug 205964: as long as the type is a class type, recurse.
|
||||||
|
@ -2700,7 +2699,7 @@ public class CPPSemantics {
|
||||||
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
||||||
innerFR.setParent(fieldReference); // connect to the AST
|
innerFR.setParent(fieldReference); // connect to the AST
|
||||||
|
|
||||||
ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, operatorName, NonMemberMode.none);
|
ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, OverloadableOperator.ARROW, NonMemberMode.none);
|
||||||
if (op == null)
|
if (op == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2723,15 +2722,13 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
||||||
char[] name = OverloadableOperator.BRACKET.toCharArray();
|
|
||||||
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
||||||
IType type = exp.getArrayExpression().getExpressionType();
|
IType type = exp.getArrayExpression().getExpressionType();
|
||||||
type = SemanticUtil.getUltimateTypeUptoPointers(type);
|
type = SemanticUtil.getUltimateTypeUptoPointers(type);
|
||||||
return findOverloadedOperator(exp, args, type, name, NonMemberMode.none);
|
return findOverloadedOperator(exp, args, type, OverloadableOperator.BRACKET, NonMemberMode.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTFunctionCallExpression exp, ICPPClassType type) {
|
public static ICPPFunction findOverloadedOperator(IASTFunctionCallExpression exp, ICPPClassType type) {
|
||||||
char[] name = OverloadableOperator.PAREN.toCharArray();
|
|
||||||
IASTInitializerClause[] args = exp.getArguments();
|
IASTInitializerClause[] args = exp.getArguments();
|
||||||
ArrayList<IASTInitializerClause> argsToPass = new ArrayList<IASTInitializerClause>(args.length + 1);
|
ArrayList<IASTInitializerClause> argsToPass = new ArrayList<IASTInitializerClause>(args.length + 1);
|
||||||
argsToPass.add(exp.getFunctionNameExpression());
|
argsToPass.add(exp.getFunctionNameExpression());
|
||||||
|
@ -2740,7 +2737,7 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
args = argsToPass.toArray(new IASTInitializerClause[argsToPass.size()]);
|
args = argsToPass.toArray(new IASTInitializerClause[argsToPass.size()]);
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, name, NonMemberMode.none);
|
return findOverloadedOperator(exp, args, type, OverloadableOperator.PAREN, NonMemberMode.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
||||||
|
@ -2764,14 +2761,14 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
|
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
|
||||||
return findOverloadedOperator(exp, argArray, type, op.toCharArray(), NonMemberMode.all);
|
return findOverloadedOperator(exp, argArray, type, op, NonMemberMode.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
||||||
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
||||||
IASTExpression[] args = { exp.getOperand() };
|
IASTExpression[] args = { exp.getOperand() };
|
||||||
IType classType = getNestedClassType(exp);
|
IType classType = getNestedClassType(exp);
|
||||||
return findOverloadedOperator(exp, args, classType, op.toCharArray(), NonMemberMode.all);
|
return findOverloadedOperator(exp, args, classType, op, NonMemberMode.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
||||||
|
@ -2907,7 +2904,7 @@ public class CPPSemantics {
|
||||||
if (!isUserDefined(type))
|
if (!isUserDefined(type))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, op.toCharArray(), NonMemberMode.limited);
|
return findOverloadedOperator(exp, args, type, op, NonMemberMode.limited);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
||||||
|
@ -2928,7 +2925,7 @@ public class CPPSemantics {
|
||||||
lookupNonMember= NonMemberMode.limited;
|
lookupNonMember= NonMemberMode.limited;
|
||||||
}
|
}
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, op1type, op.toCharArray(), lookupNonMember);
|
return findOverloadedOperator(exp, args, op1type, op, lookupNonMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2946,16 +2943,23 @@ public class CPPSemantics {
|
||||||
};
|
};
|
||||||
dummy.setParent(first);
|
dummy.setParent(first);
|
||||||
|
|
||||||
char[] name = OverloadableOperator.COMMA.toCharArray();
|
|
||||||
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
||||||
return findOverloadedOperator(dummy, args, lookupType, name, NonMemberMode.limited);
|
return findOverloadedOperator(dummy, args, lookupType, OverloadableOperator.COMMA, NonMemberMode.limited);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NonMemberMode {none, limited, all}
|
private static enum NonMemberMode {none, limited, all}
|
||||||
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
||||||
char[] operatorName, NonMemberMode mode) {
|
OverloadableOperator operator, NonMemberMode mode) {
|
||||||
ICPPClassType callToObjectOfClassType= null;
|
ICPPClassType callToObjectOfClassType= null;
|
||||||
|
IType type2= null;
|
||||||
|
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
||||||
|
type2= getUltimateTypeUptoPointers(((IASTExpression) args[1]).getExpressionType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodLookupType instanceof ICPPUnknownType || type2 instanceof ICPPUnknownType) {
|
||||||
|
return new CPPUnknownFunction(null, operator.toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
// Find a method
|
// Find a method
|
||||||
LookupData methodData = null;
|
LookupData methodData = null;
|
||||||
CPPASTName methodName = null;
|
CPPASTName methodName = null;
|
||||||
|
@ -2964,7 +2968,7 @@ public class CPPSemantics {
|
||||||
if (methodLookupType instanceof ICPPClassType) {
|
if (methodLookupType instanceof ICPPClassType) {
|
||||||
ICPPClassType classType = (ICPPClassType) methodLookupType;
|
ICPPClassType classType = (ICPPClassType) methodLookupType;
|
||||||
|
|
||||||
methodName = new CPPASTName(operatorName);
|
methodName = new CPPASTName(operator.toCharArray());
|
||||||
methodName.setParent(parent);
|
methodName.setParent(parent);
|
||||||
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
methodData = new LookupData(methodName);
|
methodData = new LookupData(methodName);
|
||||||
|
@ -2986,16 +2990,13 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a function
|
// Find a function
|
||||||
LookupData funcData = null;
|
CPPASTName funcName = new CPPASTName(operator.toCharArray());
|
||||||
CPPASTName funcName = null;
|
funcName.setParent(parent);
|
||||||
|
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
|
LookupData funcData = new LookupData(funcName);
|
||||||
|
funcData.setFunctionArguments(args);
|
||||||
|
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
||||||
if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
|
if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
|
||||||
funcName = new CPPASTName(operatorName);
|
|
||||||
funcName.setParent(parent);
|
|
||||||
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
|
||||||
funcData = new LookupData(funcName);
|
|
||||||
funcData.setFunctionArguments(args);
|
|
||||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mode != NonMemberMode.none) {
|
if (mode != NonMemberMode.none) {
|
||||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||||
|
@ -3033,10 +3034,6 @@ public class CPPSemantics {
|
||||||
// 13.3.1.2.3
|
// 13.3.1.2.3
|
||||||
// However, if no operand type has class type, only those non-member functions ...
|
// However, if no operand type has class type, only those non-member functions ...
|
||||||
if (mode == NonMemberMode.limited) {
|
if (mode == NonMemberMode.limited) {
|
||||||
IType type2= null;
|
|
||||||
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
|
||||||
type2= getUltimateTypeUptoPointers(((IASTExpression) args[1]).getExpressionType());
|
|
||||||
}
|
|
||||||
if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
|
if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
|
||||||
IEnumeration enum1= null;
|
IEnumeration enum1= null;
|
||||||
IEnumeration enum2= null;
|
IEnumeration enum2= null;
|
||||||
|
@ -3092,14 +3089,19 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
||||||
|
ICPPFunction[] builtins= BuiltinOperators.create(operator, args, parent.getTranslationUnit());
|
||||||
|
mergeResults(funcData, builtins, false);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IBinding binding = null;
|
IBinding binding = null;
|
||||||
if (methodData != null && funcData != null) {
|
if (methodData != null && funcData.hasResults()) {
|
||||||
// if there was two lookups then merge the results
|
// if there was two lookups then merge the results
|
||||||
mergeResults(funcData, methodData.foundItems, false);
|
mergeResults(funcData, methodData.foundItems, false);
|
||||||
funcData.firstArgIsImpliedMethodArg = true;
|
funcData.firstArgIsImpliedMethodArg = true;
|
||||||
binding = resolveAmbiguities(funcData, funcName);
|
binding = resolveAmbiguities(funcData, funcName);
|
||||||
} else if (funcData != null) {
|
} else if (funcData.hasResults()) {
|
||||||
binding = resolveAmbiguities(funcData, funcName);
|
binding = resolveAmbiguities(funcData, funcName);
|
||||||
} else if (methodData != null) {
|
} else if (methodData != null) {
|
||||||
binding = resolveAmbiguities(methodData, methodName);
|
binding = resolveAmbiguities(methodData, methodName);
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
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.ICPPASTCompositeTypeSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
||||||
|
@ -65,7 +66,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
|
@ -625,17 +625,4 @@ public class LookupData {
|
||||||
}
|
}
|
||||||
return IBinding.EMPTY_BINDING_ARRAY;
|
return IBinding.EMPTY_BINDING_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFoundItemCount() {
|
|
||||||
if (foundItems instanceof Object[]) {
|
|
||||||
Object[] items = (Object[]) foundItems;
|
|
||||||
int len;
|
|
||||||
for (len= items.length-1; len >=0; len--) {
|
|
||||||
if (items[len] != null)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return len+1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue