797 changes: 692 additions & 105 deletions clang/docs/AttributeReference.rst

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -950,30 +950,30 @@ def NonNull : InheritableAttr {
} }];
// FIXME: We should merge duplicates into a single nonnull attribute.
let DuplicatesAllowedWhileMerging = 1;
let Documentation = [Undocumented];
let Documentation = [NonNullDocs];
}

def ReturnsNonNull : InheritableAttr {
let Spellings = [GCC<"returns_nonnull">];
let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
"ExpectedFunctionOrMethod">;
let Documentation = [Undocumented];
let Documentation = [ReturnsNonNullDocs];
}

// Nullability type attributes.
def TypeNonNull : TypeAttr {
let Spellings = [Keyword<"__nonnull">];
let Documentation = [Undocumented];
let Documentation = [TypeNonNullDocs];
}

def TypeNullable : TypeAttr {
let Spellings = [Keyword<"__nullable">];
let Documentation = [Undocumented];
let Documentation = [TypeNullableDocs];
}

def TypeNullUnspecified : TypeAttr {
let Spellings = [Keyword<"__null_unspecified">];
let Documentation = [Undocumented];
let Documentation = [TypeNullUnspecifiedDocs];
}

def AssumeAligned : InheritableAttr {
Expand Down
111 changes: 111 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1448,3 +1448,114 @@ private address space. Kernel function arguments of a pointer or an array type
cannot point to the private address space.
}];
}

def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> {
let Content = [{
Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``__nullable``) or cannot be null (``__nonnull``).

The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``__nullable`` qualifier), doesn't have a defined meaning for null (the ``__nonnull`` qualifier), or for which the purpose of null is unclear (the ``__null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:

.. code-block:: c

// No meaningful result when 'ptr' is null (here, it happens to be undefined behavior).
int fetch(int * __nonnull ptr) { return *ptr; }

// 'ptr' may be null.
int fetch_or_zero(int * __nullable ptr) {
return ptr ? *ptr : 0;
}

// A nullable pointer to non-null pointers to const characters.
const char *join_strings(const char * __nonnull * __nullable strings, unsigned n);

In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example:

.. code-block:: objective-c

@interface NSView : NSResponder
- (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView;
@property (assign, nullable) NSView *superview;
@property (readonly, nonnull) NSArray *subviews;
@end
}];
}

def TypeNonNullDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__nonnull";
let Content = [{
The ``__nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``__nonnull`` pointer type. For example, given a declaration such as:

.. code-block:: c

int fetch(int * __nonnull ptr);

a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``__nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.
}];
}

def TypeNullableDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__nullable";
let Content = [{
The ``__nullable`` nullability qualifier indicates that a value of the ``__nullable`` pointer type can be null. For example, given:

.. code-block:: c

int fetch_or_zero(int * __nullable ptr);

a caller of ``fetch_or_zero`` can provide null.
}];
}

def TypeNullUnspecifiedDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__null_unspecified";
let Content = [{
The ``__null_unspecified`` nullability qualifier indicates that neither the ``__nonnull`` nor ``__nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
}];
}

def NonNullDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "nonnull";
let Content = [{
The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example:

.. code-block:: c

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

Here, the ``nonnull`` attribute indicates that parameters 1 and 2
cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null:

.. code-block:: c

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

Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example:

.. code-block:: c

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

Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``__nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable.
}];
}

def ReturnsNonNullDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "returns_nonnull";
let Content = [{
The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer:

.. code-block:: c

extern void * malloc (size_t size) __attribute__((returns_nonnull));

The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``__nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
}];
}