llvm/pr12463.patch

112 lines
5.4 KiB
Diff
Raw Normal View History

diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fea0fe1..1046972 100644
--- tools/clang/lib/Sema/SemaExpr.cpp
+++ tools/clang/lib/Sema/SemaExpr.cpp
@@ -6577,23 +6577,29 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
checkEnumComparison(*this, Loc, LHS, RHS);
if (!LHSType->hasFloatingRepresentation() &&
- !(LHSType->isBlockPointerType() && IsRelational) &&
- !LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID()) {
+ !(LHSType->isBlockPointerType() && IsRelational)) {
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
//
- // NOTE: Don't warn about comparison expressions resulting from macro
- // expansion. Also don't warn about comparisons which are only self
+ // NOTE: Don't warn about self-comparison expressions resulting from macro
+ // expansion, unless they don't make sense at all.
+ // Also don't warn about comparisons which are only self
// comparisons within a template specialization. The warnings should catch
// obvious cases in the definition of the template anyways. The idea is to
// warn when the typed comparison operator will always evaluate to the same
// result.
+ bool InMacro = LHS.get()->getLocStart().isMacroID() ||
+ RHS.get()->getLocStart().isMacroID();
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
+ if (isa<CastExpr>(LHSStripped))
+ LHSStripped = LHSStripped->IgnoreParenCasts();
if (DRL->getDecl() == DRR->getDecl() &&
- !IsWithinTemplateSpecialization(DRL->getDecl())) {
+ !IsWithinTemplateSpecialization(DRL->getDecl()) &&
+ !InMacro &&
+ !isa<StringLiteral>(LHSStripped) &&
+ !isa<ObjCEncodeExpr>(LHSStripped)) {
DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
@@ -6602,23 +6608,26 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
} else if (LHSType->isArrayType() && RHSType->isArrayType() &&
!DRL->getDecl()->getType()->isReferenceType() &&
!DRR->getDecl()->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
switch(Opc) {
case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
+ if (!InMacro)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 0 /* evaluates to false */ );
break;
case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
+ if (!InMacro)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 1 /* evaluates to true */ );
break;
- default:
+ default: // e.g. array1 <= array2
// best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 2 /* evaluates to constant */ );
break;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
}
}
}
diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c
index 72cff65..b17b6ec 100644
--- tools/clang/test/Sema/exprs.c
+++ tools/clang/test/Sema/exprs.c
@@ -125,6 +125,12 @@ int test12b(const char *X) {
return sizeof(X == "foo"); // no-warning
}
+// PR12463
+#define FOO_LITERAL "foo"
+int test12c(const char *X) {
+ return X == FOO_LITERAL; // expected-warning {{comparison against a string literal is unspecified (use strncmp instead)}}
+}
+
// rdar://6719156
void test13(
void (^P)()) { // expected-error {{blocks support disabled - compile with -fblocks}}
diff --git a/test/Sema/self-comparison.c b/test/Sema/self-comparison.c
index edb3a6a..8679a3f 100644
--- tools/clang/test/Sema/self-comparison.c
+++ tools/clang/test/Sema/self-comparison.c
@@ -72,6 +72,13 @@ int array_comparisons() {
return array1 <= array2; // expected-warning{{array comparison always evaluates to a constant}}
return array1 > array2; // expected-warning{{array comparison always evaluates to a constant}}
return array1 >= array2; // expected-warning{{array comparison always evaluates to a constant}}
+ // Issue a warning for this even if macro expansion is involved (PR12463)
+#define ARRAY1 array1
+#define ARRAY2 array2
+ return ARRAY1 < ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 <= ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 > ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 >= ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
}