[PATCH] D141744: [Clang] Add lifetimebound attribute to std::move/std::forward
Alexander Shaposhnikov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 13 17:50:34 PST 2023
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: rsmith, aaron.ballman, dblaikie.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Add lifetimebound attribute to std::move/std::forward.
This diff addresses https://github.com/llvm/llvm-project/issues/59900
Test plan: ninja check-clang check-clang-tools check-llvm
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D141744
Files:
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/attr-lifetimebound.cpp
clang/test/SemaCXX/builtin-std-move.cpp
Index: clang/test/SemaCXX/builtin-std-move.cpp
===================================================================
--- clang/test/SemaCXX/builtin-std-move.cpp
+++ clang/test/SemaCXX/builtin-std-move.cpp
@@ -85,7 +85,7 @@
A &forward_rval_as_lval() {
std::forward<A&&>(A()); // expected-warning {{const attribute}}
- return std::forward<A&>(A()); // expected-note {{instantiation of}}
+ return std::forward<A&>(A()); // expected-note {{instantiation of}} expected-warning {{returning reference}}
}
struct B {};
Index: clang/test/SemaCXX/attr-lifetimebound.cpp
===================================================================
--- clang/test/SemaCXX/attr-lifetimebound.cpp
+++ clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -113,3 +113,55 @@
std::map<std::string, std::string> m;
const std::string &v = findOrDefault(m, "foo"s, "bar"s); // expected-warning {{temporary bound to local reference 'v'}}
}
+
+// definitions for std::move, std::forward et al.
+namespace std {
+inline namespace foo {
+
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> constexpr typename remove_reference<T>::type &&move(T &&t) {
+ return static_cast<typename remove_reference<T>::type>(t);
+}
+
+template <class T> constexpr T&& forward(typename remove_reference<T>::type& t) {
+ return static_cast<T&&>(t);
+}
+
+template <class T> constexpr T&& forward(typename remove_reference<T>::type&& t) {
+ return static_cast<T&&>(t);
+}
+
+template<class T> constexpr const T &as_const(T &x) {
+ return x;
+}
+
+template<class T, bool RValueRef> struct PickRef { using type = typename remove_reference<T>::type&; };
+template<class T> struct PickRef<T, true> { using type = typename remove_reference<T>::type&&; };
+
+template<class T> auto move_if_noexcept(T &t) -> typename PickRef<T, noexcept(T(static_cast<T&&>(t)))>::type {
+ return static_cast<typename PickRef<T, noexcept(T(static_cast<T&&>(t)))>::type>(t);
+}
+
+} // inline namespace foo
+} // namespace std
+
+namespace move_forward_as_const_examples {
+ struct S {
+ S &self() [[clang::lifetimebound]] { return *this; }
+ };
+
+ S &&Move = std::move(S{}); // expected-warning {{temporary bound to local reference 'Move' will be destroyed at the end of the full-expression}}
+ S MoveOk = std::move(S{});
+
+ S &&Forward = std::forward<S&&>(S{}); // expected-warning {{temporary bound to local reference 'Forward' will be destroyed at the end of the full-expression}}
+ S ForwardOk = std::forward<S&&>(S{});
+
+ const S &Const = std::as_const(S{}.self()); // expected-warning {{temporary bound to local reference 'Const' will be destroyed at the end of the full-expression}}
+ const S ConstOk = std::as_const(S{}.self());
+
+ S &&MoveIfNoExcept = std::move_if_noexcept(S{}.self()); // expected-warning {{temporary bound to local reference 'MoveIfNoExcept' will be destroyed at the end of the full-expression}}
+ S MoveIfNoExceptOk = std::move_if_noexcept(S{}.self());
+} // namespace move_forward_as_const_examples
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16180,6 +16180,21 @@
default:
break;
}
+
+ // Add lifetime attribute to std::move, std::fowrard et al.
+ switch (BuiltinID) {
+ case Builtin::BIas_const:
+ case Builtin::BIforward:
+ case Builtin::BImove:
+ case Builtin::BImove_if_noexcept:
+ if (ParmVarDecl *P = FD->getParamDecl(0u);
+ !P->hasAttr<LifetimeBoundAttr>())
+ P->addAttr(
+ LifetimeBoundAttr::CreateImplicit(Context, FD->getLocation()));
+ break;
+ default:
+ break;
+ }
}
AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D141744.489171.patch
Type: text/x-patch
Size: 3928 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230114/ce435556/attachment.bin>
More information about the cfe-commits
mailing list