<div dir="ltr">OK. What would be the best way to detect if Apple clang supports _Nonnull or only __nonnull though.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 26, 2015 at 11:40 PM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Jun 26, 2015 at 5:36 PM, b17 c0de <<a href="mailto:b17c0de@gmail.com">b17c0de@gmail.com</a>> wrote:<br>
> How can one detect if an Apple clang supports the new nullability<br>
> attributes. I tried something like:<br>
><br>
> #if __has_attribute(_Nonnull)<br>
> #elif __has_attribute(__nonnull)<br>
> #define _Nonnull __nonnull<br>
> #else<br>
> #define _Nonnull<br>
> #endif<br>
><br>
> But this didn't work. Why doesn't _Nonnull/__nonnull work with<br>
> __has_attribute?<br>
<br>
</span>__has_attribute is used to test for GNU-style attribute support only.<br>
To test for nullability, you should use: __has_feature(nullability)<br>
<span class="HOEnZb"><font color="#888888"><br>
~Aaron<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
><br>
> On Wed, Jun 24, 2015 at 10:39 PM, Douglas Gregor <<a href="mailto:dgregor@apple.com">dgregor@apple.com</a>> wrote:<br>
>><br>
>> Another addendum: due to the conflict with glibc’s __nonnull, we’ll be<br>
>> renaming the __double_underscored keywords to _Big_underscored keywords,<br>
>> e.g.,<br>
>><br>
>> __nonnull -> _Nonnull<br>
>> __nullable -> _Nullable<br>
>> __null_unspecified -> _Null_unspecified<br>
>><br>
>> On Darwin, we’ll add predefines<br>
>><br>
>> #define __nonnull _Nonnull<br>
>> #define __nullable _Nullable<br>
>> #define __null_unspecified _Null_unspecified<br>
>><br>
>> to keep the existing headers working.<br>
>><br>
>> - Doug<br>
>><br>
>> On Mar 2, 2015, at 1:22 PM, Douglas Gregor <<a href="mailto:dgregor@apple.com">dgregor@apple.com</a>> wrote:<br>
>><br>
>> Hello all,<br>
>><br>
>> Null pointers are a significant source of problems in applications.<br>
>> Whether it’s SIGSEGV taking down a process or a foolhardy attempt to recover<br>
>> from NullPointerException breaking invariants everywhere, it’s a problem<br>
>> that’s bad enough for Tony Hoare to call the invention of the null reference<br>
>> his billion dollar mistake [1]. It’s not the ability to create a null<br>
>> pointer that is a problem—having a common sentinel value meaning “no value”<br>
>> is extremely useful—but that it’s very hard to determine whether, for a<br>
>> particular pointer, one is expected to be able to use null. C doesn’t<br>
>> distinguish between “nullable” and “nonnull” pointers, so we turn to<br>
>> documentation and experimentation. Consider strchr from the C standard<br>
>> library:<br>
>><br>
>> char *strchr(const char *s, int c);<br>
>><br>
>> It is “obvious” to a programmer who knows the semantics of strchr that<br>
>> it’s important to check for a returned null, because null is used as the<br>
>> sentinel for “not found”. Of course, your tools don’t know that, so they<br>
>> cannot help when you completely forget to check for the null case. Bugs<br>
>> ensue.<br>
>><br>
>> Can I pass a null string to strchr? The standard is unclear [2], and my<br>
>> platform’s implementation happily accepts a null parameter and returns null,<br>
>> so obviously I shouldn’t worry about it… until I port my code, or the<br>
>> underlying implementation changes because my expectations and the library<br>
>> implementor’s expectations differ. Given the age of strchr, I suspect that<br>
>> every implementation out there has an explicit, defensive check for a null<br>
>> string, because it’s easier to add yet more defensive (and generally<br>
>> useless) null checks than it is to ask your clients to fix their code. Scale<br>
>> this up, and code bloat ensues, as well as wasted programmer effort that<br>
>> obscures the places where checking for null really does matter.<br>
>><br>
>> In a recent version of Xcode, Apple introduced an extension to<br>
>> C/C++/Objective-C that expresses the nullability of pointers in the type<br>
>> system via new nullability qualifiers . Nullability qualifiers express<br>
>> nullability as part of the declaration of strchr  [2]:<br>
>><br>
>> __nullable char *strchr(__nonnull const char *s, int c);<br>
>><br>
>> With this, programmers and tools alike can better reason about the use of<br>
>> strchr with null pointers.<br>
>><br>
>> We’d like to contribute the implementation (and there is a patch attached<br>
>> at the end [3]), but since this is a nontrivial extension to all of the C<br>
>> family of languages that Clang supports, we believe that it needs to be<br>
>> discussed here first.<br>
>><br>
>> Goals<br>
>> We have several specific goals that informed the design of this feature.<br>
>><br>
>> Allow the intended nullability to be expressed on all pointers: Pointers<br>
>> are used throughout library interfaces, and the nullability of those<br>
>> pointers is an important part of the API contract with users. It’s too<br>
>> simplistic to only allow function parameters to have nullability, for<br>
>> example, because it’s also important information for data members,<br>
>> pointers-to-pointers (e.g., "a nonnull pointer to a nullable pointer to an<br>
>> integer”), arrays of pointers, etc.<br>
>> Enable better tools support for detecting nullability problems: The<br>
>> nullability annotations should be useful for tools (especially the static<br>
>> analyzer) that can reason about the use of null, to give warnings about both<br>
>> missed null checks (the result of strchr could be null…) as well as for<br>
>> unnecessarily-defensive code.<br>
>> Support workflows where all interfaces provide nullability annotations: In<br>
>> moving from a world where there are no nullability annotations to one where<br>
>> we hope to see many such annotations, we’ve found it helpful to move<br>
>> header-by-header, auditing a complete header to give it nullability<br>
>> qualifiers. Once one has done that, additions to the header need to be held<br>
>> to the same standard, so we need a design that allows us to warn about<br>
>> pointers that don’t provide nullability annotations for some declarations in<br>
>> a header that already has some nullability annotations.<br>
>><br>
>> Zero effect on ABI or code generation: There are a huge number of<br>
>> interfaces that could benefit from the use of nullability qualifiers, but we<br>
>> won’t get widespread adoption if introducing the nullability qualifiers<br>
>> means breaking existing code, either in the ABI (say, because nullability<br>
>> qualifiers are mangled into the type) or at execution time (e.g., because a<br>
>> non-null pointer ends up being null along some error path and causes<br>
>> undefined behavior).<br>
>><br>
>><br>
>><br>
>><br>
>> Why not __attribute__((nonnull))?<br>
>> Clang already has an attribute to express nullability, “nonnull”, which we<br>
>> inherited from GCC [4]. The “nonnull” attribute can be placed on functions<br>
>> to indicate which parameters cannot be null: one either specifies the<br>
>> indices of the arguments that cannot be null, e.g.,<br>
>><br>
>> extern void *my_memcpy (void *dest, const void *src, size_t len)<br>
>> __attribute__((nonnull (1, 2)));<br>
>><br>
>> or omits the list of indices to state that all pointer arguments cannot be<br>
>> null, e.g.,<br>
>><br>
>> extern void *my_memcpy (void *dest, const void *src, size_t len)<br>
>> __attribute__((nonnull));<br>
>><br>
>> More recently, “nonnull”  has grown the ability to be applied to<br>
>> parameters, and one can use the companion attribute returns_nonnull to state<br>
>> that a function returns a non-null pointer:<br>
>><br>
>> extern void *my_memcpy (__attribute__((nonnull)) void *dest,<br>
>> __attribute__((nonnull)) const void *src, size_t len)<br>
>> __attribute__((returns_nonnull));<br>
>><br>
>> There are a number of problems here. First, there are different attributes<br>
>> to express the same idea at different places in the grammar, and the use of<br>
>> the “nonnull” attribute on the function actually has an effect on the<br>
>> function parameters can get very, very confusing. Quick, which pointers are<br>
>> nullable vs. non-null in this example?<br>
>><br>
>> __attribute__((nonnull)) void *my_realloc (void *ptr, size_t size);<br>
>><br>
>> According to that declaration, ptr is nonnull and the function returns a<br>
>> nullable pointer… but that’s the opposite of how it reads (and behaves, if<br>
>> this is anything like a realloc that cannot fail). Moreover, because these<br>
>> two attributes are declaration attributes, not type attributes, you cannot<br>
>> express that nullability of the inner pointer in a multi-level pointer or an<br>
>> array of pointers, which makes these attributes verbose, confusing, and not<br>
>> sufficiently generally. These attributes fail the first of our goals.<br>
>><br>
>> These attributes aren’t as useful as they could be for tools support (the<br>
>> second and third goals), because they only express the nonnull case, leaving<br>
>> no way to distinguish between the unannotated case (nobody has documented<br>
>> the nullability of some parameter) and the nullable case (we know the<br>
>> pointer can be null). From a tooling perspective, this is a killer: the<br>
>> static analyzer absolutely cannot warn that one has forgotten to check for<br>
>> null for every unannotated pointer, because the false-positive rate would be<br>
>> astronomical.<br>
>><br>
>> Finally, we’ve recently started considering violations of the<br>
>> __attribute__((nonnull)) contract to be undefined behavior, which fails the<br>
>> last of our goals. This is something we could debate further if it were the<br>
>> only problem, but these declaration attributes fall all of our criteria, so<br>
>> it’s not worth discussing.<br>
>><br>
>> Nullability Qualifiers<br>
>> We propose the addition of a new set of type qualifiers,  spelled<br>
>> __nullable, __nonnull, and __null_unspecified, to Clang. These are<br>
>> collectively known as nullability qualifiers and may be written anywhere any<br>
>> other type qualifier may be written (such as const) on any type subject to<br>
>> the following restrictions:<br>
>><br>
>> Two nullability qualifiers shall not appear in the same set of qualifiers.<br>
>> A nullability qualifier shall qualify any pointer type, including pointers<br>
>> to objects, pointers to functions, C++ pointers to members, block pointers,<br>
>> and Objective-C object pointers.<br>
>> A nullability qualifier in the declaration-specifiers applies to the<br>
>> innermost pointer type of each declarator (e.g., __nonnull int * is<br>
>> equivalent to int * __nonnull).<br>
>> A nullability qualifier applied to a typedef of a nullability-qualified<br>
>> pointer type shall specify the same nullability as the underlying type of<br>
>> the typedef.<br>
>><br>
>><br>
>> The meanings of the three nullability qualifiers are as follows:<br>
>><br>
>> __nullable: the pointer may store a null value at runtime (as part of the<br>
>> API contract)<br>
>> __nonnull: the pointer should not store a null value at runtime (as part<br>
>> of the API contract). it is possible that the value can be null, e.g., in<br>
>> erroneous historic uses of an API, and it is up to the library implementor<br>
>> to decide to what degree she will accommodate such clients.<br>
>> __null_unspecified: it is unclear whether the pointer can be null or not.<br>
>> Use of this type qualifier is extremely rare in practice, but it fills a<br>
>> small but important niche when auditing a particular header to add<br>
>> nullability qualifiers: sometimes the nullability contract for a few APIs in<br>
>> the header is unclear even when looking at the implementation for historical<br>
>> reasons, and establishing the contract requires more extensive study. In<br>
>> such cases, it’s often best to mark that pointer as __null_unspecified<br>
>> (which will help silence the warning about unannotated pointers in a header)<br>
>> and move on, coming back to __null_unspecified pointers when the appropriate<br>
>> graybeard has been summoned out of retirement [5].<br>
>><br>
>> Assumes-nonnull Regions<br>
>> We’ve found that it's fairly common for the majority of pointers within a<br>
>> particular header to be __nonnull. Therefore, we’ve introduced<br>
>> assumes-nonnull regions that assume that certain unannotated pointers<br>
>> implicitly get the __nonnull nullability qualifiers. Assumes-nonnull regions<br>
>> are marked by pragmas:<br>
>><br>
>> #pragma clang assume_nonnull begin<br>
>>         __nullable char *strchr(const char *s, int c); // s is inferred to<br>
>> be __nonnull<br>
>> void *my_realloc (__nullable void *ptr, size_t size); // my_realloc is<br>
>> inferred to return __nonnull<br>
>> #pragma clang assume_nonnull end<br>
>><br>
>> We infer __nonnull within an assumes_nonnull region when:<br>
>><br>
>> The pointer is a non-typedef declaration, such as a function parameter,<br>
>> variable, or data member, or the result type of a function. It’s very rare<br>
>> for one to warn typedefs to specify nullability information; rather, it’s<br>
>> usually the user of the typedef that needs to specify nullability.<br>
>> The pointer is a single-level pointer, e.g., int* but not int**, because<br>
>> we’ve found that programmers can get confused about the nullability of<br>
>> multi-level pointers (is it a __nullable pointer to __nonnull pointers, or<br>
>> the other way around?) and inferring nullability for any of the pointers in<br>
>> a multi-level pointer compounds the situation.<br>
>><br>
>><br>
>> Note that no #include may occur within an assumes_nonnull region, and<br>
>> assumes_nonnull regions cannot cross header boundaries.<br>
>><br>
>> Type System Impact<br>
>> Nullability qualifiers are mapped to type attributes within the Clang type<br>
>> system, but a nullability-qualified pointer type is not semantically<br>
>> distinct from its unqualified pointer type. Therefore, one may freely<br>
>> convert between nullability-qualified and non-nullability-qualified<br>
>> pointers, or between nullability-qualified pointers with different<br>
>> nullability qualifiers. One cannot overload on nullability qualifiers, write<br>
>> C++ class template partial specializations that identify nullability<br>
>> qualifiers, or inspect nullability via type traits in any way.<br>
>><br>
>> Said more strongly, removing nullability qualifiers from a well-formed<br>
>> program will not change its behavior in any way, nor will the semantics of a<br>
>> program change when any set of (well-formed) nullability qualifiers are<br>
>> added to it. Operationally, this means that nullability qualifiers are not<br>
>> part of the canonical type in Clang’s type system, and that any warnings we<br>
>> produce based on nullability information will necessarily be dependent on<br>
>> Clang’s ability to retain type sugar during semantic analysis.<br>
>><br>
>> While it’s somewhat exceptional for us to introduce new type qualifiers<br>
>> that don’t produce semantically distinct types, we feel that this is the<br>
>> only plausible design and implementation strategy for this feature: pushing<br>
>> nullability qualifiers into the type system semantically would cause<br>
>> significant changes to the language (e.g., overloading, partial<br>
>> specialization) and break ABI (due to name mangling) that would drastically<br>
>> reduce the number of potential users, and we feel that Clang’s support for<br>
>> maintaining type sugar throughout semantic analysis is generally good enough<br>
>> [6] to get the benefits of nullability annotations in our tools.<br>
>><br>
>> Looking forward to our discussion.<br>
>><br>
>> - Doug (with Jordan Rose and Anna Zaks)<br>
>><br>
>> [1] <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__en.wikipedia.org_wiki_Tony-5FHoare-23Apologies-5Fand-5Fretractions&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=CnzuN65ENJ1H9py9XLiRvC_UQz6u3oG6GUNn7_wosSM&m=YC8BZC14oScwb3bdXQh8PWHUqQX_GPZNpdojq4PLaQQ&s=nM47Ybyy8YXH7_wXW-1d6PSnY69IN_2kFPJR_BQxbVQ&e=" rel="noreferrer" target="_blank">http://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions</a><br>
>> [2] The standard description of strchr seems to imply that the parameter<br>
>> cannot be null<br>
>> [3] The patch is complete, but should be reviewed on cfe-commits rather<br>
>> than here. There are also several logic parts to this monolithic patch:<br>
>> (a) __nonnull/__nullable/__null_unspecified type specifiers<br>
>> (b) nonnull/nullable/null_unspecified syntactic sugar for Objective-C<br>
>> (c) Warning about inconsistent application of nullability specifiers<br>
>> within a given header<br>
>> (d) assume_nonnnull begin/end pragmas<br>
>> (e) Objective-C null_resettable property attribute<br>
>> [4] <a href="https://urldefense.proofpoint.com/v2/url?u=https-3A__gcc.gnu.org_onlinedocs_gcc_Function-2DAttributes.html&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=CnzuN65ENJ1H9py9XLiRvC_UQz6u3oG6GUNn7_wosSM&m=YC8BZC14oScwb3bdXQh8PWHUqQX_GPZNpdojq4PLaQQ&s=Ile4hZFTiYdUuN8Rhrm_piHhWkdboA1KlEEAtFwHZtY&e=" rel="noreferrer" target="_blank">https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html</a> (search<br>
>> for “nonnull”)<br>
>> [5] No graybeards were harmed in the making of this feature.<br>
>> [6] Template instantiation is the notable exception here, because it<br>
>> always canonicalizes types.<br>
>><br>
>> <nullability.patch><br>
>> _______________________________________________<br>
>> cfe-dev mailing list<br>
>> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
>><br>
>><br>
>><br>
>> _______________________________________________<br>
>> cfe-dev mailing list<br>
>> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
>><br>
><br>
><br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
><br>
</div></div></blockquote></div><br></div>