[llvm] [clang-tools-extra] [clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-11-21 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 closed https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-27 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-27 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-26 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-25 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 commented:

Thanks for bringing this! I didn't notice the post in discourse and I'll put 
higher level comments there.

https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-25 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 edited 
https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-25 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/69360

>From be3f5faa6cd17d76f26fb1bc6d6b59a8a78ffe82 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Tue, 17 Oct 2023 19:37:28 +0200
Subject: [PATCH 1/2] Lifetime bound check for coroutine

---
 clang/lib/Sema/SemaInit.cpp   |  16 +-
 .../SemaCXX/coroutine-lifetimebound-args.cpp  | 184 ++
 2 files changed, 198 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/coroutine-lifetimebound-args.cpp

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index fd95b16b84b6e3a..54e72b220bc47a4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7607,11 +7607,23 @@ static void 
visitLifetimeBoundArguments(IndirectLocalPath , Expr *Call,
 
   if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
 VisitLifetimeBoundArg(Callee, ObjectArg);
-
+  bool checkCoroCall = false;
+  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
+for (const auto  :
+ RD->getUnderlyingDecl()->specific_attrs()) {
+  // Only for demonstration: Get feedback and add a clang annotation as an
+  // extension.
+  if (attr->getAnnotation() == "coro_type") {
+
+checkCoroCall = true;
+break;
+  }
+}
+  }
   for (unsigned I = 0,
 N = std::min(Callee->getNumParams(), Args.size());
I != N; ++I) {
-if (Callee->getParamDecl(I)->hasAttr())
+if (checkCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
   }
 }
diff --git a/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp 
b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
new file mode 100644
index 000..4cc5730ef896581
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only 
-verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused
+
+#include "Inputs/std-coroutine.h"
+
+using std::suspend_always;
+using std::suspend_never;
+
+
+#define CORO_TYPE [[clang::annotate("coro_type")]]
+#define CORO_UNSAFE [[clang::annotate("coro_unsafe")]]
+
+template  struct CORO_TYPE Gen {
+  struct promise_type {
+Gen get_return_object() {
+  return {};
+}
+suspend_always initial_suspend();
+suspend_always final_suspend() noexcept;
+void unhandled_exception();
+void return_value(const T );
+
+template 
+auto await_transform(const Gen &) {
+  struct awaitable {
+bool await_ready() noexcept { return false; }
+void await_suspend(std::coroutine_handle<>) noexcept {}
+U await_resume() noexcept { return {}; }
+  };
+  return awaitable{};
+}
+  };
+};
+
+template  using Co = Gen;
+
+Gen foo_coro(const int& b);
+
+Gen plain_return_foo_decl(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen foo_coro(const int& b) {
+  if (b > 0)
+co_return 1;
+  co_return 2;
+}
+
+int getInt() { return 0; }
+
+Co bar_coro(const int , int c) {
+  int x = co_await foo_coro(b);
+  int y = co_await foo_coro(1);
+  int z = co_await foo_coro(getInt());
+  auto unsafe1 = foo_coro(1); // expected-warning {{temporary whose address is 
used as value of local variable}}
+  auto unsafe2 = foo_coro(getInt()); // expected-warning {{temporary whose 
address is used as value of local variable}}
+  auto  safe1 = foo_coro(b);
+  auto  safe2 = foo_coro(c);
+  co_return co_await foo_coro(co_await foo_coro(1));
+}
+
+Gen plain_return_co(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen safe_forwarding(const int& b) {
+  return foo_coro(b);
+}
+
+Gen unsafe_wrapper(int b) {
+  return safe_forwarding(b); // expected-warning {{address of stack memory 
associated with parameter}}
+}
+
+Co complex_plain_return(int b) {
+  return b > 0 
+  ? foo_coro(1)   // expected-warning {{returning address of local 
temporary object}}
+  : bar_coro(0, 1); // expected-warning {{returning address of local 
temporary object}}
+}
+
+void lambdas() {
+  auto unsafe_lambda = [](int b) {
+return foo_coro(b); // expected-warning {{address of stack memory 
associated with parameter}}
+  };
+  auto safe_lambda = [](int b) -> Co {
+int x = co_await foo_coro(1);
+co_return x + co_await foo_coro(b);
+  };
+}
+// 
=
+// Safe usage when parameters are value
+// 
=
+namespace by_value {
+Gen value_coro(int b) { co_return co_await foo_coro(b); }
+
+Gen wrapper1(int b) { return value_coro(b); }
+Gen wrapper2(const int& b) { return value_coro(b); }
+}
+
+// 
=
+// std::function like 

