# RFC: Nullability qualifiers

**URL:** <https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672>\
**Category:** Clang Frontend\
**Created:** [March 2, 2015, 9:22pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672 "2015-03-02T21:22:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 2, 2015, 9:22pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/1 "2015-03-02T21:22:28Z")

</div>

Hello all,

Null pointers are a significant source of problems in applications. Whether it’s SIGSEGV taking down a process or a foolhardy attempt to recover from NullPointerException breaking invariants everywhere, it’s a problem that’s bad enough for Tony Hoare to call the invention of the null reference his billion dollar mistake [1]. It’s not the ability to create a null pointer that is a problem—having a common sentinel value meaning “no value” is extremely useful—but that it’s very hard to determine whether, for a particular pointer, one is expected to be able to use null. C doesn’t distinguish between “nullable” and “nonnull” pointers, so we turn to documentation and experimentation. Consider strchr from the C standard library:

char \*strchr(const char \*s, int c);

It is “obvious” to a programmer who knows the semantics of strchr that it’s important to check for a returned null, because null is used as the sentinel for “not found”. Of course, your tools don’t know that, so they cannot help when you completely forget to check for the null case. Bugs ensue.

Can I pass a null string to strchr? The standard is unclear [2], and my platform’s implementation happily accepts a null parameter and returns null, so obviously I shouldn’t worry about it… until I port my code, or the underlying implementation changes because my expectations and the library implementor’s expectations differ. Given the age of strchr, I suspect that every implementation out there has an explicit, defensive check for a null string, because it’s easier to add yet more defensive (and generally useless) null checks than it is to ask your clients to fix their code. Scale this up, and code bloat ensues, as well as wasted programmer effort that obscures the places where checking for null really does matter.

In a recent version of Xcode, Apple introduced an extension to C/C++/Objective-C that expresses the nullability of pointers in the type system via new nullability qualifiers . Nullability qualifiers express nullability as part of the declaration of strchr [2]:

\_\_nullable char \*strchr(\_\_nonnull const char \*s, int c);

With this, programmers and tools alike can better reason about the use of strchr with null pointers.

We’d like to contribute the implementation (and there is a patch attached at the end [3]), but since this is a nontrivial extension to all of the C family of languages that Clang supports, we believe that it needs to be discussed here first.

**Goals**  
We have several specific goals that informed the design of this feature.

- **Allow the intended nullability to be expressed on all pointers** : Pointers are used throughout library interfaces, and the nullability of those pointers is an important part of the API contract with users. It’s too simplistic to only allow function parameters to have nullability, for example, because it’s also important information for data members, pointers-to-pointers (e.g., "a nonnull pointer to a nullable pointer to an integer”), arrays of pointers, etc.

- **Enable better tools support for detecting nullability problems:** The nullability annotations should be useful for tools (especially the static analyzer) that can reason about the use of null, to give warnings about both missed null checks (the result of strchr could be null…) as well as for unnecessarily-defensive code.

- **Support workflows where all interfaces provide nullability annotations:** In moving from a world where there are no nullability annotations to one where we hope to see many such annotations, we’ve found it helpful to move header-by-header, auditing a complete header to give it nullability qualifiers. Once one has done that, additions to the header need to be held to the same standard, so we need a design that allows us to warn about pointers that don’t provide nullability annotations for some declarations in a header that already has some nullability annotations.

- **Zero effect on ABI or code generation:** There are a huge number of interfaces that could benefit from the use of nullability qualifiers, but we won’t get widespread adoption if introducing the nullability qualifiers means breaking existing code, either in the ABI (say, because nullability qualifiers are mangled into the type) or at execution time (e.g., because a non-null pointer ends up being null along some error path and causes undefined behavior).

**Why not attribute((nonnull))?**  
Clang already has an attribute to express nullability, “nonnull”, which we inherited from GCC [4]. The “nonnull” attribute can be placed on functions to indicate which parameters cannot be null: one either specifies the indices of the arguments that cannot be null, e.g.,

```auto
	extern void *my_memcpy (void *dest, const void *src, size_t len) __attribute__ ((nonnull (1, 2)));

```

or omits the list of indices to state that all pointer arguments cannot be null, e.g.,

```auto
	extern void *my_memcpy (void *dest, const void *src, size_t len) __attribute__ ((nonnull));

```

More recently, “nonnull” has grown the ability to be applied to parameters, and one can use the companion attribute returns\_nonnull to state that a function returns a non-null pointer:

```auto
	extern void *my_memcpy ( __attribute__ ((nonnull)) void *dest, __attribute__ ((nonnull)) const void *src, size_t len) __attribute__ ((returns_nonnull));

```

There are a number of problems here. First, there are different attributes to express the same idea at different places in the grammar, and the use of the “nonnull” attribute _on the function_ actually has an effect _on the function parameters_ can get very, very confusing. Quick, which pointers are nullable vs. non-null in this example?

**attribute** ((nonnull)) void \*my\_realloc (void \*ptr, size\_t size);

According to that declaration, ptr is nonnull and the function returns a nullable pointer… but that’s the opposite of how it reads (and behaves, if this is anything like a realloc that cannot fail). Moreover, because these two attributes are _declaration_ attributes, not type attributes, you cannot express that nullability of the inner pointer in a multi-level pointer or an array of pointers, which makes these attributes verbose, confusing, and not sufficiently generally. These attributes fail the first of our goals.

These attributes aren’t as useful as they could be for tools support (the second and third goals), because they only express the nonnull case, leaving no way to distinguish between the unannotated case (nobody has documented the nullability of some parameter) and the nullable case (we know the pointer can be null). From a tooling perspective, this is a killer: the static analyzer absolutely cannot warn that one has forgotten to check for null for every unannotated pointer, because the false-positive rate would be astronomical.

Finally, we’ve recently started considering violations of the **attribute** ((nonnull)) contract to be undefined behavior, which fails the last of our goals. This is something we could debate further if it were the only problem, but these declaration attributes fall all of our criteria, so it’s not worth discussing.

**Nullability Qualifiers**  
We propose the addition of a new set of type qualifiers, spelled \_\_nullable, \_\_nonnull, and \_\_null\_unspecified, to Clang. These are collectively known as _nullability qualifiers_ and may be written anywhere any other type qualifier may be written (such as const) on any type subject to the following restrictions:

- Two nullability qualifiers shall not appear in the same set of qualifiers.
- A nullability qualifier shall qualify any pointer type, including pointers to objects, pointers to functions, C++ pointers to members, block pointers, and Objective-C object pointers.
- A nullability qualifier in the declaration-specifiers applies to the innermost pointer type of each declarator (e.g., \_\_nonnull int \* is equivalent to int \* \_\_nonnull).
- A nullability qualifier applied to a typedef of a nullability-qualified pointer type shall specify the same nullability as the underlying type of the typedef.

The meanings of the three nullability qualifiers are as follows:

\_\_nullable: the pointer may store a null value at runtime (as part of the API contract)  
\_\_nonnull: the pointer should not store a null value at runtime (as part of the API contract). it is possible that the value can be null, e.g., in erroneous historic uses of an API, and it is up to the library implementor to decide to what degree she will accommodate such clients.  
\_\_null\_unspecified: it is unclear whether the pointer can be null or not. Use of this type qualifier is extremely rare in practice, but it fills a small but important niche when auditing a particular header to add nullability qualifiers: sometimes the nullability contract for a few APIs in the header is unclear _even when looking at the implementation_ for historical reasons, and establishing the contract requires more extensive study. In such cases, it’s often best to mark that pointer as \_\_null\_unspecified (which will help silence the warning about unannotated pointers in a header) and move on, coming back to \_\_null\_unspecified pointers when the appropriate graybeard has been summoned out of retirement [5].

**Assumes-nonnull Regions**  
We’ve found that it’s fairly common for the majority of pointers within a particular header to be \_\_nonnull. Therefore, we’ve introduced assumes-nonnull regions that assume that certain unannotated pointers implicitly get the \_\_nonnull nullability qualifiers. Assumes-nonnull regions are marked by pragmas:

#pragma clang assume\_nonnull begin  
\_\_nullable char \*strchr(const char \*s, int c); // s is inferred to be \_\_nonnull  
void \*my\_realloc (\_\_nullable void \*ptr, size\_t size); // my\_realloc is inferred to return \_\_nonnull  
#pragma clang assume\_nonnull end

We infer \_\_nonnull within an assumes\_nonnull region when:

- The pointer is a non-typedef declaration, such as a function parameter, variable, or data member, or the result type of a function. It’s very rare for one to warn typedefs to specify nullability information; rather, it’s usually the user of the typedef that needs to specify nullability.
- The pointer is a single-level pointer, e.g., int\* but not int\*\*, because we’ve found that programmers can get confused about the nullability of multi-level pointers (is it a \_\_nullable pointer to \_\_nonnull pointers, or the other way around?) and inferring nullability for any of the pointers in a multi-level pointer compounds the situation.

Note that no #include may occur within an assumes\_nonnull region, and assumes\_nonnull regions cannot cross header boundaries.

**Type System Impact**  
Nullability qualifiers are mapped to type attributes within the Clang type system, but a nullability-qualified pointer type is not semantically distinct from its unqualified pointer type. Therefore, one may freely convert between nullability-qualified and non-nullability-qualified pointers, or between nullability-qualified pointers with different nullability qualifiers. One cannot overload on nullability qualifiers, write C++ class template partial specializations that identify nullability qualifiers, or inspect nullability via type traits in any way.

Said more strongly, removing nullability qualifiers from a well-formed program will not change its behavior in any way, nor will the semantics of a program change when any set of (well-formed) nullability qualifiers are added to it. Operationally, this means that _nullability qualifiers are not part of the canonical type_ in Clang’s type system, and that any warnings we produce based on nullability information will necessarily be dependent on Clang’s ability to retain type sugar during semantic analysis.

While it’s somewhat exceptional for us to introduce new type qualifiers that don’t produce semantically distinct types, we feel that this is the only plausible design and implementation strategy for this feature: pushing nullability qualifiers into the type system semantically would cause significant changes to the language (e.g., overloading, partial specialization) and break ABI (due to name mangling) that would drastically reduce the number of potential users, and we feel that Clang’s support for maintaining type sugar throughout semantic analysis is generally good enough [6] to get the benefits of nullability annotations in our tools.

Looking forward to our discussion.

- Doug (with Jordan Rose and Anna Zaks)

[1] [http://en.wikipedia.org/wiki/Tony\_Hoare#Apologies\_and\_retractions](http://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions)  
[2] The standard description of strchr seems to imply that the parameter cannot be null  
[3] The patch is complete, but should be reviewed on cfe-commits rather than here. There are also several logic parts to this monolithic patch:  
(a) \_\_nonnull/\_\_nullable/\_\_null\_unspecified type specifiers

(b) nonnull/nullable/null\_unspecified syntactic sugar for Objective-C  
(c) Warning about inconsistent application of nullability specifiers within a given header  
(d) assume\_nonnnull begin/end pragmas  
(e) Objective-C null\_resettable property attribute

[4] [https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) (search for “nonnull”)  
[5] No graybeards were harmed in the making of this feature.  
[6] Template instantiation is the notable exception here, because it always canonicalizes types.

[nullability.patch](https://discourse.llvm.org/uploads/short-url/tqjBUHYktuF6FaLgYSLLpIb2KCj.patch) (185 KB)

---

<div class="post-metadata">

**Author:** ![zygoloid](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/zygoloid/32/14068_2.png) [@zygoloid](https://discourse.llvm.org/u/zygoloid)\
**Post date:** [March 2, 2015, 11:34pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/2 "2015-03-02T23:34:18Z")

</div>

> Hello all,
> 
> Null pointers are a significant source of problems in applications.  
> Whether it’s SIGSEGV taking down a process or a foolhardy attempt to  
> recover from NullPointerException breaking invariants everywhere, it’s a  
> problem that’s bad enough for Tony Hoare to call the invention of the null  
> reference his billion dollar mistake [1]. It’s not the ability to create a  
> null pointer that is a problem—having a common sentinel value meaning “no  
> value” is extremely useful—but that it’s very hard to determine whether,  
> for a particular pointer, one is expected to be able to use null. C doesn’t  
> distinguish between “nullable” and “nonnull” pointers, so we turn to  
> documentation and experimentation. Consider strchr from the C standard  
> library:
> 
> char \*strchr(const char \*s, int c);
> 
> It is “obvious” to a programmer who knows the semantics of strchr that  
> it’s important to check for a returned null, because null is used as the  
> sentinel for “not found”. Of course, your tools don’t know that, so they  
> cannot help when you completely forget to check for the null case. Bugs  
> ensue.
> 
> Can I pass a null string to strchr? The standard is unclear [2], and my  
> platform’s implementation happily accepts a null parameter and returns  
> null, so obviously I shouldn’t worry about it… until I port my code, or the  
> underlying implementation changes because my expectations and the library  
> implementor’s expectations differ. Given the age of strchr, I suspect that  
> every implementation out there has an explicit, defensive check for a null  
> string, because it’s easier to add yet more defensive (and generally  
> useless) null checks than it is to ask your clients to fix their code.  
> Scale this up, and code bloat ensues, as well as wasted programmer effort  
> that obscures the places where checking for null really does matter.
> 
> In a recent version of Xcode, Apple introduced an extension to  
> C/C++/Objective-C that expresses the nullability of pointers in the type  
> system via new nullability qualifiers . Nullability qualifiers express  
> nullability as part of the declaration of strchr [2]:
> 
> \_\_nullable char \*strchr(\_\_nonnull const char \*s, int c);
> 
> With this, programmers and tools alike can better reason about the use of  
> strchr with null pointers.
> 
> We’d like to contribute the implementation (and there is a patch attached  
> at the end [3]), but since this is a nontrivial extension to all of the C  
> family of languages that Clang supports, we believe that it needs to be  
> discussed here first.
> 
> \*Goals\*  
> We have several specific goals that informed the design of this feature.
> 
> &nbsp;&nbsp;&nbsp;- \*Allow the intended nullability to be expressed on all pointers\*:  
> &nbsp;&nbsp;&nbsp;Pointers are used throughout library interfaces, and the nullability of  
> &nbsp;&nbsp;&nbsp;those pointers is an important part of the API contract with users. It’s  
> &nbsp;&nbsp;&nbsp;too simplistic to only allow function parameters to have nullability, for  
> &nbsp;&nbsp;&nbsp;example, because it’s also important information for data members,  
> &nbsp;&nbsp;&nbsp;pointers-to-pointers (e.g., "a nonnull pointer to a nullable pointer to an  
> &nbsp;&nbsp;&nbsp;integer”), arrays of pointers, etc.  
> &nbsp;&nbsp;&nbsp;- \*Enable better tools support for detecting nullability problems:\* The  
> &nbsp;&nbsp;&nbsp;nullability annotations should be useful for tools (especially the static  
> &nbsp;&nbsp;&nbsp;analyzer) that can reason about the use of null, to give warnings about  
> &nbsp;&nbsp;&nbsp;both missed null checks (the result of strchr could be null…) as well as  
> &nbsp;&nbsp;&nbsp;for unnecessarily-defensive code.  
> &nbsp;&nbsp;&nbsp;- \*Support workflows where all interfaces provide nullability  
> &nbsp;&nbsp;&nbsp;annotations:\* In moving from a world where there are no nullability  
> &nbsp;&nbsp;&nbsp;annotations to one where we hope to see many such annotations, we’ve found  
> &nbsp;&nbsp;&nbsp;it helpful to move header-by-header, auditing a complete header to give it  
> &nbsp;&nbsp;&nbsp;nullability qualifiers. Once one has done that, additions to the header  
> &nbsp;&nbsp;&nbsp;need to be held to the same standard, so we need a design that allows us to  
> &nbsp;&nbsp;&nbsp;warn about pointers that don’t provide nullability annotations for some  
> &nbsp;&nbsp;&nbsp;declarations in a header that already has some nullability annotations.
> 
> &nbsp;&nbsp;&nbsp;- \*Zero effect on ABI or code generation:\* There are a huge number of  
> &nbsp;&nbsp;&nbsp;interfaces that could benefit from the use of nullability qualifiers, but  
> &nbsp;&nbsp;&nbsp;we won’t get widespread adoption if introducing the nullability qualifiers  
> &nbsp;&nbsp;&nbsp;means breaking existing code, either in the ABI (say, because nullability  
> &nbsp;&nbsp;&nbsp;qualifiers are mangled into the type) or at execution time (e.g., because a  
> &nbsp;&nbsp;&nbsp;non-null pointer ends up being null along some error path and causes  
> &nbsp;&nbsp;&nbsp;undefined behavior).
> 
> A sanitizer for this feature would seem very useful, but this bullet point

suggests that such a sanitizer would violate the model. Likewise, I don't  
see why we should rule out the option of optimizing on the basis of these  
qualifiers (under a -fstrict-nonnull flag or similar).

> \*Why not \_\_attribute\_\_((nonnull))?\*  
> Clang already has an attribute to express nullability, “nonnull”, which we  
> inherited from GCC [4]. The “nonnull” attribute can be placed on functions  
> to indicate which parameters cannot be null: one either specifies the  
> indices of the arguments that cannot be null, e.g.,
> 
> &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull (1, 2)));
> 
> or omits the list of indices to state that all pointer arguments cannot be  
> null, e.g.,
> 
> &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull));
> 
> More recently, “nonnull” has grown the ability to be applied to  
> parameters, and one can use the companion attribute returns\_nonnull to  
> state that a function returns a non-null pointer:
> 
> &nbsp;&nbsp;extern void \*my\_memcpy (\_\_attribute\_\_((nonnull)) void \*dest, \_\_attribute\_\_((nonnull)) const void \*src, size\_t len) \_\_attribute\_\_((returns\_nonnull));
> 
> There are a number of problems here. First, there are different attributes  
> to express the same idea at different places in the grammar, and the use of  
> the “nonnull” attribute \*on the function\* actually has an effect \*on the  
> function parameters\* can get very, very confusing. Quick, which pointers  
> are nullable vs. non-null in this example?
> 
> \_\_attribute\_\_((nonnull)) void \*my\_realloc (void \*ptr, size\_t size);
> 
> According to that declaration, ptr is nonnull and the function returns a  
> nullable pointer… but that’s the opposite of how it reads (and behaves, if  
> this is anything like a realloc that cannot fail). Moreover, because these  
> two attributes are \*declaration\* attributes, not type attributes, you  
> cannot express that nullability of the inner pointer in a multi-level  
> pointer or an array of pointers, which makes these attributes verbose,  
> confusing, and not sufficiently generally. These attributes fail the first  
> of our goals.
> 
> These attributes aren’t as useful as they could be for tools support (the  
> second and third goals), because they only express the nonnull case,  
> leaving no way to distinguish between the unannotated case (nobody has  
> documented the nullability of some parameter) and the nullable case (we  
> know the pointer can be null). From a tooling perspective, this is a  
> killer: the static analyzer absolutely cannot warn that one has forgotten  
> to check for null for every unannotated pointer, because the false-positive  
> rate would be astronomical.
> 
> Finally, we’ve recently started considering violations of the  
> \_\_attribute\_\_((nonnull)) contract to be undefined behavior, which fails the  
> last of our goals. This is something we could debate further if it were the  
> only problem, but these declaration attributes fall all of our criteria, so  
> it’s not worth discussing.
> 
> \*Nullability Qualifiers\*  
> We propose the addition of a new set of type qualifiers, spelled  
> \_\_nullable, \_\_nonnull, and \_\_null\_unspecified, to Clang. These are  
> collectively known as \*nullability qualifiers\* and may be written  
> anywhere any other type qualifier may be written (such as const) on any  
> type subject to the following restrictions:
> 
> &nbsp;&nbsp;&nbsp;- Two nullability qualifiers shall not appear in the same set of  
> &nbsp;&nbsp;&nbsp;qualifiers.  
> &nbsp;&nbsp;&nbsp;- A nullability qualifier shall qualify any pointer type, including  
> &nbsp;&nbsp;&nbsp;pointers to objects, pointers to functions, C++ pointers to members, block  
> &nbsp;&nbsp;&nbsp;pointers, and Objective-C object pointers.  
> &nbsp;&nbsp;&nbsp;- A nullability qualifier in the declaration-specifiers applies to the  
> &nbsp;&nbsp;&nbsp;innermost pointer type of each declarator (e.g., \_\_nonnull int \* is  
> &nbsp;&nbsp;&nbsp;equivalent to int \* \_\_nonnull).
> 
> What happens if there's a mixture of different kinds of declarator? (Can I

have '\_\_nonnull int (\*p)[3]'? Can I have '\_\_nonnull int \*p[3];'?)

