From: John McCall Date: Wed, 6 Oct 2010 00:25:24 +0000 (+0000) Subject: Provide a slightly specialized diagnostic for tautological comparisons X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=372e103dab4239ec52b65b9eda69fd43c0b348d4;p=clang Provide a slightly specialized diagnostic for tautological comparisons of an enum value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115725 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 42b22f4f55..fafce83b9a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2251,10 +2251,10 @@ def warn_mixed_sign_conditional : Warning< "operands of ? are integers of different signs: %0 and %1">, InGroup, DefaultIgnore; def warn_lunsigned_always_true_comparison : Warning< - "comparison of unsigned expression %0 is always %1">, + "comparison of unsigned%select{| enum}2 expression %0 is always %1">, InGroup; def warn_runsigned_always_true_comparison : Warning< - "comparison of %0 unsigned expression is always %1">, + "comparison of %0 unsigned%select{| enum}2 expression is always %1">, InGroup; def err_invalid_this_use : Error< diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index e2cc2f3263..e79b639229 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2451,23 +2451,39 @@ static bool IsZero(Sema &S, Expr *E) { return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; } +static bool HasEnumType(Expr *E) { + // Strip off implicit integral promotions. + while (ImplicitCastExpr *ICE = dyn_cast(E)) { + switch (ICE->getCastKind()) { + case CK_IntegralCast: + case CK_NoOp: + E = ICE->getSubExpr(); + continue; + default: + break; + } + } + + return E->getType()->isEnumeralType(); +} + void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { BinaryOperatorKind op = E->getOpcode(); if (op == BO_LT && IsZero(S, E->getRHS())) { S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) - << "< 0" << "false" + << "< 0" << "false" << HasEnumType(E->getLHS()) << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } else if (op == BO_GE && IsZero(S, E->getRHS())) { S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) - << ">= 0" << "true" + << ">= 0" << "true" << HasEnumType(E->getLHS()) << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } else if (op == BO_GT && IsZero(S, E->getLHS())) { S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) - << "0 >" << "false" + << "0 >" << "false" << HasEnumType(E->getRHS()) << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } else if (op == BO_LE && IsZero(S, E->getLHS())) { S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) - << "0 <=" << "true" + << "0 <=" << "true" << HasEnumType(E->getRHS()) << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } } diff --git a/test/Sema/compare.c b/test/Sema/compare.c index 2a6917e607..5221b172a6 100644 --- a/test/Sema/compare.c +++ b/test/Sema/compare.c @@ -305,3 +305,10 @@ int rdar8414119_bar(unsigned x) { #undef ZERO #undef CHECK +int rdar8511238() { + enum A { A_foo, A_bar }; + enum A a; + if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}} + return 0; + return 20; +}