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 <yronglin...@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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits