Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2874,14 +2874,22 @@ // static const bool __is_signed; // // then treat __is_signed as an identifier rather than as a keyword. - if (DS.getTypeSpecType() == TST_bool && - DS.getTypeQualifiers() == DeclSpec::TQ_const && - DS.getStorageClassSpec() == DeclSpec::SCS_static) - TryKeywordIdentFallback(true); - - // We're done with the declaration-specifiers. - goto DoneWithDeclSpec; - + switch (DS.getTypeSpecType()) { + case TST_typename: + { + auto SeenType = Sema::GetTypeFromParser(DS.getRepAsType()); + if (!SeenType->isBooleanType()) + goto DoneWithDeclSpec; + // fall through + } + case TST_bool: + if (DS.getTypeQualifiers() == DeclSpec::TQ_const && + DS.getStorageClassSpec() == DeclSpec::SCS_static) + TryKeywordIdentFallback(true); + // fall through + default: + goto DoneWithDeclSpec; + } // typedef-name case tok::kw___super: case tok::kw_decltype: Index: test/SemaCXX/libstdcxx_is_pod_hack.cpp =================================================================== --- test/SemaCXX/libstdcxx_is_pod_hack.cpp +++ test/SemaCXX/libstdcxx_is_pod_hack.cpp @@ -27,6 +27,9 @@ static const bool __is_signed = true; // expected-warning {{keyword '__is_signed' will be made available as an identifier}} }; +// The case where `bool` above is hidden behind a typedef is tested +// in libstdcxx_is_signed_hack.cpp + bool check_signed = test_is_signed::__is_signed; template struct must_be_true {}; Index: test/SemaCXX/libstdcxx_is_signed_hack.cpp =================================================================== --- /dev/null +++ test/SemaCXX/libstdcxx_is_signed_hack.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// libstdc++ 4.4 uses __is_signed as an identifier, while Clang treats it +// as a keyword for the __is_signed type trait. Cope with this conflict +// via some hackish recovery: if we see a declaration of the form +// +// static const T __is_signed +// +// where T is bool or a typedef that reduces to bool, then we stop treating +// __is_signed as a keyword and instead treat it as an identifier. + +typedef bool BOOL; +struct test_is_signed_typedef { + static const BOOL __is_signed = true; // expected-warning {{keyword '__is_signed' will be made available as an identifier}} +};