diff options
author | John McCall <rjmccall@apple.com> | 2010-10-06 00:25:24 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-10-06 00:25:24 +0000 |
commit | 372e103dab4239ec52b65b9eda69fd43c0b348d4 (patch) | |
tree | f662e9cdf7632c21921d44817a4c1dab74534618 | |
parent | 3ff83dd534ccc828203670ce3f5125a4eb4199f8 (diff) |
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
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 24 | ||||
-rw-r--r-- | test/Sema/compare.c | 7 |
3 files changed, 29 insertions, 6 deletions
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<SignCompare>, 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<TautologicalCompare>; 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<TautologicalCompare>; 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<ImplicitCastExpr>(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; +} |