llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) <details> <summary>Changes</summary> Constructs like `__is_pointer(Foo)` are never considered to be functions declarations. This matches usages in libstdc++, and we can hope no one else redefine these reserved identifiers. Fixes #<!-- -->95598 --- Full diff: https://github.com/llvm/llvm-project/pull/95969.diff 5 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1-1) - (modified) clang/include/clang/Parse/Parser.h (+4) - (modified) clang/lib/Parse/ParseExpr.cpp (+84-79) - (modified) clang/lib/Parse/ParseTentative.cpp (+6) - (modified) clang/test/Parser/cxx-template-argument.cpp (+12) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0f958d213172a..e4cd93a3635d9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -872,7 +872,7 @@ Bug Fixes to C++ Support between the addresses of two labels (a GNU extension) to a pointer within a constant expression. (#GH95366). - Fix immediate escalation bugs in the presence of dependent call arguments. (#GH94935) - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - +- Fix parsing of built-in type-traits such as ``__is_pointer`` in libstdc++ headers. (#GH95598) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d054b8cf0d240..b84d59605cc45 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1877,6 +1877,10 @@ class Parser : public CodeCompletionHandler { UnaryExprOnly, PrimaryExprOnly }; + + bool isRevertibleTypeTrait(const IdentifierInfo *Id, + clang::tok::TokenKind *Kind = nullptr); + ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index eb7447fa038e4..132bf283158d0 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -760,6 +760,87 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { }; } +bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II, + tok::TokenKind *Kind) { + if (RevertibleTypeTraits.empty()) { +#define RTT_JOIN(X, Y) X##Y +#define REVERTIBLE_TYPE_TRAIT(Name) \ + RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] = RTT_JOIN(tok::kw_, Name) + + REVERTIBLE_TYPE_TRAIT(__is_abstract); + REVERTIBLE_TYPE_TRAIT(__is_aggregate); + REVERTIBLE_TYPE_TRAIT(__is_arithmetic); + REVERTIBLE_TYPE_TRAIT(__is_array); + REVERTIBLE_TYPE_TRAIT(__is_assignable); + REVERTIBLE_TYPE_TRAIT(__is_base_of); + REVERTIBLE_TYPE_TRAIT(__is_bounded_array); + REVERTIBLE_TYPE_TRAIT(__is_class); + REVERTIBLE_TYPE_TRAIT(__is_complete_type); + REVERTIBLE_TYPE_TRAIT(__is_compound); + REVERTIBLE_TYPE_TRAIT(__is_const); + REVERTIBLE_TYPE_TRAIT(__is_constructible); + REVERTIBLE_TYPE_TRAIT(__is_convertible); + REVERTIBLE_TYPE_TRAIT(__is_convertible_to); + REVERTIBLE_TYPE_TRAIT(__is_destructible); + REVERTIBLE_TYPE_TRAIT(__is_empty); + REVERTIBLE_TYPE_TRAIT(__is_enum); + REVERTIBLE_TYPE_TRAIT(__is_floating_point); + REVERTIBLE_TYPE_TRAIT(__is_final); + REVERTIBLE_TYPE_TRAIT(__is_function); + REVERTIBLE_TYPE_TRAIT(__is_fundamental); + REVERTIBLE_TYPE_TRAIT(__is_integral); + REVERTIBLE_TYPE_TRAIT(__is_interface_class); + REVERTIBLE_TYPE_TRAIT(__is_layout_compatible); + REVERTIBLE_TYPE_TRAIT(__is_literal); + REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr); + REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference); + REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer); + REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer); + REVERTIBLE_TYPE_TRAIT(__is_member_pointer); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible); + REVERTIBLE_TYPE_TRAIT(__is_nullptr); + REVERTIBLE_TYPE_TRAIT(__is_object); + REVERTIBLE_TYPE_TRAIT(__is_pod); + REVERTIBLE_TYPE_TRAIT(__is_pointer); + REVERTIBLE_TYPE_TRAIT(__is_polymorphic); + REVERTIBLE_TYPE_TRAIT(__is_reference); + REVERTIBLE_TYPE_TRAIT(__is_referenceable); + REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr); + REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference); + REVERTIBLE_TYPE_TRAIT(__is_same); + REVERTIBLE_TYPE_TRAIT(__is_scalar); + REVERTIBLE_TYPE_TRAIT(__is_scoped_enum); + REVERTIBLE_TYPE_TRAIT(__is_sealed); + REVERTIBLE_TYPE_TRAIT(__is_signed); + REVERTIBLE_TYPE_TRAIT(__is_standard_layout); + REVERTIBLE_TYPE_TRAIT(__is_trivial); + REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); + REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); + REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); + REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); + REVERTIBLE_TYPE_TRAIT(__is_union); + REVERTIBLE_TYPE_TRAIT(__is_unsigned); + REVERTIBLE_TYPE_TRAIT(__is_void); + REVERTIBLE_TYPE_TRAIT(__is_volatile); + REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ + REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); +#include "clang/Basic/TransformTypeTraits.def" +#undef REVERTIBLE_TYPE_TRAIT +#undef RTT_JOIN + } + llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known = + RevertibleTypeTraits.find(II); + if (Known != RevertibleTypeTraits.end()) { + if (Kind) + *Kind = Known->second; + return true; + } + return false; +} + /// Parse a cast-expression, or, if \pisUnaryExpression is true, parse /// a unary-expression. /// @@ -1103,85 +1184,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, else if (Next.is(tok::l_paren) && Tok.is(tok::identifier) && Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { IdentifierInfo *II = Tok.getIdentifierInfo(); - // Build up the mapping of revertible type traits, for future use. - if (RevertibleTypeTraits.empty()) { -#define RTT_JOIN(X,Y) X##Y -#define REVERTIBLE_TYPE_TRAIT(Name) \ - RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \ - = RTT_JOIN(tok::kw_,Name) - - REVERTIBLE_TYPE_TRAIT(__is_abstract); - REVERTIBLE_TYPE_TRAIT(__is_aggregate); - REVERTIBLE_TYPE_TRAIT(__is_arithmetic); - REVERTIBLE_TYPE_TRAIT(__is_array); - REVERTIBLE_TYPE_TRAIT(__is_assignable); - REVERTIBLE_TYPE_TRAIT(__is_base_of); - REVERTIBLE_TYPE_TRAIT(__is_bounded_array); - REVERTIBLE_TYPE_TRAIT(__is_class); - REVERTIBLE_TYPE_TRAIT(__is_complete_type); - REVERTIBLE_TYPE_TRAIT(__is_compound); - REVERTIBLE_TYPE_TRAIT(__is_const); - REVERTIBLE_TYPE_TRAIT(__is_constructible); - REVERTIBLE_TYPE_TRAIT(__is_convertible); - REVERTIBLE_TYPE_TRAIT(__is_convertible_to); - REVERTIBLE_TYPE_TRAIT(__is_destructible); - REVERTIBLE_TYPE_TRAIT(__is_empty); - REVERTIBLE_TYPE_TRAIT(__is_enum); - REVERTIBLE_TYPE_TRAIT(__is_floating_point); - REVERTIBLE_TYPE_TRAIT(__is_final); - REVERTIBLE_TYPE_TRAIT(__is_function); - REVERTIBLE_TYPE_TRAIT(__is_fundamental); - REVERTIBLE_TYPE_TRAIT(__is_integral); - REVERTIBLE_TYPE_TRAIT(__is_interface_class); - REVERTIBLE_TYPE_TRAIT(__is_layout_compatible); - REVERTIBLE_TYPE_TRAIT(__is_literal); - REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr); - REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference); - REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer); - REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer); - REVERTIBLE_TYPE_TRAIT(__is_member_pointer); - REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable); - REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible); - REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible); - REVERTIBLE_TYPE_TRAIT(__is_nullptr); - REVERTIBLE_TYPE_TRAIT(__is_object); - REVERTIBLE_TYPE_TRAIT(__is_pod); - REVERTIBLE_TYPE_TRAIT(__is_pointer); - REVERTIBLE_TYPE_TRAIT(__is_polymorphic); - REVERTIBLE_TYPE_TRAIT(__is_reference); - REVERTIBLE_TYPE_TRAIT(__is_referenceable); - REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr); - REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference); - REVERTIBLE_TYPE_TRAIT(__is_same); - REVERTIBLE_TYPE_TRAIT(__is_scalar); - REVERTIBLE_TYPE_TRAIT(__is_scoped_enum); - REVERTIBLE_TYPE_TRAIT(__is_sealed); - REVERTIBLE_TYPE_TRAIT(__is_signed); - REVERTIBLE_TYPE_TRAIT(__is_standard_layout); - REVERTIBLE_TYPE_TRAIT(__is_trivial); - REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); - REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); - REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); - REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); - REVERTIBLE_TYPE_TRAIT(__is_union); - REVERTIBLE_TYPE_TRAIT(__is_unsigned); - REVERTIBLE_TYPE_TRAIT(__is_void); - REVERTIBLE_TYPE_TRAIT(__is_volatile); - REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); -#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ - REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); -#include "clang/Basic/TransformTypeTraits.def" -#undef REVERTIBLE_TYPE_TRAIT -#undef RTT_JOIN - } - - // If we find that this is in fact the name of a type trait, - // update the token kind in place and parse again to treat it as - // the appropriate kind of type trait. - llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known - = RevertibleTypeTraits.find(II); - if (Known != RevertibleTypeTraits.end()) { - Tok.setKind(Known->second); + tok::TokenKind Kind; + if (isRevertibleTypeTrait(II, &Kind)) { + Tok.setKind(Kind); return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression); diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index ea17c3e3252ec..dac7a6a662f6e 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1385,6 +1385,12 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, if (!getLangOpts().ObjC && Next.is(tok::identifier)) return TPResult::True; + if (Next.is(tok::l_paren) && + Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() && + isRevertibleTypeTrait(Tok.getIdentifierInfo())) { + return TPResult::False; + } + if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { // Determine whether this is a valid expression. If not, we will hit // a parse error one way or another. In that case, tell the caller that diff --git a/clang/test/Parser/cxx-template-argument.cpp b/clang/test/Parser/cxx-template-argument.cpp index 667dd8698435b..3c2169f86d6e7 100644 --- a/clang/test/Parser/cxx-template-argument.cpp +++ b/clang/test/Parser/cxx-template-argument.cpp @@ -141,3 +141,15 @@ namespace r360308_regression { return a == b; } } + +namespace GH95598 { +template<typename _Tp, bool _IsPtr = __is_pointer(_Tp)> +struct __is_pointer {}; +// expected-warning@-1 {{keyword '__is_pointer' will be made available as an identifier for the remainder of the translation unit}} + +template<bool> +struct ts{}; + +template<typename _Tp> + struct is_pointer : ts<__is_pointer(_Tp)> {}; +} `````````` </details> https://github.com/llvm/llvm-project/pull/95969 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits