diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1621,6 +1621,10 @@ 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. + Deprecated, use ``__reference_constructs_from_temporary``. +* ``__reference_constructs_from_temporary(T, U)`` (C++) + Returns true if a reference ``T`` can be constructed from a temporary of type + a non-cv-qualified ``U``. * ``__underlying_type`` (C++, GNU, Microsoft) In addition, the following expression traits are supported: diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -531,6 +531,7 @@ TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX) TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) +TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1695,6 +1695,7 @@ .Case("__array_rank", true) .Case("__array_extent", true) .Case("__reference_binds_to_temporary", true) + .Case("__reference_constructs_from_temporary", true) #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true) #include "clang/Basic/TransformTypeTraits.def" .Default(false); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1655,7 +1655,9 @@ 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)) // 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 diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1128,6 +1128,8 @@ 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); #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); #include "clang/Basic/TransformTypeTraits.def" diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -30,6 +30,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/EnterExpressionEvaluationContext.h" @@ -5410,14 +5411,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: { @@ -5494,11 +5496,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) diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -2542,6 +2542,51 @@ { 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; + using RRef = ConvertsToRef; + using CLRef = ConvertsToRef; + using LongRef = ConvertsToRef; + 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 array_rank() { int t01[T(__array_rank(IntAr) == 1)]; int t02[T(__array_rank(ConstIntArAr) == 2)]; diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -228,199 +228,6 @@ P2797R0 No - - Change scope of lambda trailing-return-type - P2036R3 - Clang 17 - - - P2579R0 - - - Multidimensional subscript operator - P2128R6 - Clang 15 - - - Non-literal variables (and labels and gotos) in constexpr functions - P2242R3 - Clang 15 - - - Character encoding of diagnostic text - P2246R1 - Yes - - - Character sets and encodings - P2314R4 - Yes - - - Consistent character literal encoding - P2316R2 - Yes - - - Add support for preprocessing directives elifdef and elifndef - P2334R1 - Clang 13 - - - Extend init-statement to allow alias-declaration - P2360R0 - Clang 14 - - - auto(x): decay-copy in the language - P0849R8 - Clang 15 - - - - Attributes on Lambda-Expressions - P2173R1 - Clang 13 - - - constexpr for <cmath> and <cstdlib> - P0533R9 - No - - - Type trait to determine if a reference binds to a temporary - P2255R2 - -
Partial - Clang provides a __reference_binds_to_temporary type trait - builtin, with which the library facility can be partially implemented. - Both __reference_constructs_from_temporary and - __reference_converts_from_temporary builtins should be - provided, following the normal cross-vendor convention to implement - traits requiring compiler support directly. -
- - - - - The Equality Operator You Are Looking For - P2468R2 - Clang 16 - - - De-deprecating volatile compound operations - P2327R1 - Clang 15 - - - Support for #warning - P2437R1 - Yes - - - Remove non-encodable wide character literals and multicharacter wide character literals - P2362R3 - Clang 14 - - - Labels at the end of compound statements - P2324R2 - Clang 16 - - - Delimited escape sequences - P2290R3 - Clang 15 - - - Named universal character escapes - P2071R2 - Clang 15 - - - Relaxing some constexpr restrictions - P2448R2 - -
Clang 17 (Partial) - We do not support outside of defaulted special memeber functions the change that constexpr functions no - longer have to be constexpr compatible but rather support a less restricted requirements for constexpr - functions. Which include allowing non-literal types as return values and parameters, allow calling of - non-constexpr functions and constructors. -
- - - - Using unknown pointers and references in constant expressions - P2280R4 (DR) - No - - - static operator() - P1169R4 - Clang 16 - - - Extended floating-point types and standard names - P1467R9 - No - - - Class template argument deduction from inherited constructors - P2582R1 - No - - - Portable assumptions - P1774R8 - No - - - Support for UTF-8 as a portable source file encoding - P2295R6 - Clang 15 - - - char8_t Compatibility and Portability Fix - P2513R3 - Clang 16 - - - Relax requirements on wchar_t to match existing practices - P2460R2 - Yes - - - Explicit lifetime management - P2590R2 - No - - - - static operator[] - P2589R1 - Clang 16 - - - Permitting static constexpr variables in constexpr functions - P2647R1 - Clang 16 - - - consteval needs to propagate up - P2564R3 (DR) - Clang 17 - - - Lifetime extension in range-based for loops - P2718R0 - No - - - - Referencing The Unicode Standard - P2736R2 - Yes - @@ -1091,6 +898,197 @@ P0195R2 Clang 4 + Change scope of lambda trailing-return-type + P2036R3 + Clang 17 + + + P2579R0 + + + Multidimensional subscript operator + P2128R6 + Clang 15 + + + Non-literal variables (and labels and gotos) in constexpr functions + P2242R3 + Clang 15 + + + Character encoding of diagnostic text + P2246R1 + Yes + + + Character sets and encodings + P2314R4 + Yes + + + Consistent character literal encoding + P2316R2 + Yes + + + Add support for preprocessing directives elifdef and elifndef + P2334R1 + Clang 13 + + + Extend init-statement to allow alias-declaration + P2360R0 + Clang 14 + + + auto(x): decay-copy in the language + P0849R8 + Clang 15 + + + + Attributes on Lambda-Expressions + P2173R1 + Clang 13 + + + constexpr for <cmath> and <cstdlib> + P0533R9 + No + + + Type trait to determine if a reference binds to a temporary + P2255R2 + +
Partial + Clang provides a __reference_binds_to_temporary type trait + builtin, with which the library facility can be partially implemented. + Both __reference_constructs_from_temporary and + __reference_converts_from_temporary builtins should be + provided, following the normal cross-vendor convention to implement + traits requiring compiler support directly. + + + + + The Equality Operator You Are Looking For + P2468R2 + Clang 16 + + + De-deprecating volatile compound operations + P2327R1 + Clang 15 + + + Support for #warning + P2437R1 + Yes + + + Remove non-encodable wide character literals and multicharacter wide character literals + P2362R3 + Clang 14 + + + Labels at the end of compound statements + P2324R2 + Clang 16 + + + Delimited escape sequences + P2290R3 + Clang 15 + + + Named universal character escapes + P2071R2 + Clang 15 + + + Relaxing some constexpr restrictions + P2448R2 + +
Clang 17 (Partial) + We do not support outside of defaulted special memeber functions the change that constexpr functions no + longer have to be constexpr compatible but rather support a less restricted requirements for constexpr + functions. Which include allowing non-literal types as return values and paremeters, allow calling of + non-constexpr functions and constructors. +
+ + + + Using unknown pointers and references in constant expressions + P2280R4 + No + + + static operator() + P1169R4 + Clang 16 + + + Extended floating-point types and standard names + P1467R9 + No + + + Class template argument deduction from inherited constructors + P2582R1 + No + + + Portable assumptions + P1774R8 + No + + + Support for UTF-8 as a portable source file encoding + P2295R6 + Clang 15 + + + char8_t Compatibility and Portability Fix + P2513R3 + Clang 16 + + + Relax requirements on wchar_t to match existing practices + P2460R2 + Yes + + + Explicit lifetime management + P2590R2 + No + + + + static operator[] + P2589R1 + Clang 16 + + + Permitting static constexpr variables in constexpr functions + P2647R1 + Clang 16 + + + consteval needs to propagate up + P2564R3 (DR) + No + + + Lifetime extension in range-based for loops + P2718R0 + No + + + + Referencing The Unicode Standard + P2736R2 + Yes +