Quick Links:

bal | bbl | bdl | bsl

Component bsla_nonnullarg
[Package bsla]

Provide macros to hint at null arguments to functions. More...

Outline
Purpose:
Provide macros to hint at null arguments to functions.
Macros:
BSLA_NONNULLARGS warn if any pointer arguments are null
BSLA_NONNULLARG(...) warn if indexed arguments are null
BSLA_NONNULLARGS_IS_ACTIVE 1 if BSLA_NONNULLARGS is active, 0 otherwise
BSLA_NONNULLARG_IS_ACTIVE 1 if BSLA_NONNULLARG is active, 0 otherwise
See also:
Component 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:
  • NULL
  • 0
  • static_cast<TYPE *>(0)
  • nullptr (with C++11)
  • a const variable known to be 0 (clang only, no warning with g++)
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
BSLS_NONNULLARGS_IS_ACTIVE In these two cases, X_IS_ACTIVE is defined to 0 if X expands to nothing and 1 otherwise.
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:
  void usagePrint1(const char *string, int repetition) BSLA_NONNULLARG(1);
      // Print the specified 'string' the specified 'repetition' times.

  void usagePrint1(const char *string, int repetition)
  {
      for (int ii = 0; ii < repetition; ++ii) {
          printf("%s\n", string);
      }
  }
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:
  void usagePrint2(const char *string, int repetition) BSLA_NONNULLARGS;
      // Print the specified 'string' the specified 'repetition' times.

  void usagePrint2(const char *string, int repetition)
  {
      for (int ii = 0; ii < repetition; ++ii) {
          printf("%s\n", string);
      }
  }
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++
                  ~~~     ^