[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-25 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-25 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-24 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/69360

>From be3f5faa6cd17d76f26fb1bc6d6b59a8a78ffe82 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Tue, 17 Oct 2023 19:37:28 +0200
Subject: [PATCH] Lifetime bound check for coroutine

---
 clang/lib/Sema/SemaInit.cpp   |  16 +-
 .../SemaCXX/coroutine-lifetimebound-args.cpp  | 184 ++
 2 files changed, 198 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/coroutine-lifetimebound-args.cpp

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index fd95b16b84b6e3a..54e72b220bc47a4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7607,11 +7607,23 @@ static void 
visitLifetimeBoundArguments(IndirectLocalPath , Expr *Call,
 
   if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
 VisitLifetimeBoundArg(Callee, ObjectArg);
-
+  bool checkCoroCall = false;
+  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
+for (const auto  :
+ RD->getUnderlyingDecl()->specific_attrs()) {
+  // Only for demonstration: Get feedback and add a clang annotation as an
+  // extension.
+  if (attr->getAnnotation() == "coro_type") {
+
+checkCoroCall = true;
+break;
+  }
+}
+  }
   for (unsigned I = 0,
 N = std::min(Callee->getNumParams(), Args.size());
I != N; ++I) {
-if (Callee->getParamDecl(I)->hasAttr())
+if (checkCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
   }
 }
diff --git a/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp 
b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
new file mode 100644
index 000..4cc5730ef896581
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only 
-verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused
+
+#include "Inputs/std-coroutine.h"
+
+using std::suspend_always;
+using std::suspend_never;
+
+
+#define CORO_TYPE [[clang::annotate("coro_type")]]
+#define CORO_UNSAFE [[clang::annotate("coro_unsafe")]]
+
+template  struct CORO_TYPE Gen {
+  struct promise_type {
+Gen get_return_object() {
+  return {};
+}
+suspend_always initial_suspend();
+suspend_always final_suspend() noexcept;
+void unhandled_exception();
+void return_value(const T );
+
+template 
+auto await_transform(const Gen &) {
+  struct awaitable {
+bool await_ready() noexcept { return false; }
+void await_suspend(std::coroutine_handle<>) noexcept {}
+U await_resume() noexcept { return {}; }
+  };
+  return awaitable{};
+}
+  };
+};
+
+template  using Co = Gen;
+
+Gen foo_coro(const int& b);
+
+Gen plain_return_foo_decl(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen foo_coro(const int& b) {
+  if (b > 0)
+co_return 1;
+  co_return 2;
+}
+
+int getInt() { return 0; }
+
+Co bar_coro(const int , int c) {
+  int x = co_await foo_coro(b);
+  int y = co_await foo_coro(1);
+  int z = co_await foo_coro(getInt());
+  auto unsafe1 = foo_coro(1); // expected-warning {{temporary whose address is 
used as value of local variable}}
+  auto unsafe2 = foo_coro(getInt()); // expected-warning {{temporary whose 
address is used as value of local variable}}
+  auto  safe1 = foo_coro(b);
+  auto  safe2 = foo_coro(c);
+  co_return co_await foo_coro(co_await foo_coro(1));
+}
+
+Gen plain_return_co(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen safe_forwarding(const int& b) {
+  return foo_coro(b);
+}
+
+Gen unsafe_wrapper(int b) {
+  return safe_forwarding(b); // expected-warning {{address of stack memory 
associated with parameter}}
+}
+
+Co complex_plain_return(int b) {
+  return b > 0 
+  ? foo_coro(1)   // expected-warning {{returning address of local 
temporary object}}
+  : bar_coro(0, 1); // expected-warning {{returning address of local 
temporary object}}
+}
+
+void lambdas() {
+  auto unsafe_lambda = [](int b) {
+return foo_coro(b); // expected-warning {{address of stack memory 
associated with parameter}}
+  };
+  auto safe_lambda = [](int b) -> Co {
+int x = co_await foo_coro(1);
+co_return x + co_await foo_coro(b);
+  };
+}
+// 
=
+// Safe usage when parameters are value
+// 
=
+namespace by_value {
+Gen value_coro(int b) { co_return co_await foo_coro(b); }
+
+Gen wrapper1(int b) { return value_coro(b); }
+Gen wrapper2(const int& b) { return value_coro(b); }
+}
+
+// 
=
+// std::function like 

