Search code examples
c++templatesboost-asio

Unexpected 'pointer is null' warning in boost asio library?


I'm compiling a project that incorporates the asio C++ library, and I'm getting a pesky warning:

../opendnp3/_deps/asio-src/asio/include/asio/impl/connect.hpp:75:73: 
warning: ‘this’ pointer is null [-Wnonnull]
   75 |         (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
   76 |           *static_cast<const asio::error_code*>(0),
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      
   77 |           *static_cast<const Iterator*>(0)))) != 1;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     

In the code below, the asio connect.hpp file (line 67)

template <typename T, typename Iterator>
struct is_legacy_connect_condition
{
  static char asio_connect_condition_check(char);
  static char (&asio_connect_condition_check(Iterator))[2];

  static const bool value =
  sizeof(asio_connect_condition_check(
    (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
      *static_cast<const asio::error_code*>(0),
      *static_cast<const Iterator*>(0)))) != 1;
};

I'm a little bit too new with templates to diagnose this warning. Has anyone run into this, and/or have any insight into whether it indicates an actual problem, and how I can prevent the warning? (There's actually several similar warnings, adds a lot of clutter to the output.) Thank you.


Solution

  • This is checking whether the result of calling a legacy_connect_condition_helper<T, Iterator> is an Iterator or not, which in turn checks whether or not T is a function that accepts an error_code and an Iterator and returns an Iterator.

    What's important though, is that it doesn't matter that the pointers are null, becuase sizeof is an unevaluated context. Only the types involved matter; the expression isn't executed, and so all of those null pointer dereferences are safe.

    In more modern code you would probably use std::declval instead of casting null pointers:

    template <typename T, typename Iterator>
    struct is_legacy_connect_condition
    {
      static char asio_connect_condition_check(char);
      static char (&asio_connect_condition_check(Iterator))[2];
    
      static const bool value =
      sizeof(asio_connect_condition_check(
        (std::declval<legacy_connect_condition_helper<T, Iterator>>())(
          std::declval<const asio::error_code>(),
          std::declval<const Iterator>()))) != 1;
    };
    

    But std::declval wasn't introduced until C++11. Asio is quite old, and had to work on old compilers with no C++11 support.


    As for how to avoid the warning, your best bet is to update to a newer asio release. The offending code was replaced with the declval version in this commit three years ago and was released as part of asio standalone version 1.21.0 or boost 1.78.

    If you're stuck on the old version for some reason and you're using GCC you can add the asio include directories as system includes (use -isystem instead of -I). That will disable warning reporting for those headers (mostly).

    Otherwise you'll need to globally disable the nonnull warning. Either stop passing -Wnonnull or add -Wno-nonnull (if nonnull is enabled by some other warning flag).