Skip to content

Type-trait keywords reverting to identifiers causing arcane error messages #29631

@llvmbot

Description

@llvmbot
Bugzilla Link 30283
Version 3.8
OS All
Reporter LLVM Bugzilla Contributor
CC @DougGregor

Extended Description

Clang has the feature that certain type-trait keywords revert to being identifiers if declared as the name of a struct. This seems to be in order to support certain standard headers that use these keywords as a struct name, i.e. to support historic code, as best as I can see.

Unfortunately, the mechanism used is a very broad-brush approach since depending on what is #included, valid code can suddenly fail to compile, in what appears to the user to be unknown reasons. The problem only gets worse when these keywords are used inside multiple headers because one translation unit will compile fine and the next will fail -- simply because the #include directives are in a different order.

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 construction

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

Unfortunately, the given 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, I feel it would be good to improve the error output to show the source line where the type-trait keyword reverts to an identifier as a note to the error given. Of course, of the two routes given here, this last one really is nothing more than a work-around to the problem hinting to the user that they need to swap the order of their #includes around.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillac++clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions