diff options
author | Alejandro Colomar <alx.manpages@gmail.com> | 2021-11-15 16:47:54 +0100 |
---|---|---|
committer | Alejandro Colomar <alx.manpages@gmail.com> | 2021-11-15 16:47:54 +0100 |
commit | 383870120327f93fcbe1a9bdafb39d5103ace9ee (patch) | |
tree | 5e61f13241274268288a7fcd74df84b43bf87dd9 |
nonnull.7: Initial draft
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
-rw-r--r-- | nonnull.7 | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/nonnull.7 b/nonnull.7 new file mode 100644 index 0000000..1ba0218 --- /dev/null +++ b/nonnull.7 @@ -0,0 +1,228 @@ +.TH nonnull 3 2021-11-15 C3X Nxxxx +.SH NAME +nonnull \- non-null pointer +.SH SYNOPSIS +.nf +.I type-qualifier: +.B " const" +.B " nonnull" +.B " restrict" +.B " volatile" +.B " _Atomic" +.fi +.SH DESCRIPTION +.SS Constraints +Types other than pointer types +shall not be +.BR \%nonnull -qualified. +.SS Semantics +The properties associated with qualified types are meaningfull +only for expressions that are lvalues. +.PP +If the same qualifier appears more than once +in the same specifier-qualifier list +or as declaration specifiers, +either directly or via one or more +.BR typedef s, +the behavior is the same as if it appeared only once. +If other qualifiers appear along with the +.B \%_Atomic +qualifier, +the resulting type is the so-qualified atomic type. +.PP +If an attempt is made to assign +.B NULL +to a pointer defined with the +.B \%nonnull +qualifier, +the behavior is undefined. +If an attempt is made to refer to +a pointer with a +.RB non- \%nonnull -qualified +type +through the use of +an lvalue with +.BR \%nonnull -qualified +type, +the behavior is undefined. +.PP +The intended use of the +.B \%nonnull +and +.B \%restrict +qualifiers +(like the +.B \%register +storage class) +is to promote optimization, +and deleting all instances of the qualifier +from all preprocessing translation units composing a conforming program +does not change its meaning (i.e., observable behavior). +.SH NOTES +These rules for +.B nonnull +are somewhat of the reverse of +.BR const : +Instead of forbidding the discarding of the qualifier, +we forbid the addition of the qualifier. +The reason is that constant variables are a subset of variables, +and the danger is in treating a +.B const +as a variable. +Similarly, +.B nonnull +pointers are a subset of +.RB (possibly- NULL ) +pointers, +but the danger is in treating +.RB possibly- NULL +pointers as +.B \%nonnull +pointers. +.SS Prior art +GCC has +.BR [[gnu::nonnull]] . +Why is this better? +.PP +It can be applied more specifically in the case of pointers to pointers. +And, like with +.BR const , +the +.BR nonnull -ness +can be better enforced by passing the qualifier around. +.PP +However, we recognize the optimizations allowed by +.BR [[gnu::nonnull]] , +and also allow them, +by specifying the behavior as undefined +when the qualifier is misused, +as GCC does. +.PP +Clang has +.BR _Nonnull . +Why is this better? +.PP +Clang found that using a qualifier was better than an attribute, +since it allowed to more specifically apply it to pointers to pointers. +We recognize that, +and also use a qualifier. +.PP +Clang doesn't specify the behavior as being undefined. +That forbids optimizations, +that would otherwise be possible. +We prefer to allow for those optimizations. +.PP +Clang considers this qualifier to be useful only as a diagnostics generator. +We not only allow for diagnostics to be issued, +but we have stricter rules that +make it more difficult to produce incorrect code. +.PP +Even though the language has reserved identifiers +starting with underscore + uppercase +for this kind of keywords, +Clang has already used +.BR _Nonnull , +and since we are changing the meaning, +it might cause problems to existing code. +So +.B nonnull +seems a better name, +which hopefully is not used by existing code, +or at least it is less used. +.SH EXAMPLES +.SS Correct +.BR strcpy (3) +may be implemented in the following way, +to signify that it cannot accept +.B NULL +as input to any of its arguments, +and that it cannot ever return +.B NULL +either. +.PP +.EX +char *nonnull strcpy(char *nonnull restrict dest, + const char *nonnull restrict src) +{ + char *d; + + d = dest; + while ((*d++ = *src++) != '\e0'); + + return dest; +} +.EE +.PP +Note that +.I d +need not be +.BR nonnull -qualified, +since possibly being +.B NULL +is a superset of not possibly being +.BR NULL . +.PP +The following variations of the above are incorrect, +for the reasons that follow the code examples. +.SS Incorrect +.EX +char *strcpy(char *nonnull restrict dest, + const char *nonnull restrict src) +{ + char *d; + + d = dest; + while ((*d++ = *src++) != '\e0'); + + return dest; +} +.EE +.PP +Although this would be valid by itself +(wouldn't have undefined behavior), +it forbids callers of the function +from assigning the return value to a +.BR \%nonnull -qualified +pointer. +.PP +.SS Undefined behavior +.EX +char *nonnull strcpy(char *restrict dest, + const char *nonnull restrict src) +{ + char *d; + + d = dest; + while ((*d++ = *src++) != '\e0'); + + return dest; +} +.EE +This causes undefined behavior, +since it assigns a +.RB non- \%nonnull -qualified +pointer +.RI ( dest ) +to a qualified one +(the return value). +It's also dangerous, +since the user isn't properly informed that +.B NULL +may cause undefined behavior in the implementation of the function +.RI ( dest +is dereferenced). +.SH AUTHORS +Alejandro Colomar +.UR alx.manpages@gmail.com +.PP +I must thank the GCC and Clang programmers +for having provided a solid base +on which I based this proposal. +.SH SEE ALSO +N2731 - 6.7.3 +.PP +.UR https://gcc.gnu.org/\:onlinedocs/\:gcc/\:Common-Function-Attributes.html\:#Common-Function-Attributes +.UE +.PP +.UR https://clang.llvm.org/\:docs/\:AttributeReference.html\:#nullability-attributes +.UE |