[committed] analyzer: fix missing uninit warning on args to stdio builtins [PR104224]
Commit Message
We were failing to check for uninitialized arguments to stdio builtins,
such as when passing local "go" to the call to "printf" in "main" in
the testcase.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r12-6876-g9ff3e2368d86c1bf7d1e8876a14e58c0d6617ffe.
gcc/analyzer/ChangeLog:
PR analyzer/104224
* region-model.cc (region_model::check_call_args): New.
(region_model::on_call_pre): Call it when ignoring stdio builtins.
* region-model.h (region_model::check_call_args): New decl
gcc/testsuite/ChangeLog:
PR analyzer/104224
* gcc.dg/analyzer/pr104224.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
gcc/analyzer/region-model.cc | 11 +++
gcc/analyzer/region-model.h | 2 +
gcc/testsuite/gcc.dg/analyzer/pr104224.c | 106 +++++++++++++++++++++++
3 files changed, 119 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr104224.c
@@ -1044,6 +1044,16 @@ region_model::on_stmt_pre (const gimple *stmt,
}
}
+/* Ensure that all arguments at the call described by CD are checked
+ for poisoned values, by calling get_rvalue on each argument. */
+
+void
+region_model::check_call_args (const call_details &cd) const
+{
+ for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++)
+ cd.get_arg_svalue (arg_idx);
+}
+
/* Update this model for the CALL stmt, using CTXT to report any
diagnostics - the first half.
@@ -1173,6 +1183,7 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
/* These stdio builtins have external effects that are out
of scope for the analyzer: we only want to model the effects
on the return value. */
+ check_call_args (cd);
break;
}
else if (is_named_call_p (callee_fndecl, "malloc", call, 1))
@@ -832,6 +832,8 @@ class region_model
void check_region_for_read (const region *src_reg,
region_model_context *ctxt) const;
+ void check_call_args (const call_details &cd) const;
+
/* Storing this here to avoid passing it around everywhere. */
region_model_manager *const m_mgr;
new file mode 100644
@@ -0,0 +1,106 @@
+#include <stdio.h>
+
+struct test {
+ int one;
+ int two;
+};
+
+void func2(const struct test *t)
+{
+ if (t->one == 0)
+ printf("init func2\n");
+
+ if (t->two == 0) /* { dg-warning "uninitialized" } */
+ printf("uninit func2\n");
+}
+
+void func1(struct test *t)
+{
+ t->one = 1;
+ func2(t);
+}
+
+int func3(int num)
+{
+ if (num)
+ return num;
+ else
+ return 0;
+}
+
+void func4(int *a, int max)
+{
+ int i;
+ // skip the first
+ for (i=1; i<max; i++)
+ a[i] = 0;
+}
+
+void func5(const int *a, int max)
+{
+ /* a[0] is uninitialized, but the rest of the array is initialized. */
+ int i;
+ for (i=0; i<max; i++) {
+ if (a[i]) /* { dg-warning "uninitialized" "" { xfail *-*-* } } */
+ printf("func5: %d\n", i);
+ }
+}
+
+int func6(const int *num)
+{
+ if (*num) /* { dg-warning "uninitialized" } */
+ return *num; /* { dg-warning "uninitialized" } */
+ else
+ return 0;
+}
+
+int j;
+int func7(void)
+{
+ return j; /* { dg-bogus "uninitialized" } */
+}
+
+void func8(const int *a, int max)
+{
+ int i;
+ for (i=0; i<max; i++) {
+ if (a[i]) /* { dg-warning "uninitialized" } */
+ printf("func8: %d\n", i);
+ }
+}
+
+enum {RED, AMBER, GREEN, BLACK};
+
+int main(void)
+{
+ struct test t;
+ int num;
+ int arry[10];
+ int arry_2[10];
+ int go;
+ int color = BLACK;
+
+ func1(&t);
+ func3(num); /* { dg-warning "use of uninitialized value 'num'" } */
+ func4(arry, 10);
+ func5(arry, 10);
+ func6(&num);
+
+ printf("num: %d\n", num); /* { dg-warning "use of uninitialized value 'num'" } */
+ printf("func7: %d\n", func7());
+ func8(arry_2, 10);
+
+ switch (color) {
+ case RED:
+ case AMBER:
+ go = 0;
+ break;
+ case GREEN:
+ go = 1;
+ break;
+ }
+
+ printf("go :%d\n", go); /* { dg-warning "use of uninitialized value 'go'" } */
+
+ return 0;
+}