aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-10-06 00:25:24 +0000
committerJohn McCall <rjmccall@apple.com>2010-10-06 00:25:24 +0000
commit372e103dab4239ec52b65b9eda69fd43c0b348d4 (patch)
treef662e9cdf7632c21921d44817a4c1dab74534618
parent3ff83dd534ccc828203670ce3f5125a4eb4199f8 (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.td4
-rw-r--r--lib/Sema/SemaChecking.cpp24
-rw-r--r--test/Sema/compare.c7
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;
+}