From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9109 invoked by alias); 17 May 2017 11:13:11 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 9098 invoked by uid 89); 17 May 2017 11:13:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM autolearn=no version=3.3.2 spammy=pleasantly, wanting, H*f:sk:O4oFJaz, H*f:sk:Y3bbEns X-HELO: mail-wm0-f42.google.com Received: from mail-wm0-f42.google.com (HELO mail-wm0-f42.google.com) (74.125.82.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 17 May 2017 11:13:09 +0000 Received: by mail-wm0-f42.google.com with SMTP id v15so2365071wmv.0 for ; Wed, 17 May 2017 04:13:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=kwTnqKt6IA0mh2uWU3kPkQJEEBCNuRuAY1Z4BFVC0yQ=; b=aLjT2Uxyr+DVF8CTJG+bQwBB3WCFJFIteNiU7NfevvO8lGjRKOz3gJP2dL+uE8nJxk UlOYRte4yK0ecO5MBnV5uGdoqQBeUOvIhBmr0tarFmXjlp0YBQz+ggdQqeQXLEQdsP2M CKe1dYB7q8cikgEFjJ4CVy4cK7uocjop7DmB22ZLmvuWigTcxgvO7VvQaL4O3nRJSeU4 YNUVRzWfSgqiOyXX2rBuvp7QiIpmn2QrKUoRMVysji2A2WN0or7iWlMJte5bZJFc0Esz L58FlBqtUuc0cCaUq+KZ3JnLrpP+CEyic/XhTzs6wCkWNDL9Tq0Zjgpnz4i2YJcKMDuH QncQ== X-Gm-Message-State: AODbwcDBPnqxa48qlJ9SVrTNl3r0aehoDGaA707zWL0YqEYHtLuKKlyi joe4CsP6wo2PmzbX X-Received: by 10.28.87.72 with SMTP id l69mr9860712wmb.111.1495019590573; Wed, 17 May 2017 04:13:10 -0700 (PDT) Received: from [192.168.0.101] ([37.189.166.198]) by smtp.gmail.com with ESMTPSA id b80sm17410150wma.5.2017.05.17.04.13.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 17 May 2017 04:13:09 -0700 (PDT) Subject: Re: [PATCH] warn on mem calls modifying objects of non-trivial types (PR 80560) To: Martin Sebor , Jason Merrill References: <656ca1db-1082-b1ed-a911-ba7bf48f09c0@redhat.com> <42ef9731-e92e-34c7-2b6c-7901d83cf682@redhat.com> <34474869-722f-422b-fb1f-3b798e68f803@gmail.com> Cc: Gcc Patch List From: Pedro Alves Message-ID: <6231301e-78a3-c940-35de-a1b938fce7af@redhat.com> Date: Wed, 17 May 2017 11:23:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <34474869-722f-422b-fb1f-3b798e68f803@gmail.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-SW-Source: 2017-05/txt/msg01363.txt.bz2 On 05/17/2017 02:55 AM, Martin Sebor wrote: > On 05/16/2017 04:48 PM, Pedro Alves wrote: >> On 05/16/2017 08:41 PM, Jason Merrill wrote: >> >>> I agree that it makes sense to >>> check for a trivial assignment operator specifically. I guess we want >>> a slightly stronger "trivially copyable" that also requires a >>> non-deleted assignment operator. >>> >>> It seems to me that the relevant tests are: >>> >>> bcopy/memcpy/memmove want trivally copyable + non-deleted assignment. >>> bzero/memset want trivial + non-deleted assignment. >>> >>> I'm still not convinced we need to consider standard-layout at all. >> >> What do you think of warning for memset of types with references? Having slept, I now realize you had that covered already by the "non-deleted assignment" requirement... A reference data member makes the assignment operator be implicitly deleted. Sorry for the noise. >> While at it, maybe the same reasoning would justify warn of memcpy/memset >> of types with const data members? Ditto. > I did this because objects with references cannot be assigned > to (the default copy assignment is deleted). So as a baseline > rule, I made the warning trigger whenever a native assignment > or copy isn't valid. In the IMO unlikely event that a memcpy > over a reference is intended, the warning is easy to suppress. Agreed. I wondered whether we'll end up wanting to distinguish these cases: #1 memcpy (T *, const T *src, size_t n); #2.1 memcpy (T *, const char *src, size_t n); // char, void, std::byte... #2.2 memcpy (char *, const T *src, size_t n); // char, void, std::byte... #3 memcpy (T *, const U *src, size_t n); Where: - T is a trivially copyable type that still triggers the new warning. - U is a type unrelated to T, and is not (unsigned) char, void or std::byte. #1 is the case that looks like copy. #2.1 and 2.2 may well appear in type-erasing code. #3 would look like a way to work around aliasing issues and (even though ISTR that it's OK as GNU extension if T and U are trivial) worthy of a warning even if T is trivial under the definition of the warning. Reading your updated patch, I see that you warn already when T is trivial and U is not trivial, but IIUC, not if U is also trivial, even if unrelated to T. Anyway, I don't really want to argue about this -- I started writing this paragraph before actually reading the patch, and then actually read the patch and was pleasantly surprised with what I saw. I think it's looking great. > I used a similar (though not exactly the same) rationale for > warning for const members. They too cannot be assigned to, > and letting memset or memcpy silently change them violates > const-correctnes. *Nod* > It's also undefined I'm not sure, I think there may be nuances, as usual. AFAICS, it's generally valid to memcpy into trivially copyable types that have const members to/from untyped/char storage, AFAICS. Might need to apply std::launder afterwards. But it isn't clear to me, since whether memcpy starts a (trivial) object's lifetime is up in the air, AFAIK. But I'm not suggesting to really consider that. The rare specialized code will be able to work around the spurious warning. > and the immutability > of such members an optimization opportunity waiting to be > exploited. > *nod* >>> +Wnon-trivial-memaccess >>> +C++ ObjC++ Var(warn_nontrival_memaccess) Warning LangEnabledBy(C++ >>> ObjC++, Wall) >>> +Warn for raw memory writes to objects of non-trivial types. >> >> May I suggest renaming the warning (and the description above) from >> -Wnon-trivial-memaccess to something else that avoids "trivial" in >> its name? Because it's no longer strictly about "trivial" in the >> standard C++ sense. The documentation talks about "The safe way", >> and "does not warn on safe calls", so maybe call it -Wunsafe-memaccess? > > I debated whether to rename things (not just the warning but > also the function that implements it in GCC). Ultimately I > decided it wasn't necessary because the rules seem close enough > to be based on some notion of triviality and because no better > name came to mind. -Wunsafe-memaccess might work. The one mild > concern I have with it is that it could suggest it might do more > than simple type checking (e.g., buffer overflow and what not). > Let's see what Jason thinks. Yet another motivation of avoiding "trivial" that crossed my mind is that you may want to enable the warning in C too, e.g., for warning about the memcpy of types with const members. But C as no concept of "trivial", everything is "trivial". >> (I spotted a couple typos in the new patch: "otherwse", "becase", btw.) > > I'm a horrible typist. I'll proofread the patch again and fix > them up before committing it. Thanks much for working on this. I think this will uncover lots of latent bugs in many codebases. Looking forward to have this in. Thanks, Pedro Alves