https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/142554
>From 81d30c987905ad7bdfbc6c92939a7e80a45d3a79 Mon Sep 17 00:00:00 2001 From: "A. Jiang" <d...@live.cn> Date: Tue, 3 Jun 2025 16:46:32 +0800 Subject: [PATCH] [Clang] Implement LWG3819 for `__reference_meows_from_temporary` Also fix use cases for function reference binding ( `__reference_binds_to_temporary` is also affected despite being deprecated). --- clang/docs/ReleaseNotes.rst | 9 +++++++++ clang/lib/Sema/SemaTypeTraits.cpp | 26 ++++++++++++++++++------ clang/test/SemaCXX/type-traits.cpp | 32 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a73c71cdd7201..eccee1aeef846 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -703,6 +703,15 @@ Bug Fixes to Compiler Builtins are ``__builtin_is_cpp_trivially_relocatable``. It is recommended to use ``__builtin_trivially_relocate`` instead. +- ``__reference_binds_to_temporary``, ``__reference_constructs_from_temporary`` + and ``__reference_converts_from_temporary`` intrinsics no longer consider + function references can bind to temporary objects. (#GH114344) + +- ``__reference_constructs_from_temporary`` and + ``__reference_converts_from_temporary`` intrinsics detect reference binding + to prvalue instead of xvalue now if the second operand is an object type, per + `LWG3819 <https://cplusplus.github.io/LWG/issue3819>`_. + Bug Fixes to Attribute Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125 diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 04f54d7044e4f..8578521e59cd7 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1183,9 +1183,14 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Rhs, SourceLocation KeyLoc); +namespace { +enum class ConvertibilityFrom { RawType, RefType }; +} // namespace + static ExprResult CheckConvertibilityForTypeTraits( Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, - SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) { + SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator, + ConvertibilityFrom ConvChk) { QualType LhsT = Lhs->getType(); QualType RhsT = Rhs->getType(); @@ -1224,8 +1229,11 @@ static ExprResult CheckConvertibilityForTypeTraits( Self.isAbstractType(Rhs->getTypeLoc().getBeginLoc(), RhsT)) return ExprError(); - // Compute the result of add_rvalue_reference. - if (LhsT->isObjectType() || LhsT->isFunctionType()) + // LWG3819: For reference_meows_from_temporary traits, && is not added to the + // source object type. + // Otherwise, compute the result of add_rvalue_reference. + if ((LhsT->isObjectType() && ConvChk == ConvertibilityFrom::RefType) || + LhsT->isFunctionType()) LhsT = Self.Context.getRValueReferenceType(LhsT); // Build a fake source and destination for initialization. @@ -1386,6 +1394,10 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, if (!T->isReferenceType()) return false; + // A function reference never binds to a temporary object. + if (T.getNonReferenceType()->isFunctionType()) + return false; + if (!Init.isDirectReferenceBinding()) return true; @@ -1401,7 +1413,8 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo( S.Context.getPointerType(U.getNonReferenceType())); return !CheckConvertibilityForTypeTraits(S, UPtr, TPtr, RParenLoc, - OpaqueExprAllocator) + OpaqueExprAllocator, + ConvertibilityFrom::RawType) .isInvalid(); } @@ -1654,8 +1667,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, if (RhsT->isVoidType()) return LhsT->isVoidType(); llvm::BumpPtrAllocator OpaqueExprAllocator; - ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, KeyLoc, - OpaqueExprAllocator); + ExprResult Result = CheckConvertibilityForTypeTraits( + Self, Lhs, Rhs, KeyLoc, OpaqueExprAllocator, + ConvertibilityFrom::RefType); if (Result.isInvalid()) return false; diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 56cca05402f45..3f0124755c674 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -3143,6 +3143,10 @@ void reference_binds_to_temporary_checks() { static_assert(!(__reference_binds_to_temporary(int, long))); static_assert((__reference_binds_to_temporary(const int &, long))); + + // Test that function references are never considered bound to temporaries. + static_assert(!__reference_binds_to_temporary(void(&)(), void())); + static_assert(!__reference_binds_to_temporary(void(&&)(), void())); } @@ -3156,6 +3160,14 @@ struct ExplicitConversionRef { explicit operator int&(); }; +struct NonMovable { + NonMovable(NonMovable&&) = delete; +}; + +struct ConvertsFromNonMovable { + ConvertsFromNonMovable(NonMovable); +}; + void reference_constructs_from_temporary_checks() { static_assert(!__reference_constructs_from_temporary(int &, int &)); static_assert(!__reference_constructs_from_temporary(int &, int &&)); @@ -3193,6 +3205,16 @@ void reference_constructs_from_temporary_checks() { static_assert(__reference_constructs_from_temporary(const int &, long)); + // Test that function references are never considered bound to temporaries. + static_assert(!__reference_constructs_from_temporary(void(&&)(), void())); + static_assert(!__reference_constructs_from_temporary(void(&)(), void())); + + // LWG3819: reference_meows_from_temporary should not use is_meowible + static_assert(__reference_constructs_from_temporary(ConvertsFromNonMovable&&, NonMovable) == __cplusplus >= 201703L); + // For scalar types, cv-qualifications are dropped first for prvalues. + static_assert(__reference_constructs_from_temporary(int&&, const int)); + static_assert(__reference_constructs_from_temporary(int&&, volatile int)); + // Additional checks static_assert(__reference_constructs_from_temporary(POD const&, Derives)); static_assert(__reference_constructs_from_temporary(int&&, int)); @@ -3250,6 +3272,16 @@ void reference_converts_from_temporary_checks() { static_assert(__reference_converts_from_temporary(const int &, long)); + // Test that function references are never considered bound to temporaries. + static_assert(!__reference_converts_from_temporary(void(&)(), void())); + static_assert(!__reference_converts_from_temporary(void(&&)(), void())); + + // LWG3819: reference_meows_from_temporary should not use is_meowible + static_assert(__reference_converts_from_temporary(ConvertsFromNonMovable&&, NonMovable) == __cplusplus >= 201703L); + // For scalar types, cv-qualifications are dropped first for prvalues. + static_assert(__reference_converts_from_temporary(int&&, const int)); + static_assert(__reference_converts_from_temporary(int&&, volatile int)); + // Additional checks static_assert(__reference_converts_from_temporary(POD const&, Derives)); static_assert(__reference_converts_from_temporary(int&&, int)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits