The GIMPLE frontend, when bypassing gimplification, doesn't set DECL_SEEN_IN_BIND_EXPR_P given there are no such things in GIMPLE. But it probably should set the flag anyway to avoid later ICEs when regimplifying.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR middle-end/112741 gcc/c/ * gimple-parser.cc (c_parser_parse_gimple_body): Also set DECL_SEEN_IN_BIND_EXPR_Pfor locals. * gcc.dg/ubsan/pr112741.c: New testcase. --- gcc/c/gimple-parser.cc | 8 +++++++- gcc/testsuite/gcc.dg/ubsan/pr112741.c | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/ubsan/pr112741.c diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index f43c0398655..72bff1cb305 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -280,7 +280,13 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, for (tree var = BIND_EXPR_VARS (stmt); var; var = DECL_CHAIN (var)) if (VAR_P (var) && !DECL_EXTERNAL (var)) - add_local_decl (cfun, var); + { + add_local_decl (cfun, var); + /* When the middle-end re-gimplifies any expression we might + run into the assertion that we've seen the decl in a BIND. */ + if (!TREE_STATIC (var)) + DECL_SEEN_IN_BIND_EXPR_P (var) = 1; + } /* We have a CFG. Build the edges. */ for (unsigned i = 0; i < parser.edges.length (); ++i) { diff --git a/gcc/testsuite/gcc.dg/ubsan/pr112741.c b/gcc/testsuite/gcc.dg/ubsan/pr112741.c new file mode 100644 index 00000000000..13994f634a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pr112741.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -fsanitize=undefined" } */ + +int __GIMPLE(ssa) foo(int j) +{ + int c[1][10][1]; + int _1; + +__BB(2): + c[0][1][0] = 1; + c[0][1] = _Literal (int[1]) {}; + _1 = c[0][j_2(D)][0]; + return _1; +} + +int main() +{ + if (foo (1) != 0) + __builtin_abort (); + return 0; +} -- 2.35.3