From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by sourceware.org (Postfix) with ESMTPS id B79CC3857C64; Fri, 10 Dec 2021 18:10:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B79CC3857C64 Received: by mail-wr1-x433.google.com with SMTP id c4so16273830wrd.9; Fri, 10 Dec 2021 10:10:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=kRhrv3bhAI3FvKiWhNCXvDPQdMlkLwfSmAFck3ys29k=; b=UJIvYthUgwOrlgamdtti2ErNOTVFp4iPq/J7DPfLXiFNXOjKTkri1Xp5BbkWjbCxnw geO9JToz+NLDMTh5bb5jeyg5WLhcYatVqSXLbFncuTRj2rD3DvbLb6PwsFAI1ap3OVU4 7Wohgu4jGIZhqN4WINDR6tqS1MI9C/O+BL9rKT84LKR68RZ1VyBu2NKvOIjBVIBsbPDO qG1Bgtp0o/4DJd/aQNsoTzuR4TokfR24Dwe7nhJTP+3ab3PHcOo43dzxwuFhEuCvC1kL dlYHu37bmBYLTvG3BAHhQUBec7gQrk5Jg/OJVsJUd/S+aUcR6j2U5lOdP1qSNO+yehZN noIQ== X-Gm-Message-State: AOAM532AFIKNr2xNQrcyxndhix/tXH4ljxLcUMbhmJ4w9HiuBsAjtGI2 VzRmS6vLlByIiEyT0Z4gyV9x0eKYtwAPE0uvc2c= X-Google-Smtp-Source: ABdhPJzjmxIVgGFqwptLTX8rBjGnvCLkQh0RcpsOd0gLqnZSwKHdanDCKm6MtBtrc3ygsZb7udDzABYqMh5NOlUeXbM= X-Received: by 2002:adf:fa0b:: with SMTP id m11mr15585647wrr.152.1639159829588; Fri, 10 Dec 2021 10:10:29 -0800 (PST) MIME-Version: 1.0 References: <20211209232453.1568609-1-jwakely@redhat.com> <8a43115a-fab5-e2e7-6737-e0fbc43ebb59@gmail.com> In-Reply-To: <8a43115a-fab5-e2e7-6737-e0fbc43ebb59@gmail.com> From: Jonathan Wakely Date: Fri, 10 Dec 2021 18:10:18 +0000 Message-ID: Subject: Re: [committed] libstdc++: Disable over-zealous warnings about std::string copies [PR103332] To: Martin Sebor Cc: Jonathan Wakely , "libstdc++" , gcc-patches Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Dec 2021 18:10:33 -0000 On Fri, 10 Dec 2021 at 16:35, Martin Sebor wrote: > > On 12/10/21 3:12 AM, Jonathan Wakely wrote: > > On Fri, 10 Dec 2021 at 01:50, Martin Sebor via Libstdc++ > > wrote: > >> > >> On 12/9/21 5:38 PM, Martin Sebor wrote: > >>> On 12/9/21 4:24 PM, Jonathan Wakely via Gcc-patches wrote: > >>>> These warnings are triggered by perfectly valid code using std::stri= ng. > >>>> They're particularly bad when --enable-fully-dynamic-string is used, > >>>> because even std::string().begin() will give a warning. > >>>> > >>>> Use pragmas to stop the troublesome warnings for copies done by > >>>> std::char_traits. > >>> > >>> I'm still experimenting with some of the approaches we discussed > >>> last week, but based on my findings so far this was going to be > >>> my suggestion at lest for now, until or unless the problem turns > >>> out to affect more code than just std::string. > >> > >> Just minutes after I wrote this I tried following the clue > >> in the note printed for the test case from PR 103534 with > >> an enhancement I'm experimenting with: > >> > >> /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_t= raits.h:426:56: > >> warning: =E2=80=98void* __builtin_memcpy(void*, const void*, long unsi= gned int)=E2=80=99 > >> specified size between 18446744073709551600 and 18446744073709551615 > >> exceeds maximum object size 9223372036854775807 [-Wstringop-overflow= =3D] > >> 426 | return static_cast(__builtin_memcpy(__s1= , > >> __s2, __n)); > >> | > >> ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ > >> /build/gcc-master/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_t= raits.h:426:56: > >> note: when > >> =E2=80=98(.std::__cxx11::basic_string::_M_string_leng= th > > >> 18446744073709551599)=E2=80=99 > >> > >> and adding an assert to string::size(): > >> > >> constexpr > >> size_type > >> size() const noexcept > >> { > >> if (_M_string_length >=3D -1LU >> 1) > > > > I think that will be wrong for 64-bit Windows, where long is 32-bit, > > but the string's max size is closer to -1LLU >> 2, and we don't want > > to just use -1LLU because that's wrong for 32-bit targets. > > > > Technically the max size is (N - 1)/2 where N is the allocator's max > > size, which is PTRDIFF_MAX for std::allocator, SIZE_MAX for allocators > > that use the default value from std::allocator_traits, or some other > > value that the allocator defines. And the value is reduced > > appropriately if sizeof(char_type) > 1. > > > > But if we call this->max_size() which calls _Alloc_traits::max_size() > > which potentially calls allocator_type::max_size(), will the compiler > > actually make those calls to mark the path unreachable, or will it > > just ignore the unreachable if it can't fold all those calls at > > compile time? > > The above was just a quick proof of concept experiment. You're > of course right that the final solution can't be so crude(*). > But if the required functions are always_inline (I think member > functions defined in the body of the class implicitly are) then They're implicitly inline, but not implicitly always_inline. > I'd expect them to be folded at compile time at all optimization > levels. That's what makes -Winvalid-memory-order work in C++ > even at -O0 in the patch I posted earlier this week. > > If I still remember my C++-library-fu, even though the standard > requires containers to call max_size() etc., since std::string > is (or can be) an explicit specialization, there shouldn't be > a way for a conforming program to find out if it does, so it > could take shortcuts. That makes me wonder if it could even > call malloc instead of operator new to get around the problem > with the operator's replaceability. std::string is required to use std::allocator and users can't specialize that to observe its allocations, but it does require: The storage for the array is obtained by calling ::operator new (17.6.3), but it is unspecified when or how often this function is called. Users can certainly observe whether std::string *never* calls their replaced operator new (and if they've replaced it specifically to ensure allocations use their own source, and not malloc, they wouldn't be happy).