6

I've got some logging macros in my code along the lines of:

#define LOG_MSG (pri, msg, ... ) \
    if (pri > PriorityLevel ) \
        printf( msg, ##\__VA_ARGS__);

I know I can use LCOV_EXCL_START, LCOV_EXCL_STOP or LCOV_EXCL_LINE to suppress a branch. But that only works if I add it every place I call LOG_MSG:

LOG_MSG(ERROR, "An Error has occurred\n");//LCOV_EXCL_LINE

I'd like to include that comment in the macro, but LCOV doesn't recognize it if I put it there. For example, this code still produces branches.

#define LOG_MSG (pri, msg, ... ) \
    if (pri > PriorityLevel ) \
        printf( msg, ##\__VA_ARGS__);//LCOV_EXCL_LINE

Is there a good way to suppress these branches in the macro itself?

perogiex
  • 505
  • 5
  • 10
  • if pri is a const the compiler is smart enough that you don't need to do any of this :-/ – IdeaHat Jan 03 '14 at 15:09
  • The macro is a bit more complex. PriorityLevel is not constant and can be altered at runtime. The actual macro also includes a check for an Enabled constant. When its false, the if statement is optimized away. But that's for the release code. I suppose I could try to have Release, Debug and CodeCoverage configurations. The Coverage being a debug build with logging disabled. – perogiex Jan 03 '14 at 15:28
  • This issue has also been reported on github: https://github.com/linux-test-project/lcov/issues/44 – dpi Jun 23 '19 at 12:02

5 Answers5

3

the new lcov version 1.11 (or 1.12) introduce LCOV_EXCL_BR_LINE keyword. So in your case:

LOG_MSG(ERROR, "An Error has occurred\n"); //LCOV_EXCL_BR_LINE

or, even better:

LOG_MSG(ERROR, "An Error has occurred\n"); (void)("LCOV_EXCL_BR_LINE");

which survives precompiler comment stripping.

tutejszy
  • 602
  • 7
  • 22
  • Under what conditions is this comment being stripped? Is it `cpp` that's doing that? – jdpipe Nov 03 '17 at 03:53
  • "The comments are replaced with a single space in the "translation phase", which happens prior to the Preprocessing directive parsing. VC++ and the GNU C Compiler both follow this paradigm" https://stackoverflow.com/questions/1510869/does-the-c-preprocessor-strip-comments-or-expand-macros-first – tutejszy Dec 13 '17 at 13:18
2

Why not turn the macro into function ?

like:

template <typename ... Ts>
void LOG_MSG(int priority, const std::string& message, Ts&&...ts)
{
    if (priority > PriorityLevel)
        printf(message.c_str(), std::forward<Ts>(ts)...);
    // Or more appropriate stuff
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I had made it a macro, so that when the code goes to production, the logging can be turned off by re-defining the macro as a no-op. – perogiex Jan 06 '14 at 13:51
  • Once the code is in function, you may add any suppress mechanism (as `//LCOV_EXCL_LINE`). Then you may create your Macro which calls the function (So adjust name). – Jarod42 Jan 06 '14 at 13:59
  • If you are using a logging system that has runtime configuration, you will have at minimum the one branch in the macro unless you're willing to have all log message expressions evaluated even for levels or loggers that are not enabled. – washley Jul 27 '17 at 23:22
  • @perogiex Actually if any one expression has a side effect in debug mode because it's getting logged, a no-op is not always a good idea. With a function as presented here, you can easily setup the `PriorityLevel` to `std::numeric_limits::max()` and exit immediately if priority is small or equal (i.e. always when the limit is `max()`). – Alexis Wilke Jul 15 '22 at 16:41
2

I can't figure out how to tack code onto an answer, but this is a response to the solution from @Jarod42. I'm not using C++0x so I modified his solution a bit:

void LogMsgFunc( U32 pri, const char* msg, ... )
{
    //LCOV_EXCL_START
    va_list variableArgumentList;
    va_start( variableArgumentList, msg );
    if ( pri <= PriorityLevel ) 
    { 
        vfprintf( stderr, msg, variableArgumentList );
    }    
    va_end( variableArgumentList );
    //LCOV_EXCL_STOP
}

#define LOG_MSG (pri, msg, ... ) \
    LogMsgFunc(pri, msg, ##__VA_ARGS__);
perogiex
  • 505
  • 5
  • 10
0

How about

#define LOG_MSG__LCOV_EXCL_BR_LINE LOG_MSG

and then replace any LOG_MSG calls that you don't want coverage-tested with the new macro LOG_MSG__LCOV_EXCL_BR_LINE. Would that work?

jdpipe
  • 232
  • 1
  • 11
0

How about the solution which mentioned in: https://github.com/linux-test-project/lcov/issues/44#issuecomment-427449082

Change the lcovrc add:

lcov_excl_br_line = LCOV_EXCL_BR_LINE|LOG_MSG
robin
  • 51
  • 7