I think you're saying that this decision is made based on the syntax of the  
declarator and not based on the underlying type, right? (So in

&nbsp;&nbsp;\_\_nonnull T \*

the \_\_nonnull appertains to the \*, even if T names a pointer type.) Given  
that...

> &nbsp;&nbsp;&nbsp;- A nullability qualifier applied to a typedef of a  
> &nbsp;&nbsp;&nbsp;nullability-qualified pointer type shall specify the same nullability as  
> &nbsp;&nbsp;&nbsp;the underlying type of the typedef.
> 
> ... I don't really see what this rule is for. I would expect "\_\_nonnull T"

to be ill-formed because the innermost component of the declarator is not a  
pointer, irrespective of whether T is a pointer type and whether it's  
nullable. And I'd expect "\_\_nonnull T \*" to be valid whether or not T is a  
typedef for a \_\_nonnull pointer.

On the whole, I find it a little strange to allow a nullability qualifier  
in the decl-specifier-seq / specifiers-and-qualifiers that applies to some  
later pointer declarator; I would have expected this to be permitted in the  
cv-qualifier-seq / type-qualifier-list after the pointer operator, and  
nowhere else (or perhaps permitted in a decl-specifier-seq that also  
contains a type-specifier for a pointer type). This kind of flexibility has  
proven a disaster for the comprehensibility of GCC's type attributes.

