diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3519,6 +3519,7 @@ } case tok::kw___is_signed: + case tok::kw___is_unsigned: // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang // typically treats it as a trait. If we see __is_signed as it appears // in libstdc++, e.g., @@ -3526,8 +3527,15 @@ // static const bool __is_signed; // // then treat __is_signed as an identifier rather than as a keyword. + // + // Similarly, libstdc++ 13 trunk at one point used __is_unsigned as an + // identifier as + // + // static constexpr bool __is_unsigned; + // if (DS.getTypeSpecType() == TST_bool && - DS.getTypeQualifiers() == DeclSpec::TQ_const && + (DS.getTypeQualifiers() == DeclSpec::TQ_const || + DS.getConstexprSpecifier() == ConstexprSpecKind::Constexpr) && DS.getStorageClassSpec() == DeclSpec::SCS_static) TryKeywordIdentFallback(true); diff --git a/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp b/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp --- a/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp +++ b/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp @@ -29,6 +29,13 @@ bool check_signed = test_is_signed::__is_signed; +// Another, similar egregious hack for __is_unsigned, which is a type +// trait in Embarcadero's compiler but is used as an identifier in +// libstdc++. +struct test_is_unsigned { + static constexpr bool __is_unsigned = true; // expected-warning {{keyword '__is_unsigned' will be made available as an identifier}} +}; + template struct must_be_true {}; template<> struct must_be_true;