How to detect trait keywords that have reverted to identifiers


I'm having a problem that maybe someone here knows a good solution to.

I have headers that use the clang type-trait built-ins, for example __is_void.
However, using these headers will throw spurious errors if certain system
headers are included before them.

Here is a minimal bit of code that demonstrates the problem:

  #include <math.h>

  template <bool> struct Test { };
  using T = Test<__is_void(void)>;

Compiling with:
  clang++ -std=c++14 -Wall test.cpp

produces the sole error:
  test.cpp:4:30: error: expected '(' for function-style cast or type

Take out the "#include <math.h>" line, or compile on a system with a different
system header implementation, and everything is fine.

Unfortunately, the error message is less than helpful. The cause is due to
math.h including, along the way, c++/6.1.1/bits/cpp_type_traits.h, which
has struct std::__is_void defined. Now, if this segment of the header is
placed in the source file itself, then I get the warning that __is_void has
reverted to an identifier for the rest of the translation unit, which explains
the reason behind the otherwise cryptic error message.

Could it not be possible for clang to manage some sort of scoping -- after
all, why can't std::__is_void be a struct and the standalone __is_void still
act as the built-in type-trait?!

Failing that, is there any way of detecting, in code, that a type-trait has
reverted to an identifier, to allow something akin to...

    "__is_void has reverted to identifier; consider re-ordering include files");

... to be placed in the header using __is_void?

If anyone has a good idea, I would love to hear!