The meanings of the three nullability qualifiers are as follows:

> \_\_nullable: the pointer may store a null value at runtime (as part of the  
> API contract)  
> \_\_nonnull: the pointer should not store a null value at runtime (as part  
> of the API contract). it is possible that the value can be null, e.g., in  
> erroneous historic uses of an API, and it is up to the library implementor  
> to decide to what degree she will accommodate such clients.  
> \_\_null\_unspecified: it is unclear whether the pointer can be null or not.  
> Use of this type qualifier is extremely rare in practice, but it fills a  
> small but important niche when auditing a particular header to add  
> nullability qualifiers: sometimes the nullability contract for a few APIs  
> in the header is unclear \*even when looking at the implementation\* for  
> historical reasons, and establishing the contract requires more extensive  
> study. In such cases, it’s often best to mark that pointer as  
> \_\_null\_unspecified (which will help silence the warning about unannotated  
> pointers in a header) and move on, coming back to \_\_null\_unspecified  
> pointers when the appropriate graybeard has been summoned out of retirement  
> [5].

Have you considered adding C++11 attributes as synonyms for these?

\*Assumes-nonnull Regions\*

> We’ve found that it's fairly common for the majority of pointers within a  
> particular header to be \_\_nonnull. Therefore, we’ve introduced  
> assumes-nonnull regions that assume that certain unannotated pointers  
> implicitly get the \_\_nonnull nullability qualifiers. Assumes-nonnull  
> regions are marked by pragmas:
> 
> #pragma clang assume\_nonnull begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_nullable char \*strchr(const char \*s, int c); // s is inferred to  
> be \_\_nonnull  
> void \*my\_realloc (\_\_nullable void \*ptr, size\_t size); // my\_realloc is  
> inferred to return \_\_nonnull  
> #pragma clang assume\_nonnull end

These pragmas seem easy to miss when moving declarations around while  
refactoring. Do you have enough experience with the feature to know if  
that's an issue in practice?

We infer \_\_nonnull within an assumes\_nonnull region when:

> &nbsp;&nbsp;&nbsp;- The pointer is a non-typedef declaration, such as a function  
> &nbsp;&nbsp;&nbsp;parameter, variable, or data member, or the result type of a function. It’s  
> &nbsp;&nbsp;&nbsp;very rare for one to warn typedefs to specify nullability information;  
> &nbsp;&nbsp;&nbsp;rather, it’s usually the user of the typedef that needs to specify  
> &nbsp;&nbsp;&nbsp;nullability.
> 
> How can they do this, given the earlier rules?

> &nbsp;&nbsp;&nbsp;- The pointer is a single-level pointer, e.g., int\* but not int\*\*,  
> &nbsp;&nbsp;&nbsp;because we’ve found that programmers can get confused about the nullability  
> &nbsp;&nbsp;&nbsp;of multi-level pointers (is it a \_\_nullable pointer to \_\_nonnull pointers,  
> &nbsp;&nbsp;&nbsp;or the other way around?) and inferring nullability for any of the pointers  
> &nbsp;&nbsp;&nbsp;in a multi-level pointer compounds the situation.
> 
> Note that no #include may occur within an assumes\_nonnull region, and  
> assumes\_nonnull regions cannot cross header boundaries.

That sounds like it would make the lives of library maintainers using this  
feature painful -- they would need to textually duplicate these pragmas and  
the surrounding #ifdefs in every system header that needs them, rather than  
factoring them out into #includable begin/end files. But I suppose we can  
encourage the use of a macro expanding to \_Pragma for those cases.

> \*Type System Impact\*  
> Nullability qualifiers are mapped to type attributes within the Clang type  
> system, but a nullability-qualified pointer type is not semantically  
> distinct from its unqualified pointer type. Therefore, one may freely  
> convert between nullability-qualified and non-nullability-qualified  
> pointers, or between nullability-qualified pointers with different  
> nullability qualifiers. One cannot overload on nullability qualifiers,  
> write C++ class template partial specializations that identify nullability  
> qualifiers, or inspect nullability via type traits in any way.
> 
> Said more strongly, removing nullability qualifiers from a well-formed  
> program will not change its behavior in any way, nor will the semantics of  
> a program change when any set of (well-formed) nullability qualifiers are  
> added to it. Operationally, this means that \*nullability qualifiers are  
> not part of the canonical type\* in Clang’s type system, and that any  
> warnings we produce based on nullability information will necessarily be  
> dependent on Clang’s ability to retain type sugar during semantic analysis.
> 
> While it’s somewhat exceptional for us to introduce new type qualifiers  
> that don’t produce semantically distinct types, we feel that this is the  
> only plausible design and implementation strategy for this feature: pushing  
> nullability qualifiers into the type system semantically would cause  
> significant changes to the language (e.g., overloading, partial  
> specialization) and break ABI (due to name mangling) that would drastically  
> reduce the number of potential users, and we feel that Clang’s support for  
> maintaining type sugar throughout semantic analysis is generally good  
> enough [6] to get the benefits of nullability annotations in our tools.

This seems reasonable to me, given the constraints. (I've had some offline  
discussions with various people about template type sugar reconstruction,  
which would help to diagnose issues here.)

Looking forward to our discussion.

---

<div class="post-metadata">

**Author:** ![Dean\_Sutherland1](https://avatars.discourse-cdn.com/v4/letter/d/54ee81/32.png) [@Dean\_Sutherland1](https://discourse.llvm.org/u/Dean_Sutherland1)\
**Post date:** [March 2, 2015, 11:41pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/3 "2015-03-02T23:41:41Z")

</div>

What a very good idea! Strong support for expressing and checking intent regarding potential nullability can clearly help us all right more reliable programs. I have a few questions, though.

- Consider LoadHTMLString:BaseURL: from the UIWebView class. Providing a null pointer for the BaseURL is clearly _legal_. It even has a defined meaning, which is “don’t bother to enforce the same origin policy for this content.” So the BaseURL argument is nullable in terms of the analysis you propose above. So far, so good. Sadly, turning off the “same origin policy” is nearly always a serious security bug. Permitting a null pointer in this context is extremely likely to be wrong; it probably represents a bug 999 times out of 1000 uses. (I’d claim it was _always_ wrong, but someone at some point decided it was a feature worth supporting and documenting. And I have seen a very few unit tests where passing a null pointer for the BaseURL was arguably OK). Do you intend to address this kind of “legal, but virtually certain to be wrong” usage, or is that out of scope?

- Based on your discussion of type system impact, I’m sure you are all well aware that the compiler support for “maintaining type sugar through semantic analysis” needed to make this proposal work is _almost_ enough to support a full “plug-able type system” similar to what’s available in recent versions of Java. Do you have any plans to address the missing pieces? Being able to support pluggable type information more broadly (while continuing to guarantee that adding such qualifiers/attributes/however-it’s-expressed would have zero impact on generated code) would enable all sorts of interesting analyses. A few examples that spring to mind include compile-time enforcement of physical unit compatibility, various protocol-level checks (type states, a la Bierhoff & Aldrich), and many more. When last I investigated this question (about a year ago), the limitation regarding templates (your [6]) was the only significant missing piece. Closing that gap would greatly reduce the difficulty (and project risk) of implementing such analyses.

Dean F. Sutherland

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 3, 2015, 12:20am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/4 "2015-03-03T00:20:13Z")

</div>

