[clang] [clang-tools-extra] [clang-tidy][dataflow] Add `bugprone-null-check-after-dereference` check (PR #84166)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 27 03:52:16 PDT 2024
================
@@ -0,0 +1,330 @@
+// RUN: %check_clang_tidy %s bugprone-null-check-after-dereference %t
+
+struct S {
+ int a;
+};
+
+int warning_deref(int *p) {
+ *p = 42;
+
+ if (p) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point [bugprone-null-check-after-dereference]
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: one of the locations where the pointer's value cannot be null
+ // FIXME: If there's a direct path, make the error message more precise, ie. remove `one of the locations`
+ *p += 20;
+ return *p;
+ } else {
+ return 0;
+ }
+}
+
+int warning_member(S *q) {
+ q->a = 42;
+
+ if (q) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: one of the locations where the pointer's value cannot be null
+ q->a += 20;
+ return q->a;
+ } else {
+ return 0;
+ }
+}
+
+int negative_warning(int *p) {
+ *p = 42;
+
+ if (!p) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: one of the locations where the pointer's value cannot be null
+ return 0;
+ } else {
+ *p += 20;
+ return *p;
+ }
+}
+
+int no_warning(int *p, bool b) {
+ if (b) {
+ *p = 42;
+ }
+
+ if (p) {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ *p += 20;
+ return *p;
+ } else {
+ return 0;
+ }
+}
+
+int else_branch_warning(int *p, bool b) {
+ if (b) {
+ *p = 42;
+ } else {
+ *p = 20;
+ }
+
+ if (p) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-7]]:5: note: one of the locations where the pointer's value cannot be null
+ return 0;
+ } else {
+ *p += 20;
+ return *p;
+ }
+}
+
+int two_branches_warning(int *p, bool b) {
+ if (b) {
+ *p = 42;
+ }
+
+ if (!b) {
+ *p = 20;
+ }
+
+ if (p) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-9]]:5: note: one of the locations where the pointer's value cannot be null
+ return 0;
+ } else {
+ *p += 20;
+ return *p;
+ }
+}
+
+int two_branches_reversed(int *p, bool b) {
+ if (!b) {
+ *p = 42;
+ }
+
+ if (b) {
+ *p = 20;
+ }
+
+ if (p) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-9]]:5: note: one of the locations where the pointer's value cannot be null
+ return 0;
+ } else {
+ *p += 20;
+ return *p;
+ }
+}
+
+
+int regular_assignment(int *p, int *q) {
+ *p = 42;
+ q = p;
+
+ if (q) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-5]]:3: note: one of the locations where the pointer's value cannot be null
+ *p += 20;
+ return *p;
+ } else {
+ return 0;
+ }
+}
+
+int nullptr_assignment(int *nullptr_param, bool b) {
+ *nullptr_param = 42;
+ int *nullptr_assigned;
+
+ if (b) {
+ nullptr_assigned = nullptr;
+ } else {
+ nullptr_assigned = nullptr_param;
+ }
+
+ if (nullptr_assigned) {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ *nullptr_assigned = 20;
+ return *nullptr_assigned;
+ } else {
+ return 0;
+ }
+}
+
+extern int *fncall();
+extern void refresh_ref(int *&ptr);
+extern void refresh_ptr(int **ptr);
+
+int fncall_reassignment(int *fncall_reassigned) {
+ *fncall_reassigned = 42;
+
+ fncall_reassigned = fncall();
+
+ if (fncall_reassigned) {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ *fncall_reassigned = 42;
+ }
+
+ fncall_reassigned = fncall();
+
+ *fncall_reassigned = 42;
+
+ if (fncall_reassigned) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: one of the locations where the pointer's value cannot be null
+ *fncall_reassigned = 42;
+ }
+
+ refresh_ptr(&fncall_reassigned);
+
+ if (fncall_reassigned) {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ *fncall_reassigned = 42;
+ }
+
+ refresh_ptr(&fncall_reassigned);
+ *fncall_reassigned = 42;
+
+ if (fncall_reassigned) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer value is checked even though it cannot be null at this point
+ // CHECK-MESSAGES: :[[@LINE-4]]:3: note: one of the locations where the pointer's value cannot be null
+ *fncall_reassigned = 42;
+ return *fncall_reassigned;
+ } else {
+ return 0;
+ }
+}
+
+int chained_references(int *a, int *b, int *c, int *d, int *e) {
----------------
martinboehme wrote:
Can you remove the unused parameters `d` and `e` too?
https://github.com/llvm/llvm-project/pull/84166
More information about the cfe-commits
mailing list