I would like to warn on logical negation of operands with known non-null value;
as in "if (!array)…", just as we warn on "if (array == 0)…"
Note that this is a c-only patch. c++ already has a warning when such non-null
pointers are implicitly converted to bool.
Is this ok for check-in?
- Fariborz
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h (revision 220486)
+++ include/clang/AST/Expr.h (working copy)
@@ -641,7 +641,10 @@
NPCK_CXX11_nullptr,
/// \brief Expression is a GNU-style __null constant.
- NPCK_GNUNull
+ NPCK_GNUNull,
+
+ /// \brief Expression is operand of a logical negation operator
+ NPCK_LNEG_ZeroLiteral
};
/// \brief Enumeration used to describe how \c isNullPointerConstant()
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 220486)
+++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
@@ -2512,6 +2512,10 @@
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
"equal to a null pointer is always %select{true|false}2">,
InGroup<TautologicalPointerCompare>;
+def warn_null_logical_negation_compare : Warning<
+ "logical negation of %select{address of|function|array}0 '%1' is "
+ "always %select{true|false}2">,
+ InGroup<TautologicalPointerCompare>;
def warn_this_null_compare : Warning<
"'this' pointer cannot be null in well-defined C++ code; comparison may be "
"assumed to always evaluate to %select{true|false}0">,
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp (revision 220486)
+++ lib/Sema/SemaChecking.cpp (working copy)
@@ -6697,8 +6697,11 @@
llvm::raw_string_ostream S(Str);
E->printPretty(S, nullptr, getPrintingPolicy());
- unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
- : diag::warn_impcast_pointer_to_bool;
+ unsigned DiagID =
+ IsCompare ? (NullKind != Expr::NPCK_LNEG_ZeroLiteral
+ ? diag::warn_null_pointer_compare
+ : diag::warn_null_logical_negation_compare)
+ : diag::warn_impcast_pointer_to_bool;
unsigned DiagType;
if (IsAddressOf)
DiagType = AddressOf;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp (revision 220486)
+++ lib/Sema/SemaExpr.cpp (working copy)
@@ -9952,7 +9952,10 @@
// that are explicitly defined as valid by the standard).
if (Opc != UO_AddrOf && Opc != UO_Deref)
CheckArrayAccess(Input.get());
-
+ if (Opc == UO_LNot && Input.get()->getType()->isPointerType() &&
+ !getLangOpts().CPlusPlus)
+ DiagnoseAlwaysNonNullPointer(Input.get(), Expr::NPCK_LNEG_ZeroLiteral,
+ true, SourceRange());
return new (Context)
UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc);
}
Index: test/Sema/warn-tautological-compare.c
===================================================================
--- test/Sema/warn-tautological-compare.c (revision 0)
+++ test/Sema/warn-tautological-compare.c (working copy)
@@ -0,0 +1,34 @@
+// 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 {{logical negation of array 'b' is always
false}}
+ if (b == 0) {} // expected-warning {{comparison of array 'b' equal to a null
pointer is always false}}
+ if (!c.x) {} // expected-warning {{logical negation of array 'c.x' is always
false}}
+ if (c.x == 0) {} // expected-warning {{comparison of array 'c.x' equal to a
null pointer is always false}}
+ if (!str) {} // expected-warning {{logical negation of array 'str' is always
false}}
+ 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 {{logical negation of array 'array' is
always false}}
+ 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;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits