Skip to content

Commit 986254e

Browse files
[Clang] Implement LWG3819 for __reference_meows_from_temporary (#142554)
Also fix use cases for function reference binding (`__reference_binds_to_temporary` is also affected despite being deprecated).
1 parent 407a338 commit 986254e

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,15 @@ Bug Fixes to Compiler Builtins
703703
are ``__builtin_is_cpp_trivially_relocatable``. It is recommended to use
704704
``__builtin_trivially_relocate`` instead.
705705

706+
- ``__reference_binds_to_temporary``, ``__reference_constructs_from_temporary``
707+
and ``__reference_converts_from_temporary`` intrinsics no longer consider
708+
function references can bind to temporary objects. (#GH114344)
709+
710+
- ``__reference_constructs_from_temporary`` and
711+
``__reference_converts_from_temporary`` intrinsics detect reference binding
712+
to prvalue instead of xvalue now if the second operand is an object type, per
713+
`LWG3819 <https://cplusplus.github.io/LWG/issue3819>`_.
714+
706715
Bug Fixes to Attribute Support
707716
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
708717
- Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1343,12 +1343,21 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
13431343
if (RD && RD->isAbstract())
13441344
return false;
13451345

1346+
// LWG3819: For reference_meows_from_temporary traits, && is not added to
1347+
// the source object type.
1348+
// Otherwise, compute the result of add_rvalue_reference_t.
1349+
bool UseRawObjectType =
1350+
Kind == clang::BTT_ReferenceBindsToTemporary ||
1351+
Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1352+
Kind == clang::BTT_ReferenceConvertsFromTemporary;
1353+
13461354
llvm::BumpPtrAllocator OpaqueExprAllocator;
13471355
SmallVector<Expr *, 2> ArgExprs;
13481356
ArgExprs.reserve(Args.size() - 1);
13491357
for (unsigned I = 1, N = Args.size(); I != N; ++I) {
13501358
QualType ArgTy = Args[I]->getType();
1351-
if (ArgTy->isObjectType() || ArgTy->isFunctionType())
1359+
if ((ArgTy->isObjectType() && !UseRawObjectType) ||
1360+
ArgTy->isFunctionType())
13521361
ArgTy = S.Context.getRValueReferenceType(ArgTy);
13531362
ArgExprs.push_back(
13541363
new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())
@@ -1386,6 +1395,10 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
13861395
if (!T->isReferenceType())
13871396
return false;
13881397

1398+
// A function reference never binds to a temporary object.
1399+
if (T.getNonReferenceType()->isFunctionType())
1400+
return false;
1401+
13891402
if (!Init.isDirectReferenceBinding())
13901403
return true;
13911404

clang/test/SemaCXX/type-traits.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3143,6 +3143,10 @@ void reference_binds_to_temporary_checks() {
31433143
static_assert(!(__reference_binds_to_temporary(int, long)));
31443144

31453145
static_assert((__reference_binds_to_temporary(const int &, long)));
3146+
3147+
// Test that function references are never considered bound to temporaries.
3148+
static_assert(!__reference_binds_to_temporary(void(&)(), void()));
3149+
static_assert(!__reference_binds_to_temporary(void(&&)(), void()));
31463150
}
31473151

31483152

@@ -3156,6 +3160,14 @@ struct ExplicitConversionRef {
31563160
explicit operator int&();
31573161
};
31583162

3163+
struct NonMovable {
3164+
NonMovable(NonMovable&&) = delete;
3165+
};
3166+
3167+
struct ConvertsFromNonMovable {
3168+
ConvertsFromNonMovable(NonMovable);
3169+
};
3170+
31593171
void reference_constructs_from_temporary_checks() {
31603172
static_assert(!__reference_constructs_from_temporary(int &, int &));
31613173
static_assert(!__reference_constructs_from_temporary(int &, int &&));
@@ -3193,6 +3205,16 @@ void reference_constructs_from_temporary_checks() {
31933205

31943206
static_assert(__reference_constructs_from_temporary(const int &, long));
31953207

3208+
// Test that function references are never considered bound to temporaries.
3209+
static_assert(!__reference_constructs_from_temporary(void(&&)(), void()));
3210+
static_assert(!__reference_constructs_from_temporary(void(&)(), void()));
3211+
3212+
// LWG3819: reference_meows_from_temporary should not use is_meowible
3213+
static_assert(__reference_constructs_from_temporary(ConvertsFromNonMovable&&, NonMovable) == __cplusplus >= 201703L);
3214+
// For scalar types, cv-qualifications are dropped first for prvalues.
3215+
static_assert(__reference_constructs_from_temporary(int&&, const int));
3216+
static_assert(__reference_constructs_from_temporary(int&&, volatile int));
3217+
31963218
// Additional checks
31973219
static_assert(__reference_constructs_from_temporary(POD const&, Derives));
31983220
static_assert(__reference_constructs_from_temporary(int&&, int));
@@ -3250,6 +3272,16 @@ void reference_converts_from_temporary_checks() {
32503272

32513273
static_assert(__reference_converts_from_temporary(const int &, long));
32523274

3275+
// Test that function references are never considered bound to temporaries.
3276+
static_assert(!__reference_converts_from_temporary(void(&)(), void()));
3277+
static_assert(!__reference_converts_from_temporary(void(&&)(), void()));
3278+
3279+
// LWG3819: reference_meows_from_temporary should not use is_meowible
3280+
static_assert(__reference_converts_from_temporary(ConvertsFromNonMovable&&, NonMovable) == __cplusplus >= 201703L);
3281+
// For scalar types, cv-qualifications are dropped first for prvalues.
3282+
static_assert(__reference_converts_from_temporary(int&&, const int));
3283+
static_assert(__reference_converts_from_temporary(int&&, volatile int));
3284+
32533285
// Additional checks
32543286
static_assert(__reference_converts_from_temporary(POD const&, Derives));
32553287
static_assert(__reference_converts_from_temporary(int&&, int));

0 commit comments

Comments
 (0)