I agree that a sanitizer would be useful as a debugging aid. My primary concern here is that optimizing based on this information _not_ be a part of any normal optimization flag (-O2, -Os, whatever), because it will hamper widespread adoption of this feature if adding the annotations to indicate the API contract suddenly starts breaking existing clients by, e.g., optimizing out existing, defensive null checks.

> 

I’ve said it poorly. It is based on the type, so

\_\_nonnull T \*

applies \_\_nonnull to T unless T is a known type that is not a pointer type. In the patch Type::canHaveNullability() computes the operation, and essentially we apply the \_\_nonnull to T when:

- T is of pointer, C++ member pointer, block pointer, or Objective-C object pointer
- T is a dependent type that could instantiate to some kind of pointer type

> 

It’s an attempt to make the simple cases read better, e.g., “\_\_nonnull int \*” reads a whole lot better than “int \* \_\_nonnull” for most

> 

We haven’t seen a disaster, but we have seen some confusion with multi-level pointers, because we have seen people try

\_\_nonnull int \* \_\_nullable \*

and scratch their heads when we complain about duplicate specifiers.

That said, the developers that have been using this feature have become perhaps a little accustomed to writing type qualifiers in the decl-specifier-seq that actually apply to the pointer, because the Objective-C ARC qualifiers (\_\_weak, \_\_autoreleasing) do the same thing in a more limited manner (that doesn’t run into the multi-level pointer problem).

> 

I think it’s totally reasonable to add [[nullable]], [[nonnull]], and [[null\_unspecified]]. If we feel that this feature is working out as we hope, we can push for standardization.

> 

I don’t feel like we have enough experience here to be certain that it’s not a trap for users. We’ve pushed a significant number of headers through the process of applying nullability annotations in a production environment, but the feature hasn’t been in production use long enough for us to see the kinds of mistakes that could get introduced through refactoring. Additionally, it’s possible that we have more safeguards in place than your average programmer would, so these mistakes might be happening and then getting fixed before we hear about them. We also try to reduce mistakes by convention: headers should have begin pragma at the beginning of the header (after the #includes, of course) and the end pragma at the end of the header, rather than chopping up sections of the header that are audited vs. non-audited.

> 

I hope that I’ve clarified my poor representation of the rules here.

> 

We’re advocating for the use of a pair of macros to expand to the begin/end pragmas.

> 

Template type sugar reconstruction would be a great QoI improvement in general, and would let the nullability qualifiers flow though template instantiations in the expected manner.

- Doug

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 3, 2015, 12:40am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/5 "2015-03-03T00:40:05Z")

</div>

> What a very good idea! Strong support for expressing and checking intent regarding potential nullability can clearly help us all right more reliable programs. I have a few questions, though.
> 
> - Consider LoadHTMLString:BaseURL: from the UIWebView class. Providing a null pointer for the BaseURL is clearly _legal_. It even has a defined meaning, which is “don’t bother to enforce the same origin policy for this content.” So the BaseURL argument is nullable in terms of the analysis you propose above. So far, so good. Sadly, turning off the “same origin policy” is nearly always a serious security bug. Permitting a null pointer in this context is extremely likely to be wrong; it probably represents a bug 999 times out of 1000 uses. (I’d claim it was _always_ wrong, but someone at some point decided it was a feature worth supporting and documenting. And I have seen a very few unit tests where passing a null pointer for the BaseURL was arguably OK). Do you intend to address this kind of “legal, but virtually certain to be wrong” usage, or is that out of scope?

This kind of decision is really up to the owner of that API. If she believes that her API shouldn’t make it easy to introduce this form of security problem, she can mark it as “\_\_nonnull” and put in some defensive code to either fail softly or emulate prior behavior. Clients that pass a null value will start to see warnings that there is an issue.

> - Based on your discussion of type system impact, I’m sure you are all well aware that the compiler support for “maintaining type sugar through semantic analysis” needed to make this proposal work is _almost_ enough to support a full “plug-able type system” similar to what’s available in recent versions of Java. Do you have any plans to address the missing pieces? Being able to support pluggable type information more broadly (while continuing to guarantee that adding such qualifiers/attributes/however-it’s-expressed would have zero impact on generated code) would enable all sorts of interesting analyses. A few examples that spring to mind include compile-time enforcement of physical unit compatibility, various protocol-level checks (type states, a la Bierhoff & Aldrich), and many more. When last I investigated this question (about a year ago), the limitation regarding templates (your [6]) was the only significant missing piece. Closing that gap would greatly reduce the difficulty (and project risk) of implementing such analyses.

We’re almost there in Clang, although I doubt that I personally will have time any time soon to work on addressing the issue of type sugar flowing through template specializations. I don’t think it’s fundamentally that hard to do, and beyond that I expect that we’ll see a long tail of small issues where we’re not maintaining type sugar everywhere.

- Doug

---

<div class="post-metadata">

