3

I'm compiling on with GCC on Linux, but CMake is kind enough to produce a Clang compatible compilation database. This means that I can run fancy, modern Clang based tools on my codebase and those tools have perfect knowledge of how each file is to be built (flags, defines, include paths, etc.) So far so good.

But today the Clang based static analysis in my IDE started showing a Clang specific warning. I don't think it particularly matters for my question which warning it is, but it was warning: disabled expansion of recursive macro, generated by -Wdisabled-macro-expansion. This particular macro is provided by a third party, so fixing the warning isn't an option, but I would like to suppress it as it occurs several times in the file in question.

What I'm struggling with is how to suppress the warning in Clang based analysis tools without causing new warnings in the GCC build.

  • Adding #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" suppresses the warning for Clang tools, but causes GCC to issue warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas].
  • Similarly, adding #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" suppresses the Clang warning (because Clang tries to be compatible with GCC diagnostics), but causes GCC to issue warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas].
  • Wrapping either of the above with #ifdef __clang__ makes GCC happy, but doesn't suppress the Clang warning because the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead.

Is there a way to make a diagnostic #pragma visible to Clang tooling, but not to GCC?

Parker Coates
  • 8,520
  • 3
  • 31
  • 37

1 Answers1

4

the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead

If it's reporting a clang-only warning, but does not think that __clang__ is defined, that sounds like a problem with the tooling. If it's trying to be that clever about misrepresenting itself, you may be up a creek... but also you should be complaining to the tool author for creating this situation in the first place.

That said, you could try:

#if defined(__has_warning)
#  if __has_warning("-Wdisabled-macro-expansion")
#    pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
#  endif
#endif

I'm not sure if this will work... it depends on how hard the tooling is pretending to not be clang (__has_warning is a clang-only extension).

Parker Coates
  • 8,520
  • 3
  • 31
  • 37
Matthew
  • 2,593
  • 22
  • 25
  • Interestingly, `#if defined(__has_warning)` alone is enough for my purposes as it is passes only under the Clang tooling or Clang itself. Of course, if I rely on it, it will completely blow up in my face if GCC or MSVC ever decide to implement `__has_warning`. – Parker Coates Sep 24 '18 at 19:34
  • The preprocessor has logical short-circuiting, so you can combine the inner and outer `#if` into `#if defined(__has_warning) && __has_warning("-Wdisabled-macro-expansion")` – Ruslan Sep 25 '18 at 09:13
  • 1
    @Ruslan, Matthew originally posted it as a single `#if`, but I edited it to two as `g++` 8.2.1 rejects the single line version with `error: missing binary operator before token "("` pointing to the `(` after `__hasWarning`. – Parker Coates Sep 25 '18 at 16:49