[clang] e718403 - [Clang] Implement C++26 P2748R5 "Disallow Binding a Returned Glvalue to a Temporary" (#89942)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 29 07:00:14 PDT 2024
Author: yronglin
Date: 2024-04-29T22:00:10+08:00
New Revision: e71840305d621dcc43d5253e332db990220b7fcb
URL: https://github.com/llvm/llvm-project/commit/e71840305d621dcc43d5253e332db990220b7fcb
DIFF: https://github.com/llvm/llvm-project/commit/e71840305d621dcc43d5253e332db990220b7fcb.diff
LOG: [Clang] Implement C++26 P2748R5 "Disallow Binding a Returned Glvalue to a Temporary" (#89942)
Implement P2748R5 "Disallow Binding a Returned Glvalue to a Temporary"
https://wg21.link/P2748R5
---------
Signed-off-by: yronglin <yronglin777 at gmail.com>
Added:
clang/test/CXX/stmt.stmt/stmt.return/p6.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaInit.cpp
clang/test/CXX/drs/cwg650.cpp
clang/test/SemaCXX/type-traits.cpp
clang/www/cxx_status.html
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 604782ca43dd54..347c81253d39e6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -145,6 +145,7 @@ C++2c Feature Support
- Implemented `P0609R3: Attributes for Structured Bindings <https://wg21.link/P0609R3>`_
+- Implemented `P2748R5 Disallow Binding a Returned Glvalue to a Temporary <https://wg21.link/P2748R5>`_.
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..8486fa3a02e833 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9950,6 +9950,8 @@ def warn_ret_stack_addr_ref : Warning<
def warn_ret_local_temp_addr_ref : Warning<
"returning %select{address of|reference to}0 local temporary object">,
InGroup<ReturnStackAddress>;
+def err_ret_local_temp_ref : Error<
+ "returning reference to local temporary object">;
def warn_ret_addr_label : Warning<
"returning address of label, which is local">,
InGroup<ReturnStackAddress>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 842d165c60d94c..7d9eaf6720461d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -8340,8 +8340,17 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
<< Entity.getType()->isReferenceType() << CLE->getInitializer() << 2
<< DiagRange;
} else {
- Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
- << Entity.getType()->isReferenceType() << DiagRange;
+ // P2748R5: Disallow Binding a Returned Glvalue to a Temporary.
+ // [stmt.return]/p6: In a function whose return type is a reference,
+ // other than an invented function for std::is_convertible ([meta.rel]),
+ // a return statement that binds the returned reference to a temporary
+ // expression ([class.temporary]) is ill-formed.
+ if (getLangOpts().CPlusPlus26 && Entity.getType()->isReferenceType())
+ Diag(DiagLoc, diag::err_ret_local_temp_ref)
+ << Entity.getType()->isReferenceType() << DiagRange;
+ else
+ Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
+ << Entity.getType()->isReferenceType() << DiagRange;
}
break;
}
diff --git a/clang/test/CXX/drs/cwg650.cpp b/clang/test/CXX/drs/cwg650.cpp
index dcb844095b0598..33ea179986e32b 100644
--- a/clang/test/CXX/drs/cwg650.cpp
+++ b/clang/test/CXX/drs/cwg650.cpp
@@ -4,7 +4,7 @@
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
-// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// We aren't testing this since C++26 because of P2748R5 "Disallow Binding a Returned Glvalue to a Temporary".
#if __cplusplus == 199711L
#define NOTHROW throw()
diff --git a/clang/test/CXX/stmt.stmt/stmt.return/p6.cpp b/clang/test/CXX/stmt.stmt/stmt.return/p6.cpp
new file mode 100644
index 00000000000000..c192b0c8112a73
--- /dev/null
+++ b/clang/test/CXX/stmt.stmt/stmt.return/p6.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++26 -fsyntax-only -verify %s
+
+auto&& f1() {
+ return 42; // expected-error{{returning reference to local temporary object}}
+}
+const double& f2() {
+ static int x = 42;
+ return x; // expected-error{{returning reference to local temporary object}}
+}
+auto&& id(auto&& r) {
+ return static_cast<decltype(r)&&>(r);
+}
+auto&& f3() {
+ return id(42); // OK, but probably a bug
+}
+
+void unevaluated() {
+ using a = decltype ([] () -> const int & {
+ const int &i = 0; // expected-note {{binding reference variable 'i' here}}
+ return i; // expected-error{{returning reference to local temporary object}}
+} ());
+}
+
+static_assert(__is_convertible(int, const int &));
+static_assert(__is_nothrow_convertible(int, const int &));
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index dee4a29bd2bffe..01991887b284a7 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -2509,6 +2509,20 @@ void is_convertible()
static_assert(__is_convertible(FloatWrapper, IntWrapper));
static_assert(__is_convertible(FloatWrapper, float));
static_assert(__is_convertible(float, FloatWrapper));
+ static_assert(__is_convertible(IntWrapper, IntWrapper&&));
+ static_assert(__is_convertible(IntWrapper, const IntWrapper&));
+ static_assert(__is_convertible(IntWrapper, int&&));
+ static_assert(__is_convertible(IntWrapper, const int&));
+ static_assert(__is_convertible(int, IntWrapper&&));
+ static_assert(__is_convertible(int, const IntWrapper&));
+ static_assert(__is_convertible(IntWrapper, FloatWrapper&&));
+ static_assert(__is_convertible(IntWrapper, const FloatWrapper&));
+ static_assert(__is_convertible(FloatWrapper, IntWrapper&&));
+ static_assert(__is_convertible(FloatWrapper, const IntWrapper&&));
+ static_assert(__is_convertible(FloatWrapper, float&&));
+ static_assert(__is_convertible(FloatWrapper, const float&));
+ static_assert(__is_convertible(float, FloatWrapper&&));
+ static_assert(__is_convertible(float, const FloatWrapper&));
}
void is_nothrow_convertible()
@@ -2521,6 +2535,20 @@ void is_nothrow_convertible()
static_assert(!__is_nothrow_convertible(FloatWrapper, IntWrapper));
static_assert(!__is_nothrow_convertible(FloatWrapper, float));
static_assert(__is_nothrow_convertible(float, FloatWrapper));
+ static_assert(__is_nothrow_convertible(IntWrapper, IntWrapper&&));
+ static_assert(__is_nothrow_convertible(IntWrapper, const IntWrapper&));
+ static_assert(__is_nothrow_convertible(IntWrapper, int&&));
+ static_assert(__is_nothrow_convertible(IntWrapper, const int&));
+ static_assert(!__is_nothrow_convertible(int, IntWrapper&&));
+ static_assert(!__is_nothrow_convertible(int, const IntWrapper&));
+ static_assert(!__is_nothrow_convertible(IntWrapper, FloatWrapper&&));
+ static_assert(!__is_nothrow_convertible(IntWrapper, const FloatWrapper&));
+ static_assert(!__is_nothrow_convertible(FloatWrapper, IntWrapper&&));
+ static_assert(!__is_nothrow_convertible(FloatWrapper, const IntWrapper&));
+ static_assert(!__is_nothrow_convertible(FloatWrapper, float&&));
+ static_assert(!__is_nothrow_convertible(FloatWrapper, const float&));
+ static_assert(__is_nothrow_convertible(float, FloatWrapper&&));
+ static_assert(__is_nothrow_convertible(float, const FloatWrapper&));
}
struct FromInt { FromInt(int); };
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 0d796597d05c0e..d58c35b72c22bb 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -167,7 +167,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Disallow Binding a Returned Glvalue to a Temporary</td>
<td><a href="https://wg21.link/P2748R5">P2748R5</a></td>
- <td class="none" align="center">No</td>
+ <td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Clarifying rules for brace elision in aggregate initialization</td>
More information about the cfe-commits
mailing list