sanopt: Return TODO_cleanup_cfg if any .{UB,HWA,A}SAN_* calls were lowered [PR106190]
authorJakub Jelinek <jakub@redhat.com>
Tue, 28 Mar 2023 08:56:44 +0000 (10:56 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 28 Mar 2023 08:56:44 +0000 (10:56 +0200)
commit39a43dc336561e0eba0de477b16c7355f19d84ee
tree33859750c0aea1c3eb09bcf08536b6d8a5098300
parentccaee0d2c994ada5be6bcaae1ce3e43ca56fc617
sanopt: Return TODO_cleanup_cfg if any .{UB,HWA,A}SAN_* calls were lowered [PR106190]

The following testcase ICEs, because without optimization eh lowering
decides not to duplicate finally block of try/finally and so we end up
with variable guarded cleanup.  The sanopt pass creates a cfg that ought
to be cleaned up (some IFN_UBSAN_* functions are lowered in this case with
constant conditions in gcond and when not allowing recovery some bbs which
end with noreturn calls actually have successor edges), but the cfg cleanup
is actually (it is -O0) done only during the optimized pass.  We notice
there that the d[1][a] = 0; statement which has an EH edge is unreachable
(because ubsan would always abort on the out of bounds d[1] access), remove
the EH landing pad and block, but because that block just sets a variable
and jumps to another one which tests that variable and that one is reachable
from normal control flow, the __builtin_eh_pointer (1) later in there is
kept in the IL and we ICE during expansion of that statement because the
EH region has been removed.

The following patch fixes it by doing the cfg cleanup already during
sanopt pass if we create something that might need it, while the EH
landing pad is then removed already during sanopt pass, there is ehcleanup
later and we don't ICE anymore.

2023-03-28  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/106190
* sanopt.cc (pass_sanopt::execute): Return TODO_cleanup_cfg if any
of the IFN_{UB,HWA,A}SAN_* internal fns are lowered.

* gcc.dg/asan/pr106190.c: New test.
gcc/sanopt.cc
gcc/testsuite/gcc.dg/asan/pr106190.c [new file with mode: 0644]