From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 0B0CA3858C00; Mon, 27 Feb 2023 12:49:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0B0CA3858C00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677502141; bh=EwiwM+4hlIW5HoY65S4Vk4W3zyxZ5049kFEXXj9RmK8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=iJjn6At+VbMlbSQoBE1N3H408/Wdecog37z0auXKKTyd2JKWL+xfdHp3F+iBsVVll NyWF5EGShLcunvAyj/AKCpGfCeIaIbKUdEZqqVd3NlMM7BLp/x15OnMb4ec3dkHRSl FCy+CTL8EH4sRqN3suSNL2s9/HXVcSW97VxxLRgI= From: "rguenth at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/107561] [13 Regression] g++.dg/pr71488.C and [g++.dg/warn/Warray-bounds-16.C -m32] regression due to -Wstringop-overflow problem Date: Mon, 27 Feb 2023 12:49:00 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 13.0 X-Bugzilla-Keywords: diagnostic, missed-optimization X-Bugzilla-Severity: normal X-Bugzilla-Who: rguenth at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P1 X-Bugzilla-Assigned-To: rguenth at gcc dot gnu.org X-Bugzilla-Target-Milestone: 13.0 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc keywords Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D107561 Richard Biener changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jwakely.gcc at gmail dot c= om Keywords|testsuite-fail |missed-optimization --- Comment #11 from Richard Biener --- So I've missed the VR_ANTI_RANGE handling in get_size_range where we run in= to wide_int maxsize =3D wi::to_wide (max_object_size ()); min =3D wide_int::from (min, maxsize.get_precision (), UNSIGNED); max =3D wide_int::from (max, maxsize.get_precision (), UNSIGNED); if (wi::eq_p (0, min - 1)) { /* EXP is unsigned and not in the range [1, MAX]. That means it's either zero or greater than MAX. Even though 0 would normally be detected by -Walloc-zero, unless ALLOW_ZERO is set, set the range to [MAX, TYPE_MAX] so that when MAX is greater than the limit the whole range is diagnosed. */ wide_int maxsize =3D wi::to_wide (max_object_size ()); if (flags & SR_ALLOW_ZERO) { if (wi::leu_p (maxsize, max + 1) || !(flags & SR_USE_LARGEST)) min =3D max =3D wi::zero (expprec); else { min =3D max + 1; max =3D wi::to_wide (TYPE_MAX_VALUE (exptype)); } } else { min =3D max + 1; max =3D wi::to_wide (TYPE_MAX_VALUE (exptype)); } and from [0,0] [8, +INF] pick [8, +INF] based on the comments reasoning. This all wouldn't happen if we'd be able to CSE the zero size ... We can now try to put additional heuristic ontop of the above heuristic, namely when the object we write to is of size zero set SR_ALLOW_ZERO. Or try to "undo" the multiplication trick which would probably make us end up with VARYING. I'll note that with the earlier proposed change we regress the following, that's an observation I make a lot of times - all "weirdness" in the code is backed by (artificial) testcases verifying it works exactly as coded ... FAIL: gcc.dg/Wstringop-overflow-15.c pr82608 (test for warnings, line 3= 7) FAIL: gcc.dg/Wstringop-overflow-15.c pr82608 (test for warnings, line 3= 8) FAIL: gcc.dg/Wstringop-overflow-15.c pr82608 (test for warnings, line 6= 9) FAIL: gcc.dg/Wstringop-overflow-15.c pr82608 (test for warnings, line 7= 0) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 64) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 75) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 86) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 97) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 108) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 148) FAIL: gcc.dg/Wstringop-overflow-56.c (test for warnings, line 159) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 52) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 53) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 54) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 55) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 56) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 57) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 58) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 64) FAIL: gcc.dg/attr-alloc_size-11.c (test for warnings, line 65) FAIL: gcc.dg/attr-alloc_size-3.c (test for warnings, line 438) FAIL: gcc.dg/attr-alloc_size-4.c (test for warnings, line 138) FAIL: gcc.dg/attr-alloc_size-4.c (test for warnings, line 143) FAIL: gcc.dg/attr-alloc_size-4.c (test for warnings, line 187) FAIL: gcc.dg/pr98721-1.c (test for warnings, line 11) FAIL: gcc.dg/pr98721-1.c (test for warnings, line 12) For example gcc.dg/pr98721-1.c has int foo (int n) { if (n <=3D 0) { char vla[n]; /* { dg-message "source object 'vla= ' of size 0" } */ return __builtin_strlen (vla); /* { dg-warning "'__builtin_strlen' reading 1 or more bytes from a region of size 0" } */ but of course we do not diagnose int foo (int n) { if (n < 0) { char vla[n]; or when no condition is present or a n > 32 condition is present. I fear it's not possible to "fix" this testcase without changing the expectation on a bunch of other testcases. But the messaging to the user is quite unhelpful because it doesn't actually inform him about above reasoning. That we are not allowed to optimize the code is not of help either. We can again work around this in libstdc++ by CSEing ->_M_size ourselves. The following helps: diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray index 7a23c27a0ce..7383071f98d 100644 --- a/libstdc++-v3/include/std/valarray +++ b/libstdc++-v3/include/std/valarray @@ -647,8 +647,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline valarray<_Tp>::valarray(const valarray<_Tp>& __v) : _M_size(__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_siz= e)) - { std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, - _M_data); } + { + auto __v_M_size =3D __v._M_size; + _M_size =3D __v_M_size; + _M_data =3D __valarray_get_storage<_Tp>(__v_M_size); + std::__valarray_copy_construct(__v._M_data, __v._M_data + __v_M_size, + _M_data); + } #if __cplusplus >=3D 201103L template=