**Author:** ![zygoloid](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/zygoloid/32/14068_2.png) [@zygoloid](https://discourse.llvm.org/u/zygoloid)\
**Post date:** [March 3, 2015, 1:11am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/6 "2015-03-03T01:11:25Z")

</div>

> > Hello all,
> > 
> > Null pointers are a significant source of problems in applications.  
> > Whether it’s SIGSEGV taking down a process or a foolhardy attempt to  
> > recover from NullPointerException breaking invariants everywhere, it’s a  
> > problem that’s bad enough for Tony Hoare to call the invention of the null  
> > reference his billion dollar mistake [1]. It’s not the ability to create a  
> > null pointer that is a problem—having a common sentinel value meaning “no  
> > value” is extremely useful—but that it’s very hard to determine whether,  
> > for a particular pointer, one is expected to be able to use null. C doesn’t  
> > distinguish between “nullable” and “nonnull” pointers, so we turn to  
> > documentation and experimentation. Consider strchr from the C standard  
> > library:
> > 
> > char \*strchr(const char \*s, int c);
> > 
> > It is “obvious” to a programmer who knows the semantics of strchr that  
> > it’s important to check for a returned null, because null is used as the  
> > sentinel for “not found”. Of course, your tools don’t know that, so they  
> > cannot help when you completely forget to check for the null case. Bugs  
> > ensue.
> > 
> > Can I pass a null string to strchr? The standard is unclear [2], and my  
> > platform’s implementation happily accepts a null parameter and returns  
> > null, so obviously I shouldn’t worry about it… until I port my code, or the  
> > underlying implementation changes because my expectations and the library  
> > implementor’s expectations differ. Given the age of strchr, I suspect that  
> > every implementation out there has an explicit, defensive check for a null  
> > string, because it’s easier to add yet more defensive (and generally  
> > useless) null checks than it is to ask your clients to fix their code.  
> > Scale this up, and code bloat ensues, as well as wasted programmer effort  
> > that obscures the places where checking for null really does matter.
> > 
> > In a recent version of Xcode, Apple introduced an extension to  
> > C/C++/Objective-C that expresses the nullability of pointers in the type  
> > system via new nullability qualifiers . Nullability qualifiers express  
> > nullability as part of the declaration of strchr [2]:
> > 
> > \_\_nullable char \*strchr(\_\_nonnull const char \*s, int c);
> > 
> > With this, programmers and tools alike can better reason about the use of  
> > strchr with null pointers.
> > 
> > We’d like to contribute the implementation (and there is a patch attached  
> > at the end [3]), but since this is a nontrivial extension to all of the C  
> > family of languages that Clang supports, we believe that it needs to be  
> > discussed here first.
> > 
> > \*Goals\*  
> > We have several specific goals that informed the design of this feature.
> > 
> > &nbsp;&nbsp;&nbsp;- \*Allow the intended nullability to be expressed on all pointers\*:  
> > &nbsp;&nbsp;&nbsp;Pointers are used throughout library interfaces, and the nullability of  
> > &nbsp;&nbsp;&nbsp;those pointers is an important part of the API contract with users. It’s  
> > &nbsp;&nbsp;&nbsp;too simplistic to only allow function parameters to have nullability, for  
> > &nbsp;&nbsp;&nbsp;example, because it’s also important information for data members,  
> > &nbsp;&nbsp;&nbsp;pointers-to-pointers (e.g., "a nonnull pointer to a nullable pointer to an  
> > &nbsp;&nbsp;&nbsp;integer”), arrays of pointers, etc.  
> > &nbsp;&nbsp;&nbsp;- \*Enable better tools support for detecting nullability problems:\* The  
> > &nbsp;&nbsp;&nbsp;nullability annotations should be useful for tools (especially the static  
> > &nbsp;&nbsp;&nbsp;analyzer) that can reason about the use of null, to give warnings about  
> > &nbsp;&nbsp;&nbsp;both missed null checks (the result of strchr could be null…) as well as  
> > &nbsp;&nbsp;&nbsp;for unnecessarily-defensive code.  
> > &nbsp;&nbsp;&nbsp;- \*Support workflows where all interfaces provide nullability  
> > &nbsp;&nbsp;&nbsp;annotations:\* In moving from a world where there are no nullability  
> > &nbsp;&nbsp;&nbsp;annotations to one where we hope to see many such annotations, we’ve found  
> > &nbsp;&nbsp;&nbsp;it helpful to move header-by-header, auditing a complete header to give it  
> > &nbsp;&nbsp;&nbsp;nullability qualifiers. Once one has done that, additions to the header  
> > &nbsp;&nbsp;&nbsp;need to be held to the same standard, so we need a design that allows us to  
> > &nbsp;&nbsp;&nbsp;warn about pointers that don’t provide nullability annotations for some  
> > &nbsp;&nbsp;&nbsp;declarations in a header that already has some nullability annotations.
> > 
> > &nbsp;&nbsp;&nbsp;- \*Zero effect on ABI or code generation:\* There are a huge number of  
> > &nbsp;&nbsp;&nbsp;interfaces that could benefit from the use of nullability qualifiers, but  
> > &nbsp;&nbsp;&nbsp;we won’t get widespread adoption if introducing the nullability qualifiers  
> > &nbsp;&nbsp;&nbsp;means breaking existing code, either in the ABI (say, because nullability  
> > &nbsp;&nbsp;&nbsp;qualifiers are mangled into the type) or at execution time (e.g., because a  
> > &nbsp;&nbsp;&nbsp;non-null pointer ends up being null along some error path and causes  
> > &nbsp;&nbsp;&nbsp;undefined behavior).
> > 
> > A sanitizer for this feature would seem very useful, but this bullet
> 
> point suggests that such a sanitizer would violate the model. Likewise, I  
> don't see why we should rule out the option of optimizing on the basis of  
> these qualifiers (under a -fstrict-nonnull flag or similar).
> 
> I agree that a sanitizer would be useful as a debugging aid. My primary  
> concern here is that optimizing based on this information \*not\* be a part  
> of any normal optimization flag (-O2, -Os, whatever), because it will  
> hamper widespread adoption of this feature if adding the annotations to  
> indicate the API contract suddenly starts breaking existing clients by,  
> e.g., optimizing out existing, defensive null checks.
> 
> > \*Why not \_\_attribute\_\_((nonnull))?\*  
> > Clang already has an attribute to express nullability, “nonnull”, which  
> > we inherited from GCC [4]. The “nonnull” attribute can be placed on  
> > functions to indicate which parameters cannot be null: one either specifies  
> > the indices of the arguments that cannot be null, e.g.,
> > 
> > &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull (1, 2)));
> > 
> > or omits the list of indices to state that all pointer arguments cannot  
> > be null, e.g.,
> > 
> > &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull));
> > 
> > More recently, “nonnull” has grown the ability to be applied to  
> > parameters, and one can use the companion attribute returns\_nonnull to  
> > state that a function returns a non-null pointer:
> > 
> > &nbsp;&nbsp;extern void \*my\_memcpy (\_\_attribute\_\_((nonnull)) void \*dest, \_\_attribute\_\_((nonnull)) const void \*src, size\_t len) \_\_attribute\_\_((returns\_nonnull));
> > 
> > There are a number of problems here. First, there are different  
> > attributes to express the same idea at different places in the grammar, and  
> > the use of the “nonnull” attribute \*on the function\* actually has an  
> > effect \*on the function parameters\* can get very, very confusing. Quick,  
> > which pointers are nullable vs. non-null in this example?
> > 
> > \_\_attribute\_\_((nonnull)) void \*my\_realloc (void \*ptr, size\_t size);
> > 
> > According to that declaration, ptr is nonnull and the function returns a  
> > nullable pointer… but that’s the opposite of how it reads (and behaves, if  
> > this is anything like a realloc that cannot fail). Moreover, because these  
> > two attributes are \*declaration\* attributes, not type attributes, you  
> > cannot express that nullability of the inner pointer in a multi-level  
> > pointer or an array of pointers, which makes these attributes verbose,  
> > confusing, and not sufficiently generally. These attributes fail the first  
> > of our goals.
> > 
> > These attributes aren’t as useful as they could be for tools support (the  
> > second and third goals), because they only express the nonnull case,  
> > leaving no way to distinguish between the unannotated case (nobody has  
> > documented the nullability of some parameter) and the nullable case (we  
> > know the pointer can be null). From a tooling perspective, this is a  
> > killer: the static analyzer absolutely cannot warn that one has forgotten  
> > to check for null for every unannotated pointer, because the false-positive  
> > rate would be astronomical.
> > 
> > Finally, we’ve recently started considering violations of the  
> > \_\_attribute\_\_((nonnull)) contract to be undefined behavior, which fails the  
> > last of our goals. This is something we could debate further if it were the  
> > only problem, but these declaration attributes fall all of our criteria, so  
> > it’s not worth discussing.
> > 
> > \*Nullability Qualifiers\*  
> > We propose the addition of a new set of type qualifiers, spelled  
> > \_\_nullable, \_\_nonnull, and \_\_null\_unspecified, to Clang. These are  
> > collectively known as \*nullability qualifiers\* and may be written  
> > anywhere any other type qualifier may be written (such as const) on any  
> > type subject to the following restrictions:
> > 
> > &nbsp;&nbsp;&nbsp;- Two nullability qualifiers shall not appear in the same set of  
> > &nbsp;&nbsp;&nbsp;qualifiers.  
> > &nbsp;&nbsp;&nbsp;- A nullability qualifier shall qualify any pointer type, including  
> > &nbsp;&nbsp;&nbsp;pointers to objects, pointers to functions, C++ pointers to members, block  
> > &nbsp;&nbsp;&nbsp;pointers, and Objective-C object pointers.  
> > &nbsp;&nbsp;&nbsp;- A nullability qualifier in the declaration-specifiers applies to  
> > &nbsp;&nbsp;&nbsp;the innermost pointer type of each declarator (e.g., \_\_nonnull int \* is  
> > &nbsp;&nbsp;&nbsp;equivalent to int \* \_\_nonnull).
> > 
> > What happens if there's a mixture of different kinds of declarator? (Can
> 
> I have '\_\_nonnull int (\*p)[3]'? Can I have '\_\_nonnull int \*p[3];'?)
> 
> I think you're saying that this decision is made based on the syntax of  
> the declarator and not based on the underlying type, right? (So in
> 
> &nbsp;&nbsp;\_\_nonnull T \*
> 
> the \_\_nonnull appertains to the \*, even if T names a pointer type.)
> 
> I’ve said it poorly. It is based on the type, so
> 
> \_\_nonnull T \*
> 
> applies \_\_nonnull to T unless T is a known type that is not a pointer  
> type. In the patch Type::canHaveNullability() computes the operation, and  
> essentially we apply the \_\_nonnull to T when:  
> - T is of pointer, C++ member pointer, block pointer, or Objective-C  
> object pointer  
> - T is a dependent type that could instantiate to some kind of pointer type

That seems like it could be very confusing:

&nbsp;&nbsp;void f(\_\_nonnull int \*p);

&nbsp;&nbsp;template\<typename Integral\>  
&nbsp;&nbsp;void f(\_\_nonnull Integral \*p);

... would apply the \_\_nonnull to different components of the type (and I  
don't even want to think about what happens when T is a member of the  
current instantiation). The outcome seems to be that people writing  
templates need to know about both ways of writing this, and they need to  
know the gotchas and the minutiae of the rules, and they need to be able to  
reason with precision about which types are dependent.

This is a problem in C too. Consider:

&nbsp;&nbsp;#include \<some\_library.h\> // vends an opaque\_t typedef  
&nbsp;&nbsp;void use\_library(\_\_nonnull opaque\_t \*handle);

We cannot know what this program means without depending on an  
implementation detail of some\_library.h. And this is not an exotic problem;  
consider, for instance, some\_library == stdio and opaque\_t == FILE.

> Given that...
> 
> > &nbsp;&nbsp;&nbsp;- A nullability qualifier applied to a typedef of a  
> > &nbsp;&nbsp;&nbsp;nullability-qualified pointer type shall specify the same nullability as  
> > &nbsp;&nbsp;&nbsp;the underlying type of the typedef.
> > 
> > ... I don't really see what this rule is for. I would expect "\_\_nonnull
> 
> T" to be ill-formed because the innermost component of the declarator is  
> not a pointer, irrespective of whether T is a pointer type and whether it's  
> nullable. And I'd expect "\_\_nonnull T \*" to be valid whether or not T is a  
> typedef for a \_\_nonnull pointer.
> 
> On the whole, I find it a little strange to allow a nullability qualifier  
> in the decl-specifier-seq / specifiers-and-qualifiers that applies to some  
> later pointer declarator; I would have expected this to be permitted in the  
> cv-qualifier-seq / type-qualifier-list after the pointer operator, and  
> nowhere else (or perhaps permitted in a decl-specifier-seq that also  
> contains a type-specifier for a pointer type).
> 
> It’s an attempt to make the simple cases read better, e.g., “\_\_nonnull int  
> \*” reads a whole lot better than “int \* \_\_nonnull” for most
> 
> This kind of flexibility has proven a disaster for the comprehensibility  
> of GCC's type attributes.
> 
> We haven’t seen a disaster, but we have seen some confusion with  
> multi-level pointers, because we have seen people try
> 
> \_\_nonnull int \* \_\_nullable \*
> 
> and scratch their heads when we complain about duplicate specifiers.
> 
> That said, the developers that have been using this feature have become  
> perhaps a little accustomed to writing type qualifiers in the  
> decl-specifier-seq that actually apply to the pointer, because the  
> Objective-C ARC qualifiers (\_\_weak, \_\_autoreleasing) do the same thing in a  
> more limited manner (that doesn’t run into the multi-level pointer  
> problem).

Based on your experience, how painful would it be to remove the  
'nullability qualifier on decl-specifier-seq gets implicitly rewritten to  
be somewhere else sometimes' rule?

> The meanings of the three nullability qualifiers are as follows:
> 
> > \_\_nullable: the pointer may store a null value at runtime (as part of  
> > the API contract)  
> > \_\_nonnull: the pointer should not store a null value at runtime (as part  
> > of the API contract). it is possible that the value can be null, e.g., in  
> > erroneous historic uses of an API, and it is up to the library implementor  
> > to decide to what degree she will accommodate such clients.  
> > \_\_null\_unspecified: it is unclear whether the pointer can be null or  
> > not. Use of this type qualifier is extremely rare in practice, but it fills  
> > a small but important niche when auditing a particular header to add  
> > nullability qualifiers: sometimes the nullability contract for a few APIs  
> > in the header is unclear \*even when looking at the implementation\* for  
> > historical reasons, and establishing the contract requires more extensive  
> > study. In such cases, it’s often best to mark that pointer as  
> > \_\_null\_unspecified (which will help silence the warning about unannotated  
> > pointers in a header) and move on, coming back to \_\_null\_unspecified  
> > pointers when the appropriate graybeard has been summoned out of retirement  
> > [5].
> 
> Have you considered adding C++11 attributes as synonyms for these?
> 
> I think it’s totally reasonable to add [[nullable]], [[nonnull]], and  
> [[null\_unspecified]]. If we feel that this feature is working out as we  
> hope, we can push for standardization.

