This is an archive of the discontinued LLVM Phabricator instance.

Add some macros to abstract marking of parameters as "not null", and use them in <cstring>
Needs ReviewPublic

Authored by mclow.lists on Aug 11 2015, 10:48 AM.

Details

Reviewers
EricWF
rsmith
Summary

The C standard says that calling memcpy, etc with null parameters is undefined behavior.
GCC (and clang) have attributes that allow us to mark the parameters of functions as "must not be null".

Define a mechanism to do this, and use it (for the first time) to mark the parameters of memcpy, memmove, memcmp and strncmp as "must not be null".

This gives us compile time checking for constant pointers, and hints to the code generator.

Note: This will not be a big win on systems that use glibc, because it marks the global functions ::memcpy, etc the same way. On Mac OS X, iOS, Android, FreeBSD, etc, this will make a bigger difference.

I will be adding tests as well; this post is to gather consensus that this is the right way to go.

Diff Detail

Event Timeline

mclow.lists retitled this revision from to Add some macros to abstract marking of parameters as "not null", and use them in <cstring>.
mclow.lists updated this object.
mclow.lists added reviewers: chandlerc, rsmith, EricWF.
mclow.lists added a subscriber: cfe-commits.
nlopes added a subscriber: nlopes.Aug 11 2015, 11:26 AM
nlopes added inline comments.
include/cstring
96

typo here.

emaste added a subscriber: emaste.Aug 11 2015, 11:31 AM
joerg added a subscriber: joerg.Aug 11 2015, 11:42 AM

I'm against doing this unconditionally. IMO it creates bugs without reasonable compensation. Just because glibc wants to hurt people doesn't mean anyone should get hurt.

I'm against doing this unconditionally. IMO it creates bugs without reasonable compensation. Just because glibc wants to hurt people doesn't mean anyone should get hurt.

+1. We don't want this in Android.

mclow.lists added inline comments.Aug 11 2015, 12:08 PM
include/cstring
96

Oops. Thanks!

mclow.lists added a comment.EditedAug 11 2015, 12:10 PM

I'm against doing this unconditionally. IMO it creates bugs without reasonable compensation. Just because glibc wants to hurt people doesn't mean anyone should get hurt.

Really? I see it as: It tells people who have UB in their code that they have a bug.

There's nothing here that "creates bugs".

No, it doesn't. It tells the compiler that it is free to make such assumptions. Take a step back from the standard. Can you think of any reasonable and efficient implementation of memcpy and friends, which fails for size 0? Adding the annotations (whether here or in string.h) effectively changes the behavior of the program. It is behavior people have been expecting for two decades, even when C90 said something else. This is completely different from the warning annotations. I'm just waiting for some of the bigger projects like PostgreSQL to start getting annoyed enough to introduce sane_memcpy for this.
I can't speak for Linux distributions using glibc, but I find this kind of smoking gun completely unacceptable to force unconditionally on everyone.

No, it doesn't. It tells the compiler that it is free to make such assumptions.

Again, I disagree. The compiler already knows it is free to make such assumptions.
(LLVM has an entire optimizer pass devoted to memcpy and friends)

joerg added a comment.Aug 11 2015, 1:45 PM

LLVM makes the assumptions only if the prototype has them too? Attribute nonnull is certainly changing optimiser behavior with GCC...

  • Original Message -----

From: "Marshall Clow via cfe-commits" <cfe-commits@lists.llvm.org>
To: "mclow lists" <mclow.lists@gmail.com>, chandlerc@gmail.com, richard@metafoo.co.uk, eric@efcs.ca
Cc: joerg@NetBSD.org, cfe-commits@lists.llvm.org
Sent: Tuesday, August 11, 2015 3:30:10 PM
Subject: Re: [PATCH] D11948: Add some macros to abstract marking of parameters as "not null", and use them in
<cstring>

mclow.lists added a comment.

In http://reviews.llvm.org/D11948#221991, @joerg wrote:

No, it doesn't. It tells the compiler that it is free to make such
assumptions.

Again, I disagree. The compiler already knows it is free to make such
assumptions.
(LLVM has an entire optimizer pass devoted to memcpy and friends)

I agree with Marshall. This ship has already sailed - the standard says what is says, and GCC and other compilers already take advantage of it, and thus portable code already cannot depend on the behavior of passing null pointers. Even non-portable code will be locked to specific compiler/library versions (which is already true with GCC) because, annotations aside, compilers are free to assume the standard semantics regardless. The annotations at least give users some more information on what the compiler is assuming, and so having them is better than not.

-Hal

http://reviews.llvm.org/D11948


cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

chandlerc edited edge metadata.Aug 13 2015, 2:16 PM

I agree with both Marshall and Hal.

However, I'm also not opposed to platforms opting out if this if they want to. If a particular platform wants to define the behavior of null pointers passed to these functions, that seems like a reasonable thing to support here. The two platforms that seem interested in supporting null pointers here are Android and FreeBSD, so I think we should disable this for those platforms.

But I want to point out and emphasize what Hal said: the compiler can *already do this*. Please make sure that both of those platforms configure Clang and LLVM to specially handle these routines to support null pointers. You're providing a conforming extension for your platform, but you can't *just* do that in the STL, you need to do that at every layer of the toolchain.

For Linux, given the *very* long precedent of glibc and GCC behavior, I'm confident we want these annotations. I'll let folks that actually support other platforms chime up for the cases they care about.

mclow.lists edited edge metadata.

Fixed a typo in the patch for strncmp, and added a macro _LIBCPP_HAS_NO_NONNULL to allow people to disable these checks.

Marked them as disabled for non-clang and non-gcc compilers.