1
votes

I can't figure out what is wrong with this code. When I pass 1 argument to LOG_INFO, it works fine, but fails with 0 arguments.

#define LOG_INFO(...) CLOG(INFO, "default", ##__VA_ARGS__)

LOG_INFO() << "Log using default file";

When I compile this code I get this error:

error:
expected primary-expression before ‘)’ token

This is what I did to debug it.

When I run g++ -E on this file, LOG_INFO() IS expanded correctly:

CLOG(INFO, "default") << "Log using default file";

When I replace

LOG_INFO() << "Log using default file";

with

CLOG(INFO, "default") << "Log using default file";

It compiles fine! But when I put back the pre-expansion macro, it fails again.

To answer commentators: Here's the definition of CLOG

#define CLOG(LEVEL, ...)\
    C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__)

full file can be found here:

https://github.com/easylogging/easyloggingpp/blob/master/src/easylogging%2B%2B.h

running: gcc version 4.7.2 (Debian 4.7.2-5)

1
What compiler are you using? What options? You should show a complete, minimal example, including the entire .cpp file, and compiler command-line, and compiler output - not snippets. - Jonathon Reinhart
I think there is nothing you can do about this. IIRC the GCC compiler "fixed" this but its non-standard. You have a trailing comma with empty args. - Galik
@Galik, I have updated my question, the expansion seems to work fine. This is very weird - Kam
You forgot to ask a question. You describe behavior that seems precisely like what you'd expect and then your question just stops. - David Schwartz
@DavidSchwartz Ah sorry I wasn't clear in the question, I will rephrase - Kam

1 Answers

1
votes

When I run g++ -E on this file, LOG_INFO() IS expanded correctly:

CLOG(INFO, "default") << "Log using default file";

I don't think this is expanded correctly. It should be fully expanded.

CLOG(INFO, "default")

should not be in the expanded file. It should have expanded to

CINFO(el::base::Writer, el::base::DispatchAction::NormalLog, "default")

which in turn should have expanded to something else. The actual line will be some crazy C++ which contains no macros.


I think you are running into a defect in the ##__VA_ARGS__ engine. Something similar to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56825 or https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61613.


You can test this by replacing

#define LOG_INFO(...) CLOG(INFO, "default", ##__VA_ARGS__)

with

#define LOG_INFO() CLOG(INFO, "default")

and looking at the output of g++ -E.


As to a possible solution, you may have luck with some double expansion tricks.

#define LOG_INFO_HELPER(...) , ## __VA_ARGS__
#define LOG_INFO_COMMA_AND(...) LOG_INFO_HELPER(__VA_ARGS__)
#define LOG_INFO(...) CLOG(INFO, "default" LOG_INFO_COMMA_AND(__VA_ARGS__))

See https://llvm.org/bugs/show_bug.cgi?id=19141

I'm not 100% sure this will work in your case.