Bug 104165 - [12 Regression] -Warray-bounds for unreachable code inlined from std::sort()
Summary: [12 Regression] -Warray-bounds for unreachable code inlined from std::sort()
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.0
: P2 normal
Target Milestone: 12.5
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic, missed-optimization
Depends on:
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2022-01-21 15:40 UTC by Keeran Brabazon
Modified: 2024-06-20 09:01 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work: 11.1.0, 13.0
Known to fail: 12.0
Last reconfirmed: 2022-01-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Keeran Brabazon 2022-01-21 15:40:24 UTC
In file included from /home/install/include/c++/12.0.1/algorithm:61,
                 from repro.cpp:1:
In function ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bar(int, int)::<lambda(int, int)> >]’,
    inlined from ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bar(int, int)::<lambda(int, int)> >]’ at /home/install/include/c++/12.0.1/bits/stl_algo.h:1940:31,
    inlined from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int*; _Compare = bar(int, int)::<lambda(int, int)>]’ at
/home/install/include/c++/12.0.1/bits/stl_algo.h:4853:18,
    inlined from ‘int bar(int, int)’ at repro.cpp:17:14,
    inlined from ‘int foo(int)’ at repro.cpp:25:13:
/home/install/include/c++/12.0.1/bits/stl_algo.h:1849:32: error: array subscript 16 is outside array bounds of ‘unsigned char [16]’ [-Werror=array-bounds]
 1849 |           std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
      |           ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘int bar(int, int)’,
    inlined from ‘int foo(int)’ at repro.cpp:25:13:
repro.cpp:4:7: note: at offset 64 into object ‘f.140’ of size 16
    4 |   int f[l];
      |       ^
cc1plus: all warnings being treated as errors
make: *** [Makefile:5: all] Error 1

Getting the above bogus warning when compiling following reproducer

#include <algorithm>

static int bar(int n, int l) { // make function non-static and warning goes away
	int f[l];
	int x = 0;
	int r = n;

	for (; x < l;) {
		if (r) {
			x = l;
		} else { // Take out this else and the warning goes away
			r = 1;
		}
	}

	if (r == 1) { // Take out this branch and the warning goes away
		std::sort(f, f + x,
				[](int a, int b) { return a > b; });
	}
	return 1;

}

int foo(int n) {
	return bar(n, 4);
}


Compiled with HEAD of GCC (as of 20/01/2021)
g++ -c -march=armv8-a -Werror -Wall -O2  repro.cpp

The compiler sees that the size of the array is 4 ints (16-bytes), but doesn't see that x <= 4, so that no array out of bounds should occur. Workaround is to use malloc for the array.
Comment 1 Martin Sebor 2022-01-21 17:16:43 UTC
The warning triggers for the out of bounds pointer addition in &f.148 + 64 for an array of 16 chars:

