| /******************************************************************************* |
| * Copyright (c) 2012, 2017 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 |
| * Sergey Prigogin (Google) |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; |
| |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_assign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAnd; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAndAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryOr; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryOrAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryXor; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryXorAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_divide; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_divideAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_equals; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_greaterEqual; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_greaterThan; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_lessEqual; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_lessThan; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_logicalAnd; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_logicalOr; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_minus; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_minusAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_modulo; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_moduloAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_multiply; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_multiplyAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_notequals; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_plus; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_plusAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_pmarrow; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_pmdot; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeft; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeftAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRight; |
| import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRightAssign; |
| import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; |
| import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; |
| import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.glvalueType; |
| import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType; |
| import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueTypeWithResolvedTypedefs; |
| import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall; |
| import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; |
| 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 org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IArrayType; |
| import org.eclipse.cdt.core.dom.ast.IBasicType; |
| import org.eclipse.cdt.core.dom.ast.IBinding; |
| import org.eclipse.cdt.core.dom.ast.IPointerType; |
| import org.eclipse.cdt.core.dom.ast.ISemanticProblem; |
| import org.eclipse.cdt.core.dom.ast.IType; |
| import org.eclipse.cdt.core.dom.ast.IValue; |
| 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.ICPPPointerToMemberType; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; |
| import org.eclipse.cdt.internal.core.dom.parser.DependentValue; |
| import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; |
| import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; |
| import org.eclipse.cdt.internal.core.dom.parser.ProblemType; |
| import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; |
| 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.CPPFunction; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil.Pair; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| |
| /** |
| * Performs evaluation of an expression. |
| */ |
| public class EvalBinary extends CPPDependentEvaluation { |
| public final static int op_arrayAccess= Byte.MAX_VALUE; |
| private final int fOperator; |
| |
| private final ICPPEvaluation fArg1; |
| private final ICPPEvaluation fArg2; |
| |
| private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; |
| private ICPPEvaluation fOverloadCall; |
| private IType fType; |
| private boolean fCheckedIsConstantExpression; |
| private boolean fIsConstantExpression; |
| |
| public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IASTNode pointOfDefinition) { |
| this(operator, arg1, arg2, findEnclosingTemplate(pointOfDefinition)); |
| } |
| |
| public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IBinding templateDefinition) { |
| super(templateDefinition); |
| fOperator= operator; |
| fArg1= arg1; |
| fArg2= arg2; |
| } |
| |
| public int getOperator() { |
| return fOperator; |
| } |
| |
| public ICPPEvaluation getArg1() { |
| return fArg1; |
| } |
| |
| public ICPPEvaluation getArg2() { |
| return fArg2; |
| } |
| |
| @Override |
| public boolean isInitializerList() { |
| return false; |
| } |
| |
| @Override |
| public boolean isFunctionSet() { |
| return false; |
| } |
| |
| @Override |
| public IType getType() { |
| if (fType == null) { |
| if (isTypeDependent()) { |
| fType= new TypeOfDependentExpression(this); |
| } else { |
| ICPPFunction overload = getOverload(); |
| if (overload != null) { |
| fType= ExpressionTypes.restoreTypedefs( |
| ExpressionTypes.typeFromFunctionCall(overload), fArg1.getType(), fArg2.getType()); |
| } else { |
| fType= computeType(); |
| } |
| } |
| } |
| return fType; |
| } |
| |
| private ICPPEvaluation createOperatorOverloadEvaluation(ICPPFunction overload, ICPPEvaluation arg1, ICPPEvaluation arg2) { |
| EvalFunctionCall operatorCall; |
| IASTNode point = CPPSemantics.getCurrentLookupPoint(); |
| if (overload instanceof ICPPMethod) { |
| EvalMemberAccess opAccess = new EvalMemberAccess(arg1.getType(), ValueCategory.LVALUE, overload, arg1, false, point); |
| ICPPEvaluation[] args = new ICPPEvaluation[]{opAccess, arg2}; |
| operatorCall = new EvalFunctionCall(args, arg1, point); |
| } else { |
| EvalBinding op = new EvalBinding(overload, overload.getType(), point); |
| ICPPEvaluation[] args = new ICPPEvaluation[]{op, arg1, arg2}; |
| operatorCall = new EvalFunctionCall(args, null, point); |
| } |
| return operatorCall; |
| } |
| |
| private boolean operatorAllowsContextualConversion() { |
| return fOperator == op_logicalAnd || fOperator == op_logicalOr; |
| } |
| |
| @Override |
| public IValue getValue() { |
| ICPPEvaluation arg1 = fArg1; |
| ICPPEvaluation arg2 = fArg2; |
| ICPPFunction overload = getOverload(); |
| if (overload != null) { |
| IType[] parameterTypes = SemanticUtil.getParameterTypesIncludingImplicitThis(overload); |
| if (parameterTypes.length >= 2) { |
| boolean allowContextualConversion = operatorAllowsContextualConversion(); |
| arg1 = maybeApplyConversion(fArg1, parameterTypes[0], allowContextualConversion); |
| arg2 = maybeApplyConversion(fArg2, parameterTypes[1], allowContextualConversion); |
| } else { |
| CCorePlugin.log(IStatus.ERROR, "Unexpected overload for binary operator " + fOperator //$NON-NLS-1$ |
| + ": '" + overload.getName() + "'"); //$NON-NLS-1$//$NON-NLS-2$ |
| } |
| |
| if (!(overload instanceof CPPImplicitFunction)) { |
| if (!overload.isConstexpr()) { |
| return IntegralValue.ERROR; |
| } |
| if (fOverloadCall == null) { |
| fOverloadCall = createOperatorOverloadEvaluation(overload, arg1, arg2); |
| } |
| return fOverloadCall.getValue(); |
| } |
| } |
| |
| IValue v1 = arg1.getValue(); |
| if (v1 == null || v1 == IntegralValue.UNKNOWN) |
| return IntegralValue.UNKNOWN; |
| IValue v2 = arg2.getValue(); |
| if (v2 == null || v2 == IntegralValue.UNKNOWN) |
| return IntegralValue.UNKNOWN; |
| |
| switch (fOperator) { |
| case op_equals: |
| if (v1.equals(v2)) |
| return IntegralValue.create(true); |
| break; |
| case op_notequals: |
| if (v1.equals(v2)) |
| return IntegralValue.create(false); |
| break; |
| case op_assign: |
| return v2; |
| } |
| |
| Number num1 = v1.numberValue(); |
| if (num1 != null) { |
| if (num1 instanceof Long && num1.longValue() == 0) { |
| if (fOperator == op_logicalAnd) { |
| return v1; |
| } |
| } else if (fOperator == op_logicalOr) { |
| return v1; |
| } |
| |
| Number num2 = v2.numberValue(); |
| if (num2 != null) { |
| return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2); |
| } |
| } |
| return DependentValue.create(this); |
| } |
| |
| @Override |
| public boolean isTypeDependent() { |
| if (fType != null) { |
| return fType instanceof TypeOfDependentExpression; |
| } |
| return fArg1.isTypeDependent() || fArg2.isTypeDependent(); |
| } |
| |
| @Override |
| public boolean isValueDependent() { |
| return fArg1.isValueDependent() || fArg2.isValueDependent(); |
| } |
| |
| @Override |
| public boolean isConstantExpression() { |
| if (!fCheckedIsConstantExpression) { |
| fCheckedIsConstantExpression = true; |
| fIsConstantExpression = computeIsConstantExpression(); |
| } |
| return fIsConstantExpression; |
| } |
| |
| @Override |
| public boolean isEquivalentTo(ICPPEvaluation other) { |
| if (!(other instanceof EvalBinary)) { |
| return false; |
| } |
| EvalBinary o = (EvalBinary) other; |
| return fOperator == o.fOperator |
| && fArg1.isEquivalentTo(o.fArg1) |
| && fArg2.isEquivalentTo(o.fArg2); |
| } |
| |
| private boolean computeIsConstantExpression() { |
| return fArg1.isConstantExpression() |
| && fArg2.isConstantExpression() |
| && isNullOrConstexprFunc(getOverload()); |
| } |
| |
| @Override |
| public ValueCategory getValueCategory() { |
| if (isTypeDependent()) |
| return ValueCategory.PRVALUE; |
| |
| ICPPFunction overload = getOverload(); |
| if (overload != null) |
| return ExpressionTypes.valueCategoryFromFunctionCall(overload); |
| |
| switch (fOperator) { |
| case op_arrayAccess: |
| case op_assign: |
| case op_binaryAndAssign: |
| case op_binaryOrAssign: |
| case op_binaryXorAssign: |
| case op_divideAssign: |
| case op_minusAssign: |
| case op_moduloAssign: |
| case op_multiplyAssign: |
| case op_plusAssign: |
| case op_shiftLeftAssign: |
| case op_shiftRightAssign: |
| return LVALUE; |
| |
| case op_pmdot: |
| if (!(getType() instanceof ICPPFunctionType)) |
| return fArg1.getValueCategory(); |
| break; |
| |
| case op_pmarrow: |
| if (!(getType() instanceof ICPPFunctionType)) |
| return LVALUE; |
| break; |
| } |
| |
| return ValueCategory.PRVALUE; |
| } |
| |
| public ICPPFunction getOverload() { |
| if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) { |
| fOverload= computeOverload(); |
| } |
| return fOverload; |
| } |
| |
| private ICPPFunction computeOverload() { |
| if (isTypeDependent()) |
| return null; |
| |
| if (fOperator == op_arrayAccess) { |
| IType type = fArg1.getType(); |
| type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); |
| if (type instanceof ICPPClassType) { |
| return CPPSemantics.findOverloadedBinaryOperator(getTemplateDefinitionScope(), |
| OverloadableOperator.BRACKET, fArg1, fArg2); |
| } |
| } else { |
| final OverloadableOperator op = OverloadableOperator.fromBinaryExpression(fOperator); |
| if (op != null) { |
| return CPPSemantics.findOverloadedBinaryOperator(getTemplateDefinitionScope(), |
| op, fArg1, fArg2); |
| } |
| } |
| return null; |
| } |
| |
| public IType computeType() { |
| // Check for overloaded operator. |
| ICPPFunction o= getOverload(); |
| if (o != null) |
| return typeFromFunctionCall(o); |
| |
| final IType originalType1 = fArg1.getType(); |
| final IType type1 = prvalueTypeWithResolvedTypedefs(originalType1); |
| if (type1 instanceof ISemanticProblem) { |
| return type1; |
| } |
| |
| final IType originalType2 = fArg2.getType(); |
| final IType type2 = prvalueTypeWithResolvedTypedefs(originalType2); |
| if (type2 instanceof ISemanticProblem) { |
| return type2; |
| } |
| |
| IType type= CPPArithmeticConversion.convertCppOperandTypes(fOperator, type1, type2); |
| if (type != null) { |
| return ExpressionTypes.restoreTypedefs(type, originalType1, originalType2); |
| } |
| |
| switch (fOperator) { |
| case op_arrayAccess: |
| if (type1 instanceof IPointerType) { |
| return glvalueType(((IPointerType) type1).getType()); |
| } |
| if (type2 instanceof IPointerType) { |
| return glvalueType(((IPointerType) type2).getType()); |
| } |
| return ProblemType.UNKNOWN_FOR_EXPRESSION; |
| |
| case op_lessEqual: |
| case op_lessThan: |
| case op_greaterEqual: |
| case op_greaterThan: |
| case op_logicalAnd: |
| case op_logicalOr: |
| case op_equals: |
| case op_notequals: |
| return CPPBasicType.BOOLEAN; |
| |
| case op_plus: |
| if (type1 instanceof IPointerType) { |
| return ExpressionTypes.restoreTypedefs(type1, originalType1); |
| } |
| if (type2 instanceof IPointerType) { |
| return ExpressionTypes.restoreTypedefs(type2, originalType2); |
| } |
| break; |
| |
| case op_minus: |
| if (type1 instanceof IPointerType) { |
| if (type2 instanceof IPointerType) { |
| return CPPVisitor.getPointerDiffType(); |
| } |
| return originalType1; |
| } |
| break; |
| |
| case op_pmarrow: |
| case op_pmdot: |
| if (type2 instanceof ICPPPointerToMemberType) { |
| IType t= ((ICPPPointerToMemberType) type2).getType(); |
| if (t instanceof ICPPFunctionType) |
| return t; |
| if (fOperator == op_pmdot && fArg1.getValueCategory() == PRVALUE) { |
| return prvalueType(t); |
| } |
| return glvalueType(t); |
| } |
| return ProblemType.UNKNOWN_FOR_EXPRESSION; |
| } |
| return type1; |
| } |
| |
| @Override |
| public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { |
| buffer.putShort(ITypeMarshalBuffer.EVAL_BINARY); |
| buffer.putByte((byte) fOperator); |
| buffer.marshalEvaluation(fArg1, includeValue); |
| buffer.marshalEvaluation(fArg2, includeValue); |
| marshalTemplateDefinition(buffer); |
| } |
| |
| public static ICPPEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { |
| int op= buffer.getByte(); |
| ICPPEvaluation arg1= buffer.unmarshalEvaluation(); |
| ICPPEvaluation arg2= buffer.unmarshalEvaluation(); |
| IBinding templateDefinition= buffer.unmarshalBinding(); |
| return new EvalBinary(op, arg1, arg2, templateDefinition); |
| } |
| |
| @Override |
| public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { |
| ICPPEvaluation arg1 = fArg1.instantiate(context, maxDepth); |
| ICPPEvaluation arg2 = fArg2.instantiate(context, maxDepth); |
| if (arg1 == fArg1 && arg2 == fArg2) |
| return this; |
| return new EvalBinary(fOperator, arg1, arg2, getTemplateDefinition()); |
| } |
| |
| @Override |
| public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { |
| ICPPFunction overload = getOverload(); |
| if (overload != null) { |
| ICPPEvaluation operatorCall = createOperatorOverloadEvaluation(overload, fArg1, fArg2); |
| return operatorCall.computeForFunctionCall(record, context); |
| } |
| |
| Pair<ICPPEvaluation, ICPPEvaluation> vp1 = EvalUtil.getValuePair(fArg1, record, context); |
| final ICPPEvaluation updateable1 = vp1.getFirst(); |
| final ICPPEvaluation fixed1 = vp1.getSecond(); |
| Pair<ICPPEvaluation, ICPPEvaluation> vp2 = EvalUtil.getValuePair(fArg2, record, context); |
| final ICPPEvaluation fixed2 = vp2.getSecond(); |
| ICPPEvaluation eval = fixed1 == fArg1 && fixed2 == fArg2 ? this : new EvalBinary(fOperator, fixed1, fixed2, getTemplateDefinition()); |
| |
| if (isBinaryOperationWithAssignment(fOperator)) { |
| if (isPointerToArray(fixed1) && hasIntType(fixed2)) { |
| EvalPointer evalPointer = (EvalPointer) fixed1; |
| int currentPos = evalPointer.getPosition(); |
| int rhs = fixed2.getValue().numberValue().intValue(); |
| |
| if (fOperator == op_plusAssign) { |
| evalPointer.setPosition(currentPos + rhs); |
| } else if (fOperator == op_minusAssign) { |
| evalPointer.setPosition(currentPos - rhs); |
| } else { |
| return EvalFixed.INCOMPLETE; |
| } |
| } else { |
| if (updateable1 == EvalFixed.INCOMPLETE) |
| return EvalFixed.INCOMPLETE; |
| int binaryOperator = getBinaryOperatorWithoutAssignment(fOperator); |
| EvalBinary binaryOpEval = new EvalBinary(binaryOperator, fixed1, fixed2, getTemplateDefinition()); |
| EvalBinary assignmentEval = new EvalBinary(op_assign, updateable1, binaryOpEval, getTemplateDefinition()); |
| return assignmentEval.computeForFunctionCall(record, context); |
| } |
| } else if (fOperator == op_assign) { |
| ICPPEvaluation newValue = null; |
| if (fixed2 instanceof EvalPointer) { |
| newValue = fixed2; |
| } else { |
| newValue = new EvalFixed(fixed2.getType(), fixed2.getValueCategory(), fixed2.getValue()); |
| } |
| |
| if (updateable1 instanceof EvalReference && !(updateable1 instanceof EvalPointer)) { |
| EvalReference evalRef = (EvalReference) updateable1; |
| evalRef.update(newValue); |
| } else if (updateable1 instanceof EvalCompositeAccess) { |
| EvalCompositeAccess evalCompAccess = (EvalCompositeAccess) updateable1; |
| evalCompAccess.update(newValue); |
| } else if (updateable1 instanceof EvalBinding) { |
| EvalBinding evalBinding = (EvalBinding) updateable1; |
| record.update(evalBinding.getBinding(), newValue); |
| } |
| return updateable1; |
| } else if (fOperator == op_arrayAccess) { |
| Number numericValue = fixed2.getValue().numberValue(); |
| if (numericValue == null) |
| return EvalFixed.INCOMPLETE; |
| ICPPEvaluation composite = fixed1; |
| int arrayIndex = numericValue.intValue(); |
| if (fixed1 instanceof EvalPointer) { |
| ICPPEvaluation elementEval = ((EvalPointer) fixed1).getTargetEvaluation(); |
| if (elementEval instanceof EvalCompositeAccess) { |
| // 'composite' will now be the underlying array that the pointer points into. |
| // Since the pointer may not point at the beginning of the array, the array |
| // index needs to be shifted by the pointer's position. |
| composite = ((EvalCompositeAccess) elementEval).getParent(); |
| arrayIndex += ((EvalPointer) fixed1).getPosition(); |
| } |
| } |
| return new EvalCompositeAccess(composite, arrayIndex); |
| } else if ((isArray(fixed1) || isArray(fixed2)) && (hasIntType(fixed1) || hasIntType(fixed2))) { |
| int offset = hasIntType(fixed1) ? fixed1.getValue().numberValue().intValue() : fixed2.getValue().numberValue().intValue(); |
| EvalCompositeAccess evalCompositeAccess = new EvalCompositeAccess(isArray(fixed1) ? fixed1 : fixed2, offset); |
| return new EvalPointer(record, evalCompositeAccess, evalCompositeAccess.getTemplateDefinition()); |
| } else if ((isPointerToArray(fixed1) || isPointerToArray(fixed2)) && (hasIntType(fixed1) || hasIntType(fixed2))) { |
| final EvalPointer pointer = isPointerToArray(fixed1) ? ((EvalPointer) fixed1).copy() : ((EvalPointer) fixed2).copy(); |
| pointer.setPosition(eval.getValue().numberValue().intValue()); |
| return pointer; |
| } |
| return eval; |
| } |
| |
| private boolean hasIntType(ICPPEvaluation arg2) { |
| IType type = arg2.getType(); |
| return (type instanceof IBasicType && ((IBasicType) type).getKind() == IBasicType.Kind.eInt); |
| } |
| |
| private boolean isArray(ICPPEvaluation eval) { |
| return eval.getType() instanceof IArrayType; |
| } |
| |
| private boolean isPointerToArray(ICPPEvaluation argument) { |
| if (argument instanceof EvalPointer) { |
| EvalPointer evalPointer = (EvalPointer) argument; |
| ICPPEvaluation pointerValue = evalPointer.dereference().getTargetEvaluation(); |
| // TODO(nathanridge): What if the composite being accessed is not an array but a structure? |
| return pointerValue instanceof EvalCompositeAccess; |
| } |
| return false; |
| } |
| |
| private static boolean isBinaryOperationWithAssignment(int operator) { |
| switch (operator) { |
| case op_binaryAndAssign: |
| case op_binaryOrAssign: |
| case op_binaryXorAssign: |
| case op_divideAssign: |
| case op_plusAssign: |
| case op_minusAssign: |
| case op_multiplyAssign: |
| case op_moduloAssign: |
| case op_shiftLeftAssign: |
| case op_shiftRightAssign: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| private static int getBinaryOperatorWithoutAssignment(int operator) { |
| switch (operator) { |
| case op_binaryAndAssign: |
| return op_binaryAnd; |
| case op_binaryOrAssign: |
| return op_binaryOr; |
| case op_binaryXorAssign: |
| return op_binaryXor; |
| case op_divideAssign: |
| return op_divide; |
| case op_plusAssign: |
| return op_plus; |
| case op_minusAssign: |
| return op_minus; |
| case op_multiplyAssign: |
| return op_multiply; |
| case op_moduloAssign: |
| return op_modulo; |
| case op_shiftLeftAssign: |
| return op_shiftLeft; |
| case op_shiftRightAssign: |
| return op_shiftRight; |
| default: |
| throw new IllegalArgumentException("Operator must be binary operation with assignment"); //$NON-NLS-1$ |
| } |
| } |
| |
| @Override |
| public int determinePackSize(ICPPTemplateParameterMap tpMap) { |
| return CPPTemplates.combinePackSize(fArg1.determinePackSize(tpMap), fArg2.determinePackSize(tpMap)); |
| } |
| |
| @Override |
| public boolean referencesTemplateParameter() { |
| return fArg1.referencesTemplateParameter() || fArg2.referencesTemplateParameter(); |
| } |
| |
| @Override |
| public String toString() { |
| return fArg1.toString() + " <op> " + fArg2.toString(); //$NON-NLS-1$ |
| } |
| } |