]> git.ipfire.org Git - thirdparty/gcc.git/commit
gimplify, ubsan: Fix -fopenmp -fsanitize=bounds ICE [PR120052]
authorJakub Jelinek <jakub@redhat.com>
Tue, 25 Nov 2025 10:19:12 +0000 (11:19 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 25 Nov 2025 10:19:12 +0000 (11:19 +0100)
commit72ac4625d2a257bcc2ca562ffa360f560d7c1fd9
treea52c425a50f84e8136665d5e31f97ed8852c2788
parentd84552e1f67cb44f6b337fcf0e338b5b3571c209
gimplify, ubsan: Fix -fopenmp -fsanitize=bounds ICE [PR120052]

The following testcase ICEs, because
1) -fsanitize=bounds uses TYPE_MAX_VALUE (TYPE_DOMAIN (type)) with
   1 or 2 added as last argument of .UBSAN_BOUNDS call and that
   expression at that point is some NOP_EXPR around SAVE_EXPR with
   testing for negative sizes
2) during gimplification, gimplify_type_sizes is invoked on the DECL_EXPR
   outside of an OpenMP region, and forces TYPE_MAX_VALUE into
   a pseudo instead, with the SAVE_EXPR obviously being evaluated
   before that
3) the OpenMP gimplification sees an implicit or explicit data sharing
   of a VLA and among other things arranges to firstprivatize TYPE_MAX_VALUE
4) when gimplifying the .UBSAN_BOUNDS call inside of the OpenMP region,
   it sees a SAVE_EXPR and just gimplifies it to the already initialized
   s.1 temporary; but nothing marks s.1 for firstprivatization on the
   containing construct(s).  The problem is that with SAVE_EXPR we never
   know if the first use is within the same statement (typical use) or
   somewhere earlier in the same OpenMP construct or in an outer OpenMP
   construct or its parent etc., the SAVE_EXPR temporary is a function
   local var, not something that is added to the innermost scope where
   it is used (and it can't because it perhaps could be used outside of
   it); so for OpenMP purposes, SAVE_EXPRs better should be used only
   within the same OpenMP region and not across the whole function

The following patch fixes it by deferring the addition of
TYPE_MAX_VALUE in the last argument of .UBSAN_BOUNDS until gimplification
for VLAs, if it sees a VLA, instead of making the first argument
0 with pointer to the corresponding array type, it sets the first
argument to 1 with the same type and only sets the last argument to the
addend (1 or 2).  And then gimplification can detect this case and
add the TYPE_MAX_VALUE (which in the meantime should have gone through
gimplify_type_sizes).

2025-11-25  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/120052
gcc/
* gimplify.cc (gimplify_call_expr): For IFN_UBSAN_BOUNDS
call with integer_onep first argument, change that argument
to 0 and add TYPE_MAX_VALUE (TYPE_DOMAIN (arr_type)) to
3rd argument before gimplification.
gcc/c-family/
* c-ubsan.cc (ubsan_instrument_bounds): For VLAs use
1 instead of 0 as first IFN_UBSAN_BOUNDS argument and only
use the addend without TYPE_MAX_VALUE (TYPE_DOMAIN (type))
in the 3rd argument.
gcc/testsuite/
* c-c++-common/gomp/pr120052.c: New test.
gcc/c-family/c-ubsan.cc
gcc/gimplify.cc
gcc/testsuite/c-c++-common/gomp/pr120052.c [new file with mode: 0644]