aboutsummaryrefslogtreecommitdiff
path: root/test/Analysis/diagnostics/macro-null-return-suppression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/diagnostics/macro-null-return-suppression.cpp')
-rw-r--r--test/Analysis/diagnostics/macro-null-return-suppression.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/test/Analysis/diagnostics/macro-null-return-suppression.cpp b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
new file mode 100644
index 000000000000..a2928f15c1e3
--- /dev/null
+++ b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_analyze_cc1 -x c -analyzer-checker=core -analyzer-output=text -verify %s
+
+#define NULL 0
+
+int test_noparammacro() {
+ int *x = NULL; // expected-note{{'x' initialized to a null pointer value}}
+ return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
+ // expected-note@-1{{Dereference of null pointer (loaded from variable 'x')}}
+}
+
+#define DYN_CAST(X) (X ? (char*)X : 0)
+#define GENERATE_NUMBER(X) (0)
+
+char test_assignment(int *param) {
+ char *param2;
+ param2 = DYN_CAST(param);
+ return *param2;
+}
+
+char test_declaration(int *param) {
+ char *param2 = DYN_CAST(param);
+ return *param2;
+}
+
+int coin();
+
+int test_multi_decl(int *paramA, int *paramB) {
+ char *param1 = DYN_CAST(paramA), *param2 = DYN_CAST(paramB);
+ if (coin())
+ return *param1;
+ return *param2;
+}
+
+int testDivision(int a) {
+ int divider = GENERATE_NUMBER(2); // expected-note{{'divider' initialized to 0}}
+ return 1/divider; // expected-warning{{Division by zero}}
+ // expected-note@-1{{Division by zero}}
+}
+
+// Warning should not be suppressed if it happens in the same macro.
+#define DEREF_IN_MACRO(X) int fn() {int *p = 0; return *p; }
+
+DEREF_IN_MACRO(0) // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{'p' initialized to a null}}
+ // expected-note@-2{{Dereference of null pointer}}
+
+// Warning should not be suppressed if the null returned by the macro
+// is not related to the warning.
+#define RETURN_NULL() (0)
+extern int* returnFreshPointer();
+int noSuppressMacroUnrelated() {
+ int *x = RETURN_NULL();
+ x = returnFreshPointer(); // expected-note{{Value assigned to 'x'}}
+ if (x) {} // expected-note{{Taking false branch}}
+ // expected-note@-1{{Assuming 'x' is null}}
+ return *x; // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{Dereference}}
+}
+
+// Value haven't changed by the assignment, but the null pointer
+// did not come from the macro.
+int noSuppressMacroUnrelatedOtherReason() {
+ int *x = RETURN_NULL();
+ x = returnFreshPointer();
+ x = 0; // expected-note{{Null pointer value stored to 'x'}}
+ return *x; // expected-warning{{Dereference of null pointer}}
+ // expected-note@-1{{Dereference}}
+}