[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-19 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/69360

>From be3f5faa6cd17d76f26fb1bc6d6b59a8a78ffe82 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Tue, 17 Oct 2023 19:37:28 +0200
Subject: [PATCH] Lifetime bound check for coroutine

---
 clang/lib/Sema/SemaInit.cpp   |  16 +-
 .../SemaCXX/coroutine-lifetimebound-args.cpp  | 184 ++
 2 files changed, 198 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/coroutine-lifetimebound-args.cpp

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index fd95b16b84b6e3a..54e72b220bc47a4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7607,11 +7607,23 @@ static void 
visitLifetimeBoundArguments(IndirectLocalPath , Expr *Call,
 
   if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
 VisitLifetimeBoundArg(Callee, ObjectArg);
-
+  bool checkCoroCall = false;
+  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
+for (const auto  :
+ RD->getUnderlyingDecl()->specific_attrs()) {
+  // Only for demonstration: Get feedback and add a clang annotation as an
+  // extension.
+  if (attr->getAnnotation() == "coro_type") {
+
+checkCoroCall = true;
+break;
+  }
+}
+  }
   for (unsigned I = 0,
 N = std::min(Callee->getNumParams(), Args.size());
I != N; ++I) {
-if (Callee->getParamDecl(I)->hasAttr())
+if (checkCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
   }
 }
diff --git a/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp 
b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
new file mode 100644
index 000..4cc5730ef896581
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only 
-verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused
+
+#include "Inputs/std-coroutine.h"
+
+using std::suspend_always;
+using std::suspend_never;
+
+
+#define CORO_TYPE [[clang::annotate("coro_type")]]
+#define CORO_UNSAFE [[clang::annotate("coro_unsafe")]]
+
+template  struct CORO_TYPE Gen {
+  struct promise_type {
+Gen get_return_object() {
+  return {};
+}
+suspend_always initial_suspend();
+suspend_always final_suspend() noexcept;
+void unhandled_exception();
+void return_value(const T );
+
+template 
+auto await_transform(const Gen &) {
+  struct awaitable {
+bool await_ready() noexcept { return false; }
+void await_suspend(std::coroutine_handle<>) noexcept {}
+U await_resume() noexcept { return {}; }
+  };
+  return awaitable{};
+}
+  };
+};
+
+template  using Co = Gen;
+
+Gen foo_coro(const int& b);
+
+Gen plain_return_foo_decl(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen foo_coro(const int& b) {
+  if (b > 0)
+co_return 1;
+  co_return 2;
+}
+
+int getInt() { return 0; }
+
+Co bar_coro(const int , int c) {
+  int x = co_await foo_coro(b);
+  int y = co_await foo_coro(1);
+  int z = co_await foo_coro(getInt());
+  auto unsafe1 = foo_coro(1); // expected-warning {{temporary whose address is 
used as value of local variable}}
+  auto unsafe2 = foo_coro(getInt()); // expected-warning {{temporary whose 
address is used as value of local variable}}
+  auto  safe1 = foo_coro(b);
+  auto  safe2 = foo_coro(c);
+  co_return co_await foo_coro(co_await foo_coro(1));
+}
+
+Gen plain_return_co(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen safe_forwarding(const int& b) {
+  return foo_coro(b);
+}
+
+Gen unsafe_wrapper(int b) {
+  return safe_forwarding(b); // expected-warning {{address of stack memory 
associated with parameter}}
+}
+
+Co complex_plain_return(int b) {
+  return b > 0 
+  ? foo_coro(1)   // expected-warning {{returning address of local 
temporary object}}
+  : bar_coro(0, 1); // expected-warning {{returning address of local 
temporary object}}
+}
+
+void lambdas() {
+  auto unsafe_lambda = [](int b) {
+return foo_coro(b); // expected-warning {{address of stack memory 
associated with parameter}}
+  };
+  auto safe_lambda = [](int b) -> Co {
+int x = co_await foo_coro(1);
+co_return x + co_await foo_coro(b);
+  };
+}
+// 
=
+// Safe usage when parameters are value
+// 
=
+namespace by_value {
+Gen value_coro(int b) { co_return co_await foo_coro(b); }
+
+Gen wrapper1(int b) { return value_coro(b); }
+Gen wrapper2(const int& b) { return value_coro(b); }
+}
+
+// 
=
+// std::function like 

