From 720ba14b8e3f5f4fc58b0e2c05c2ca989ea2bac5 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 12 Oct 2017 22:03:20 +0000 Subject: Revert "[Sema] Diagnose tautological comparison with type's min/max values" This reverts r315614,r315615,r315621,r315622 Breaks http://bb9.pgr.jp/#/builders/20/builds/59 /home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:95:17: error: comparison 'long long' > 9223372036854775807 is always false [-Werror,-Wtautological-constant-compare] if (max_sec > Lim::max()) return false; ~~~~~~~ ^ ~~~~~~~~~~ /home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:124:13: error: comparison 'long long' < -9223372036854775808 is always false [-Werror,-Wtautological-constant-compare] if (sec < Lim::min() || sec > Lim::max()) return false; ~~~ ^ ~~~~~~~~~~ /home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:124:33: error: comparison 'long long' > 9223372036854775807 is always false [-Werror,-Wtautological-constant-compare] if (sec < Lim::min() || sec > Lim::max()) return false; ~~~ ^ ~~~~~~~~~~ 3 errors generated. -- I'm not yet sure what is the proper fix. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315631 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ReleaseNotes.rst | 4 - include/clang/Basic/DiagnosticGroups.td | 8 +- include/clang/Basic/DiagnosticSemaKinds.td | 20 +- lib/Sema/SemaChecking.cpp | 241 +++++------- test/Analysis/conversion.c | 2 +- test/Analysis/null-deref-ps.c | 4 +- test/Sema/outof-range-constant-compare.c | 159 ++++++++ test/Sema/tautological-constant-compare.c | 514 ------------------------- test/Sema/tautological-unsigned-zero-compare.c | 377 ++---------------- 9 files changed, 297 insertions(+), 1032 deletions(-) delete mode 100644 test/Sema/tautological-constant-compare.c diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 293144a832..49c26b449d 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -78,10 +78,6 @@ Improvements to Clang's diagnostics when the signed integer is coerced to an unsigned type for the comparison. ``-Wsign-compare`` was adjusted not to warn in this case. -- ``-Wtautological-constant-compare`` is a new warning that warns on - tautological comparisons between integer variable of the type ``T`` and the - largest/smallest possible integer constant of that same type. - - ``-Wnull-pointer-arithmetic`` now warns about performing pointer arithmetic on a null pointer. Such pointer arithmetic has an undefined behavior if the offset is nonzero. It also now warns about arithmetic on a null pointer diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 2f4244c98e..ae6f51775e 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -432,15 +432,13 @@ def StrncatSize : DiagGroup<"strncat-size">; def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; -def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare", - [TautologicalUnsignedZeroCompare, - TautologicalUnsignedEnumZeroCompare, - TautologicalOutOfRangeCompare]>; def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; def TautologicalCompare : DiagGroup<"tautological-compare", - [TautologicalConstantCompare, + [TautologicalUnsignedZeroCompare, + TautologicalUnsignedEnumZeroCompare, + TautologicalOutOfRangeCompare, TautologicalPointerCompare, TautologicalOverlapCompare, TautologicalUndefinedCompare]>; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4a724871d6..7f20be91df 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5938,18 +5938,18 @@ def note_typecheck_assign_const : Note< "member function %q1 is declared const here|" "%select{|nested }1data member %2 declared const here}0">; -def warn_unsigned_always_true_comparison : Warning< - "comparison of %select{%3|unsigned expression}0 %2 " - "%select{unsigned expression|%3}0 is always %select{false|true}4">, +def warn_lunsigned_always_true_comparison : Warning< + "comparison of unsigned expression %0 is always %select{false|true}1">, InGroup; -def warn_unsigned_enum_always_true_comparison : Warning< - "comparison of %select{%3|unsigned enum expression}0 %2 " - "%select{unsigned enum expression|%3}0 is always %select{false|true}4">, +def warn_runsigned_always_true_comparison : Warning< + "comparison of %0 unsigned expression is always %select{false|true}1">, + InGroup; +def warn_lunsigned_enum_always_true_comparison : Warning< + "comparison of unsigned enum expression %0 is always %select{false|true}1">, + InGroup; +def warn_runsigned_enum_always_true_comparison : Warning< + "comparison of %0 unsigned enum expression is always %select{false|true}1">, InGroup; -def warn_tautological_constant_compare : Warning< - "comparison %select{%3|%1}0 %2 " - "%select{%1|%3}0 is always %select{false|true}4">, - InGroup; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index f0e302d46f..9a94900ce2 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -8553,71 +8553,19 @@ bool IsSameFloatAfterCast(const APValue &value, void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); -bool IsEnumConstOrFromMacro(Sema &S, Expr *E) { +bool IsZero(Sema &S, Expr *E) { // Suppress cases where we are comparing against an enum constant. if (const DeclRefExpr *DR = dyn_cast(E->IgnoreParenImpCasts())) if (isa(DR->getDecl())) - return true; + return false; // Suppress cases where the '0' value is expanded from a macro. if (E->getLocStart().isMacroID()) - return true; - - return false; -} - -bool isNonBooleanIntegerValue(Expr *E) { - return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType(); -} - -bool isNonBooleanUnsignedValue(Expr *E) { - // We are checking that the expression is not known to have boolean value, - // is an integer type; and is either unsigned after implicit casts, - // or was unsigned before implicit casts. - return isNonBooleanIntegerValue(E) && - (!E->getType()->isSignedIntegerType() || - !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType()); -} - -enum class LimitType { - Max, // e.g. 32767 for short - Min // e.g. -32768 for short -}; - -/// 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 -llvm::Optional IsTypeLimit(Sema &S, Expr *Constant, Expr *Other, - const llvm::APSInt &Value) { - if (IsEnumConstOrFromMacro(S, Constant)) - return llvm::Optional(); - - if (isNonBooleanUnsignedValue(Other) && Value == 0) - return LimitType::Min; - - // TODO: Investigate using GetExprRange() to get tighter bounds - // on the bit ranges. - QualType OtherT = Other->IgnoreParenImpCasts()->getType(); - if (const auto *AT = OtherT->getAs()) - OtherT = AT->getValueType(); - - IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); - - if (llvm::APSInt::isSameValue( - llvm::APSInt::getMaxValue(OtherRange.Width, - OtherT->isUnsignedIntegerType()), - Value)) - return LimitType::Max; - - if (llvm::APSInt::isSameValue( - llvm::APSInt::getMinValue(OtherRange.Width, - OtherT->isUnsignedIntegerType()), - Value)) - return LimitType::Min; + return false; - return llvm::Optional(); + llvm::APSInt Value; + return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; } bool HasEnumType(Expr *E) { @@ -8632,60 +8580,63 @@ bool HasEnumType(Expr *E) { return E->getType()->isEnumeralType(); } -bool CheckTautologicalComparison(Sema &S, BinaryOperator *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(); - - llvm::Optional ValueType; // Which limit (min/max) is the constant? +bool isNonBooleanUnsignedValue(Expr *E) { + // We are checking that the expression is not known to have boolean value, + // is an integer type; and is either unsigned after implicit casts, + // or was unsigned before implicit casts. + return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType() && + (!E->getType()->isSignedIntegerType() || + !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType()); +} - if (!(isNonBooleanIntegerValue(Other) && - (ValueType = IsTypeLimit(S, Constant, Other, Value)))) +bool CheckTautologicalComparisonWithZero(Sema &S, BinaryOperator *E) { + // Disable warning in template instantiations. + if (S.inTemplateInstantiation()) return false; - bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant; - bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE); - bool ResultWhenConstNeOther = - ConstIsLowerBound ^ (ValueType == LimitType::Max); - if (ResultWhenConstEqualsOther != ResultWhenConstNeOther) - return false; // The comparison is not tautological. + // bool values are handled by DiagnoseOutOfRangeComparison(). - const bool Result = ResultWhenConstEqualsOther; - - unsigned Diag = (isNonBooleanUnsignedValue(Other) && Value == 0) - ? (HasEnumType(Other) - ? diag::warn_unsigned_enum_always_true_comparison - : diag::warn_unsigned_always_true_comparison) - : diag::warn_tautological_constant_compare; + BinaryOperatorKind Op = E->getOpcode(); + if (E->isValueDependent()) + return false; - // Should be enough for uint128 (39 decimal digits) - SmallString<64> PrettySourceValue; - llvm::raw_svector_ostream OS(PrettySourceValue); - OS << Value; + Expr *LHS = E->getLHS(); + Expr *RHS = E->getRHS(); - S.Diag(E->getOperatorLoc(), Diag) - << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result - << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + bool Match = true; + + if (Op == BO_LT && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { + S.Diag(E->getOperatorLoc(), + HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison + : diag::warn_lunsigned_always_true_comparison) + << "< 0" << false << LHS->getSourceRange() << RHS->getSourceRange(); + } else if (Op == BO_GE && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) { + S.Diag(E->getOperatorLoc(), + HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison + : diag::warn_lunsigned_always_true_comparison) + << ">= 0" << true << LHS->getSourceRange() << RHS->getSourceRange(); + } else if (Op == BO_GT && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { + S.Diag(E->getOperatorLoc(), + HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison + : diag::warn_runsigned_always_true_comparison) + << "0 >" << false << LHS->getSourceRange() << RHS->getSourceRange(); + } else if (Op == BO_LE && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) { + S.Diag(E->getOperatorLoc(), + HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison + : diag::warn_runsigned_always_true_comparison) + << "0 <=" << true << LHS->getSourceRange() << RHS->getSourceRange(); + } else + Match = false; - return true; + return Match; } -bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, +void 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; - - Constant = Constant->IgnoreParenImpCasts(); - Other = Other->IgnoreParenImpCasts(); + return; // TODO: Investigate using GetExprRange() to get tighter bounds // on the bit ranges. @@ -8697,6 +8648,10 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue(); + // 0 values are handled later by CheckTautologicalComparisonWithZero(). + if ((Value == 0) && (!OtherIsBooleanType)) + return; + BinaryOperatorKind op = E->getOpcode(); bool IsTrue = true; @@ -8712,7 +8667,7 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, QualType CommonT = E->getLHS()->getType(); if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT)) - return false; + return; assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) && "comparison with non-integer type"); @@ -8727,38 +8682,38 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, // Check that the constant is representable in type OtherT. if (ConstantSigned) { if (OtherWidth >= Value.getMinSignedBits()) - return false; + return; } else { // !ConstantSigned if (OtherWidth >= Value.getActiveBits() + 1) - return false; + return; } } 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; + return; } else { // !ConstantSigned if (OtherWidth >= Value.getActiveBits()) - return false; + return; } } } else { // !CommonSigned if (OtherRange.NonNegative) { if (OtherWidth >= Value.getActiveBits()) - return false; + return; } 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; + return; // 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; + return; // The constant value rests between values that OtherT can represent // after conversion. Relational comparison still works, but equality // comparisons will be tautological. @@ -8771,7 +8726,7 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, if (op == BO_EQ || op == BO_NE) { IsTrue = op == BO_NE; } else if (EqualityOnly) { - return false; + return; } else if (RhsConstant) { if (op == BO_GT || op == BO_GE) IsTrue = !PositiveConstant; @@ -8859,7 +8814,7 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, } else if (CmpRes == ATrue) { IsTrue = true; } else { - return false; + return; } } @@ -8882,8 +8837,6 @@ bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, << OS.str() << LiteralOrBoolConstant << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); - - return true; } /// Analyze the operands of the given comparison. Implements the @@ -8909,48 +8862,44 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { if (E->isValueDependent()) return AnalyzeImpConvsInComparison(S, E); - Expr *LHS = E->getLHS(); - Expr *RHS = E->getRHS(); - + Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); + Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); + + bool IsComparisonConstant = false; + + // Check whether an integer constant comparison results in a value + // of 'true' or 'false'. if (T->isIntegralType(S.Context)) { llvm::APSInt RHSValue; + bool IsRHSIntegralLiteral = + RHS->isIntegerConstantExpr(RHSValue, S.Context); llvm::APSInt LHSValue; + bool IsLHSIntegralLiteral = + LHS->isIntegerConstantExpr(LHSValue, S.Context); + if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral) + DiagnoseOutOfRangeComparison(S, E, RHS, LHS, RHSValue, true); + else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral) + DiagnoseOutOfRangeComparison(S, E, LHS, RHS, LHSValue, false); + else + IsComparisonConstant = + (IsRHSIntegralLiteral && IsLHSIntegralLiteral); + } else if (!T->hasUnsignedIntegerRepresentation()) + IsComparisonConstant = E->isIntegerConstantExpr(S.Context); + + // We don't care about value-dependent expressions or expressions + // whose result is a constant. + if (IsComparisonConstant) + return AnalyzeImpConvsInComparison(S, E); - bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context); - bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context); - - // We don't care about expressions whose result is a constant. - if (IsRHSIntegralLiteral && IsLHSIntegralLiteral) - return AnalyzeImpConvsInComparison(S, E); - - // We only care about expressions where just one side is literal - if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) { - // Is the constant on the RHS or LHS? - const bool RhsConstant = IsRHSIntegralLiteral; - Expr *Const = RhsConstant ? RHS : LHS; - Expr *Other = RhsConstant ? LHS : RHS; - const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue; - - // 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); - } - } - - if (!T->hasUnsignedIntegerRepresentation()) { - // We don't do anything special if this isn't an unsigned integral - // comparison: we're only interested in integral comparisons, and - // signed comparisons only happen in cases we don't care to warn about. + // If this is a tautological comparison, suppress -Wsign-compare. + if (CheckTautologicalComparisonWithZero(S, E)) return AnalyzeImpConvsInComparison(S, E); - } - LHS = LHS->IgnoreParenImpCasts(); - RHS = RHS->IgnoreParenImpCasts(); + // We don't do anything special if this isn't an unsigned integral + // comparison: we're only interested in integral comparisons, and + // signed comparisons only happen in cases we don't care to warn about. + if (!T->hasUnsignedIntegerRepresentation()) + return AnalyzeImpConvsInComparison(S, E); // Check to see if one of the (unmodified) operands is of different // signedness. diff --git a/test/Analysis/conversion.c b/test/Analysis/conversion.c index 7adb336eb2..a22a567654 100644 --- a/test/Analysis/conversion.c +++ b/test/Analysis/conversion.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,alpha.core.Conversion -verify %s +// RUN: %clang_analyze_cc1 -Wno-conversion -analyzer-checker=core,alpha.core.Conversion -verify %s unsigned char U8; signed char S8; diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index d0e1f9f5cc..5dee308a00 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -Wno-tautological-constant-compare -Wtautological-unsigned-zero-compare -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type typedef unsigned uintptr_t; diff --git a/test/Sema/outof-range-constant-compare.c b/test/Sema/outof-range-constant-compare.c index ccb55e4a16..36b6ff69ca 100644 --- a/test/Sema/outof-range-constant-compare.c +++ b/test/Sema/outof-range-constant-compare.c @@ -7,6 +7,58 @@ int main() { int a = value(); + if (a == 0x0000000000000000L) + return 0; + if (a != 0x0000000000000000L) + return 0; + if (a < 0x0000000000000000L) + return 0; + if (a <= 0x0000000000000000L) + return 0; + if (a > 0x0000000000000000L) + return 0; + if (a >= 0x0000000000000000L) + return 0; + + if (0x0000000000000000L == a) + return 0; + if (0x0000000000000000L != a) + return 0; + if (0x0000000000000000L < a) + return 0; + if (0x0000000000000000L <= a) + return 0; + if (0x0000000000000000L > a) + return 0; + if (0x0000000000000000L >= a) + return 0; + + if (a == 0x0000000000000000UL) + return 0; + if (a != 0x0000000000000000UL) + return 0; + if (a < 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression < 0 is always false}} + return 0; + if (a <= 0x0000000000000000UL) + return 0; + if (a > 0x0000000000000000UL) + return 0; + if (a >= 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}} + return 0; + + if (0x0000000000000000UL == a) + return 0; + if (0x0000000000000000UL != a) + return 0; + if (0x0000000000000000UL < a) + return 0; + if (0x0000000000000000UL <= a) // expected-warning {{comparison of 0 <= unsigned expression is always true}} + return 0; + if (0x0000000000000000UL > a) // expected-warning {{comparison of 0 > unsigned expression is always false}} + return 0; + if (0x0000000000000000UL >= a) + return 0; + if (a == 0x1234567812345678L) // expected-warning {{comparison of constant 1311768465173141112 with expression of type 'int' is always false}} return 0; if (a != 0x1234567812345678L) // expected-warning {{comparison of constant 1311768465173141112 with expression of type 'int' is always true}} @@ -103,6 +155,113 @@ int main() if (0x1234567812345678L >= l) return 0; + unsigned un = 0; + if (un == 0x0000000000000000L) + return 0; + if (un != 0x0000000000000000L) + return 0; + if (un < 0x0000000000000000L) // expected-warning {{comparison of unsigned expression < 0 is always false}} + return 0; + if (un <= 0x0000000000000000L) + return 0; + if (un > 0x0000000000000000L) + return 0; + if (un >= 0x0000000000000000L) // expected-warning {{comparison of unsigned expression >= 0 is always true}} + return 0; + + if (0x0000000000000000L == un) + return 0; + if (0x0000000000000000L != un) + return 0; + if (0x0000000000000000L < un) + return 0; + if (0x0000000000000000L <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}} + return 0; + if (0x0000000000000000L > un) // expected-warning {{comparison of 0 > unsigned expression is always false}} + return 0; + if (0x0000000000000000L >= un) + return 0; + + if (un == 0x0000000000000000UL) + return 0; + if (un != 0x0000000000000000UL) + return 0; + if (un < 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression < 0 is always false}} + return 0; + if (un <= 0x0000000000000000UL) + return 0; + if (un > 0x0000000000000000UL) + return 0; + if (un >= 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}} + return 0; + + if (0x0000000000000000UL == un) + return 0; + if (0x0000000000000000UL != un) + return 0; + if (0x0000000000000000UL < un) + return 0; + if (0x0000000000000000UL <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}} + return 0; + if (0x0000000000000000UL > un) // expected-warning {{comparison of 0 > unsigned expression is always false}} + return 0; + if (0x0000000000000000UL >= un) + return 0; + + float fl = 0; + if (fl == 0x0000000000000000L) + return 0; + if (fl != 0x0000000000000000L) + return 0; + if (fl < 0x0000000000000000L) + return 0; + if (fl <= 0x0000000000000000L) + return 0; + if (fl > 0x0000000000000000L) + return 0; + if (fl >= 0x0000000000000000L) + return 0; + + if (0x0000000000000000L == fl) + return 0; + if (0x0000000000000000L != fl) + return 0; + if (0x0000000000000000L < fl) + return 0; + if (0x0000000000000000L <= fl) + return 0; + if (0x0000000000000000L > fl) + return 0; + if (0x0000000000000000L >= fl) + return 0; + + double dl = 0; + if (dl == 0x0000000000000000L) + return 0; + if (dl != 0x0000000000000000L) + return 0; + if (dl < 0x0000000000000000L) + return 0; + if (dl <= 0x0000000000000000L) + return 0; + if (dl > 0x0000000000000000L) + return 0; + if (dl >= 0x0000000000000000L) + return 0; + + if (0x0000000000000000L == dl) + return 0; + if (0x0000000000000000L != dl) + return 0; + if (0x0000000000000000L < dl) + return 0; + if (0x0000000000000000L <= dl) + return 0; + if (0x0000000000000000L > dl) + return 0; + if (0x0000000000000000L >= dl) + return 0; + enum E { yes, no, diff --git a/test/Sema/tautological-constant-compare.c b/test/Sema/tautological-constant-compare.c deleted file mode 100644 index b9ade2a2db..0000000000 --- a/test/Sema/tautological-constant-compare.c +++ /dev/null @@ -1,514 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify %s -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify %s -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify -x c++ %s -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify -x c++ %s - -int value(void); - -#define macro(val) val - -#ifdef __cplusplus -template -void TFunc() { - // Make sure that we do warn for normal variables in template functions ! - unsigned char c = value(); -#ifdef TEST - if (c > 255) // expected-warning {{comparison 'unsigned char' > 255 is always false}} - return; -#else - if (c > 255) - return; -#endif - - if (c > macro(255)) - return; - - T v = value(); - if (v > 255) - return; - if (v > 32767) - return; -} -#endif - -int main() -{ -#ifdef __cplusplus - TFunc(); - TFunc(); -#endif - - short s = value(); - -#ifdef TEST - if (s == 32767) - return 0; - if (s != 32767) - return 0; - if (s < 32767) - return 0; - if (s <= 32767) // expected-warning {{comparison 'short' <= 32767 is always true}} - return 0; - if (s > 32767) // expected-warning {{comparison 'short' > 32767 is always false}} - return 0; - if (s >= 32767) - return 0; - - if (32767 == s) - return 0; - if (32767 != s) - return 0; - if (32767 < s) // expected-warning {{comparison 32767 < 'short' is always false}} - return 0; - if (32767 <= s) - return 0; - if (32767 > s) - return 0; - if (32767 >= s) // expected-warning {{comparison 32767 >= 'short' is always true}} - return 0; - - // FIXME: assumes two's complement - if (s == -32768) - return 0; - if (s != -32768) - return 0; - if (s < -32768) // expected-warning {{comparison 'short' < -32768 is always false}} - return 0; - if (s <= -32768) - return 0; - if (s > -32768) - return 0; - if (s >= -32768) // expected-warning {{comparison 'short' >= -32768 is always true}} - return 0; - - if (-32768 == s) - return 0; - if (-32768 != s) - return 0; - if (-32768 < s) - return 0; - if (-32768 <= s) // expected-warning {{comparison -32768 <= 'short' is always true}} - return 0; - if (-32768 > s) // expected-warning {{comparison -32768 > 'short' is always false}} - return 0; - if (-32768 >= s) - return 0; - - if (s == 32767UL) - return 0; - if (s != 32767UL) - return 0; - if (s < 32767UL) - return 0; - if (s <= 32767UL) // expected-warning {{comparison 'short' <= 32767 is always true}} - return 0; - if (s > 32767UL) // expected-warning {{comparison 'short' > 32767 is always false}} - return 0; - if (s >= 32767UL) - return 0; - - if (32767UL == s) - return 0; - if (32767UL != s) - return 0; - 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) // expected-warning {{comparison 32767 >= 'short' is always true}} - return 0; - - // FIXME: assumes two's complement - if (s == -32768L) - return 0; - if (s != -32768L) - return 0; - if (s < -32768L) // expected-warning {{comparison 'short' < -32768 is always false}} - return 0; - if (s <= -32768L) - return 0; - if (s > -32768L) - return 0; - if (s >= -32768L) // expected-warning {{comparison 'short' >= -32768 is always true}} - return 0; - - if (-32768L == s) - return 0; - if (-32768L != s) - return 0; - if (-32768L < s) - return 0; - if (-32768L <= s) // expected-warning {{comparison -32768 <= 'short' is always true}} - return 0; - if (-32768L > s) // expected-warning {{comparison -32768 > 'short' is always false}} - return 0; - if (-32768L >= s) - return 0; -#else - // expected-no-diagnostics - if (s == 32767) - return 0; - if (s != 32767) - return 0; - if (s < 32767) - return 0; - if (s <= 32767) - return 0; - if (s > 32767) - return 0; - if (s >= 32767) - return 0; - - if (32767 == s) - return 0; - if (32767 != s) - return 0; - if (32767 < s) - return 0; - if (32767 <= s) - return 0; - if (32767 > s) - return 0; - if (32767 >= s) - return 0; - - // FIXME: assumes two's complement - if (s == -32768) - return 0; - if (s != -32768) - return 0; - if (s < -32768) - return 0; - if (s <= -32768) - return 0; - if (s > -32768) - return 0; - if (s >= -32768) - return 0; - - if (-32768 == s) - return 0; - if (-32768 != s) - return 0; - if (-32768 < s) - return 0; - if (-32768 <= s) - return 0; - if (-32768 > s) - return 0; - if (-32768 >= s) - return 0; - - if (s == 32767UL) - return 0; - if (s != 32767UL) - return 0; - if (s < 32767UL) - return 0; - if (s <= 32767UL) - return 0; - if (s > 32767UL) - return 0; - if (s >= 32767UL) - return 0; - - if (32767UL == s) - return 0; - if (32767UL != s) - return 0; - if (32767UL < s) - return 0; - if (32767UL <= s) - return 0; - if (32767UL > s) - return 0; - if (32767UL >= s) - return 0; - - // FIXME: assumes two's complement - if (s == -32768L) - return 0; - if (s != -32768L) - return 0; - if (s < -32768L) - return 0; - if (s <= -32768L) - return 0; - if (s > -32768L) - return 0; - if (s >= -32768L) - return 0; - - if (-32768L == s) - return 0; - if (-32768L != s) - return 0; - if (-32768L < s) - return 0; - if (-32768L <= s) - return 0; - if (-32768L > s) - return 0; - if (-32768L >= s) - return 0; -#endif - - if (s == 0) - return 0; - if (s != 0) - return 0; - if (s < 0) - return 0; - if (s <= 0) - return 0; - if (s > 0) - return 0; - if (s >= 0) - return 0; - - if (0 == s) - return 0; - if (0 != s) - return 0; - if (0 < s) - return 0; - if (0 <= s) - return 0; - if (0 > s) - return 0; - if (0 >= s) - return 0; - - // However the comparison with 0U would warn - - unsigned short us = value(); - -#ifdef TEST - if (us == 65535) - return 0; - if (us != 65535) - return 0; - if (us < 65535) - return 0; - if (us <= 65535) // expected-warning {{comparison 'unsigned short' <= 65535 is always true}} - return 0; - if (us > 65535) // expected-warning {{comparison 'unsigned short' > 65535 is always false}} - return 0; - if (us >= 65535) - return 0; - - if (65535 == us) - return 0; - if (65535 != us) - return 0; - if (65535 < us) // expected-warning {{comparison 65535 < 'unsigned short' is always false}} - return 0; - if (65535 <= us) - return 0; - if (65535 > us) - return 0; - if (65535 >= us) // expected-warning {{comparison 65535 >= 'unsigned short' is always true}} - return 0; - - if (us == 65535UL) - return 0; - if (us != 65535UL) - return 0; - if (us < 65535UL) - return 0; - if (us <= 65535UL) // expected-warning {{comparison 'unsigned short' <= 65535 is always true}} - return 0; - if (us > 65535UL) // expected-warning {{comparison 'unsigned short' > 65535 is always false}} - return 0; - if (us >= 65535UL) - return 0; - - if (65535UL == us) - return 0; - if (65535UL != us) - return 0; - if (65535UL < us) // expected-warning {{comparison 65535 < 'unsigned short' is always false}} - return 0; - if (65535UL <= us) - return 0; - if (65535UL > us) - return 0; - if (65535UL >= us) // expected-warning {{comparison 65535 >= 'unsigned short' is always true}} - return 0; -#else - // expected-no-diagnostics - if (us == 65535) - return 0; - if (us != 65535) - return 0; - if (us < 65535) - return 0; - if (us <= 65535) - return 0; - if (us > 65535) - return 0; - if (us >= 65535) - return 0; - - if (65535 == us) - return 0; - if (65535 != us) - return 0; - if (65535 < us) - return 0; - if (65535 <= us) - return 0; - if (65535 > us) - return 0; - if (65535 >= us) - return 0; - - if (us == 65535UL) - return 0; - if (us != 65535UL) - return 0; - if (us < 65535UL) - return 0; - if (us <= 65535UL) - return 0; - if (us > 65535UL) - return 0; - if (us >= 65535UL) - return 0; - - if (65535UL == us) - return 0; - if (65535UL != us) - return 0; - if (65535UL < us) - return 0; - if (65535UL <= us) - return 0; - if (65535UL > us) - return 0; - if (65535UL >= us) - return 0; -#endif - - if (us == 32767) - return 0; - if (us != 32767) - return 0; - if (us < 32767) - return 0; - if (us <= 32767) - return 0; - if (us > 32767) - return 0; - if (us >= 32767) - return 0; - - if (32767 == us) - return 0; - if (32767 != us) - return 0; - if (32767 < us) - return 0; - if (32767 <= us) - return 0; - if (32767 > us) - return 0; - if (32767 >= us) - return 0; - - if (us == 32767UL) - return 0; - if (us != 32767UL) - return 0; - if (us < 32767UL) - return 0; - if (us <= 32767UL) - return 0; - if (us > 32767UL) - return 0; - if (us >= 32767UL) - return 0; - - if (32767UL == us) - return 0; - if (32767UL != us) - return 0; - if (32767UL < us) - return 0; - if (32767UL <= us) - return 0; - if (32767UL > us) - return 0; - if (32767UL >= us) - return 0; - -#if __SIZEOF_INT128__ - __int128 i128; - if (i128 == -1) // used to crash - return 0; -#endif - - - enum E { - yes, - no, - maybe - }; - enum E e; - - if (e == yes) - return 0; - if (e != yes) - return 0; - if (e < yes) - return 0; - if (e <= yes) - return 0; - if (e > yes) - return 0; - if (e >= yes) - return 0; - - if (yes == e) - return 0; - if (yes != e) - return 0; - if (yes < e) - return 0; - if (yes <= e) - return 0; - if (yes > e) - return 0; - if (yes >= e) - return 0; - - if (e == maybe) - return 0; - if (e != maybe) - return 0; - if (e < maybe) - return 0; - if (e <= maybe) - return 0; - if (e > maybe) - return 0; - if (e >= maybe) - return 0; - - if (maybe == e) - return 0; - if (maybe != e) - return 0; - if (maybe < e) - return 0; - if (maybe <= e) - return 0; - if (maybe > e) - return 0; - if (maybe >= e) - return 0; - - return 1; -} diff --git a/test/Sema/tautological-unsigned-zero-compare.c b/test/Sema/tautological-unsigned-zero-compare.c index e0611cb400..039d8f885e 100644 --- a/test/Sema/tautological-unsigned-zero-compare.c +++ b/test/Sema/tautological-unsigned-zero-compare.c @@ -1,370 +1,47 @@ // RUN: %clang_cc1 -fsyntax-only -DTEST -verify %s // RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify %s -// RUN: %clang_cc1 -fsyntax-only -DTEST -verify -x c++ %s -// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify -x c++ %s -unsigned uvalue(void); -signed int svalue(void); +unsigned value(void); -#define macro(val) val +int main() { + unsigned un = value(); -#ifdef __cplusplus -template -void TFunc() { - // Make sure that we do warn for normal variables in template functions ! - unsigned char c = svalue(); #ifdef TEST - if (c < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}} - return; -#else - if (c < 0) - return; -#endif - - if (c < macro(0)) - return; - - T v = svalue(); - if (v < 0) - return; -} -#endif - -int main() -{ -#ifdef __cplusplus - TFunc(); - TFunc(); -#endif - - unsigned un = uvalue(); - -#ifdef TEST - if (un == 0) - return 0; - if (un != 0) - return 0; if (un < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}} - return 0; - if (un <= 0) - return 0; - if (un > 0) - return 0; + return 0; if (un >= 0) // expected-warning {{comparison of unsigned expression >= 0 is always true}} - return 0; - - if (0 == un) - return 0; - if (0 != un) - return 0; - if (0 < un) - return 0; + return 0; if (0 <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}} - return 0; + return 0; if (0 > un) // expected-warning {{comparison of 0 > unsigned expression is always false}} - return 0; - if (0 >= un) - return 0; - - if (un == 0UL) - return 0; - if (un != 0UL) - return 0; - if (un < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}} - return 0; - if (un <= 0UL) - return 0; - if (un > 0UL) - return 0; - if (un >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}} - return 0; - - if (0UL == un) - return 0; - if (0UL != un) - return 0; - if (0UL < un) - return 0; - if (0UL <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}} - return 0; - if (0UL > un) // expected-warning {{comparison of 0 > unsigned expression is always false}} - return 0; - if (0UL >= un) - return 0; + return 0; + if (un < 0U) // expected-warning {{comparison of unsigned expression < 0 is always false}} + return 0; + if (un >= 0U) // expected-warning {{comparison of unsigned expression >= 0 is always true}} + return 0; + if (0U <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}} + return 0; + if (0U > un) // expected-warning {{comparison of 0 > unsigned expression is always false}} + return 0; #else // expected-no-diagnostics - if (un == 0) - return 0; - if (un != 0) - return 0; if (un < 0) - return 0; - if (un <= 0) - return 0; - if (un > 0) - return 0; + return 0; if (un >= 0) - return 0; - - if (0 == un) - return 0; - if (0 != un) - return 0; - if (0 < un) - return 0; + return 0; if (0 <= un) - return 0; + return 0; if (0 > un) - return 0; - if (0 >= un) - return 0; - - if (un == 0UL) - return 0; - if (un != 0UL) - return 0; - if (un < 0UL) - return 0; - if (un <= 0UL) - return 0; - if (un > 0UL) - return 0; - if (un >= 0UL) - return 0; - - if (0UL == un) - return 0; - if (0UL != un) - return 0; - if (0UL < un) - return 0; - if (0UL <= un) - return 0; - if (0UL > un) - return 0; - if (0UL >= un) - return 0; -#endif - - - signed int a = svalue(); - -#ifdef TEST - if (a == 0) - return 0; - if (a != 0) - return 0; - if (a < 0) - return 0; - if (a <= 0) - return 0; - if (a > 0) - return 0; - if (a >= 0) - return 0; - - if (0 == a) - return 0; - if (0 != a) - return 0; - if (0 < a) - return 0; - if (0 <= a) - return 0; - if (0 > a) - return 0; - if (0 >= a) - return 0; - - if (a == 0UL) - return 0; - if (a != 0UL) - return 0; - if (a < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}} - return 0; - if (a <= 0UL) - return 0; - if (a > 0UL) - return 0; - if (a >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}} - return 0; - - if (0UL == a) - return 0; - if (0UL != a) - return 0; - if (0UL < a) - return 0; - if (0UL <= a) // expected-warning {{comparison of 0 <= unsigned expression is always true}} - return 0; - if (0UL > a) // expected-warning {{comparison of 0 > unsigned expression is always false}} - return 0; - if (0UL >= a) - return 0; -#else -// expected-no-diagnostics - if (a == 0) - return 0; - if (a != 0) - return 0; - if (a < 0) - return 0; - if (a <= 0) - return 0; - if (a > 0) - return 0; - if (a >= 0) - return 0; - - if (0 == a) - return 0; - if (0 != a) - return 0; - if (0 < a) - return 0; - if (0 <= a) - return 0; - if (0 > a) - return 0; - if (0 >= a) - return 0; - - if (a == 0UL) - return 0; - if (a != 0UL) - return 0; - if (a < 0UL) - return 0; - if (a <= 0UL) - return 0; - if (a > 0UL) - return 0; - if (a >= 0UL) - return 0; - - if (0UL == a) - return 0; - if (0UL != a) - return 0; - if (0UL < a) - return 0; - if (0UL <= a) - return 0; - if (0UL > a) - return 0; - if (0UL >= a) - return 0; + return 0; + if (un < 0U) + return 0; + if (un >= 0U) + return 0; + if (0U <= un) + return 0; + if (0U > un) + return 0; #endif - - float fl = 0; - - if (fl == 0) - return 0; - if (fl != 0) - return 0; - if (fl < 0) - return 0; - if (fl <= 0) - return 0; - if (fl > 0) - return 0; - if (fl >= 0) - return 0; - - if (0 == fl) - return 0; - if (0 != fl) - return 0; - if (0 < fl) - return 0; - if (0 <= fl) - return 0; - if (0 > fl) - return 0; - if (0 >= fl) - return 0; - - if (fl == 0UL) - return 0; - if (fl != 0UL) - return 0; - if (fl < 0UL) - return 0; - if (fl <= 0UL) - return 0; - if (fl > 0UL) - return 0; - if (fl >= 0UL) - return 0; - - if (0UL == fl) - return 0; - if (0UL != fl) - return 0; - if (0UL < fl) - return 0; - if (0UL <= fl) - return 0; - if (0UL > fl) - return 0; - if (0UL >= fl) - return 0; - - - double dl = 0; - - if (dl == 0) - return 0; - if (dl != 0) - return 0; - if (dl < 0) - return 0; - if (dl <= 0) - return 0; - if (dl > 0) - return 0; - if (dl >= 0) - return 0; - - if (0 == dl) - return 0; - if (0 != dl) - return 0; - if (0 < dl) - return 0; - if (0 <= dl) - return 0; - if (0 > dl) - return 0; - if (0 >= dl) - return 0; - - if (dl == 0UL) - return 0; - if (dl != 0UL) - return 0; - if (dl < 0UL) - return 0; - if (dl <= 0UL) - return 0; - if (dl > 0UL) - return 0; - if (dl >= 0UL) - return 0; - - if (0UL == dl) - return 0; - if (0UL != dl) - return 0; - if (0UL < dl) - return 0; - if (0UL <= dl) - return 0; - if (0UL > dl) - return 0; - if (0UL >= dl) - return 0; - return 1; } -- cgit v1.2.3