nemequ / hedley

A C/C++ header to help move #ifdefs out of your code
https://nemequ.github.io/hedley/
Creative Commons Zero v1.0 Universal
774 stars 51 forks source link

Add HEDLED_IGNORE_WARNING? #32

Closed reddwarf69 closed 4 years ago

reddwarf69 commented 4 years ago

I am starting to add code like

#if HEDLEY_HAS_WARNING("-W<warning>")
#pragma GCC diagnostic ignored "-W<warning>"
#endif

And was wondering if there is anything stopping

HEDLED_IGNORE_WARNING_IF_EXISTS("-W<warning>")

from being possible.

Actually probably it could just be called HEDLED_IGNORE_WARNING?

nemequ commented 4 years ago

I've had the same thought, but unfortunately the preprocessor doesn't really offer a way to do it. There isn't really a way to move the conditional logic to inside of the macro. The closest we can do is to conditionally define a macro, for example:

#if defined(__has_warning)
#  define HEDLEY_HAS_WARNING(warning) __has_warning(warning)
#else
#  define HEDLEY_HAS_WARNING(warning) (0)
#endif

Notice that the logic isn't in the macro. What we would need is something like

#define HEDLEY_IGNORE_WARNING(warning) (HEDLEY_HAS_WARNING(warning) ? _Pragma("clang diagnostic ignored " # warning) : noop())

But something like that would be preprocessed to

(1 ?
#pragma clang diagnostic "-Whatever"
: noop())

Not just the pragma.

Even if you could do that, you can't actually concatenate a string for _Pragma like that. It will preprocess to something like "clang diagnostic ignored " "\"-Whatever\"" which would be fine if we were trying to construct a normal C string, but _Pragma expects a single string literal so you'll end up with an error.

It's also worth mentioning that GCC doesn't support __has_warning. AFAIK only clang, and probably some compilers based on clang (like xlclang and armclang), do, so I think the benefit would be pretty limited. If you're trying to support GCC in addition to clang, this would actually be more difficult to use since it doesn't really match with version checking. You would probably end up with something like

HEDLEY_IGNORE_WARNING("-Whatever")
#if HEDLEY_GCC_VERSION_CHECK(11,0,0)
#  pragma GCC diagnostic disabled "-Whatever"
#endif

Which is a bit awkward since you're not sure if HEDLEY_IGNORE_WARNING took care of silencing the warning or not, so the GCC version check has to be run unconditionally. It would be easier to just do something like

#if HEDLEY_HAS_WARNING("-Whatever") || HEDLEY_GCC_VERSION_CHECK(11,0,0)
#  pragma GCC diagnostic disabled "-Whatever"
#endif

So while it would be very nice if clang is all you care about, I think the majority of people would just end up using the current macros.