[clang] 8f3b0b4 - [clang] adds `__reference_constructs_from_temporary`
Christopher Di Bella via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 13 16:52:01 PDT 2023
Author: Christopher Di Bella
Date: 2023-09-13T23:51:43Z
New Revision: 8f3b0b4171431ced5550d5c8a70d1b683343f062
URL: https://github.com/llvm/llvm-project/commit/8f3b0b4171431ced5550d5c8a70d1b683343f062
DIFF: https://github.com/llvm/llvm-project/commit/8f3b0b4171431ced5550d5c8a70d1b683343f062.diff
LOG: [clang] adds `__reference_constructs_from_temporary`
This is information that the compiler already has, and should be exposed
so that the library doesn't need to reimplement the exact same
functionality.
Differential Revision: https://reviews.llvm.org/D135341
Added:
Modified:
clang/docs/LanguageExtensions.rst
clang/include/clang/Basic/TokenKinds.def
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
Removed:
################################################################################
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 11cbdca7a268fc3..b9466b5a0bc2087 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1621,6 +1621,10 @@ The following type trait primitives are supported by Clang. Those traits marked
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
index 45ebc200b168986..72e8df8c793a7b6 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -531,6 +531,7 @@ TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
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
index 775cbfafa999602..ec6a084f228f32d 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1695,6 +1695,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.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
index 730b6e55246d6b7..5fe9abb1fdcab30 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1655,7 +1655,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
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
index f8bf785da2896a3..74664c34abdbd89 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1128,6 +1128,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
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
index a7be01319a72393..bb4ef065d5c72aa 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5410,14 +5410,15 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
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 +5495,23 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
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.Context.getPointerType(S.BuiltinRemoveReference(T, UnaryTransformType::RemoveCVRef, {}));
+ QualType UPtr = S.Context.getPointerType(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
index 0fb364eaf362664..a35689d52978fcc 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -2542,6 +2542,51 @@ void reference_binds_to_temporary_checks() {
{ 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 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
index da0a1c219c0ecc7..d888c8487abe819 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -292,10 +292,9 @@ <h2 id="cxx23">C++23 implementation status</h2>
<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>
+ is 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>
More information about the cfe-commits
mailing list