aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2021-01-04 19:20:32 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2021-01-04 19:20:32 -0500
commit15af33a88065f983181550fc53821f1c6e14c5c7 (patch)
tree8dc2bf2647da05507089886acd6f04a41390e253
parent7e73f511573b3656c57f33c079e9bd1d70aaa621 (diff)
downloadgcc-15af33a88065f983181550fc53821f1c6e14c5c7.zip
gcc-15af33a88065f983181550fc53821f1c6e14c5c7.tar.gz
gcc-15af33a88065f983181550fc53821f1c6e14c5c7.tar.bz2
analyzer: fix ICE with -fsanitize=undefined [PR98293]
-fsanitize=undefined with calls to nonnull functions creates struct __ubsan_nonnull_arg_data instances with CONSTRUCTORs for RECORD_TYPEs with NULL index values. The analyzer was mistakenly using INTEGER_CST for these fields, leading to ICEs. Fix the issue by iterating through the fields in the type for such cases, imitating similar logic in varasm.c's output_constructor. gcc/analyzer/ChangeLog: PR analyzer/98293 * store.cc (binding_map::apply_ctor_to_region): When "index" is NULL, iterate through the fields for RECORD_TYPEs, rather than creating an INTEGER_CST index. gcc/testsuite/ChangeLog: PR analyzer/98293 * gcc.dg/analyzer/pr98293.c: New test.
-rw-r--r--gcc/analyzer/store.cc19
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr98293.c2
2 files changed, 20 insertions, 1 deletions
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 35a7e29..b4a4d5f 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -524,10 +524,27 @@ binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
unsigned ix;
tree index;
tree val;
+ tree parent_type = parent_reg->get_type ();
+ tree field;
+ if (TREE_CODE (parent_type) == RECORD_TYPE)
+ field = TYPE_FIELDS (parent_type);
+ else
+ field = NULL_TREE;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, index, val)
{
if (!index)
- index = build_int_cst (integer_type_node, ix);
+ {
+ /* If index is NULL, then iterate through the fields for
+ a RECORD_TYPE, or use an INTEGER_CST otherwise.
+ Compare with similar logic in output_constructor. */
+ if (field)
+ {
+ index = field;
+ field = DECL_CHAIN (field);
+ }
+ else
+ index = build_int_cst (integer_type_node, ix);
+ }
else if (TREE_CODE (index) == RANGE_EXPR)
{
tree min_index = TREE_OPERAND (index, 0);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr98293.c b/gcc/testsuite/gcc.dg/analyzer/pr98293.c
new file mode 100644
index 0000000..f750c90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr98293.c
@@ -0,0 +1,2 @@
+/* { dg-additional-options "-fsanitize=undefined" } */
+#include "../pr93399.c"