aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-02-09 17:09:51 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2023-02-09 17:09:51 -0500
commit125b57aa67400388a496c2c0c40d9c8c55e0c94a (patch)
treedfc35cfe81c72d775fcc456d2f37bf9495627eb0 /gcc
parent10827a92f1a8c3207b327515f77845b34c1d9512 (diff)
downloadgcc-125b57aa67400388a496c2c0c40d9c8c55e0c94a.zip
gcc-125b57aa67400388a496c2c0c40d9c8c55e0c94a.tar.gz
gcc-125b57aa67400388a496c2c0c40d9c8c55e0c94a.tar.bz2
analyzer: fix further overzealous state purging [PR108733]
PR analyzer/108733 reports various false positives in qemu from -Wanalyzer-use-of-uninitialized-value with __attribute__((cleanup)) at -O1 and above. Root cause is that the state-purging code was failing to treat: _25 = MEM[(void * *)&val]; as a usage of "val", leading to it erroneously purging the initialization of "val" along an execution path that didn't otherwise use "val", apart from the __attribute__((cleanup)). Fixed thusly. Integration testing on the patch show this change in the number of diagnostics: -Wanalyzer-use-of-uninitialized-value coreutils-9.1: 18 -> 16 (-2) qemu-7.2.0: 87 -> 80 (-7) where all that I investigated appear to have been false positives, hence an improvement. gcc/analyzer/ChangeLog: PR analyzer/108733 * state-purge.cc (get_candidate_for_purging): Add ADDR_EXPR and MEM_REF. gcc/testsuite/ChangeLog: PR analyzer/108733 * gcc.dg/analyzer/torture/uninit-pr108733.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/state-purge.cc2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c65
2 files changed, 67 insertions, 0 deletions
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index 5f2d1f7..3a73146 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -63,6 +63,8 @@ get_candidate_for_purging (tree node)
default:
return NULL_TREE;
+ case ADDR_EXPR:
+ case MEM_REF:
case COMPONENT_REF:
iter = TREE_OPERAND (iter, 0);
continue;
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c
new file mode 100644
index 0000000..9e684bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr108733.c
@@ -0,0 +1,65 @@
+#define NULL ((void*)0)
+
+typedef unsigned char __uint8_t;
+typedef __uint8_t uint8_t;
+typedef char gchar;
+typedef void* gpointer;
+
+extern void g_free(gpointer mem);
+extern gchar* g_strdup(const gchar* str) __attribute__((__malloc__));
+
+static inline void
+g_autoptr_cleanup_generic_gfree(void* p)
+{
+ void** pp = (void**)p;
+ g_free(*pp); /* { dg-bogus "use of uninitialized value" } */
+}
+
+typedef struct Object Object;
+
+void
+error_setg_internal(const char* fmt,
+ ...) __attribute__((__format__(gnu_printf, 1, 2)));
+void
+visit_type_str(const char* name, char** obj);
+typedef struct SpaprMachineState SpaprMachineState;
+
+extern uint8_t
+spapr_get_cap(SpaprMachineState* spapr, int cap);
+
+typedef struct SpaprCapPossible
+{
+ int num;
+ /* [...snip...] */
+ const char* vals[];
+} SpaprCapPossible;
+
+typedef struct SpaprCapabilityInfo
+{
+ const char* name;
+ /* [...snip...] */
+ int index;
+ /* [...snip...] */
+ SpaprCapPossible* possible;
+ /* [...snip...] */
+} SpaprCapabilityInfo;
+
+void
+spapr_cap_get_string(SpaprMachineState* spapr,
+ const char* name,
+ SpaprCapabilityInfo* cap)
+{
+ __attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) char* val = NULL;
+ uint8_t value = spapr_get_cap(spapr, cap->index);
+
+ if (value >= cap->possible->num) {
+ error_setg_internal("Invalid value (%d) for cap-%s",
+ value,
+ cap->name);
+ return;
+ }
+
+ val = g_strdup(cap->possible->vals[value]);
+
+ visit_type_str(name, &val);
+}