================
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety-noescape -Wlifetime-safety
-Wno-dangling -verify %s
+
+struct [[gsl::Owner]] MyObj {
+ int id;
+ ~MyObj() {} // Non-trivial destructor
+};
+
+struct [[gsl::Pointer()]] View {
+ View(const MyObj&); // Borrows from MyObj
+ View();
+ void use() const;
+};
+
+View return_noescape_directly(const MyObj& in [[clang::noescape]]) { //
expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
+ return in; // expected-note {{returned here}}
+}
+
+View return_one_of_two(
+ const MyObj& a [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ const MyObj& b [[clang::noescape]],
+ bool cond) {
+ if (cond)
+ return a; // expected-note {{returned here}}
+ return View();
+}
+
+View return_both(
+ const MyObj& a [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ const MyObj& b [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ bool cond) {
+ if (cond)
+ return a; // expected-note {{returned here}}
+ return b; // expected-note {{returned here}}
+}
+
+View mixed_noescape_lifetimebound(
+ const MyObj& a [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ const MyObj& b [[clang::lifetimebound]],
+ bool cond) {
+ if (cond)
+ return a; // expected-note {{returned here}}
+ return b;
+}
+
+View mixed_only_noescape_escapes(
+ const MyObj& a [[clang::noescape]],
+ const MyObj& b [[clang::lifetimebound]]) {
+ (void)a;
+ return b;
+}
+
+View multiple_reassign(
+ const MyObj& a [[clang::noescape]],
+ const MyObj& b [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ const MyObj& c [[clang::noescape]], // expected-warning {{parameter is
marked [[clang::noescape]] but escapes}}
+ bool cond) {
+ View v = a;
+ if (cond)
+ v = b;
+ else
+ v = c;
+ return v; // expected-note 2 {{returned here}}
+}
+
+int* return_noescape_pointer(int* p [[clang::noescape]]) { // expected-warning
{{parameter is marked [[clang::noescape]] but escapes}}
+ return p; // expected-note {{returned here}}
+}
+
+MyObj& return_noescape_reference(MyObj& r [[clang::noescape]]) { //
expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
+ return r; // expected-note {{returned here}}
+}
+
+View return_via_local(const MyObj& in [[clang::noescape]]) { //
expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
+ View v = in;
+ return v; // expected-note {{returned here}}
+}
+
+void use_locally(const MyObj& in [[clang::noescape]]) {
+ View v = in;
+ v.use();
+}
+
+View return_without_noescape(const MyObj& in) {
+ return in;
+}
+
+View return_with_lifetimebound(const MyObj& in [[clang::lifetimebound]]) {
+ return in;
+}
+
+void pointer_used_locally(MyObj* p [[clang::noescape]]) {
+ p->id = 42;
+}
+
+// Noescape should take precedence and warn since the parameter does escape.
+View both_noescape_and_lifetimebound(
+ const MyObj& in [[clang::noescape]] [[clang::lifetimebound]]) { //
expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
----------------
usx95 wrote:
In principle, `lifetimebound` and `noescape` should not occur together on a
param as they are contradictory. This should be diagnosed differently without
needing lifetime analysis at all. This belongs to a different PR.
Can you add a FIXME: to diagnose this differently for now.
https://github.com/llvm/llvm-project/pull/177260
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits