7c611aed7c
This adds few fixes, but mostly it updates the rewrite-includes patch. Sadly upstream has decided to rename the option name for whatever reason, so if unchanged 12.2 would be the only clang with the option named this way, causing further problems e.g. with icecream. So it would be very nice to get this into 12.2. As it is an isolated feature, it should be low-risk. OBS-URL: https://build.opensuse.org/request/show/127882 OBS-URL: https://build.opensuse.org/package/show/devel:tools:compiler/llvm?expand=0&rev=155
112 lines
5.4 KiB
Diff
112 lines
5.4 KiB
Diff
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}}
|
|
|
|
}
|
|
|