BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsla_nonnullarg

Macros

#define BSLA_NONNULLARG(...)
 
#define BSLA_NONNULLARGS
 

Detailed Description

Outline

Purpose

Provide macros to hint at null arguments to functions.

Macros

See also
bsla_annotations

Description

This component provides preprocessor macros that define compiler-specific compile-time annotations. These macros instruct the compiler to warn if null is passed to certain arguments to a function, or, on platforms where the feature is not supported, expand to nothing.

Note that the annotations cause warnings to be emitted if the covered argument is passed:

Macro Reference

BSLA_NONNULLARGS: This annotation indicates that a compiler warning is to be issued if any of the pointer arguments to this function are passed null.

BSLA_NONNULLARG(...): This annotation, passed a variable-length list of positive integers, indicates that a compiler warning is to be issued if null is passed to a pointer argument at any of the specified indices, where the first argument of the annotated function has an index of 1. Note that for non-static member functions, the implicit this argument has index 1.

BSLA_NONNULLARG_IS_ACTIVE: The macro BSLA_NONNULLARGS_IS_ACTIVE is defined if BSLA_NONNULLARGS expands to something with the desired effect; otherwise BSLA_NONNULLARGS_IS_ACTIVE is not defined and BSLA_NONNULLARGS expands to nothing.

BSLS_NONNULLARGS_IS_ACTIVE: The macro BSLA_NONNULLARG_IS_ACTIVE is defined if BSLA_NONNULLARG expands to something with the desired effect; otherwise BSLA_NONNULLARG_IS_ACTIVE is not defined and BSLA_NONNULLARG expands to nothing.

Usage

This section illustrates intended use of this component.

Example 1: Passing Null to Arguments Annotated as Non-Null

First, we define a function, usagePrint1, annotated such that a compiler warning will occur if the first argument of the annotated function is passed 0, NULL, nullptr, or (on clang) a null pointer constant expression:

// Print the specified 'string' the specified 'repetition' times.
void usagePrint1(const char *string, int repetition) BSLA_NONNULLARG(1);
void usagePrint1(const char *string, int repetition)
{
for (int ii = 0; ii < repetition; ++ii) {
printf("%s\n", string);
}
}
#define BSLA_NONNULLARG(...)
Definition bsla_nonnullarg.h:250

Then, we define a nearly identical function annotated with BSLA_NONNULLARGS instead. Note that only pointer arguments are affected by this annotation – repetition is not affected and may be passed 0 without a warning being emitted:

// Print the specified 'string' the specified 'repetition' times.
void usagePrint2(const char *string, int repetition) BSLA_NONNULLARGS;
void usagePrint2(const char *string, int repetition)
{
for (int ii = 0; ii < repetition; ++ii) {
printf("%s\n", string);
}
}
#define BSLA_NONNULLARGS
Definition bsla_nonnullarg.h:251

So the two different annotations on these functions have an identical effect – affecting the string argument but not the repetition argument.

Next, in main, we call both functions with a non-null first argument, and observe that no warning occurs. Note that even though 0 is passed to the integer argument to usagePrint2 and the BSLA_NONNULLARGS annotation was used, non-pointer arguments are not affected by that annotation:

usagePrint1("woof", 0);
usagePrint2("meow", 0);

Then, we call both functions passing the first argument a variable whose value is known by the compiler to be null, but since np1 is a non-const variable, no warning is issued:

char *np1 = NULL;
usagePrint1(np1, 0);
usagePrint2(np1, 0);

Now, we call both functions passing various forms of constant null pointer expressions to the first argument:

usagePrint1( 0, -10);
usagePrint2( 0, -10);
usagePrint1(NULL, -20);
usagePrint2(NULL, -20);
usagePrint1(static_cast<char *>(0), -30);
usagePrint2(static_cast<char *>(0), -30);
#if __cplusplus >= 201103L
usagePrint1(nullptr, -40);
usagePrint2(nullptr, -40);
#endif
char * const np2 = 0; // 'np2', unlike 'np1' above, is 'const'.
usagePrint1(np2, -50); // Warning with clang, not g++
usagePrint2(np2, -50); // Warning with clang, not g++

Finally, we observe that the above calls result in the following warnings with clang w/C++11 support:

.../bsla_nonnullarg.t.cpp:376:30: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint1( 0, -10);
~ ^
.../bsla_nonnullarg.t.cpp:377:30: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint2( 0, -10);
~ ^
.../bsla_nonnullarg.t.cpp:379:30: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint1(NULL, -20);
~~~~ ^
.../bsla_nonnullarg.t.cpp:380:30: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint2(NULL, -20);
~~~~ ^
.../bsla_nonnullarg.t.cpp:382:48: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint1(static_cast<char *>(0), -30);
~~~~~~~~~~~~~~~~~~~~~~ ^
.../bsla_nonnullarg.t.cpp:383:48: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint2(static_cast<char *>(0), -30);
~~~~~~~~~~~~~~~~~~~~~~ ^
.../bsla_nonnullarg.t.cpp:386:37: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint1(nullptr, -40);
~~~~~~~ ^
.../bsla_nonnullarg.t.cpp:387:37: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint2(nullptr, -40);
~~~~~~~ ^
.../bsla_nonnullarg.t.cpp:391:29: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint1(np2, -50); // Warning with clang, not g++
~~~ ^
.../bsla_nonnullarg.t.cpp:392:29: warning: null passed to a callee that
requires a non-null argument [-Wnonnull]
usagePrint2(np2, -50); // Warning with clang, not g++
~~~ ^

Macro Definition Documentation

◆ BSLA_NONNULLARG

#define BSLA_NONNULLARG (   ...)

◆ BSLA_NONNULLARGS

#define BSLA_NONNULLARGS