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

Reply via email to