https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/76818
>From cc7ff8b7ecb93165172dbb481c7d5fcb64289a96 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena
Date: Wed, 3 Jan 2024 14:44:58 +0100
Subject: [PATCH 1/5] [coroutines] Introduce [[clang::coro_not_lifetimebound]]
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Basic/Attr.td | 8 ++
clang/include/clang/Basic/AttrDocs.td | 25 ---
clang/lib/Sema/SemaInit.cpp | 3 ++-
...a-attribute-supported-attributes-list.test | 1 +
clang/test/SemaCXX/coro-lifetimebound.cpp | 15 +++
6 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ee211c16a48ac8..88a0bf7d005dab 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -357,6 +357,7 @@ Attribute Changes in Clang
- Clang now introduced ``[[clang::coro_lifetimebound]]`` attribute.
All parameters of a function are considered to be lifetime bound if the
function
returns a type annotated with ``[[clang::coro_lifetimebound]]`` and
``[[clang::coro_return_type]]``.
+ This analysis can be disabled for a function by annotating the function with
``[[clang::coro_not_lifetimebound]]``.
Improvements to Clang's diagnostics
---
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index db17211747b17d..3dd3cb305dc4ff 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1121,6 +1121,14 @@ def CoroLifetimeBound : InheritableAttr {
let SimpleHandler = 1;
}
+def CoroNotLifetimeBound : InheritableAttr {
+ let Spellings = [Clang<"coro_not_lifetimebound">];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CPlusPlus];
+ let Documentation = [CoroLifetimeBoundDoc];
+ let SimpleHandler = 1;
+}
+
// OSObject-based attributes.
def OSConsumed : InheritableParamAttr {
let Spellings = [Clang<"os_consumed">];
diff --git a/clang/include/clang/Basic/AttrDocs.td
b/clang/include/clang/Basic/AttrDocs.td
index 98a7ecc7fd7df3..d6c4d12564e6b0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7671,9 +7671,12 @@ The ``[[clang::coro_lifetimebound]]`` is a class
attribute which can be applied
to a coroutine return type (`CRT`_) (i.e.
it should also be annotated with ``[[clang::coro_return_type]]``).
-All parameters of a function are considered to be lifetime bound. See
`documentation`_
-of ``[[clang::lifetimebound]]`` for more details.
-if the function returns a coroutine return type (CRT) annotated with
``[[clang::coro_lifetimebound]]``.
+All parameters of a function are considered to be lifetime bound if the
function returns a
+coroutine return type (CRT) annotated with ``[[clang::coro_lifetimebound]]``.
+This lifetime bound analysis can be disabled for a coroutine wrapper or a
coroutine by annotating the function
+with ``[[clang::coro_not_lifetimebound]]`` function attribute .
+See `documentation`_ of ``[[clang::lifetimebound]]`` for details about
lifetime bound analysis.
+
Reference parameters of a coroutine are susceptible to capturing references to
temporaries or local variables.
@@ -7703,7 +7706,7 @@ Both coroutines and coroutine wrappers are part of this
analysis.
};
Task coro(const int& a) { co_return a + 1; }
- Task [[clang::coro_wrapper]] coro_wrapper(const int& a, const int& b) {
+ [[clang::coro_wrapper]] Task coro_wrapper(const int& a, const int& b) {
return a > b ? coro(a) : coro(b);
}
Task temporary_reference() {
@@ -7718,6 +7721,20 @@ Both coroutines and coroutine wrappers are part of this
analysis.
return coro(a); // warning: returning address of stack variable `a`.
}
+This analysis can be disabled for a particular function by annotating it with
function attribute
+``[[clang::coro_not_lifetimebound]]``. For example, this could be useful for
coroutine wrappers
+which accept reference parameters but do not pass them to the underlying
coroutine or pass them by value.
+
+.. code-block:: c++
+
+ Task coro(int a) { co_return a + 1; }
+ [[clang::coro_wrapper, clang::coro_not_lifetimebound]] Task
coro_wrapper(const int& a) {
+return coro(a + 1);
+ }
+ void use() {
+auto task = coro_wrapper(1); // use of temporary is fine as coro_wrapper
is not lifetime bound.
+ }
+
.. _`documentation`:
https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
.. _`CRT`: https://clang.llvm.org/docs/AttributeReference.html#coro-return-type
}];
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 61d244f3bb9798..130aa5d04b82f2 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7581,7 +7581,8 @@ static void visitLifetimeBoundArguments(IndirectLocalPath
, Expr *Call,
bool CheckCoroCall = false;
if (const auto *RD =