c++misralog4cplus

string concatenation, log4cplus, and MISRA compliance


I am using log4cplus, and my misra-checks for something as innocent-looking as

LOG4CPLUS_INFO(
        logger,
        std::string("ABC") + std::string("DEF"));

yield (among others) The underlying type of `0L` is implicitly reduced from `8-bit signed char` to {code{bool}}.. This happens also when I put the respective literals rather than wrapping them inside string. I wonder how to fix this. Or, more generally put, how would you concatenate several log messages and yet keep MISRA-checks happy?


Solution

  • I had a look at LOG4CPLUS_INFO and that is a macro defined as:

    #if !defined(LOG4CPLUS_DISABLE_INFO)
    #define LOG4CPLUS_INFO(logger, logEvent)                                \
        LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL)
    

    and LOG4CPLUS_MACRO_BODY is defined as:

     #define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel)                \
         LOG4CPLUS_SUPPRESS_DOWHILE_WARNING()                                \
         do {                                                                \
             log4cplus::Logger const & _l                                    \
                 = log4cplus::detail::macros_get_logger (logger);            \
             if (LOG4CPLUS_MACRO_LOGLEVEL_PRED (                             \
                     _l.isEnabledFor (log4cplus::logLevel), logLevel)) {     \
                 LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \
                 _log4cplus_buf << logEvent;                                 \
                 log4cplus::detail::macro_forced_log (_l,                    \
                     log4cplus::logLevel, _log4cplus_buf.str(),              \
                     __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ());       \
             }                                                               \
         } while (0)                                                         \
         LOG4CPLUS_RESTORE_DOWHILE_WARNING()
    

    and so your MISRA checker will be checking the invocation of the macro. And MISRA likes if statements to be defined explicitly in terms of bool e.g. rather than if(node) it likes if(node!=nullptr) and I think it may have an issue with the last line:

         } while (0)                                                         \
    

    As 0 is being implicitly cast to bool. You should see if you get the same warning by adding a simple do{}while(0); loop to your code and run your checker again.


    And if you want a MISRA safe way of logging, I would avoid the use of macros. You can make a simple logging class with a std::ofstream and a std::mutex and keep it in namespace scope defined as an extern in your header file.