mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-10 09:45:39 +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);
|
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 {
|
// namespace x {
|
||||||
// void foo();
|
// 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
|
* This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License 2.0
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Markus Schorn - initial API and implementation
|
* Markus Schorn - initial API and implementation
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
|
* Igor V. Kovalenko
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
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.DependentValue;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
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.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.CPPFunction;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
|
@ -192,25 +191,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
||||||
}
|
}
|
||||||
if (fArguments.length == 1) {
|
if (fArguments.length == 1) {
|
||||||
IValue argVal = fArguments[0].getValue();
|
IValue argVal = fArguments[0].getValue();
|
||||||
if (argVal instanceof IntegralValue && argVal.numberValue() != null) {
|
return SemanticUtil.applyIntegerConversion(argVal, inputType);
|
||||||
// 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 IntegralValue.UNKNOWN;
|
return IntegralValue.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
@ -253,6 +234,11 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
||||||
if (getConstructor() == null && fArguments.length == 1) {
|
if (getConstructor() == null && fArguments.length == 1) {
|
||||||
// maybe EvalTypeID represents a conversion
|
// maybe EvalTypeID represents a conversion
|
||||||
ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false);
|
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())
|
if (!conversionEval.isConstantExpression())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -504,6 +490,10 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
||||||
} else if (fArguments.length == 1) {
|
} else if (fArguments.length == 1) {
|
||||||
// maybe EvalTypeID represents a conversion
|
// maybe EvalTypeID represents a conversion
|
||||||
ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false);
|
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();
|
return conversionEval.isNoexcept();
|
||||||
}
|
}
|
||||||
for (ICPPEvaluation arg : fArguments) {
|
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
|
* This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License 2.0
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
* Andrew Ferguson (Symbian)
|
* Andrew Ferguson (Symbian)
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
* Nathan Ridge
|
* Nathan Ridge
|
||||||
|
* Igor V. Kovalenko
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
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.ASTTranslationUnit;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
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.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.ValueFactory;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
|
||||||
|
@ -860,45 +863,75 @@ public class SemanticUtil {
|
||||||
* @param type the type of the variable
|
* @param type the type of the variable
|
||||||
*/
|
*/
|
||||||
public static IValue getValueOfInitializer(IASTInitializer init, IType type) {
|
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);
|
CPPSemantics.pushLookupPoint(init);
|
||||||
try {
|
try {
|
||||||
if (init instanceof IASTEqualsInitializer) {
|
return SemanticUtil.applyIntegerConversion(getValueOfInitializerImpl(init, type), type);
|
||||||
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;
|
|
||||||
} finally {
|
} finally {
|
||||||
CPPSemantics.popLookupPoint();
|
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.
|
* Returns whether a type is const or a reference to a const type.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue