Skip to content

Commit

Permalink
Fix type conversion in unary and binary expression evaluations.
Browse files Browse the repository at this point in the history
  • Loading branch information
i-garrison authored and jonahgraham committed Feb 13, 2023
1 parent 09ab420 commit c022046
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2015 Wind River Systems, Inc. and others.
* Copyright (c) 2009, 2015, 2023 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -77,6 +77,14 @@ public final IType convertOperandTypes(int operator, IType op1, IType op2) {
case IASTBinaryExpression.op_max:
case IASTBinaryExpression.op_min:
return convert(op1, op2);
// Relational operators
case IASTBinaryExpression.op_lessEqual:
case IASTBinaryExpression.op_lessThan:
case IASTBinaryExpression.op_greaterEqual:
case IASTBinaryExpression.op_greaterThan:
case IASTBinaryExpression.op_equals:
case IASTBinaryExpression.op_notequals:
return convert(op1, op2);

case IASTBinaryExpression.op_shiftLeft:
case IASTBinaryExpression.op_shiftRight:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2014 Wind River Systems, Inc. and others.
* Copyright (c) 2008, 2014, 2023 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -11,6 +11,7 @@
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
* Igor V. Kovalenko
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;

Expand Down Expand Up @@ -41,6 +42,7 @@
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;

import java.util.Arrays;
import java.util.function.LongBinaryOperator;

import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
Expand All @@ -52,6 +54,7 @@
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
Expand Down Expand Up @@ -92,8 +95,8 @@ public static IValue create(IASTExpression expr) {
return val;
}

if (expr instanceof ICPPASTInitializerClause) {
ICPPEvaluation evaluation = ((ICPPASTInitializerClause) expr).getEvaluation();
if (expr instanceof ICPPASTInitializerClause clause) {
ICPPEvaluation evaluation = clause.getEvaluation();
return evaluation.getValue();
}
return IntegralValue.UNKNOWN;
Expand All @@ -102,14 +105,14 @@ public static IValue create(IASTExpression expr) {
}
}

public static IValue evaluateUnaryExpression(final int unaryOp, final IValue value) {
IValue val = applyUnaryOperator(unaryOp, value);
public static IValue evaluateUnaryExpression(final int unaryOp, final IValue value, final IType type) {
IValue val = applyUnaryOperator(unaryOp, value, type);
if (isInvalidValue(val))
return IntegralValue.UNKNOWN;
return val;
}

public static IValue evaluateBinaryExpression(final int op, final IValue v1, final IValue v2) {
public static IValue evaluateBinaryExpression(final int op, final IValue v1, final IValue v2, final IType type) {
if (v1 instanceof FloatingPointValue && v2 instanceof FloatingPointValue) {
FloatingPointValue fv1 = (FloatingPointValue) v1;
FloatingPointValue fv2 = (FloatingPointValue) v2;
Expand All @@ -125,7 +128,7 @@ public static IValue evaluateBinaryExpression(final int op, final IValue v1, fin
} else if (v1 instanceof IntegralValue && v2 instanceof IntegralValue) {
IntegralValue iv1 = (IntegralValue) v1;
IntegralValue iv2 = (IntegralValue) v2;
return applyBinaryOperator(op, iv1.numberValue().longValue(), iv2.numberValue().longValue());
return applyBinaryOperator(op, iv1.numberValue().longValue(), iv2.numberValue().longValue(), type);
}
return IntegralValue.UNKNOWN;
}
Expand Down Expand Up @@ -184,7 +187,16 @@ private static IValue applyBinaryOperator(final int op, final double v1, final d
}
}

private static IntegralValue applyBinaryOperator(final int op, final long v1, final long v2) {
private static IntegralValue applyBinaryOperator(final int op, final long v1, final long v2, final IType type) {
if ((v1 < 0 || v2 < 0) && type instanceof IBasicType basicType && basicType.isUnsigned()) {
return applyBinaryOperator(op, v1, v2, (x, y) -> Long.compareUnsigned(x, y));
} else {
return applyBinaryOperator(op, v1, v2, (x, y) -> Long.compare(x, y));
}
}

private static IntegralValue applyBinaryOperator(final int op, final long v1, final long v2,
LongBinaryOperator comparator) {
Long value = null;
switch (op) {
case IASTBinaryExpression.op_multiply:
Expand Down Expand Up @@ -213,20 +225,20 @@ private static IntegralValue applyBinaryOperator(final int op, final long v1, fi
value = v1 >> v2;
break;
case IASTBinaryExpression.op_lessThan:
value = v1 < v2 ? 1l : 0l;
value = comparator.applyAsLong(v1, v2) < 0 ? 1l : 0l;
break;
case IASTBinaryExpression.op_greaterThan:
value = v1 > v2 ? 1l : 0l;
value = comparator.applyAsLong(v1, v2) > 0 ? 1l : 0l;
break;
case IASTBinaryExpression.op_lessEqual:
value = v1 <= v2 ? 1l : 0l;
value = comparator.applyAsLong(v1, v2) <= 0 ? 1l : 0l;
break;
case IASTBinaryExpression.op_greaterEqual:
value = v1 >= v2 ? 1l : 0l;
value = comparator.applyAsLong(v1, v2) >= 0 ? 1l : 0l;
break;
case IASTBinaryExpression.op_threewaycomparison:
// TODO: implement for <=>
value = v1 < v2 ? -1l : (v1 > v2 ? 1l : 0);
value = comparator.applyAsLong(v1, v2);
break;
case IASTBinaryExpression.op_binaryAnd:
value = v1 & v2;
Expand All @@ -250,10 +262,10 @@ private static IntegralValue applyBinaryOperator(final int op, final long v1, fi
value = v1 != v2 ? 1l : 0l;
break;
case IASTBinaryExpression.op_max:
value = Math.max(v1, v2);
value = comparator.applyAsLong(v1, v2) >= 0 ? v1 : v2;
break;
case IASTBinaryExpression.op_min:
value = Math.min(v1, v2);
value = comparator.applyAsLong(v1, v2) <= 0 ? v1 : v2;
break;
}

Expand Down Expand Up @@ -514,10 +526,10 @@ private static IValue evaluateUnaryExpression(IASTUnaryExpression exp) {
return value;
if (isDeferredValue(value))
return null; // the value will be computed using the evaluation
return applyUnaryOperator(unaryOp, value);
return applyUnaryOperator(unaryOp, value, exp.getExpressionType());
}

private static IValue applyUnaryOperator(final int unaryOp, final IValue value) {
private static IValue applyUnaryOperator(final int unaryOp, final IValue value, final IType type) {
if (isInvalidValue(value) || value.numberValue() == null) {
return IntegralValue.UNKNOWN;
}
Expand Down Expand Up @@ -548,6 +560,15 @@ private static IValue applyUnaryOperator(final int unaryOp, final IValue value)
}
case IASTUnaryExpression.op_minus:
if (value instanceof IntegralValue) {
if (type instanceof IBasicType basicType && basicType.isUnsigned()) {
SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(basicType);
if (sizeAndAlignment != null && sizeAndAlignment.size < 8) {
long range = (1L << (sizeAndAlignment.size * 8));
return IntegralValue.create(range - value.numberValue().longValue());
}

return IntegralValue.create(-value.numberValue().longValue());
}
return IntegralValue.create(-value.numberValue().longValue());
} else {
FloatingPointValue fpv = (FloatingPointValue) value;
Expand Down Expand Up @@ -593,7 +614,8 @@ private static IValue evaluateBinaryExpression(IASTBinaryExpression exp) {
return o2;
if (isDeferredValue(o1) || isDeferredValue(o2))
return null; // the value will be computed using the evaluation
return evaluateBinaryExpression(op, o1, o2);
IType exprType = exp.getExpressionType();
return evaluateBinaryExpression(op, o1, o2, exprType);
}

private static IValue applyBinaryTypeIdOperator(IASTBinaryTypeIdExpression.Operator operator, IType type1,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012, 2017 Wind River Systems, Inc. and others.
* Copyright (c) 2012, 2017, 2023 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -240,7 +240,7 @@ public IValue getValue() {

Number num2 = v2.numberValue();
if (num2 != null) {
return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2);
return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2, getType());
}
}
return DependentValue.create(this);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012, 2014 Wind River Systems, Inc. and others.
* Copyright (c) 2012, 2014, 2023 Wind River Systems, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -357,7 +357,7 @@ public IValue getValue() {
if (val == null)
return IntegralValue.UNKNOWN;

return ValueFactory.evaluateUnaryExpression(fOperator, val);
return ValueFactory.evaluateUnaryExpression(fOperator, val, getType());
}

@Override
Expand Down

0 comments on commit c022046

Please sign in to comment.