cjdb updated this revision to Diff 466318. cjdb retitled this revision from "[clang] adds `__reference_constructs_from_temporary` and `__reference_converts_from_temporary`" to "[clang] adds `__reference_constructs_from_temporary`". cjdb added a comment.
discards work on `__reference_converts_from_temporary` for now. This feature isn't as trivial to implement as `__reference_constructs_from_temporary`, so it's deserving of its own commit. The two features are used exclusively, so it's not like adding one without the other will lead to an incomplete standard type. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D135341/new/ https://reviews.llvm.org/D135341 Files: clang/docs/LanguageExtensions.rst clang/include/clang/Basic/DiagnosticCommonKinds.td clang/lib/Lex/PPMacroExpansion.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Parse/ParseExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/SemaCXX/type-traits.cpp clang/www/cxx_status.html
Index: clang/www/cxx_status.html =================================================================== --- clang/www/cxx_status.html +++ clang/www/cxx_status.html @@ -1419,10 +1419,9 @@ <td><a href="https://wg21.link/P2255R2">P2255R2</a></td> <td class="partial" align="center"> <details><summary>Partial</summary> - Clang provides a <tt>__reference_binds_to_temporary</tt> type trait - builtin, with which the library facility can be partially implemented. - Both <tt>__reference_constructs_from_temporary</tt> and - <tt>__reference_converts_from_temporary</tt> builtins should be + Clang provides <tt>__reference_constructs_from_temporary</tt> type + trait builtin, with which <tt>std::reference_constructs_from_temporary</tt> + implemented. <tt>__reference_converts_from_temporary</tt> needs to be provided, following the normal cross-vendor convention to implement traits requiring compiler support directly. </details></td> Index: clang/test/SemaCXX/type-traits.cpp =================================================================== --- clang/test/SemaCXX/type-traits.cpp +++ clang/test/SemaCXX/type-traits.cpp @@ -2535,6 +2535,55 @@ { int arr[T((__reference_binds_to_temporary(const int &, long)))]; } } +void reference_constructs_from_temporary_checks() { + static_assert(!__reference_constructs_from_temporary(int &, int &), ""); + static_assert(!__reference_constructs_from_temporary(int &, int &&), ""); + + static_assert(!__reference_constructs_from_temporary(int const &, int &), ""); + static_assert(!__reference_constructs_from_temporary(int const &, int const &), ""); + static_assert(!__reference_constructs_from_temporary(int const &, int &&), ""); + + static_assert(!__reference_constructs_from_temporary(int &, long &), ""); // doesn't construct + + static_assert(__reference_constructs_from_temporary(int const &, long &), ""); + static_assert(__reference_constructs_from_temporary(int const &, long &&), ""); + static_assert(__reference_constructs_from_temporary(int &&, long &), ""); + + using LRef = ConvertsToRef<int, int &>; + using RRef = ConvertsToRef<int, int &&>; + using CLRef = ConvertsToRef<int, const int &>; + using LongRef = ConvertsToRef<long, long &>; + static_assert(__is_constructible(int &, LRef), ""); + static_assert(!__reference_constructs_from_temporary(int &, LRef), ""); + + static_assert(__is_constructible(int &&, RRef), ""); + static_assert(!__reference_constructs_from_temporary(int &&, RRef), ""); + + static_assert(__is_constructible(int const &, CLRef), ""); + static_assert(!__reference_constructs_from_temporary(int &&, CLRef), ""); + + static_assert(__is_constructible(int const &, LongRef), ""); + static_assert(__reference_constructs_from_temporary(int const &, LongRef), ""); + + // Test that it doesn't accept non-reference types as input. + static_assert(!__reference_constructs_from_temporary(int, long), ""); + + static_assert(__reference_constructs_from_temporary(const int &, long), ""); + + // Additional checks + static_assert(__reference_constructs_from_temporary(POD const&, Derives), ""); + static_assert(__reference_constructs_from_temporary(int&&, int), ""); + static_assert(__reference_constructs_from_temporary(const int&, int), ""); + static_assert(!__reference_constructs_from_temporary(int&&, int&&), ""); + static_assert(!__reference_constructs_from_temporary(const int&, int&&), ""); + static_assert(__reference_constructs_from_temporary(int&&, long&&), ""); + static_assert(__reference_constructs_from_temporary(int&&, long), ""); +} + +void reference_converts_from_temporary() { + (void)__reference_converts_from_temporary(int, int); // expected-error{{'__reference_converts_from_temporary' is a compiler-reserved identifier for a future feature}} +} + void array_rank() { int t01[T(__array_rank(IntAr) == 1)]; int t02[T(__array_rank(ConstIntArAr) == 2)]; Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" @@ -5325,14 +5326,15 @@ if (Kind <= UTT_Last) return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType()); - // Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible - // traits to avoid duplication. - if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary) + // Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary + // alongside the IsConstructible traits to avoid duplication. + if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary && Kind != BTT_ReferenceConstructsFromTemporary) return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(), Args[1]->getType(), RParenLoc); switch (Kind) { case clang::BTT_ReferenceBindsToTemporary: + case clang::BTT_ReferenceConstructsFromTemporary: case clang::TT_IsConstructible: case clang::TT_IsNothrowConstructible: case clang::TT_IsTriviallyConstructible: { @@ -5409,11 +5411,23 @@ if (Kind == clang::TT_IsConstructible) return true; - if (Kind == clang::BTT_ReferenceBindsToTemporary) { + if (Kind == clang::BTT_ReferenceBindsToTemporary || Kind == clang::BTT_ReferenceConstructsFromTemporary) { if (!T->isReferenceType()) return false; - return !Init.isDirectReferenceBinding(); + if (!Init.isDirectReferenceBinding()) + return true; + + if (Kind == clang::BTT_ReferenceBindsToTemporary) + return false; + + QualType U = Args[1]->getType(); + if (U->isReferenceType()) + return false; + + QualType TPtr = S.BuiltinAddPointer(S.BuiltinRemoveReference(T, UnaryTransformType::RemoveCVRef, {}), {}); + QualType UPtr = S.BuiltinAddPointer(S.BuiltinRemoveReference(U, UnaryTransformType::RemoveCVRef, {}), {}); + return EvaluateBinaryTypeTrait(S, TypeTrait::BTT_IsConvertibleTo, UPtr, TPtr, RParenLoc); } if (Kind == clang::TT_IsNothrowConstructible) @@ -5601,6 +5615,10 @@ QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals); return Self.Context.typesAreCompatible(Lhs, Rhs); } + case BTT_ReferenceConvertsFromTemporary: { + std::string Spelling = "'" + std::string(getTraitSpelling(BTT)) + "'"; + return Self.Diag(KeyLoc, diag::err_reserved_identifier_for_future_use) << Spelling; + } case BTT_IsConvertible: case BTT_IsConvertibleTo: { // C++0x [meta.rel]p4: Index: clang/lib/Parse/ParseExpr.cpp =================================================================== --- clang/lib/Parse/ParseExpr.cpp +++ clang/lib/Parse/ParseExpr.cpp @@ -1118,6 +1118,9 @@ REVERTIBLE_TYPE_TRAIT(__is_unsigned); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); + REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); + REVERTIBLE_TYPE_TRAIT(__reference_constructs_from_temporary); + REVERTIBLE_TYPE_TRAIT(__reference_converts_from_temporary); #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); #include "clang/Basic/TransformTypeTraits.def" Index: clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- clang/lib/Parse/ParseDeclCXX.cpp +++ clang/lib/Parse/ParseDeclCXX.cpp @@ -1628,7 +1628,10 @@ tok::kw___is_union, tok::kw___is_unsigned, tok::kw___is_void, - tok::kw___is_volatile)) + tok::kw___is_volatile, + tok::kw___reference_binds_to_temporary, + tok::kw___reference_constructs_from_temporary, + tok::kw___reference_converts_from_temporary)) // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 // and Clang. Therefore, when we see the token sequence "struct Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -1700,6 +1700,8 @@ .Case("__array_rank", true) .Case("__array_extent", true) .Case("__reference_binds_to_temporary", true) + .Case("__reference_constructs_from_temporary", true) + .Case("__reference_converts_from_temporary", true) #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true) #include "clang/Basic/TransformTypeTraits.def" .Default(false); Index: clang/include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticCommonKinds.td +++ clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -392,4 +392,7 @@ "options %0 and %1 are set to different values">; def err_opencl_feature_requires : Error< "feature %0 requires support of %1 feature">; + +def err_reserved_identifier_for_future_use : Error< + "%0 is a compiler-reserved identifier for a future feature">; } Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -1474,6 +1474,7 @@ materialized temporary object. If ``T`` is not a reference type the result is false. Note this trait will also return false when the initialization of ``T`` from ``U`` is ill-formed. +* ``__reference_constructs_from_temporary(T, U)`` (C++) * ``__underlying_type`` (C++, GNU, Microsoft) In addition, the following expression traits are supported:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits