Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with clang's (3.9) -Wexpansion-to-defined warning?

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?

like image 276
Walter Avatar asked Feb 06 '17 17:02

Walter


People also ask

Why does Apple use Clang?

Clang was intended to reduce debug time by giving proper error messages, better IDE integration etc. Of course, it has grown to support more languages than gcc and it's integration with llvm has popularized it.

Does Apple use Clang?

Release Clang VersionsClang is also provided in all major BSD or GNU/Linux distributions as part of their respective packaging systems. From Xcode 4.2, Clang is the default compiler for Mac OS X.

Does Microsoft use Clang?

The Microsoft C++ Standard Library requires at least Clang 8.0. 0. Later versions of Visual Studio provide newer versions of the Clang toolset. The bundled version of Clang gets updated automatically to stay current with updates in the Microsoft implementation of the Standard Library.


2 Answers

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)
like image 99
eerorika Avatar answered Oct 16 '22 18:10

eerorika


If you have this kind of problem with a 3d party pod, you may find this useful

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexpansion-to-defined"
#import <pop/POP.h>
#pragma clang diagnostic pop
like image 5
ilnar_al Avatar answered Oct 16 '22 17:10

ilnar_al