These should be [[clang::blah]] until standardized, but otherwise that  
works for me.

---

<div class="post-metadata">

**Author:** ![Finkel\_Hal\_J](https://avatars.discourse-cdn.com/v4/letter/f/a9adbd/32.png) [@Finkel\_Hal\_J](https://discourse.llvm.org/u/Finkel_Hal_J)\
**Post date:** [March 4, 2015, 3:55am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/7 "2015-03-04T03:55:29Z")

</div>

> From: "Richard Smith" \<richard@metafoo.co.uk\>  
> To: "Douglas Gregor" \<dgregor@apple.com\>  
> Cc: "cfe-dev Developers" \<cfe-dev@cs.uiuc.edu\>  
> Sent: Monday, March 2, 2015 5:34:18 PM  
> Subject: Re: [cfe-dev] RFC: Nullability qualifiers

> \> Hello all,
> 
> \> Null pointers are a significant source of problems in applications.  
> \> Whether it’s SIGSEGV taking down a process or a foolhardy attempt  
> \> to  
> \> recover from NullPointerException breaking invariants everywhere,  
> \> it’s a problem that’s bad enough for Tony Hoare to call the  
> \> invention of the null reference his billion dollar mistake [1].  
> \> It’s  
> \> not the ability to create a null pointer that is a problem—having a  
> \> common sentinel value meaning “no value” is extremely useful—but  
> \> that it’s very hard to determine whether, for a particular pointer,  
> \> one is expected to be able to use null. C doesn’t distinguish  
> \> between “nullable” and “nonnull” pointers, so we turn to  
> \> documentation and experimentation. Consider strchr from the C  
> \> standard library:
> 
> \> char \*strchr(const char \*s, int c);
> 
> \> It is “obvious” to a programmer who knows the semantics of strchr  
> \> that it’s important to check for a returned null, because null is  
> \> used as the sentinel for “not found”. Of course, your tools don’t  
> \> know that, so they cannot help when you completely forget to check  
> \> for the null case. Bugs ensue.
> 
> \> Can I pass a null string to strchr? The standard is unclear [2],  
> \> and  
> \> my platform’s implementation happily accepts a null parameter and  
> \> returns null, so obviously I shouldn’t worry about it… until I port  
> \> my code, or the underlying implementation changes because my  
> \> expectations and the library implementor’s expectations differ.  
> \> Given the age of strchr, I suspect that every implementation out  
> \> there has an explicit, defensive check for a null string, because  
> \> it’s easier to add yet more defensive (and generally useless) null  
> \> checks than it is to ask your clients to fix their code. Scale this  
> \> up, and code bloat ensues, as well as wasted programmer effort that  
> \> obscures the places where checking for null really does matter.
> 
> \> In a recent version of Xcode, Apple introduced an extension to  
> \> C/C++/Objective-C that expresses the nullability of pointers in the  
> \> type system via new nullability qualifiers . Nullability qualifiers  
> \> express nullability as part of the declaration of strchr [2]:
> 
> \> \_\_nullable char \*strchr(\_\_nonnull const char \*s, int c);
> 
> \> With this, programmers and tools alike can better reason about the  
> \> use of strchr with null pointers.
> 
> \> We’d like to contribute the implementation (and there is a patch  
> \> attached at the end [3]), but since this is a nontrivial extension  
> \> to all of the C family of languages that Clang supports, we believe  
> \> that it needs to be discussed here first.
> 
> \> Goals
> 
> \> We have several specific goals that informed the design of this  
> \> feature.
> 
> \> \* Allow the intended nullability to be expressed on all pointers :  
> \> Pointers are used throughout library interfaces, and the  
> \> nullability  
> \> of those pointers is an important part of the API contract with  
> \> users. It’s too simplistic to only allow function parameters to  
> \> have  
> \> nullability, for example, because it’s also important information  
> \> for data members, pointers-to-pointers (e.g., "a nonnull pointer to  
> \> a nullable pointer to an integer”), arrays of pointers, etc.
> 
> \> \* Enable better tools support for detecting nullability problems:  
> \> The  
> \> nullability annotations should be useful for tools (especially the  
> \> static analyzer) that can reason about the use of null, to give  
> \> warnings about both missed null checks (the result of strchr could  
> \> be null…) as well as for unnecessarily-defensive code.
> 
> \> \* Support workflows where all interfaces provide nullability  
> \> annotations: In moving from a world where there are no nullability  
> \> annotations to one where we hope to see many such annotations,  
> \> we’ve  
> \> found it helpful to move header-by-header, auditing a complete  
> \> header to give it nullability qualifiers. Once one has done that,  
> \> additions to the header need to be held to the same standard, so we  
> \> need a design that allows us to warn about pointers that don’t  
> \> provide nullability annotations for some declarations in a header  
> \> that already has some nullability annotations.
> 
> \> \* Zero effect on ABI or code generation: There are a huge number of  
> \> interfaces that could benefit from the use of nullability  
> \> qualifiers, but we won’t get widespread adoption if introducing the  
> \> nullability qualifiers means breaking existing code, either in the  
> \> ABI (say, because nullability qualifiers are mangled into the type)  
> \> or at execution time (e.g., because a non-null pointer ends up  
> \> being  
> \> null along some error path and causes undefined behavior).
> 
> A sanitizer for this feature would seem very useful, but this bullet  
> point suggests that such a sanitizer would violate the model.  
> Likewise, I don't see why we should rule out the option of  
> optimizing on the basis of these qualifiers (under a  
> -fstrict-nonnull flag or similar).

> \> Why not \_\_attribute\_\_((nonnull))?
> 
> \> Clang already has an attribute to express nullability, “nonnull”,  
> \> which we inherited from GCC [4]. The “nonnull” attribute can be  
> \> placed on functions to indicate which parameters cannot be null:  
> \> one  
> \> either specifies the indices of the arguments that cannot be null,  
> \> e.g.,
> 
> \> extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len)  
> \> \_\_attribute\_\_((nonnull (1, 2)));
> 
> \> or omits the list of indices to state that all pointer arguments  
> \> cannot be null, e.g.,
> 
> \> extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len)  
> \> \_\_attribute\_\_((nonnull));
> 
> \> More recently, “nonnull” has grown the ability to be applied to  
> \> parameters, and one can use the companion attribute returns\_nonnull  
> \> to state that a function returns a non-null pointer:
> 
> \> extern void \*my\_memcpy (\_\_attribute\_\_((nonnull)) void \*dest,  
> \> \_\_attribute\_\_((nonnull)) const void \*src, size\_t len)  
> \> \_\_attribute\_\_((returns\_nonnull));
> 
> \> There are a number of problems here. First, there are different  
> \> attributes to express the same idea at different places in the  
> \> grammar, and the use of the “nonnull” attribute on the function  
> \> actually has an effect on the function parameters can get very,  
> \> very  
> \> confusing. Quick, which pointers are nullable vs. non-null in this  
> \> example?
> 
> \> \_\_attribute\_\_((nonnull)) void \*my\_realloc (void \*ptr, size\_t size);
> 
> \> According to that declaration, ptr is nonnull and the function  
> \> returns a nullable pointer… but that’s the opposite of how it reads  
> \> (and behaves, if this is anything like a realloc that cannot fail).  
> \> Moreover, because these two attributes are declaration attributes,  
> \> not type attributes, you cannot express that nullability of the  
> \> inner pointer in a multi-level pointer or an array of pointers,  
> \> which makes these attributes verbose, confusing, and not  
> \> sufficiently generally. These attributes fail the first of our  
> \> goals.
> 
> \> These attributes aren’t as useful as they could be for tools  
> \> support  
> \> (the second and third goals), because they only express the nonnull  
> \> case, leaving no way to distinguish between the unannotated case  
> \> (nobody has documented the nullability of some parameter) and the  
> \> nullable case (we know the pointer can be null). From a tooling  
> \> perspective, this is a killer: the static analyzer absolutely  
> \> cannot  
> \> warn that one has forgotten to check for null for every unannotated  
> \> pointer, because the false-positive rate would be astronomical.
> 
> \> Finally, we’ve recently started considering violations of the  
> \> \_\_attribute\_\_((nonnull)) contract to be undefined behavior, which  
> \> fails the last of our goals. This is something we could debate  
> \> further if it were the only problem, but these declaration  
> \> attributes fall all of our criteria, so it’s not worth discussing.

On this last point, how do you want to define the interaction between these? Should we not consider the violation to be undefined behavior if these new qualifiers are present?

-Hal

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 4, 2015, 7:51pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/8 "2015-03-04T19:51:49Z")

</div>

> * * *
> 
> > **From:** “Richard Smith” \<[richard@metafoo.co.uk](mailto:richard@metafoo.co.uk)\>  
> > **To:** “Douglas Gregor” \<[dgregor@apple.com](mailto:dgregor@apple.com)\>  
> > **Cc:** “cfe-dev Developers” \<[cfe-dev@cs.uiuc.edu](mailto:cfe-dev@cs.uiuc.edu)\>  
> > **Sent:** Monday, March 2, 2015 5:34:18 PM  
> > **Subject:** Re: [cfe-dev] RFC: Nullability qualifiers
> 
> On this last point, how do you want to define the interaction between these? Should we not consider the violation to be undefined behavior if these new qualifiers are present?

I think we should continue to say that the existing nonnull attributes require nonnull values (UB if a null gets in there). The type qualifiers will not.

