Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c++ apply integer conversions add tests #284

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12793,6 +12793,66 @@ public void testNegativeCastToUnsigned_544509() throws Exception {
helper.assertVariableValue("waldo", 0);
}

// constexpr int int_from_positive_long = (1L << 32) + 1;
// constexpr short short_from_positive_long = (1L << 32) + 1;
// constexpr unsigned int uint_from_positive_long = (1L << 32) + 1;
// constexpr unsigned short ushort_from_positive_long = (1L << 32) + 1;
//
// constexpr int int_from_negative_long = -((1L << 32) + 1);
// constexpr short short_from_negative_long = -((1L << 32) + 1);
// constexpr unsigned int uint_from_negative_long = -((1L << 32) + 1);
// constexpr unsigned short ushort_from_negative_long = -((1L << 32) + 1);
public void testIntegerImplicitConversions() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();

helper.assertVariableValue("int_from_positive_long", 1);
helper.assertVariableValue("short_from_positive_long", 1);
helper.assertVariableValue("uint_from_positive_long", 1);
helper.assertVariableValue("ushort_from_positive_long", 1);

helper.assertVariableValue("int_from_negative_long", -1);
helper.assertVariableValue("short_from_negative_long", -1);
helper.assertVariableValue("uint_from_negative_long", (1L << 32) - 1);
helper.assertVariableValue("ushort_from_negative_long", (1L << 16) - 1);
}

// constexpr bool bool_from_int_positive = 2;
// constexpr bool bool_from_int_negative = -2;
// constexpr bool bool_from_int_0 = 0;
// constexpr bool bool_from_int_expr = int(0x100000001L) < 2;
// constexpr bool bool_from_short_expr = short(0x100010001L) < 2;
// constexpr int int_from_cast_to_int = (int)((1L << 32) + 1);
public void testIntegerTrunctatingConversions() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableValue("bool_from_int_positive", 1);
helper.assertVariableValue("bool_from_int_negative", 1);
helper.assertVariableValue("bool_from_int_0", 0);
helper.assertVariableValue("bool_from_int_expr", 1);
helper.assertVariableValue("bool_from_short_expr", 1);
helper.assertVariableValue("int_from_cast_to_int", 1);
}

// constexpr unsigned int uint_from_ulong_literal = -1UL;
// constexpr unsigned int uint_from_ulong_negation = -(1UL);
// constexpr unsigned short ushort_from_ulong_literal = -1UL;
// constexpr unsigned short ushort_from_ulong_negation = -(1UL);
//
// constexpr unsigned int uint_from_uint_literal_negation = -(1U);
// constexpr unsigned int uint_from_uint_cast_negation = -(1U);
// constexpr unsigned short ushort_from_ushort_cast_negation = -((unsigned short)1);
public void testUnsignedIntegerUnaryMinus() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();

helper.assertVariableValue("uint_from_ulong_literal", (1L << 32) - 1);
helper.assertVariableValue("uint_from_ulong_negation", (1L << 32) - 1);
helper.assertVariableValue("ushort_from_ulong_literal", (1L << 16) - 1);
helper.assertVariableValue("ushort_from_ulong_negation", (1L << 16) - 1);

helper.assertVariableValue("uint_from_uint_literal_negation", (1L << 32) - 1);
helper.assertVariableValue("uint_from_uint_cast_negation", (1L << 32) - 1);
helper.assertVariableValue("ushort_from_ushort_cast_negation", (1L << 16) - 1);
}

// namespace x {
// void foo();
// }
Expand Down Expand Up @@ -13761,4 +13821,28 @@ public void testNullPointerConstantConversion_573764() throws Exception {
// Invalid argument (not null pointer constant)
assertTrue(collector.getName(callIndexStart + 13).resolveBinding() instanceof IProblemBinding);
}

// template <typename SignedType, typename UnsignedType>
// constexpr bool calculate(SignedType x, UnsignedType y) {
// if (sizeof(x) == sizeof(y)) {
// return x - y >= 0;
// } else {
// return true;
// }
// }
//
// constexpr auto test_32 = calculate<signed long, unsigned int>(1, 2);
// constexpr auto test_64 = calculate<signed long long, unsigned long>(1, 2);
public void testArithmeticConversionIssue_265() throws Exception {
// Depending on size of integer types above it may happen that the rank of unsigned type operand
// is less than rank of signed type operand, and both types are of same size.
// If so the conversion is to unsigned integer type corresponding to the type of the operand
// with signed integer type, and calculated result cannot be less than zero - check it.
// 32-bit case used to fail with signed long and unsigned int,
// 64-bit case used to fail with signed long long and unsigned long.
parseAndCheckBindings();
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableValue("test_32", 1);
helper.assertVariableValue("test_64", 1);
}
}
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, 2014 Google, Inc and others.
* Copyright (c) 2012, 2014, 2023 Google, 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:
* Sergey Prigogin (Google) - initial API and implementation
* Nathan Ridge
* Igor V. Kovalenko
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;

Expand All @@ -34,6 +35,7 @@
import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
import org.eclipse.core.runtime.CoreException;

public abstract class CPPEvaluation implements ICPPEvaluation {
Expand Down Expand Up @@ -207,9 +209,12 @@ protected static ICPPEvaluation maybeApplyConversion(ICPPEvaluation argument, IT

// Source type is not a class type, or is but a conversion operator wasn't used.
// Check for standard conversions.
if (!Conversions.checkImplicitConversionSequence(targetType, type, valueCategory, UDCMode.FORBIDDEN,
Context.ORDINARY).converts()) {
Cost cost = Conversions.checkImplicitConversionSequence(targetType, type, valueCategory, UDCMode.FORBIDDEN,
Context.ORDINARY);
if (!cost.converts()) {
return EvalFixed.INCOMPLETE;
} else if (cost.getRank() == Rank.CONVERSION) {
return new EvalTypeId(targetType, argument.getTemplateDefinition(), false, false, argument);
}
} catch (DOMException e) {
CCorePlugin.log(e);
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
Loading