[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-17 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 4480e650b3cf7cc63cfd3767cd6b120f8bfad2ac 
be3f5faa6cd17d76f26fb1bc6d6b59a8a78ffe82 -- 
clang/test/SemaCXX/coroutine-lifetimebound-args.cpp clang/lib/Sema/SemaInit.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 54e72b220bc4..52e05b62e505 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7614,7 +7614,7 @@ static void visitLifetimeBoundArguments(IndirectLocalPath 
, Expr *Call,
   // Only for demonstration: Get feedback and add a clang annotation as an
   // extension.
   if (attr->getAnnotation() == "coro_type") {
-
+
 checkCoroCall = true;
 break;
   }

``




https://github.com/llvm/llvm-project/pull/69360
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RFC] Perform lifetime bound checks for arguments to coroutine (PR #69360)

2023-10-17 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 created https://github.com/llvm/llvm-project/pull/69360

None

>From be3f5faa6cd17d76f26fb1bc6d6b59a8a78ffe82 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Tue, 17 Oct 2023 19:37:28 +0200
Subject: [PATCH] Lifetime bound check for coroutine

---
 clang/lib/Sema/SemaInit.cpp   |  16 +-
 .../SemaCXX/coroutine-lifetimebound-args.cpp  | 184 ++
 2 files changed, 198 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/coroutine-lifetimebound-args.cpp

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index fd95b16b84b6e3a..54e72b220bc47a4 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7607,11 +7607,23 @@ static void 
visitLifetimeBoundArguments(IndirectLocalPath , Expr *Call,
 
   if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
 VisitLifetimeBoundArg(Callee, ObjectArg);
-
+  bool checkCoroCall = false;
+  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
+for (const auto  :
+ RD->getUnderlyingDecl()->specific_attrs()) {
+  // Only for demonstration: Get feedback and add a clang annotation as an
+  // extension.
+  if (attr->getAnnotation() == "coro_type") {
+
+checkCoroCall = true;
+break;
+  }
+}
+  }
   for (unsigned I = 0,
 N = std::min(Callee->getNumParams(), Args.size());
I != N; ++I) {
-if (Callee->getParamDecl(I)->hasAttr())
+if (checkCoroCall || Callee->getParamDecl(I)->hasAttr())
   VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
   }
 }
diff --git a/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp 
b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
new file mode 100644
index 000..4cc5730ef896581
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-lifetimebound-args.cpp
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only 
-verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused
+
+#include "Inputs/std-coroutine.h"
+
+using std::suspend_always;
+using std::suspend_never;
+
+
+#define CORO_TYPE [[clang::annotate("coro_type")]]
+#define CORO_UNSAFE [[clang::annotate("coro_unsafe")]]
+
+template  struct CORO_TYPE Gen {
+  struct promise_type {
+Gen get_return_object() {
+  return {};
+}
+suspend_always initial_suspend();
+suspend_always final_suspend() noexcept;
+void unhandled_exception();
+void return_value(const T );
+
+template 
+auto await_transform(const Gen &) {
+  struct awaitable {
+bool await_ready() noexcept { return false; }
+void await_suspend(std::coroutine_handle<>) noexcept {}
+U await_resume() noexcept { return {}; }
+  };
+  return awaitable{};
+}
+  };
+};
+
+template  using Co = Gen;
+
+Gen foo_coro(const int& b);
+
+Gen plain_return_foo_decl(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen foo_coro(const int& b) {
+  if (b > 0)
+co_return 1;
+  co_return 2;
+}
+
+int getInt() { return 0; }
+
+Co bar_coro(const int , int c) {
+  int x = co_await foo_coro(b);
+  int y = co_await foo_coro(1);
+  int z = co_await foo_coro(getInt());
+  auto unsafe1 = foo_coro(1); // expected-warning {{temporary whose address is 
used as value of local variable}}
+  auto unsafe2 = foo_coro(getInt()); // expected-warning {{temporary whose 
address is used as value of local variable}}
+  auto  safe1 = foo_coro(b);
+  auto  safe2 = foo_coro(c);
+  co_return co_await foo_coro(co_await foo_coro(1));
+}
+
+Gen plain_return_co(int b) {
+  return foo_coro(b); // expected-warning {{address of stack memory associated 
with parameter}}
+}
+
+Gen safe_forwarding(const int& b) {
+  return foo_coro(b);
+}
+
+Gen unsafe_wrapper(int b) {
+  return safe_forwarding(b); // expected-warning {{address of stack memory 
associated with parameter}}
+}
+
+Co complex_plain_return(int b) {
+  return b > 0 
+  ? foo_coro(1)   // expected-warning {{returning address of local 
temporary object}}
+  : bar_coro(0, 1); // expected-warning {{returning address of local 
temporary object}}
+}
+
+void lambdas() {
+  auto unsafe_lambda = [](int b) {
+return foo_coro(b); // expected-warning {{address of stack memory 
associated with parameter}}
+  };
+  auto safe_lambda = [](int b) -> Co {
+int x = co_await foo_coro(1);
+co_return x + co_await foo_coro(b);
+  };
+}
+// 
=
+// Safe usage when parameters are value
+// 
=
+namespace by_value {
+Gen value_coro(int b) { co_return co_await foo_coro(b); }
+
+Gen wrapper1(int b) { return value_coro(b); }
+Gen wrapper2(const int& b) { return value_coro(b); }
+}
+
+// 
=
+// std::function