}
namespace {
+/// The promoted range of values of a type. In general this has the
+/// following structure:
+///
+/// |-----------| . . . |-----------|
+/// ^ ^ ^ ^
+/// Min HoleMin HoleMax Max
+///
+/// ... where there is only a hole if a signed type is promoted to unsigned
+/// (in which case Min and Max are the smallest and largest representable
+/// values).
+struct PromotedRange {
+ // Min, or HoleMax if there is a hole.
+ llvm::APSInt PromotedMin;
+ // Max, or HoleMin if there is a hole.
+ llvm::APSInt PromotedMax;
+
+ PromotedRange(IntRange R, unsigned BitWidth, bool Unsigned) {
+ if (R.Width == 0)
+ PromotedMin = PromotedMax = llvm::APSInt(BitWidth, Unsigned);
+ else if (R.Width >= BitWidth && !Unsigned) {
+ // Promotion made the type *narrower*. This happens when promoting
+ // a < 32-bit unsigned / <= 32-bit signed bit-field to 'signed int'.
+ // Treat all values of 'signed int' as being in range for now.
+ PromotedMin = llvm::APSInt::getMinValue(BitWidth, Unsigned);
+ PromotedMax = llvm::APSInt::getMaxValue(BitWidth, Unsigned);
+ } else {
+ PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative)
+ .extOrTrunc(BitWidth);
+ PromotedMin.setIsUnsigned(Unsigned);
-enum class LimitType {
- Max = 1U << 0U, // e.g. 32767 for short
- Min = 1U << 1U, // e.g. -32768 for short
- Both = Max | Min // When the value is both the Min and the Max limit at the
- // same time; e.g. in C++, A::a in enum A { a = 0 };
-};
-
-} // namespace
-
-/// Checks whether Expr 'Constant' may be the
-/// std::numeric_limits<>::max() or std::numeric_limits<>::min()
-/// of the Expr 'Other'. If true, then returns the limit type (min or max).
-/// The Value is the evaluation of Constant
-static llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant,
- Expr *Other,
- const llvm::APSInt &Value) {
- if (IsEnumConstOrFromMacro(S, Constant))
- return llvm::Optional<LimitType>();
+ PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative)
+ .extOrTrunc(BitWidth);
+ PromotedMax.setIsUnsigned(Unsigned);
+ }
+ }
- if (isKnownToHaveUnsignedValue(Other) && Value == 0)
- return LimitType::Min;
+ // Determine whether this range is contiguous (has no hole).
+ bool isContiguous() const { return PromotedMin <= PromotedMax; }
- // TODO: Investigate using GetExprRange() to get tighter bounds
- // on the bit ranges.
- QualType OtherT = Other->IgnoreParenImpCasts()->getType();
- if (const auto *AT = OtherT->getAs<AtomicType>())
- OtherT = AT->getValueType();
+ // Where a constant value is within the range.
+ enum ComparisonResult {
+ LT = 0x1,
+ LE = 0x2,
+ GT = 0x4,
+ GE = 0x8,
+ EQ = 0x10,
+ NE = 0x20,
+ InRangeFlag = 0x40,
- IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
- if (Other->isKnownToHaveBooleanValue())
- OtherRange = IntRange::forBoolType();
+ Less = LE | LT | NE,
+ Min = LE | InRangeFlag,
+ InRange = InRangeFlag,
+ Max = GE | InRangeFlag,
+ Greater = GE | GT | NE,
- // Special-case for C++ for enum with one enumerator with value of 0.
- if (OtherRange.Width == 0)
- return Value == 0 ? LimitType::Both : llvm::Optional<LimitType>();
+ OnlyValue = LE | GE | EQ | InRangeFlag,
+ InHole = NE
+ };
- if (llvm::APSInt::isSameValue(
- llvm::APSInt::getMaxValue(OtherRange.Width, OtherRange.NonNegative),
- Value))
- return LimitType::Max;
+ ComparisonResult compare(const llvm::APSInt &Value) const {
+ assert(Value.getBitWidth() == PromotedMin.getBitWidth() &&
+ Value.isUnsigned() == PromotedMin.isUnsigned());
+ if (!isContiguous()) {
+ assert(Value.isUnsigned() && "discontiguous range for signed compare");
+ if (Value.isMinValue()) return Min;
+ if (Value.isMaxValue()) return Max;
+ if (Value >= PromotedMin) return InRange;
+ if (Value <= PromotedMax) return InRange;
+ return InHole;
+ }
+
+ switch (llvm::APSInt::compareValues(Value, PromotedMin)) {
+ case -1: return Less;
+ case 0: return PromotedMin == PromotedMax ? OnlyValue : Min;
+ case 1:
+ switch (llvm::APSInt::compareValues(Value, PromotedMax)) {
+ case -1: return InRange;
+ case 0: return Max;
+ case 1: return Greater;
+ }
+ }
- if (llvm::APSInt::isSameValue(
- llvm::APSInt::getMinValue(OtherRange.Width, OtherRange.NonNegative),
- Value))
- return LimitType::Min;
+ llvm_unreachable("impossible compare result");
+ }
- return llvm::None;
+ static llvm::Optional<bool> constantValue(BinaryOperatorKind Op,
+ ComparisonResult R,
+ bool ConstantOnRHS) {
+ ComparisonResult TrueFlag, FalseFlag;
+ if (Op == BO_EQ) {
+ TrueFlag = EQ;
+ FalseFlag = NE;
+ } else if (Op == BO_NE) {
+ TrueFlag = NE;
+ FalseFlag = EQ;
+ } else {
+ if ((Op == BO_LT || Op == BO_GE) ^ ConstantOnRHS) {
+ TrueFlag = LT;
+ FalseFlag = GE;
+ } else {
+ TrueFlag = GT;
+ FalseFlag = LE;
+ }
+ if (Op == BO_GE || Op == BO_LE)
+ std::swap(TrueFlag, FalseFlag);
+ }
+ if (R & TrueFlag)
+ return true;
+ if (R & FalseFlag)
+ return false;
+ return llvm::None;
+ }
+};
}
static bool HasEnumType(Expr *E) {
Expr *Constant, Expr *Other,
const llvm::APSInt &Value,
bool RhsConstant) {
- // Disable warning in template instantiations
- // and only analyze <, >, <= and >= operations.
- if (S.inTemplateInstantiation() || !E->isRelationalOp())
- return false;
-
- BinaryOperatorKind Op = E->getOpcode();
-
- QualType OType = Other->IgnoreParenImpCasts()->getType();
- if (!OType->isIntegerType())
- return false;
-
- // Determine which limit (min/max) the constant is, if either.
- llvm::Optional<LimitType> ValueType = IsTypeLimit(S, Constant, Other, Value);
- if (!ValueType)
- return false;
-
- bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant;
- bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE);
- if (ValueType != LimitType::Both) {
- bool ResultWhenConstNeOther =
- ConstIsLowerBound ^ (ValueType == LimitType::Max);
- if (ResultWhenConstEqualsOther != ResultWhenConstNeOther)
- return false; // The comparison is not tautological.
- } else if (ResultWhenConstEqualsOther == ConstIsLowerBound)
- return false; // The comparison is not tautological.
-
- const bool Result = ResultWhenConstEqualsOther;
-
- // Should be enough for uint128 (39 decimal digits)
- SmallString<64> PrettySourceValue;
- llvm::raw_svector_ostream OS(PrettySourceValue);
- OS << Value;
-
- // FIXME: We use a somewhat different formatting for the cases involving
- // boolean values for historical reasons. We should pick a consistent way
- // of presenting these diagnostics.
- if (Other->isKnownToHaveBooleanValue()) {
- S.DiagRuntimeBehavior(
- E->getOperatorLoc(), E,
- S.PDiag(diag::warn_tautological_bool_compare)
- << OS.str() << classifyConstantValue(Constant->IgnoreParenImpCasts())
- << OType << !OType->isBooleanType() << Result
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
- return true;
- }
-
- unsigned Diag = (isKnownToHaveUnsignedValue(Other) && Value == 0)
- ? (HasEnumType(Other)
- ? diag::warn_unsigned_enum_always_true_comparison
- : diag::warn_unsigned_always_true_comparison)
- : diag::warn_tautological_constant_compare;
-
- S.Diag(E->getOperatorLoc(), Diag)
- << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
-
- return true;
-}
-
-static bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
- Expr *Constant, Expr *Other,
- const llvm::APSInt &Value,
- bool RhsConstant) {
- // Disable warning in template instantiations.
if (S.inTemplateInstantiation())
return false;
+ Expr *OriginalOther = Other;
+
Constant = Constant->IgnoreParenImpCasts();
Other = Other->IgnoreParenImpCasts();
+ // Suppress warnings on tautological comparisons between values of the same
+ // enumeration type. There are only two ways we could warn on this:
+ // - If the constant is outside the range of representable values of
+ // the enumeration. In such a case, we should warn about the cast
+ // to enumeration type, not about the comparison.
+ // - If the constant is the maximum / minimum in-range value. For an
+ // enumeratin type, such comparisons can be meaningful and useful.
+ if (Constant->getType()->isEnumeralType() &&
+ S.Context.hasSameUnqualifiedType(Constant->getType(), Other->getType()))
+ return false;
+
// TODO: Investigate using GetExprRange() to get tighter bounds
// on the bit ranges.
QualType OtherT = Other->getType();
if (const auto *AT = OtherT->getAs<AtomicType>())
OtherT = AT->getValueType();
-
IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
// Whether we're treating Other as being a bool because of the form of
if (OtherIsBooleanDespiteType)
OtherRange = IntRange::forBoolType();
- unsigned OtherWidth = OtherRange.Width;
-
- BinaryOperatorKind op = E->getOpcode();
- bool IsTrue = true;
-
- // Check whether the constant value can be represented in OtherRange. Bail
- // out if so; this isn't an out-of-range comparison.
- {
- QualType ConstantT = Constant->getType();
- QualType CommonT = E->getLHS()->getType();
-
- if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT) &&
- !OtherIsBooleanDespiteType)
- return false;
- assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
- "comparison with non-integer type");
-
- bool ConstantSigned = ConstantT->isSignedIntegerType();
- bool CommonSigned = CommonT->isSignedIntegerType();
-
- bool EqualityOnly = false;
-
- if (CommonSigned) {
- // The common type is signed, therefore no signed to unsigned conversion.
- if (!OtherRange.NonNegative) {
- // Check that the constant is representable in type OtherT.
- if (ConstantSigned) {
- if (OtherWidth >= Value.getMinSignedBits())
- return false;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits() + 1)
- return false;
- }
- } else { // !OtherSigned
- // Check that the constant is representable in type OtherT.
- // Negative values are out of range.
- if (ConstantSigned) {
- if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
- return false;
- } else { // !ConstantSigned
- if (OtherWidth >= Value.getActiveBits())
- return false;
- }
- }
- } else { // !CommonSigned
- if (OtherRange.NonNegative) {
- if (OtherWidth >= Value.getActiveBits())
- return false;
- } else { // OtherSigned
- assert(!ConstantSigned &&
- "Two signed types converted to unsigned types.");
- // Check to see if the constant is representable in OtherT.
- if (OtherWidth > Value.getActiveBits())
- return false;
- // Check to see if the constant is equivalent to a negative value
- // cast to CommonT.
- if (S.Context.getIntWidth(ConstantT) ==
- S.Context.getIntWidth(CommonT) &&
- Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
- return false;
- // The constant value rests between values that OtherT can represent
- // after conversion. Relational comparison still works, but equality
- // comparisons will be tautological.
- EqualityOnly = true;
- }
- }
-
- bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+ // Determine the promoted range of the other type and see if a comparison of
+ // the constant against that range is tautological.
+ PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(),
+ Value.isUnsigned());
+ auto Cmp = OtherPromotedRange.compare(Value);
+ auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant);
+ if (!Result)
+ return false;
- if (op == BO_EQ || op == BO_NE) {
- IsTrue = op == BO_NE;
- } else if (EqualityOnly) {
- return false;
- } else if (RhsConstant) {
- if (op == BO_GT || op == BO_GE)
- IsTrue = !PositiveConstant;
- else // op == BO_LT || op == BO_LE
- IsTrue = PositiveConstant;
- } else {
- if (op == BO_LT || op == BO_LE)
- IsTrue = !PositiveConstant;
- else // op == BO_GT || op == BO_GE
- IsTrue = PositiveConstant;
- }
- }
+ // Suppress the diagnostic for an in-range comparison if the constant comes
+ // from a macro or enumerator. We don't want to diagnose
+ //
+ // some_long_value <= INT_MAX
+ //
+ // when sizeof(int) == sizeof(long).
+ bool InRange = Cmp & PromotedRange::InRangeFlag;
+ if (InRange && IsEnumConstOrFromMacro(S, Constant))
+ return false;
// If this is a comparison to an enum constant, include that
// constant in the diagnostic.
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant))
ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
+ // Should be enough for uint128 (39 decimal digits)
SmallString<64> PrettySourceValue;
llvm::raw_svector_ostream OS(PrettySourceValue);
if (ED)
else
OS << Value;
- S.DiagRuntimeBehavior(
- E->getOperatorLoc(), E,
- S.PDiag(diag::warn_out_of_range_compare)
- << OS.str() << classifyConstantValue(Constant)
- << OtherT << OtherIsBooleanDespiteType << IsTrue
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
+ // FIXME: We use a somewhat different formatting for the in-range cases and
+ // cases involving boolean values for historical reasons. We should pick a
+ // consistent way of presenting these diagnostics.
+ if (!InRange || Other->isKnownToHaveBooleanValue()) {
+ S.DiagRuntimeBehavior(
+ E->getOperatorLoc(), E,
+ S.PDiag(!InRange ? diag::warn_out_of_range_compare
+ : diag::warn_tautological_bool_compare)
+ << OS.str() << classifyConstantValue(Constant)
+ << OtherT << OtherIsBooleanDespiteType << *Result
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
+ } else {
+ unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
+ ? (HasEnumType(OriginalOther)
+ ? diag::warn_unsigned_enum_always_true_comparison
+ : diag::warn_unsigned_always_true_comparison)
+ : diag::warn_tautological_constant_compare;
- return true;
+ S.Diag(E->getOperatorLoc(), Diag)
+ << RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ }
+
+ return true;
}
/// Analyze the operands of the given comparison. Implements the
// Check whether an integer constant comparison results in a value
// of 'true' or 'false'.
-
if (CheckTautologicalComparison(S, E, Const, Other, Value, RhsConstant))
return AnalyzeImpConvsInComparison(S, E);
-
- if (DiagnoseOutOfRangeComparison(S, E, Const, Other, Value, RhsConstant))
- return AnalyzeImpConvsInComparison(S, E);
}
}
#ifdef SILENCE
// expected-no-diagnostics
-#endif
+#else
+ // If we promote to unsigned, it doesn't matter whether the enum's underlying
+ // type was signed.
+ if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ return 0;
+ if (0U >= a)
+ return 0;
+ if (a > 0U)
+ return 0;
+ if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ return 0;
+ if (a <= 0U)
+ return 0;
+ if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ return 0;
+ if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ return 0;
+ if (0U < a)
+ return 0;
-#ifdef UNSIGNED
-#ifndef SILENCE
- if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (a < 4294967295U)
return 0;
- if (0 >= a)
+ if (4294967295U >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
return 0;
- if (a > 0)
+ if (a > 4294967295U) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
return 0;
- if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (4294967295U <= a)
return 0;
- if (a <= 0)
+ if (a <= 4294967295U) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
return 0;
- if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (4294967295U > a)
return 0;
- if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (a >= 4294967295U)
return 0;
- if (0 < a)
+ if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
return 0;
- if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (a < 2147483647U)
return 0;
- if (0U >= a)
+ if (2147483647U >= a)
return 0;
- if (a > 0U)
+ if (a > 2147483647U)
return 0;
- if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (2147483647U <= a)
return 0;
- if (a <= 0U)
+ if (a <= 2147483647U)
return 0;
- if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (2147483647U > a)
return 0;
- if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (a >= 2147483647U)
return 0;
- if (0U < a)
+ if (2147483647U < a)
return 0;
+#endif
- if (a < 4294967295)
+#if defined(UNSIGNED) && !defined(SILENCE)
+ if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
- if (4294967295 >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
+ if (0 >= a)
return 0;
- if (a > 4294967295) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
+ if (a > 0)
return 0;
- if (4294967295 <= a)
+ if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
- if (a <= 4294967295) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
+ if (a <= 0)
return 0;
- if (4294967295 > a)
+ if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (a >= 4294967295)
+ if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
- if (4294967295 < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
+ if (0 < a)
return 0;
- if (a < 4294967295U)
+ if (a < 4294967295)
return 0;
- if (4294967295U >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
+ if (4294967295 >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}}
return 0;
- if (a > 4294967295U) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
+ if (a > 4294967295) // expected-warning {{comparison 'enum A' > 4294967295 is always false}}
return 0;
- if (4294967295U <= a)
+ if (4294967295 <= a)
return 0;
- if (a <= 4294967295U) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
+ if (a <= 4294967295) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}}
return 0;
- if (4294967295U > a)
+ if (4294967295 > a)
return 0;
- if (a >= 4294967295U)
+ if (a >= 4294967295)
return 0;
- if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
+ if (4294967295 < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
return 0;
-#else // SILENCE
+#else // SIGNED || SILENCE
if (a < 0)
return 0;
if (0 >= a)
if (0 < a)
return 0;
- if (a < 0U)
+#ifndef SILENCE
+ if (a < 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}}
return 0;
- if (0U >= a)
+ if (4294967295 >= a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}}
return 0;
- if (a > 0U)
+ if (a > 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}}
return 0;
- if (0U <= a)
+ if (4294967295 <= a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}}
return 0;
- if (a <= 0U)
+ if (a <= 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}}
return 0;
- if (0U > a)
+ if (4294967295 > a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}}
return 0;
- if (a >= 0U)
+ if (a >= 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}}
return 0;
- if (0U < a)
+ if (4294967295 < a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}}
return 0;
-
+#else
if (a < 4294967295)
return 0;
if (4294967295 >= a)
return 0;
if (4294967295 < a)
return 0;
-
- if (a < 4294967295U)
- return 0;
- if (4294967295U >= a)
- return 0;
- if (a > 4294967295U)
- return 0;
- if (4294967295U <= a)
- return 0;
- if (a <= 4294967295U)
- return 0;
- if (4294967295U > a)
- return 0;
- if (a >= 4294967295U)
- return 0;
- if (4294967295U < a)
- return 0;
#endif
-#elif defined(SIGNED)
-#ifndef SILENCE
+#endif
+
+#if defined(SIGNED) && !defined(SILENCE)
if (a < -2147483648) // expected-warning {{comparison 'enum A' < -2147483648 is always false}}
return 0;
if (-2147483648 >= a)
return 0;
if (2147483647 < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}}
return 0;
-
- if (a < 2147483647U)
+#elif defined(UNSIGNED) && !defined(SILENCE)
+#ifndef SILENCE
+ if (a < -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}}
return 0;
- if (2147483647U >= a) // expected-warning {{comparison 2147483647 >= 'enum A' is always true}}
+ if (-2147483648 >= a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}}
return 0;
- if (a > 2147483647U) // expected-warning {{comparison 'enum A' > 2147483647 is always false}}
+ if (a > -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}}
return 0;
- if (2147483647U <= a)
+ if (-2147483648 <= a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}}
return 0;
- if (a <= 2147483647U) // expected-warning {{comparison 'enum A' <= 2147483647 is always true}}
+ if (a <= -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}}
return 0;
- if (2147483647U > a)
+ if (-2147483648 > a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}}
return 0;
- if (a >= 2147483647U)
+ if (a >= -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}}
return 0;
- if (2147483647U < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}}
+ if (-2147483648 < a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}}
return 0;
-#else // SILENCE
+#else
if (a < -2147483648)
return 0;
if (-2147483648 >= a)
return 0;
if (-2147483648 < a)
return 0;
+#endif
if (a < 2147483647)
return 0;
return 0;
if (2147483647 < a)
return 0;
-
- if (a < 2147483647U)
- return 0;
- if (2147483647U >= a)
- return 0;
- if (a > 2147483647U)
- return 0;
- if (2147483647U <= a)
- return 0;
- if (a <= 2147483647U)
- return 0;
- if (2147483647U > a)
- return 0;
- if (a >= 2147483647U)
- return 0;
- if (2147483647U < a)
- return 0;
-#endif
#endif
return 1;