public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Martin Sebor <msebor@gmail.com>, Jason Merrill <jason@redhat.com>
Cc: Gcc Patch List <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] warn on mem calls modifying objects of non-trivial types (PR 80560)
Date: Wed, 17 May 2017 11:23:00 -0000	[thread overview]
Message-ID: <6231301e-78a3-c940-35de-a1b938fce7af@redhat.com> (raw)
In-Reply-To: <34474869-722f-422b-fb1f-3b798e68f803@gmail.com>

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

  reply	other threads:[~2017-05-17 11:13 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-29 22:10 Martin Sebor
     [not found] ` <alpine.DEB.2.20.1704302338540.1461@digraph.polyomino.org.uk>
2017-05-03 16:18   ` Martin Sebor
     [not found] ` <656ca1db-1082-b1ed-a911-ba7bf48f09c0@redhat.com>
2017-05-01 15:49   ` Jason Merrill
2017-05-11 20:03     ` Martin Sebor
2017-05-12  2:43       ` Martin Sebor
2017-05-17 11:53         ` Pedro Alves
2017-06-29 16:15       ` Jan Hubicka
2017-06-29 20:23         ` Martin Sebor
2017-06-29 22:34           ` Jan Hubicka
2017-06-30  0:16             ` Martin Sebor
2017-06-30  8:34           ` Richard Biener
2017-06-30 14:29             ` Martin Sebor
2017-07-04  9:33         ` Richard Earnshaw (lists)
2017-05-11 16:34   ` Martin Sebor
2017-05-11 16:57     ` Jakub Jelinek
2017-05-11 17:17       ` Martin Sebor
2017-05-16 19:46     ` Jason Merrill
2017-05-16 22:28       ` Martin Sebor
2017-05-19 19:14         ` Jason Merrill
2017-05-19 21:11           ` Martin Sebor
2017-05-19 21:56             ` Jason Merrill
2017-05-22  2:07               ` Martin Sebor
2017-05-22  6:07                 ` Jason Merrill
2017-05-24 20:28                   ` Martin Sebor
2017-05-24 20:48                     ` Martin Sebor
2017-05-24 21:36                       ` Jason Merrill
2017-05-28  5:02                         ` Martin Sebor
     [not found]                           ` <cc62e93c-3b49-8e2f-70b9-acdd013fe760@redhat.com>
2017-06-02 21:28                             ` Martin Sebor
2017-06-05  2:02                               ` Jason Merrill
2017-06-05  7:53                                 ` Jason Merrill
2017-06-05 16:07                                   ` Martin Sebor
2017-06-05 19:13                                     ` Martin Sebor
2017-06-06  1:53                                       ` Martin Sebor
2017-06-06 22:24                                         ` Martin Sebor
2017-06-08  1:09                                           ` Jason Merrill
2017-06-08 20:25                                             ` Martin Sebor
2017-06-12 21:36                                               ` Jason Merrill
2017-06-15 16:26                                                 ` Martin Sebor
2017-06-15 21:31                                                   ` Jason Merrill
2017-06-16  7:38                                                     ` Richard Biener
2017-06-16  7:40                                                       ` Richard Biener
2017-05-17  1:01       ` Pedro Alves
2017-05-17  1:57         ` Martin Sebor
2017-05-17 11:23           ` Pedro Alves [this message]
2017-07-05 20:58   ` Andrew Pinski
2017-07-05 22:33     ` Martin Sebor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6231301e-78a3-c940-35de-a1b938fce7af@redhat.com \
    --to=palves@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    --cc=msebor@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).