Author: hans Date: Fri Dec 8 08:54:08 2017 New Revision: 320162 URL: http://llvm.org/viewvc/llvm-project?rev=320162&view=rev Log: Revert "Unify implementation of our two different flavours of -Wtautological-compare."
> Unify implementation of our two different flavours of -Wtautological-compare. > > In so doing, fix a handful of remaining bugs where we would report false > positives or false negatives if we promote a signed value to an unsigned type > for the comparison. This caused a new warning in Chromium: ../../base/trace_event/trace_log.cc:1545:29: error: comparison of constant 64 with expression of type 'unsigned int' is always true [-Werror,-Wtautological-constant-out-of-range-compare] DCHECK(handle.event_index < TraceBufferChunk::kTraceBufferChunkSize); ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The 'unsigned int' is really a 6-bit bitfield, which is why it's always less than 64. I thought we didn't use to warn (with out-of-range-compare) when comparing against the boundaries of a type? Modified: cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/tautological-constant-compare.c cfe/trunk/test/Sema/tautological-constant-enum-compare.c cfe/trunk/test/SemaCXX/compare.cpp Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=320162&r1=320161&r2=320162&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Dec 8 08:54:08 2017 @@ -8662,113 +8662,54 @@ static bool isKnownToHaveUnsignedValue(E } 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 { - PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative) - .extOrTrunc(BitWidth); - PromotedMin.setIsUnsigned(Unsigned); - - PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative) - .extOrTrunc(BitWidth); - PromotedMax.setIsUnsigned(Unsigned); - } - } - // Determine whether this range is contiguous (has no hole). - bool isContiguous() const { return PromotedMin <= PromotedMax; } +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 }; +}; - // Where a constant value is within the range. - enum ComparisonResult { - LT = 0x1, - LE = 0x2, - GT = 0x4, - GE = 0x8, - EQ = 0x10, - NE = 0x20, - InRangeFlag = 0x40, - - Less = LE | LT | NE, - Min = LE | InRangeFlag, - InRange = InRangeFlag, - Max = GE | InRangeFlag, - Greater = GE | GT | NE, +} // namespace - OnlyValue = LE | GE | EQ | InRangeFlag, - InHole = NE - }; +/// 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>(); - 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; - } + if (isKnownToHaveUnsignedValue(Other) && Value == 0) + return LimitType::Min; - 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; - } - } + // 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(); - llvm_unreachable("impossible compare result"); - } + IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); + if (Other->isKnownToHaveBooleanValue()) + OtherRange = IntRange::forBoolType(); - 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; - } -}; + // 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>(); + + if (llvm::APSInt::isSameValue( + llvm::APSInt::getMaxValue(OtherRange.Width, OtherRange.NonNegative), + Value)) + return LimitType::Max; + + if (llvm::APSInt::isSameValue( + llvm::APSInt::getMinValue(OtherRange.Width, OtherRange.NonNegative), + Value)) + return LimitType::Min; + + return llvm::None; } static bool HasEnumType(Expr *E) { @@ -8806,47 +8747,29 @@ static bool CheckTautologicalComparison( if (S.inTemplateInstantiation() || !E->isRelationalOp()) return false; - if (IsEnumConstOrFromMacro(S, Constant)) - return false; - - Expr *OriginalOther = Other; + BinaryOperatorKind Op = E->getOpcode(); - Constant = Constant->IgnoreParenImpCasts(); - Other = Other->IgnoreParenImpCasts(); - - // 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 - // expression despite it having another type (typically 'int' in C). - bool OtherIsBooleanDespiteType = - !OtherT->isBooleanType() && Other->isKnownToHaveBooleanValue(); - if (OtherIsBooleanDespiteType) - OtherRange = IntRange::forBoolType(); - - if (FieldDecl *Bitfield = Other->getSourceBitField()) - if (!Bitfield->getBitWidth()->isValueDependent()) - OtherRange.Width = - std::min(Bitfield->getBitWidthValue(S.Context), OtherRange.Width); - - // Check whether the constant value can be represented in OtherRange. Bail - // out if so; this isn't an out-of-range comparison. - PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(), - Value.isUnsigned()); - - auto Cmp = OtherPromotedRange.compare(Value); - if (Cmp != PromotedRange::Min && Cmp != PromotedRange::Max && - Cmp != PromotedRange::OnlyValue) + QualType OType = Other->IgnoreParenImpCasts()->getType(); + if (!OType->isIntegerType()) return false; - auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant); - if (!Result) + // 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); @@ -8859,20 +8782,20 @@ static bool CheckTautologicalComparison( S.DiagRuntimeBehavior( E->getOperatorLoc(), E, S.PDiag(diag::warn_tautological_bool_compare) - << OS.str() << classifyConstantValue(Constant) - << OtherT << !OtherT->isBooleanType() << *Result + << OS.str() << classifyConstantValue(Constant->IgnoreParenImpCasts()) + << OType << !OType->isBooleanType() << Result << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); return true; } - unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0) - ? (HasEnumType(OriginalOther) + 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 << OtherT << E->getOpcodeStr() << OS.str() << *Result + << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); return true; @@ -8894,6 +8817,7 @@ static bool DiagnoseOutOfRangeComparison 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 @@ -8903,25 +8827,91 @@ static bool DiagnoseOutOfRangeComparison if (OtherIsBooleanDespiteType) OtherRange = IntRange::forBoolType(); - if (FieldDecl *Bitfield = Other->getSourceBitField()) - if (!Bitfield->getBitWidth()->isValueDependent()) - OtherRange.Width = - std::min(Bitfield->getBitWidthValue(S.Context), OtherRange.Width); + 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. - PromotedRange OtherPromotedRange(OtherRange, Value.getBitWidth(), - Value.isUnsigned()); - auto Cmp = OtherPromotedRange.compare(Value); - - // If Value is in the range of possible Other values, this comparison is not - // tautological. - if (Cmp & PromotedRange::InRangeFlag) - return false; + { + QualType ConstantT = Constant->getType(); + QualType CommonT = E->getLHS()->getType(); - auto IsTrue = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant); - if (!IsTrue) - return false; + 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(); + + 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; + } + } // If this is a comparison to an enum constant, include that // constant in the diagnostic. @@ -8940,7 +8930,7 @@ static bool DiagnoseOutOfRangeComparison E->getOperatorLoc(), E, S.PDiag(diag::warn_out_of_range_compare) << OS.str() << classifyConstantValue(Constant) - << OtherT << OtherIsBooleanDespiteType << *IsTrue + << OtherT << OtherIsBooleanDespiteType << IsTrue << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); return true; Modified: cfe/trunk/test/Sema/tautological-constant-compare.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-constant-compare.c?rev=320162&r1=320161&r2=320162&view=diff ============================================================================== --- cfe/trunk/test/Sema/tautological-constant-compare.c (original) +++ cfe/trunk/test/Sema/tautological-constant-compare.c Fri Dec 8 08:54:08 2017 @@ -94,17 +94,15 @@ int main() if (-32768 >= s) return 0; - // Note: both sides are promoted to unsigned long prior to the comparison, so - // it is perfectly possible for a short to compare greater than 32767UL. if (s == 32767UL) return 0; if (s != 32767UL) return 0; if (s < 32767UL) return 0; - if (s <= 32767UL) + if (s <= 32767UL) // expected-warning {{comparison 'short' <= 32767 is always true}} return 0; - if (s > 32767UL) + if (s > 32767UL) // expected-warning {{comparison 'short' > 32767 is always false}} return 0; if (s >= 32767UL) return 0; @@ -113,66 +111,13 @@ int main() return 0; if (32767UL != s) return 0; - if (32767UL < s) + if (32767UL < s) // expected-warning {{comparison 32767 < 'short' is always false}} return 0; if (32767UL <= s) return 0; if (32767UL > s) return 0; - if (32767UL >= s) - return 0; - - if (s == 0UL) - return 0; - if (s != 0UL) - return 0; - if (s < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}} - return 0; - if (s <= 0UL) - return 0; - if (s > 0UL) - return 0; - if (s >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}} - return 0; - - if (0UL == s) - return 0; - if (0UL != s) - return 0; - if (0UL < s) - return 0; - if (0UL <= s) // expected-warning {{comparison of 0 <= unsigned expression is always true}} - return 0; - if (0UL > s) // expected-warning {{comparison of 0 > unsigned expression is always false}} - return 0; - if (0UL >= s) - return 0; - - enum { ULONG_MAX = (2UL * (unsigned long)__LONG_MAX__ + 1UL) }; - if (s == 2UL * (unsigned long)__LONG_MAX__ + 1UL) - return 0; - if (s != 2UL * (unsigned long)__LONG_MAX__ + 1UL) - return 0; - if (s < 2UL * (unsigned long)__LONG_MAX__ + 1UL) - return 0; - if (s <= 2UL * (unsigned long)__LONG_MAX__ + 1UL) // expected-warning-re {{comparison 'short' <= {{.*}} is always true}} - return 0; - if (s > 2UL * (unsigned long)__LONG_MAX__ + 1UL) // expected-warning-re {{comparison 'short' > {{.*}} is always false}} - return 0; - if (s >= 2UL * (unsigned long)__LONG_MAX__ + 1UL) - return 0; - - if (2UL * (unsigned long)__LONG_MAX__ + 1UL == s) - return 0; - if (2UL * (unsigned long)__LONG_MAX__ + 1UL != s) - return 0; - if (2UL * (unsigned long)__LONG_MAX__ + 1UL < s) // expected-warning-re {{comparison {{.*}} < 'short' is always false}} - return 0; - if (2UL * (unsigned long)__LONG_MAX__ + 1UL <= s) - return 0; - if (2UL * (unsigned long)__LONG_MAX__ + 1UL > s) - return 0; - if (2UL * (unsigned long)__LONG_MAX__ + 1UL >= s) // expected-warning-re {{comparison {{.*}} >= 'short' is always true}} + if (32767UL >= s) // expected-warning {{comparison 32767 >= 'short' is always true}} return 0; // FIXME: assumes two's complement @@ -336,6 +281,8 @@ int main() if (0 >= s) return 0; + // However the comparison with 0U would warn + unsigned short us = value(); #ifdef TEST Modified: cfe/trunk/test/Sema/tautological-constant-enum-compare.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-constant-enum-compare.c?rev=320162&r1=320161&r2=320162&view=diff ============================================================================== --- cfe/trunk/test/Sema/tautological-constant-enum-compare.c (original) +++ cfe/trunk/test/Sema/tautological-constant-enum-compare.c Fri Dec 8 08:54:08 2017 @@ -9,96 +9,78 @@ int main() { #ifdef SILENCE // expected-no-diagnostics -#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; +#endif - if (a < 4294967295U) +#ifdef UNSIGNED +#ifndef SILENCE + if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} return 0; - if (4294967295U >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}} + if (0 >= a) return 0; - if (a > 4294967295U) // expected-warning {{comparison 'enum A' > 4294967295 is always false}} + if (a > 0) return 0; - if (4294967295U <= a) + if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} return 0; - if (a <= 4294967295U) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}} + if (a <= 0) return 0; - if (4294967295U > a) + if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} return 0; - if (a >= 4294967295U) + if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} return 0; - if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}} + if (0 < a) return 0; - if (a < 2147483647U) + if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} return 0; - if (2147483647U >= a) + if (0U >= a) return 0; - if (a > 2147483647U) + if (a > 0U) return 0; - if (2147483647U <= a) + if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}} return 0; - if (a <= 2147483647U) + if (a <= 0U) return 0; - if (2147483647U > a) + if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}} return 0; - if (a >= 2147483647U) + if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} return 0; - if (2147483647U < a) + if (0U < a) return 0; -#endif -#if defined(UNSIGNED) && !defined(SILENCE) - if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + if (a < 4294967295) return 0; - if (0 >= a) + if (4294967295 >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}} return 0; - if (a > 0) + if (a > 4294967295) // 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 (4294967295 <= a) return 0; - if (a <= 0) + if (a <= 4294967295) // 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 (4294967295 > a) return 0; - if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}} + if (a >= 4294967295) return 0; - if (0 < a) + if (4294967295 < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}} return 0; - if (a < 4294967295) + if (a < 4294967295U) return 0; - if (4294967295 >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}} + if (4294967295U >= a) // expected-warning {{comparison 4294967295 >= 'enum A' is always true}} return 0; - if (a > 4294967295) // expected-warning {{comparison 'enum A' > 4294967295 is always false}} + if (a > 4294967295U) // expected-warning {{comparison 'enum A' > 4294967295 is always false}} return 0; - if (4294967295 <= a) + if (4294967295U <= a) return 0; - if (a <= 4294967295) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}} + if (a <= 4294967295U) // expected-warning {{comparison 'enum A' <= 4294967295 is always true}} return 0; - if (4294967295 > a) + if (4294967295U > a) return 0; - if (a >= 4294967295) + if (a >= 4294967295U) return 0; - if (4294967295 < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}} + if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}} return 0; -#else // SIGNED || SILENCE +#else // SILENCE if (a < 0) return 0; if (0 >= a) @@ -116,24 +98,23 @@ int main() { if (0 < a) return 0; -#ifndef SILENCE - if (a < 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}} + if (a < 0U) return 0; - if (4294967295 >= a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}} + if (0U >= a) return 0; - if (a > 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}} + if (a > 0U) return 0; - if (4294967295 <= a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}} + if (0U <= a) return 0; - if (a <= 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}} + if (a <= 0U) return 0; - if (4294967295 > a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always true}} + if (0U > a) return 0; - if (a >= 4294967295) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}} + if (a >= 0U) return 0; - if (4294967295 < a) // expected-warning {{comparison of constant 4294967295 with expression of type 'enum A' is always false}} + if (0U < a) return 0; -#else + if (a < 4294967295) return 0; if (4294967295 >= a) @@ -150,10 +131,26 @@ int main() { return 0; if (4294967295 < a) return 0; -#endif -#endif -#if defined(SIGNED) && !defined(SILENCE) + 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 if (a < -2147483648) // expected-warning {{comparison 'enum A' < -2147483648 is always false}} return 0; if (-2147483648 >= a) @@ -187,25 +184,24 @@ int main() { return 0; if (2147483647 < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}} return 0; -#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}} + + if (a < 2147483647U) return 0; - if (-2147483648 >= a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}} + if (2147483647U >= a) // expected-warning {{comparison 2147483647 >= 'enum A' is always true}} return 0; - if (a > -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}} + if (a > 2147483647U) // expected-warning {{comparison 'enum A' > 2147483647 is always false}} return 0; - if (-2147483648 <= a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}} + if (2147483647U <= a) return 0; - if (a <= -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}} + if (a <= 2147483647U) // expected-warning {{comparison 'enum A' <= 2147483647 is always true}} return 0; - if (-2147483648 > a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always false}} + if (2147483647U > a) return 0; - if (a >= -2147483648) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}} + if (a >= 2147483647U) return 0; - if (-2147483648 < a) // expected-warning {{comparison of constant -2147483648 with expression of type 'enum A' is always true}} + if (2147483647U < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}} return 0; -#else +#else // SILENCE if (a < -2147483648) return 0; if (-2147483648 >= a) @@ -222,7 +218,6 @@ int main() { return 0; if (-2147483648 < a) return 0; -#endif if (a < 2147483647) return 0; @@ -240,6 +235,24 @@ int main() { 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; Modified: cfe/trunk/test/SemaCXX/compare.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/compare.cpp?rev=320162&r1=320161&r2=320162&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/compare.cpp (original) +++ cfe/trunk/test/SemaCXX/compare.cpp Fri Dec 8 08:54:08 2017 @@ -245,8 +245,8 @@ void test4(short s) { // unsigned. const unsigned B = -1; void (s < B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} - void (s > B); // expected-warning{{comparison 'short' > 4294967295 is always false}} - void (s <= B); // expected-warning{{comparison 'short' <= 4294967295 is always true}} + void (s > B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} + void (s <= B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} void (s >= B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} void (s == B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} void (s != B); // expected-warning{{comparison of integers of different signs: 'short' and 'const unsigned int'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits