1

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?

Ilonpilaaja
  • 1,169
  • 2
  • 15
  • 26
  • MISRA allows the use of concantenating two strings. I am unfamiliar with log4cplus but it could be invoking a macro which MISRA does not like. Alternatively if it doesn't complain about one message then just construct the string beforehand and pass in the concatenated string. – 0RR Jan 17 '21 at 07:42
  • This macro does not seem to fin into any of MISRA approved use case categories: *"C++ macros shall only be used for include guards, type qualifiers, or storage class specifiers."* – user7860670 Jan 17 '21 at 08:48
  • @user7860670 Well dynamic memory shouldn't be used either and `std::string` uses that, there are many things it does not allow – 0RR Jan 17 '21 at 09:09
  • Indeed... why are you using std::string in a MISRA application? Not to mention that evil-looking function-like macro. – Lundin Jan 18 '21 at 07:20

1 Answers1

1

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.

0RR
  • 1,538
  • 10
  • 21
  • 1
    True, I've also found this out, looking into the source code of the log4cplus library... – Ilonpilaaja Jan 17 '21 at 09:08
  • Let me add that log4cplus's macros are only a convenience. You can implement whatever logging means you want with the methods of the API without any macros. – wilx Jan 23 '21 at 23:16