int foo (int n)
{
  unsigned char f.148[16];
  ...
  <bb 8> [local count: 116203857]:
  _25 = ASSERT_EXPR <_15, _15 != &f.148>;
  _6 = (signed long) _14;
  _19 = _6 /[ex] 4;
  __n.3_20 = (long unsigned int) _19;
  _21 = __builtin_clzl (__n.3_20);
  _22 = 63 - _21;
  _23 = (long int) _22;
  _24 = _23 * 2;
  std::__introsort_loop<int*, long int, __gnu_cxx::__ops::_Iter_comp_iter<bar(int, int)::<lambda(int, int)> > > (&f.148, _25, _24, __comp);
  if (_14 > 64)
    goto <bb 9>; [50.00%]
  else
    goto <bb 15>; [50.00%]

  <bb 9> [local count: 58101929]:
  std::__insertion_sort.constprop (&f.148, &MEM <int[0:D.48109]> [(void *)&f.148 + 64B]);   <<< -Warray-bounds
  goto <bb 14>; [100.00%]

The basic block is removed later, in CCP3, as unreachable:

Removing basic block 8
;; basic block 8, loop depth 0
;;  pred:      
std::__insertion_sort.constprop (&f.148, &MEM <int[0:D.48109]> [(void *)&f.148 + 64B]);
if (&MEM <int[0:D.48109]> [(void *)&f.148 + 64B] != _15)
  goto <bb 9>; [89.00%]
else
  goto <bb 13>; [11.00%]
;;  succ:       9
;;              13


The warning runs too early to benefit from the subsequent simplification.  This is one instance of a false positive that something like __builtin_warning() would cure.

GCC 11 emits (and eliminates) the same invalid expression but the warning is suppressed because in GCC 11 -Warray-bounds wasn't issued code inlined from system headers.  That's a GCC 12 change.
Comment 2 Martin Sebor 2022-02-08 21:07:07 UTC
See also another similar test case reduced in https://bugzilla.redhat.com/show_bug.cgi?id=2051783:

#include <algorithm>

bool cond;
int foo;
                                      
int func (void)
{
  int a[3], qa = 0;
  for(int i = 0; i < 3; i++)
    if (cond)
      a[qa++] = foo;

  std::sort (a, a + qa);
  return 0;
}

The warning is issued for the synthesized call to std::__insertion_sort.isra() in basic block 9 (vrp1 output):

  <bb 9> [local count: 71766220]:
  std::__insertion_sort.isra (&a, &MEM <int[3]> [(void *)&a + 64B]);   <<< -Warray-bounds
  goto <bb 14>; [100.00%]

The block is unreachable but GCC is unable to determine that from the loop.  Adding an annotation just after the loop asserting that avoids the warning and also improves the emitted object code.

The same warning triggers in GCC 11 with -Wsystem-headers.  The difference in GCC 12 is that -Wsystem-headers no longer disables warnings for code defined in system headers that's inlined into user code.
Comment 3 Jakub Jelinek 2022-05-06 08:32:26 UTC
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
Comment 4 Richard Biener 2022-08-19 08:25:29 UTC
GCC 12.2 is being released, retargeting bugs to GCC 12.3.
Comment 5 Richard Biener 2022-12-05 15:39:19 UTC
This seems to be fixed on trunk - can somebody bisect what did so?
Comment 6 Jakub Jelinek 2022-12-05 16:05:15 UTC
r13-2894-gbe4a6551ed37c1e7dbdfb9400fc2e2b5d40c5be2 made the warning go away.
Comment 7 GCC Commits 2022-12-06 07:24:14 UTC
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>:

https://gcc.gnu.org/g:790ff87f675f28bce5e7e35918ae09c3ece4ec4d

commit r13-4499-g790ff87f675f28bce5e7e35918ae09c3ece4ec4d
Author: Richard Biener <rguenther@suse.de>
Date:   Tue Dec 6 08:22:01 2022 +0100

    tree-optimization/104165 - bougs -Warray-bounds, add testcase
    
    The following adds the testcase from the description which was
    fixed by r13-2894-gbe4a6551ed37c1.
    
            PR tree-optimization/104165
            * g++.dg/warn/Warray-bounds-pr104165-1.C: New testcase.
Comment 8 Richard Biener 2022-12-06 07:29:25 UTC
I have opened PR107986 for the testcase in comment#2 which isn't yet fixed on trunk.
Comment 9 Richard Biener 2023-05-08 12:23:39 UTC
GCC 12.3 is being released, retargeting bugs to GCC 12.4.
Comment 10 Fedor Chelnokov 2023-09-27 12:36:41 UTC
This issue happens in GCC 13.2 as well:
https://godbolt.org/z/TfGx3YccG
Comment 11 teodor_spaeren 2024-06-03 17:36:50 UTC
This just hit me on gcc 14.1:

https://godbolt.org/z/31G5dxz55
Comment 12 Xi Ruoyao 2024-06-03 18:09:52 UTC
(In reply to teodor_spaeren from comment #11)
> This just hit me on gcc 14.1:
> 
> https://godbolt.org/z/31G5dxz55

It's PR107986 and not this one.  The underlying reason is different.
Comment 13 Xi Ruoyao 2024-06-03 18:10:51 UTC
For anyone attempting to claim this not fixed for 13 or later please see PR107986 first.
Comment 14 Richard Biener 2024-06-20 09:01:01 UTC
GCC 12.4 is being released, retargeting bugs to GCC 12.5.