Skip to content

Annotate API with nullability #373

Description

@eschaton

The clang static analyzer can help prevent bugs resulting from allowing NULL to be passed into places it shouldn't be, by allowing pointers in APIs and internals to be annotated with nullability.

This can also help clarify the use of APIs, e.g. whether srunner_create() is allowed to take a NULL Suite as a parameter. (It currently is, but that required source inspection to determine.)

The typical way to use these annotations would be to put them behind macros such as CK_NULLABLE and CK_NONNULL so that with non-clang compilers (or versions of clang too old to have the feature) the macros are just empty. And if other compilers (or the language standard) get nullability annotations, they can be opted in at that point.

As an example, the full declaration of srunner_create() would look like this (also assuming CK_EXPORT and CK_DLL_EXP are combined per #371):

CK_EXPORT SRunner * CK_NULLABLE srunner_create(Suite * CK_NULLABLE s);

In 10+ years of writing C and Objective-C with these types of nullability annotation, I haven't found them to be particularly cumbersome, while I have found them to provide substantial value. They obey regular C rules like const so they apply to the pointer to their left, and since you generally only write them in function signatures they don't overwhelm the code. And the static analysis they enable can help reveal subtle bugs.

One additional trick is to have "assume-nonnull" begin & end macros (e.g. CK_ASSUME_NONNULL_BEGIN and CK_ASSUME_NONNULL_END) that are put around header and source files such that any pointers in function signatures within the macros are assumed to be non-null unless specifically annotated. This further reduces the amount of "noise" in APIs since only places where a NULL is specifically allowed need to be annotated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions