mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 17:35:35 +02:00
Fix assertion evaluating binary shifts of comparison op results
Currently CDT evaluates result type of comparison ops to the converted type of their operands. When floating point values are compared and then the result is binary shifted this trips an assertion trying to promote floating point value. Fix this by limiting operand types of binary shifts to integral or unscoped enumerations. Additionally fix return type of comparison op to be boolean value.
This commit is contained in:
parent
c69eed48e3
commit
f1c15e3a3d
3 changed files with 61 additions and 15 deletions
|
@ -96,6 +96,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
|||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
|
||||
|
@ -147,6 +148,7 @@ import org.eclipse.cdt.core.parser.IProblem;
|
|||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
import org.eclipse.cdt.core.parser.util.AttributeUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
|
||||
|
@ -13845,4 +13847,29 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
|||
helper.assertVariableValue("test_32", 1);
|
||||
helper.assertVariableValue("test_64", 1);
|
||||
}
|
||||
|
||||
// constexpr auto shiftdouble = (1. << 1);
|
||||
public void testArithmeticEvaluationWithDoubleShiftOp() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
IVariable shiftdouble = helper.assertNonProblem("shiftdouble = ", 11);
|
||||
IValue value = shiftdouble.getInitialValue();
|
||||
assertTrue(IntegralValue.ERROR.equals(value) || IntegralValue.UNKNOWN.equals(value));
|
||||
}
|
||||
|
||||
// constexpr auto shiftdouble = (1. <<= 1);
|
||||
public void testArithmeticEvaluationWithDoubleShiftAssignOp() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
IVariable shiftdouble = helper.assertNonProblem("shiftdouble = ", 11);
|
||||
IValue value = shiftdouble.getInitialValue();
|
||||
assertTrue(IntegralValue.ERROR.equals(value) || IntegralValue.UNKNOWN.equals(value));
|
||||
}
|
||||
|
||||
// enum Shift { Horizontal, Vertical };
|
||||
// constexpr double zero = 0.;
|
||||
// constexpr double x = 1., y = 1.;
|
||||
// constexpr int shiftpack = ((x > zero) << Horizontal) | ((y > zero) << Vertical);
|
||||
public void testArithmeticEvaluationOfRelationalOps() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertVariableValue("shiftpack", 3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,12 @@ public abstract class ArithmeticConversion {
|
|||
return convert(op1, op2);
|
||||
|
||||
case IASTBinaryExpression.op_shiftLeft:
|
||||
case IASTBinaryExpression.op_shiftLeftAssign:
|
||||
case IASTBinaryExpression.op_shiftRight:
|
||||
case IASTBinaryExpression.op_shiftRightAssign:
|
||||
if (!isIntegralOrUnscopedEnum(op1) || !isIntegralOrUnscopedEnum(op2)) {
|
||||
return null;
|
||||
}
|
||||
return promote(op1, getDomain(op1));
|
||||
|
||||
default:
|
||||
|
|
|
@ -101,6 +101,7 @@ public class EvalBinary extends CPPDependentEvaluation {
|
|||
private ICPPFunction fOverload = CPPFunction.UNINITIALIZED_FUNCTION;
|
||||
private ICPPEvaluation fOverloadCall;
|
||||
private IType fType;
|
||||
private IType fCommonType;
|
||||
private boolean fCheckedIsConstantExpression;
|
||||
private boolean fIsConstantExpression;
|
||||
|
||||
|
@ -160,6 +161,13 @@ public class EvalBinary extends CPPDependentEvaluation {
|
|||
return fType;
|
||||
}
|
||||
|
||||
private IType getCommonType() {
|
||||
if (fCommonType == null) {
|
||||
fCommonType = computeCommonType();
|
||||
}
|
||||
return fCommonType;
|
||||
}
|
||||
|
||||
private ICPPEvaluation createOperatorOverloadEvaluation(ICPPFunction overload, ICPPEvaluation arg1,
|
||||
ICPPEvaluation arg2) {
|
||||
EvalFunctionCall operatorCall;
|
||||
|
@ -240,7 +248,7 @@ public class EvalBinary extends CPPDependentEvaluation {
|
|||
|
||||
Number num2 = v2.numberValue();
|
||||
if (num2 != null) {
|
||||
return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2, getType());
|
||||
return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2, getCommonType());
|
||||
}
|
||||
}
|
||||
return DependentValue.create(this);
|
||||
|
@ -352,6 +360,26 @@ public class EvalBinary extends CPPDependentEvaluation {
|
|||
if (o != null)
|
||||
return typeFromFunctionCall(o);
|
||||
|
||||
switch (fOperator) {
|
||||
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_threewaycomparison:
|
||||
// TODO: implement for <=>
|
||||
return ProblemType.UNKNOWN_FOR_EXPRESSION;
|
||||
}
|
||||
|
||||
return getCommonType();
|
||||
}
|
||||
|
||||
private IType computeCommonType() {
|
||||
final IType originalType1 = fArg1.getType();
|
||||
final IType type1 = prvalueTypeWithResolvedTypedefs(originalType1);
|
||||
if (type1 instanceof ISemanticProblem) {
|
||||
|
@ -379,20 +407,6 @@ public class EvalBinary extends CPPDependentEvaluation {
|
|||
}
|
||||
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_threewaycomparison:
|
||||
// TODO: implement for <=>
|
||||
return ProblemType.UNKNOWN_FOR_EXPRESSION;
|
||||
|
||||
case op_plus:
|
||||
if (type1 instanceof IPointerType) {
|
||||
return ExpressionTypes.restoreTypedefs(type1, originalType1);
|
||||
|
|
Loading…
Add table
Reference in a new issue