clang 3.9 has added to -Wall
a the warning -Wexpansion-to-defined
, which produces
macro expansion producing 'defined' has undefined behaviour
in case defined
is used outside an #if
expression, including the case of a macro that is then used within an #if
expression. For example the following code
// in some file:
#define HAS_GNU (defined(__GNUC__) && !defined(__clang__))
// possibly in another file:
#if defined(__clang__) || HAS_GNU
/* ... */
#endif
produces
test.cc:5:27: warning: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined]
#if defined(__clang__) || HAS_GNU
^
test.cc:3:18: note: expanded from macro 'HAS_GNU'
#define HAS_GNU (defined(__GNUC__) && !defined(__clang__))
^
test.cc:5:27: warning: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined]
test.cc:3:40: note: expanded from macro 'HAS_GNU'
#define HAS_GNU (defined(__GNUC__) && !defined(__clang__))
So what's the 'correct' way to do that?
You can use #if - #else macros:
#if defined(__GNUC__) && !defined(__clang__)
#define HAS_GNU 1
#else
#define HAS_GNU 0
#endif
Or, if you're willing to change the code that uses HAS_GNU
, perhaps more conventional way:
#if defined(__GNUC__) && !defined(__clang__)
#define HAS_GNU
#endif
#if defined(__clang__) || defined(HAS_GNU)