diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2014-11-11 19:59:16 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2014-11-11 19:59:16 +0000 |
commit | c5fd4844da5233d514a43762d1670a912d7ce3ac (patch) | |
tree | da6e7139c3ace3f9bc837af0d7b0f96e310f9a68 | |
parent | 944547deab183814b199018a7389df91cd384cdb (diff) | |
download | bcm5719-llvm-c5fd4844da5233d514a43762d1670a912d7ce3ac.tar.gz bcm5719-llvm-c5fd4844da5233d514a43762d1670a912d7ce3ac.zip |
Patch to warn when logical evaluation of operand evalutes to a true value;
That this is a c-only patch. c++ already has this warning.
This addresses rdar://18716393
llvm-svn: 221702
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | clang/test/Analysis/logical-ops.c | 3 | ||||
-rw-r--r-- | clang/test/Sema/exprs.c | 6 | ||||
-rw-r--r-- | clang/test/Sema/warn-tautological-compare.c | 80 |
6 files changed, 104 insertions, 3 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4ad7463767d..aa039e3e47c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8033,6 +8033,7 @@ public: void DiagnoseAlwaysNonNullPointer(Expr *E, Expr::NullPointerConstantKind NullType, bool IsEqual, SourceRange Range); + void CheckAlwaysNonNullPointer(Expr *OrigExp); /// type checking for vector binary operators. QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ea4f3476b6c..fe47bfb12e9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6748,6 +6748,17 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, << FixItHint::CreateInsertion(getLocForEndOfToken(E->getLocEnd()), "()"); } +void Sema::CheckAlwaysNonNullPointer(Expr *OrigExpr) { + if (const UnaryOperator *U = dyn_cast<UnaryOperator>(OrigExpr)) + if (U->getOpcode() == UO_LNot) + return CheckAlwaysNonNullPointer(U->getSubExpr()); + + Expr *E = OrigExpr->IgnoreParenImpCasts(); + QualType Source = E->getType(); + if (Source->isPointerType() || Source->canDecayToPointerType()) + DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false, + SourceRange()); +} /// Diagnoses "dangerous" implicit conversions within the given /// expression (which is a full expression). Implements -Wconversion diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 37a08cfb081..a8429b92ed6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8413,7 +8413,10 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] if (!LHS.get()->getType()->isScalarType() || !RHS.get()->getType()->isScalarType()) return InvalidOperands(Loc, LHS, RHS); - + + CheckAlwaysNonNullPointer(LHS.get()); + CheckAlwaysNonNullPointer(RHS.get()); + return Context.IntTy; } @@ -12971,6 +12974,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { << T << E->getSourceRange(); return ExprError(); } + CheckAlwaysNonNullPointer(E); } return E; diff --git a/clang/test/Analysis/logical-ops.c b/clang/test/Analysis/logical-ops.c index afaa2f10778..2a03d96c0cb 100644 --- a/clang/test/Analysis/logical-ops.c +++ b/clang/test/Analysis/logical-ops.c @@ -36,4 +36,5 @@ int between(char *x) { int undef(void) {} // expected-warning{{control reaches end of non-void function}} void useUndef(void) { 0 || undef(); } -void testPointer(void) { (void) (1 && testPointer && 0); } +void testPointer(void) { (void) (1 && testPointer && 0); } // expected-warning {{address of function 'testPointer' will always evaluate to 'true'}} \ + // expected-note {{prefix with the address-of operator to silence this warning}} diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index 2fb17e4880c..17b1aa2851b 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -244,6 +244,10 @@ void test22() { if ("help") (void) 0; - if (test22) + if (test22) // expected-warning {{address of function 'test22' will always evaluate to 'true'}} \ + // expected-note {{prefix with the address-of operator to silence this warning}} + (void) 0; + + if (&test22) (void) 0; } diff --git a/clang/test/Sema/warn-tautological-compare.c b/clang/test/Sema/warn-tautological-compare.c new file mode 100644 index 00000000000..2856eddc7b0 --- /dev/null +++ b/clang/test/Sema/warn-tautological-compare.c @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify %s +// rdar://18716393 + +extern int a[] __attribute__((weak)); +int b[] = {8,13,21}; +struct { + int x[10]; +} c; +const char str[] = "text"; + +void ignore() { + if (!a) {} +} +void test() { + if (!b) {} // expected-warning {{address of array 'b' will always evaluate to 'true'}} + if (b == 0) {} // expected-warning {{comparison of array 'b' equal to a null pointer is always false}} + if (!c.x) {} // expected-warning {{address of array 'c.x' will always evaluate to 'true'}} + if (c.x == 0) {} // expected-warning {{comparison of array 'c.x' equal to a null pointer is always false}} + if (!str) {} // expected-warning {{address of array 'str' will always evaluate to 'true'}} + if (0 == str) {} // expected-warning {{comparison of array 'str' equal to a null pointer is always false}} +} + +int array[2]; +int test1() +{ + if (!array) { // expected-warning {{address of array 'array' will always evaluate to 'true'}} + return array[0]; + } else if (array != 0) { // expected-warning {{comparison of array 'array' not equal to a null pointer is always true}} + return array[1]; + } + if (array == 0) // expected-warning {{comparison of array 'array' equal to a null pointer is always false}} + return 1; + return 0; +} + +#define NULL (void*)0 + +int test2(int* pointer, char ch, void * pv) { + if (!&pointer) { // expected-warning {{address of 'pointer' will always evaluate to 'true'}} + return 0; + } + + if (&pointer) { // expected-warning {{address of 'pointer' will always evaluate to 'true'}} + return 0; + } + + if (&pointer == NULL) {} // expected-warning {{comparison of address of 'pointer' equal to a null pointer is always false}} + + if (&pointer != NULL) {} // expected-warning {{comparison of address of 'pointer' not equal to a null pointer is always true}} + + return 1; +} + +void test3() { + if (array) { } // expected-warning {{address of array 'array' will always evaluate to 'true'}} + if (array != 0) {} // expected-warning {{comparison of array 'array' not equal to a null pointer is always true}} + if (!array) { } // expected-warning {{address of array 'array' will always evaluate to 'true'}} + if (array == 0) {} // expected-warning {{comparison of array 'array' equal to a null pointer is always false}} + + if (array[0] && + array) {} // expected-warning {{address of array 'array' will always evaluate to 'true'}} + + if (array[0] || + array) {} // expected-warning {{address of array 'array' will always evaluate to 'true'}} + + if (array[0] && + !array) {} // expected-warning {{address of array 'array' will always evaluate to 'true'}} + if (array[0] || + !array) {} // expected-warning {{address of array 'array' will always evaluate to 'true'}} + + if (array && // expected-warning {{address of array 'array' will always evaluate to 'true'}} + array[0]) {} + if (!array || // expected-warning {{address of array 'array' will always evaluate to 'true'}} + array[0]) {} + + if (array || // expected-warning {{address of array 'array' will always evaluate to 'true'}} + (!array && array[0])) {} // expected-warning {{address of array 'array' will always evaluate to 'true'}} + } + + |