mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 01:15:29 +02:00
Apply truncation and sign-extension to result of initializer evaluation
This commit is contained in:
parent
8dd97763a3
commit
beb201e082
3 changed files with 138 additions and 55 deletions
|
@ -12793,6 +12793,66 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
|||
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();
|
||||
// }
|
||||
|
|
|
@ -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
|
||||
|
@ -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.cpp.semantics;
|
||||
|
||||
|
@ -41,8 +42,6 @@ import org.eclipse.cdt.internal.core.dom.parser.CompositeValue;
|
|||
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.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
|
@ -192,25 +191,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
}
|
||||
if (fArguments.length == 1) {
|
||||
IValue argVal = fArguments[0].getValue();
|
||||
if (argVal instanceof IntegralValue && argVal.numberValue() != null) {
|
||||
// Cast signed integer to unsigned.
|
||||
Long val = argVal.numberValue().longValue();
|
||||
if (val < 0 && inputType instanceof ICPPBasicType && ((ICPPBasicType) inputType).isUnsigned()) {
|
||||
SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(inputType);
|
||||
if (sizeAndAlignment != null) {
|
||||
long sizeof = sizeAndAlignment.size;
|
||||
if (sizeof > 4) {
|
||||
// Java's "long" can't represent the full range of an 64-bit unsigned integer
|
||||
// in C++.
|
||||
sizeof = 4;
|
||||
}
|
||||
long range = (1L << (sizeof * 8 - 1));
|
||||
val += range;
|
||||
return IntegralValue.create(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return argVal;
|
||||
return SemanticUtil.applyIntegerConversion(argVal, inputType);
|
||||
}
|
||||
return IntegralValue.UNKNOWN;
|
||||
}
|
||||
|
@ -253,6 +234,11 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
if (getConstructor() == null && fArguments.length == 1) {
|
||||
// maybe EvalTypeID represents a conversion
|
||||
ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false);
|
||||
if (isEquivalentTo(conversionEval)) {
|
||||
// still the same conversion, no need to recurse into isConstantExpression()
|
||||
conversionEval = fArguments[0];
|
||||
}
|
||||
|
||||
if (!conversionEval.isConstantExpression())
|
||||
return false;
|
||||
}
|
||||
|
@ -504,6 +490,10 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
} else if (fArguments.length == 1) {
|
||||
// maybe EvalTypeID represents a conversion
|
||||
ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false);
|
||||
if (isEquivalentTo(conversionEval)) {
|
||||
// still the same conversion, no need to recurse into isConstantExpression()
|
||||
conversionEval = fArguments[0];
|
||||
}
|
||||
return conversionEval.isNoexcept();
|
||||
}
|
||||
for (ICPPEvaluation arg : fArguments) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2015 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2015, 2023 IBM Corporation and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
|
@ -15,6 +15,7 @@
|
|||
* Andrew Ferguson (Symbian)
|
||||
* Sergey Prigogin (Google)
|
||||
* Nathan Ridge
|
||||
* Igor V. Kovalenko
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
|
@ -78,6 +79,8 @@ import org.eclipse.cdt.core.parser.util.ObjectSet;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ValueFactory;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
|
||||
|
@ -860,45 +863,75 @@ public class SemanticUtil {
|
|||
* @param type the type of the variable
|
||||
*/
|
||||
public static IValue getValueOfInitializer(IASTInitializer init, IType type) {
|
||||
IASTInitializerClause clause = null;
|
||||
// applyIntegerConversion() uses SizeofCalculator, make sure AST is available via lookup point
|
||||
CPPSemantics.pushLookupPoint(init);
|
||||
try {
|
||||
if (init instanceof IASTEqualsInitializer) {
|
||||
clause = ((IASTEqualsInitializer) init).getInitializerClause();
|
||||
} else if (init instanceof ICPPASTConstructorInitializer) {
|
||||
IASTInitializerClause[] args = ((ICPPASTConstructorInitializer) init).getArguments();
|
||||
if (args.length == 1 && args[0] instanceof IASTExpression) {
|
||||
IType typeUpToPointers = SemanticUtil.getUltimateTypeUptoPointers(type);
|
||||
if (typeUpToPointers instanceof IPointerType || typeUpToPointers instanceof IBasicType) {
|
||||
clause = args[0];
|
||||
}
|
||||
}
|
||||
} else if (init instanceof ICPPASTInitializerList) {
|
||||
ICPPASTInitializerList list = (ICPPASTInitializerList) init;
|
||||
switch (list.getSize()) {
|
||||
case 0:
|
||||
return IntegralValue.create(0);
|
||||
case 1:
|
||||
clause = list.getClauses()[0];
|
||||
break;
|
||||
default:
|
||||
return ((ICPPASTInitializerList) init).getEvaluation().getValue();
|
||||
|
||||
}
|
||||
}
|
||||
if (clause instanceof IASTExpression) {
|
||||
return ValueFactory.create((IASTExpression) clause);
|
||||
}
|
||||
|
||||
if (clause instanceof ICPPASTInitializerList) {
|
||||
return ((ICPPASTInitializerList) clause).getEvaluation().getValue();
|
||||
}
|
||||
return IntegralValue.UNKNOWN;
|
||||
return SemanticUtil.applyIntegerConversion(getValueOfInitializerImpl(init, type), type);
|
||||
} finally {
|
||||
CPPSemantics.popLookupPoint();
|
||||
}
|
||||
}
|
||||
|
||||
private static IValue getValueOfInitializerImpl(IASTInitializer init, IType type) {
|
||||
IASTInitializerClause clause = null;
|
||||
if (init instanceof IASTEqualsInitializer) {
|
||||
clause = ((IASTEqualsInitializer) init).getInitializerClause();
|
||||
} else if (init instanceof ICPPASTConstructorInitializer) {
|
||||
IASTInitializerClause[] args = ((ICPPASTConstructorInitializer) init).getArguments();
|
||||
if (args.length == 1 && args[0] instanceof IASTExpression) {
|
||||
IType typeUpToPointers = SemanticUtil.getUltimateTypeUptoPointers(type);
|
||||
if (typeUpToPointers instanceof IPointerType || typeUpToPointers instanceof IBasicType) {
|
||||
clause = args[0];
|
||||
}
|
||||
}
|
||||
} else if (init instanceof ICPPASTInitializerList) {
|
||||
ICPPASTInitializerList list = (ICPPASTInitializerList) init;
|
||||
switch (list.getSize()) {
|
||||
case 0:
|
||||
return IntegralValue.create(0);
|
||||
case 1:
|
||||
clause = list.getClauses()[0];
|
||||
break;
|
||||
default:
|
||||
return ((ICPPASTInitializerList) init).getEvaluation().getValue();
|
||||
|
||||
}
|
||||
}
|
||||
if (clause instanceof IASTExpression) {
|
||||
return ValueFactory.create((IASTExpression) clause);
|
||||
}
|
||||
|
||||
if (clause instanceof ICPPASTInitializerList) {
|
||||
return ((ICPPASTInitializerList) clause).getEvaluation().getValue();
|
||||
}
|
||||
return IntegralValue.UNKNOWN;
|
||||
}
|
||||
|
||||
public static IValue applyIntegerConversion(IValue value, IType targetType) {
|
||||
if (value instanceof IntegralValue && value.numberValue() != null
|
||||
&& SemanticUtil.getUltimateTypeUptoPointers(targetType) instanceof IBasicType basicType) {
|
||||
if (basicType.getKind() == Kind.eBoolean) {
|
||||
return IntegralValue.create(value.numberValue().longValue() == 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
// Cast to different size and signedness
|
||||
SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(basicType);
|
||||
if (sizeAndAlignment != null && sizeAndAlignment.size < 8) {
|
||||
long val = value.numberValue().longValue();
|
||||
boolean doSignExtend = val < 0 && !basicType.isUnsigned();
|
||||
long mask = (1L << (sizeAndAlignment.size * 8)) - 1;
|
||||
// truncate
|
||||
val &= mask;
|
||||
if (doSignExtend) {
|
||||
//sign-extend
|
||||
val |= ~mask;
|
||||
}
|
||||
return IntegralValue.create(val);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a type is const or a reference to a const type.
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue