diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-03-28 09:43:07 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-03-28 09:43:07 -0400 |
commit | 875342766d42988fa2f8eb7d34ef562ba69e340a (patch) | |
tree | 16efcaf31e5671325a77f4303f041fe36b6be9a7 /gcc | |
parent | 19b87a06482756739087283cd8b884cb3de693f9 (diff) | |
download | gcc-875342766d42988fa2f8eb7d34ef562ba69e340a.zip gcc-875342766d42988fa2f8eb7d34ef562ba69e340a.tar.gz gcc-875342766d42988fa2f8eb7d34ef562ba69e340a.tar.bz2 |
gimple-fold: fix location of loads for memory ops [PR104308]
PR analyzer/104308 reports that when -Wanalyzer-use-of-uninitialized-value
complains about certain memmove operations where the source is
uninitialized, the diagnostic uses UNKNOWN_LOCATION:
In function 'main':
cc1: warning: use of uninitialized value '*(short unsigned int *)&s + 1' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
'main': event 1
|
|pr104308.c:5:8:
| 5 | char s[5]; /* { dg-message "region created on stack here" } */
| | ^
| | |
| | (1) region created on stack here
|
'main': event 2
|
|cc1:
| (2): use of uninitialized value '*(short unsigned int *)&s + 1' here
|
The issue is that gimple_fold_builtin_memory_op converts a memmove to:
_3 = MEM <unsigned short> [(char * {ref-all})_1];
MEM <unsigned short> [(char * {ref-all})&s] = _3;
but only sets the location of the 2nd stmt, not the 1st.
Fixed thusly, giving:
pr104308.c: In function 'main':
pr104308.c:6:3: warning: use of uninitialized value '*(short unsigned int *)&s + 1' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
6 | memmove(s, s + 1, 2); /* { dg-warning "use of uninitialized value" } */
| ^~~~~~~~~~~~~~~~~~~~
'main': events 1-2
|
| 5 | char s[5]; /* { dg-message "region created on stack here" } */
| | ^
| | |
| | (1) region created on stack here
| 6 | memmove(s, s + 1, 2); /* { dg-warning "use of uninitialized value" } */
| | ~~~~~~~~~~~~~~~~~~~~
| | |
| | (2) use of uninitialized value '*(short unsigned int *)&s + 1' here
|
One side-effect of this change is a change in part of the output of
gcc.dg/uninit-40.c from:
uninit-40.c:47:3: warning: ‘*(long unsigned int *)(&u[1][0][0])’ is used uninitialized [-Wuninitialized]
47 | __builtin_memcpy (&v[1], &u[1], sizeof (V));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uninit-40.c:45:5: note: ‘*(long unsigned int *)(&u[1][0][0])’ was declared here
45 | V u[2], v[2];
| ^
to:
uninit-40.c:47:3: warning: ‘u’ is used uninitialized [-Wuninitialized]
47 | __builtin_memcpy (&v[1], &u[1], sizeof (V));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uninit-40.c:45:5: note: ‘u’ declared here
45 | V u[2], v[2];
| ^
What's happening is that pass "early_uninit"(29)'s call to
maybe_warn_operand is guarded by this condition:
1051 else if (gimple_assign_load_p (stmt)
1052 && gimple_has_location (stmt))
Before the patch, the stmt:
_3 = MEM <unsigned long> [(char * {ref-all})&u + 8B];
has no location, and so early_uninit skips this operand at line
1052 above. Later, pass "uninit"(217) tests the var_decl "u$8", and
emits a warning for it.
With the patch, the stmt has a location, and so early_uninit emits a
warning for "u" and sets a NW_UNINIT warning suppression at that
location. Later, pass "uninit"(217)'s test of "u$8" is rejected
due to that per-location suppression of uninit warnings, from the
earlier warning.
gcc/ChangeLog:
PR analyzer/104308
* gimple-fold.cc (gimple_fold_builtin_memory_op): When optimizing
to loads then stores, set the location of the new load stmt.
gcc/testsuite/ChangeLog:
PR analyzer/104308
* gcc.dg/analyzer/pr104308.c: New test.
* gcc.dg/uninit-40.c (foo): Update expression in expected message.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/gimple-fold.cc | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/pr104308.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/uninit-40.c | 2 |
3 files changed, 10 insertions, 1 deletions
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 5eff7d6..e73bc6a 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -1039,6 +1039,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, new_stmt); gimple_assign_set_lhs (new_stmt, srcmem); gimple_set_vuse (new_stmt, gimple_vuse (stmt)); + gimple_set_location (new_stmt, loc); gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); } if (dest_align < GET_MODE_ALIGNMENT (mode)) diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104308.c b/gcc/testsuite/gcc.dg/analyzer/pr104308.c new file mode 100644 index 0000000..9cd5ee6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr104308.c @@ -0,0 +1,8 @@ +#include <string.h> + +int main() +{ + char s[5]; /* { dg-message "region created on stack here" } */ + memmove(s, s + 1, 2); /* { dg-warning "use of uninitialized value" } */ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/uninit-40.c b/gcc/testsuite/gcc.dg/uninit-40.c index 8708079..567707a 100644 --- a/gcc/testsuite/gcc.dg/uninit-40.c +++ b/gcc/testsuite/gcc.dg/uninit-40.c @@ -44,7 +44,7 @@ foo (int *q) /* memcpy folding is too target dependent to test it everywhere. */ V u[2], v[2]; u[0][0][0] = 1; - __builtin_memcpy (&v[1], &u[1], sizeof (V)); /* { dg-warning "'\\*\\(\(long \)?long unsigned int \\*\\)\\(&u\\\[1\\\]\\\[0\\\]\\\[0\\\]\\)' is used uninitialized" "" { target i?86-*-* x86_64-*-* } } */ + __builtin_memcpy (&v[1], &u[1], sizeof (V)); /* { dg-warning "'u' is used uninitialized" "" { target i?86-*-* x86_64-*-* } } */ baz (&v[1]); #endif } |