Moreover, we should have the existing nonnull/returns\_nonnull attributes imply \_\_nonnull, since we’ll get more utility out of existing annotations with way.

- Doug

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 4, 2015, 8:02pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/9 "2015-03-04T20:02:32Z")

</div>

> 

Yes, that’s a good point. The warning about missing nullability annotations in headers, as well as the fact that this feature has only been deployed on one platform, probably accounts for the lack of reports of actual confusion caused by this.

> 

It will be painful, but we think we can do it. We’ll investigate further.

---

<div class="post-metadata">

**Author:** ![\_sean\_silva](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/_sean_silva/32/166_2.png) [@\_sean\_silva](https://discourse.llvm.org/u/_sean_silva)\
**Post date:** [March 5, 2015, 3:23am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/10 "2015-03-05T03:23:48Z")

</div>

> > > Hello all,
> > > 
> > > Null pointers are a significant source of problems in applications.  
> > > Whether it’s SIGSEGV taking down a process or a foolhardy attempt to  
> > > recover from NullPointerException breaking invariants everywhere, it’s a  
> > > problem that’s bad enough for Tony Hoare to call the invention of the null  
> > > reference his billion dollar mistake [1]. It’s not the ability to create a  
> > > null pointer that is a problem—having a common sentinel value meaning “no  
> > > value” is extremely useful—but that it’s very hard to determine whether,  
> > > for a particular pointer, one is expected to be able to use null. C doesn’t  
> > > distinguish between “nullable” and “nonnull” pointers, so we turn to  
> > > documentation and experimentation. Consider strchr from the C standard  
> > > library:
> > > 
> > > char \*strchr(const char \*s, int c);
> > > 
> > > It is “obvious” to a programmer who knows the semantics of strchr that  
> > > it’s important to check for a returned null, because null is used as the  
> > > sentinel for “not found”. Of course, your tools don’t know that, so they  
> > > cannot help when you completely forget to check for the null case. Bugs  
> > > ensue.
> > > 
> > > Can I pass a null string to strchr? The standard is unclear [2], and my  
> > > platform’s implementation happily accepts a null parameter and returns  
> > > null, so obviously I shouldn’t worry about it… until I port my code, or the  
> > > underlying implementation changes because my expectations and the library  
> > > implementor’s expectations differ. Given the age of strchr, I suspect that  
> > > every implementation out there has an explicit, defensive check for a null  
> > > string, because it’s easier to add yet more defensive (and generally  
> > > useless) null checks than it is to ask your clients to fix their code.  
> > > Scale this up, and code bloat ensues, as well as wasted programmer effort  
> > > that obscures the places where checking for null really does matter.
> > > 
> > > In a recent version of Xcode, Apple introduced an extension to  
> > > C/C++/Objective-C that expresses the nullability of pointers in the type  
> > > system via new nullability qualifiers . Nullability qualifiers express  
> > > nullability as part of the declaration of strchr [2]:
> > > 
> > > \_\_nullable char \*strchr(\_\_nonnull const char \*s, int c);
> > > 
> > > With this, programmers and tools alike can better reason about the use  
> > > of strchr with null pointers.
> > > 
> > > We’d like to contribute the implementation (and there is a patch  
> > > attached at the end [3]), but since this is a nontrivial extension to all  
> > > of the C family of languages that Clang supports, we believe that it needs  
> > > to be discussed here first.
> > > 
> > > \*Goals\*  
> > > We have several specific goals that informed the design of this feature.
> > > 
> > > &nbsp;&nbsp;&nbsp;- \*Allow the intended nullability to be expressed on all pointers\*:  
> > > &nbsp;&nbsp;&nbsp;Pointers are used throughout library interfaces, and the nullability of  
> > > &nbsp;&nbsp;&nbsp;those pointers is an important part of the API contract with users. It’s  
> > > &nbsp;&nbsp;&nbsp;too simplistic to only allow function parameters to have nullability, for  
> > > &nbsp;&nbsp;&nbsp;example, because it’s also important information for data members,  
> > > &nbsp;&nbsp;&nbsp;pointers-to-pointers (e.g., "a nonnull pointer to a nullable pointer to an  
> > > &nbsp;&nbsp;&nbsp;integer”), arrays of pointers, etc.  
> > > &nbsp;&nbsp;&nbsp;- \*Enable better tools support for detecting nullability problems:\* The  
> > > &nbsp;&nbsp;&nbsp;nullability annotations should be useful for tools (especially the static  
> > > &nbsp;&nbsp;&nbsp;analyzer) that can reason about the use of null, to give warnings about  
> > > &nbsp;&nbsp;&nbsp;both missed null checks (the result of strchr could be null…) as well as  
> > > &nbsp;&nbsp;&nbsp;for unnecessarily-defensive code.  
> > > &nbsp;&nbsp;&nbsp;- \*Support workflows where all interfaces provide nullability  
> > > &nbsp;&nbsp;&nbsp;annotations:\* In moving from a world where there are no nullability  
> > > &nbsp;&nbsp;&nbsp;annotations to one where we hope to see many such annotations, we’ve found  
> > > &nbsp;&nbsp;&nbsp;it helpful to move header-by-header, auditing a complete header to give it  
> > > &nbsp;&nbsp;&nbsp;nullability qualifiers. Once one has done that, additions to the header  
> > > &nbsp;&nbsp;&nbsp;need to be held to the same standard, so we need a design that allows us to  
> > > &nbsp;&nbsp;&nbsp;warn about pointers that don’t provide nullability annotations for some  
> > > &nbsp;&nbsp;&nbsp;declarations in a header that already has some nullability annotations.
> > > 
> > > &nbsp;&nbsp;&nbsp;- \*Zero effect on ABI or code generation:\* There are a huge number  
> > > &nbsp;&nbsp;&nbsp;of interfaces that could benefit from the use of nullability qualifiers,  
> > > &nbsp;&nbsp;&nbsp;but we won’t get widespread adoption if introducing the nullability  
> > > &nbsp;&nbsp;&nbsp;qualifiers means breaking existing code, either in the ABI (say, because  
> > > &nbsp;&nbsp;&nbsp;nullability qualifiers are mangled into the type) or at execution time  
> > > &nbsp;&nbsp;&nbsp;(e.g., because a non-null pointer ends up being null along some error path  
> > > &nbsp;&nbsp;&nbsp;and causes undefined behavior).
> > > 
> > > A sanitizer for this feature would seem very useful, but this bullet
> > 
> > point suggests that such a sanitizer would violate the model. Likewise, I  
> > don't see why we should rule out the option of optimizing on the basis of  
> > these qualifiers (under a -fstrict-nonnull flag or similar).
> > 
> > I agree that a sanitizer would be useful as a debugging aid. My primary  
> > concern here is that optimizing based on this information \*not\* be a  
> > part of any normal optimization flag (-O2, -Os, whatever), because it will  
> > hamper widespread adoption of this feature if adding the annotations to  
> > indicate the API contract suddenly starts breaking existing clients by,  
> > e.g., optimizing out existing, defensive null checks.
> > 
> > > \*Why not \_\_attribute\_\_((nonnull))?\*  
> > > Clang already has an attribute to express nullability, “nonnull”, which  
> > > we inherited from GCC [4]. The “nonnull” attribute can be placed on  
> > > functions to indicate which parameters cannot be null: one either specifies  
> > > the indices of the arguments that cannot be null, e.g.,
> > > 
> > > &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull (1, 2)));
> > > 
> > > or omits the list of indices to state that all pointer arguments cannot  
> > > be null, e.g.,
> > > 
> > > &nbsp;&nbsp;extern void \*my\_memcpy (void \*dest, const void \*src, size\_t len) \_\_attribute\_\_((nonnull));
> > > 
> > > More recently, “nonnull” has grown the ability to be applied to  
> > > parameters, and one can use the companion attribute returns\_nonnull to  
> > > state that a function returns a non-null pointer:
> > > 
> > > &nbsp;&nbsp;extern void \*my\_memcpy (\_\_attribute\_\_((nonnull)) void \*dest, \_\_attribute\_\_((nonnull)) const void \*src, size\_t len) \_\_attribute\_\_((returns\_nonnull));
> > > 
> > > There are a number of problems here. First, there are different  
> > > attributes to express the same idea at different places in the grammar, and  
> > > the use of the “nonnull” attribute \*on the function\* actually has an  
> > > effect \*on the function parameters\* can get very, very confusing.  
> > > Quick, which pointers are nullable vs. non-null in this example?
> > > 
> > > \_\_attribute\_\_((nonnull)) void \*my\_realloc (void \*ptr, size\_t size);
> > > 
> > > According to that declaration, ptr is nonnull and the function returns a  
> > > nullable pointer… but that’s the opposite of how it reads (and behaves, if  
> > > this is anything like a realloc that cannot fail). Moreover, because these  
> > > two attributes are \*declaration\* attributes, not type attributes, you  
> > > cannot express that nullability of the inner pointer in a multi-level  
> > > pointer or an array of pointers, which makes these attributes verbose,  
> > > confusing, and not sufficiently generally. These attributes fail the first  
> > > of our goals.
> > > 
> > > These attributes aren’t as useful as they could be for tools support  
> > > (the second and third goals), because they only express the nonnull case,  
> > > leaving no way to distinguish between the unannotated case (nobody has  
> > > documented the nullability of some parameter) and the nullable case (we  
> > > know the pointer can be null). From a tooling perspective, this is a  
> > > killer: the static analyzer absolutely cannot warn that one has forgotten  
> > > to check for null for every unannotated pointer, because the false-positive  
> > > rate would be astronomical.
> > > 
> > > Finally, we’ve recently started considering violations of the  
> > > \_\_attribute\_\_((nonnull)) contract to be undefined behavior, which fails the  
> > > last of our goals. This is something we could debate further if it were the  
> > > only problem, but these declaration attributes fall all of our criteria, so  
> > > it’s not worth discussing.
> > > 
> > > \*Nullability Qualifiers\*  
> > > We propose the addition of a new set of type qualifiers, spelled  
> > > \_\_nullable, \_\_nonnull, and \_\_null\_unspecified, to Clang. These are  
> > > collectively known as \*nullability qualifiers\* and may be written  
> > > anywhere any other type qualifier may be written (such as const) on any  
> > > type subject to the following restrictions:
> > > 
> > > &nbsp;&nbsp;&nbsp;- Two nullability qualifiers shall not appear in the same set of  
> > > &nbsp;&nbsp;&nbsp;qualifiers.  
> > > &nbsp;&nbsp;&nbsp;- A nullability qualifier shall qualify any pointer type, including  
> > > &nbsp;&nbsp;&nbsp;pointers to objects, pointers to functions, C++ pointers to members, block  
> > > &nbsp;&nbsp;&nbsp;pointers, and Objective-C object pointers.  
> > > &nbsp;&nbsp;&nbsp;- A nullability qualifier in the declaration-specifiers applies to  
> > > &nbsp;&nbsp;&nbsp;the innermost pointer type of each declarator (e.g., \_\_nonnull int \* is  
> > > &nbsp;&nbsp;&nbsp;equivalent to int \* \_\_nonnull).
> > > 
> > > What happens if there's a mixture of different kinds of declarator? (Can
> > 
> > I have '\_\_nonnull int (\*p)[3]'? Can I have '\_\_nonnull int \*p[3];'?)
> > 
> > I think you're saying that this decision is made based on the syntax of  
> > the declarator and not based on the underlying type, right? (So in
> > 
> > &nbsp;&nbsp;\_\_nonnull T \*
> > 
> > the \_\_nonnull appertains to the \*, even if T names a pointer type.)
> > 
> > I’ve said it poorly. It is based on the type, so
> > 
> > \_\_nonnull T \*
> > 
> > applies \_\_nonnull to T unless T is a known type that is not a pointer  
> > type. In the patch Type::canHaveNullability() computes the operation, and  
> > essentially we apply the \_\_nonnull to T when:  
> > - T is of pointer, C++ member pointer, block pointer, or Objective-C  
> > object pointer  
> > - T is a dependent type that could instantiate to some kind of pointer  
> > type
> 
> That seems like it could be very confusing:
> 
> &nbsp;&nbsp;void f(\_\_nonnull int \*p);
> 
> &nbsp;&nbsp;template\<typename Integral\>  
> &nbsp;&nbsp;void f(\_\_nonnull Integral \*p);
> 
> ... would apply the \_\_nonnull to different components of the type (and I  
> don't even want to think about what happens when T is a member of the  
> current instantiation). The outcome seems to be that people writing  
> templates need to know about both ways of writing this, and they need to  
> know the gotchas and the minutiae of the rules, and they need to be able to  
> reason with precision about which types are dependent.
> 
> This is a problem in C too. Consider:
> 
> &nbsp;&nbsp;#include \<some\_library.h\> // vends an opaque\_t typedef  
> &nbsp;&nbsp;void use\_library(\_\_nonnull opaque\_t \*handle);
> 
> We cannot know what this program means without depending on an  
> implementation detail of some\_library.h. And this is not an exotic problem;  
> consider, for instance, some\_library == stdio and opaque\_t == FILE.

Random idea: could we bootstrap on programmer's knowledge of of const and  
volatile and have the rule be "\_\_nonnull \<something\>" applies to the  
pointer that points to the const thing in "const \<something\>"? Since cv are  
eligible for template specialization and nullability-qualifiers aren't,  
maybe that just trades-off for another inconsistency?

-- Sean Silva

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 5, 2015, 4:09am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/11 "2015-03-05T04:09:13Z")

</div>

Personally, I feel like we shouldn’t conflate constness with nullability, because they’re really orthogonal notions. Plus, Richard has convinced me that we shouldn’t move the nullability qualifiers away from the decl-specifiers.

- Doug

---

<div class="post-metadata">

**Author:** ![Marshall\_Clow1](https://avatars.discourse-cdn.com/v4/letter/m/58f4c7/32.png) [@Marshall\_Clow1](https://discourse.llvm.org/u/Marshall_Clow1)\
**Post date:** [March 5, 2015, 2:51pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/12 "2015-03-05T14:51:54Z")

</div>

I think that these would be great.  
(along with a sanitizer)

— Marshall

---

<div class="post-metadata">

**Author:** ![Marshall\_Clow1](https://avatars.discourse-cdn.com/v4/letter/m/58f4c7/32.png) [@Marshall\_Clow1](https://discourse.llvm.org/u/Marshall_Clow1)\
**Post date:** [March 5, 2015, 3:05pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/13 "2015-03-05T15:05:28Z")

</div>

I’m pretty sure that you know this, Doug, but:

gcc already does (some of) this kind of stuff, and they _absolutely_ use it in their codegen decisions.

consider the following (simplified, fanciful) code:

char global[1000];

char \*foo (char \*p, size\_t sz)  
{  
// stash a copy away  
memcpy(global, p, sz);

if (p == NULL)  
p = (char \*) malloc(100);  
return p;  
}

char \*p2 = NULL;  
char \*p3 = foo(p2, 0);

After executing this code, what will the value of ‘p3’ be?  
Under gcc/glibc, it will be NULL, because memcpy is marked with “non-null” attributes, and so the “if (p==NULL)” branch is removed.  
(Yes, even though memcpy(x, y, 0) will not dereference the pointer)

— Marshall

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [March 9, 2015, 6:08am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/14 "2015-03-09T06:08:06Z")

</div>

So, we’re going to remove the ability for a nullability qualifier written in the decl-specifiers to move to a pointer/block/member pointer declarator. To aid our own transition, I’ll commit it as a warning (in its own, unique warning group) set to DefaultError that has a proper Fix-It, and once the transition is complete, we’ll change it to an error.

Thanks for all the helpful feedback!

- Doug

---

<div class="post-metadata">

**Author:** ![DougGregor](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/douggregor/32/17273_2.png) [@DougGregor](https://discourse.llvm.org/u/DougGregor)\
**Post date:** [June 24, 2015, 8:39pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/15 "2015-06-24T20:39:02Z")

</div>

Another addendum: due to the conflict with glibc’s \_\_nonnull, we’ll be renaming the \_\_double\_underscored keywords to \_Big\_underscored keywords, e.g.,

\_\_nonnull → \_Nonnull  
\_\_nullable → \_Nullable  
\_\_null\_unspecified → \_Null\_unspecified

On Darwin, we’ll add predefines

#define \_\_nonnull \_Nonnull  
#define \_\_nullable \_Nullable  
#define \_\_null\_unspecified \_Null\_unspecified

to keep the existing headers working.

- Doug

---

<div class="post-metadata">

**Author:** ![Joerg\_Sonnenberger1](https://avatars.discourse-cdn.com/v4/letter/j/839c29/32.png) [@Joerg\_Sonnenberger1](https://discourse.llvm.org/u/Joerg_Sonnenberger1)\
**Post date:** [June 24, 2015, 9:25pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/16 "2015-06-24T21:25:50Z")

</div>

Thanks for that.

Joerg

---

<div class="post-metadata">

**Author:** ![davidchisnall](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/davidchisnall/32/13533_2.png) [@davidchisnall](https://discourse.llvm.org/u/davidchisnall)\
**Post date:** [June 25, 2015, 9:01am UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/17 "2015-06-25T09:01:02Z")

</div>

Has anyone proposed these to WG14? They seem like they’d be good additions to the C standard and, if nothing else, it would be good to make sure that the next C standard doesn’t use the same spelling for something subtly different.

David

---

<div class="post-metadata">

**Author:** ![Kal](https://avatars.discourse-cdn.com/v4/letter/k/9de053/32.png) [@Kal](https://discourse.llvm.org/u/Kal)\
**Post date:** [June 26, 2015, 9:36pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/18 "2015-06-26T21:36:37Z")

</div>

How can one detect if an Apple clang supports the new nullability attributes. I tried something like:

#if \_\_has\_attribute(\_Nonnull)  
#elif \_\_has\_attribute(\_\_nonnull)  
#define \_Nonnull \_\_nonnull  
#else  
#define \_Nonnull  
#endif

But this didn’t work. Why doesn’t \_Nonnull/\_\_nonnull work with \_\_has\_attribute?

---

<div class="post-metadata">

**Author:** ![AaronBallman](https://sea1.discourse-cdn.com/flex021/user_avatar/discourse.llvm.org/aaronballman/32/13680_2.png) [@AaronBallman](https://discourse.llvm.org/u/AaronBallman)\
**Post date:** [June 26, 2015, 9:40pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/19 "2015-06-26T21:40:51Z")

</div>

> How can one detect if an Apple clang supports the new nullability  
> attributes. I tried something like:
> 
> #if \_\_has\_attribute(\_Nonnull)  
> #elif \_\_has\_attribute(\_\_nonnull)  
> #define \_Nonnull \_\_nonnull  
> #else  
> #define \_Nonnull  
> #endif
> 
> But this didn't work. Why doesn't \_Nonnull/\_\_nonnull work with  
> \_\_has\_attribute?

\_\_has\_attribute is used to test for GNU-style attribute support only.  
To test for nullability, you should use: \_\_has\_feature(nullability)

~Aaron

---

<div class="post-metadata">

**Author:** ![Kal](https://avatars.discourse-cdn.com/v4/letter/k/9de053/32.png) [@Kal](https://discourse.llvm.org/u/Kal)\
**Post date:** [June 26, 2015, 9:44pm UTC](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672/20 "2015-06-26T21:44:31Z")

</div>

OK. What would be the best way to detect if Apple clang supports \_Nonnull or only \_\_nonnull though.

[Next page](https://discourse.llvm.org/t/rfc-nullability-qualifiers/35672.md?page=2)
