CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
202 lines
7.0 KiB
C++
202 lines
7.0 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference -Wlifetime-safety-noescape -verify %s
|
|
|
|
#include "Inputs/lifetime-analysis.h"
|
|
|
|
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;
|
|
}
|
|
|
|
// FIXME: diagnose differently when parameter has both '[[clang::noescape]]' and '[[clang::lifetimebound]]'.
|
|
View both_noescape_and_lifetimebound(
|
|
const MyObj& in [[clang::noescape]] [[clang::lifetimebound]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return in; // expected-note {{returned here}}
|
|
}
|
|
|
|
View identity_lifetimebound(View v [[clang::lifetimebound]]) { return v; }
|
|
|
|
View escape_through_lifetimebound_call(
|
|
const MyObj& in [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return identity_lifetimebound(in); // expected-note {{returned here}}
|
|
}
|
|
|
|
View no_annotation_identity(View v) { return v; }
|
|
|
|
View escape_through_unannotated_call(const MyObj& in [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return no_annotation_identity(in); // expected-note {{returned here}}
|
|
}
|
|
|
|
View global_view; // expected-note {{escapes to this global storage}}
|
|
|
|
void escape_through_global_var(const MyObj& in [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
global_view = in;
|
|
}
|
|
struct ObjWithStaticField {
|
|
static int *static_field; // expected-note {{escapes to this static storage}}
|
|
};
|
|
|
|
void escape_to_static_data_member(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
ObjWithStaticField::static_field = data;
|
|
}
|
|
|
|
|
|
|
|
void escape_through_static_local(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
static int *static_local; // expected-note {{escapes to this static storage}}
|
|
static_local = data;
|
|
}
|
|
|
|
thread_local int *thread_local_storage; // expected-note {{escapes to this global storage}}
|
|
|
|
void escape_through_thread_local(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
// FIXME: We might want to report whenever anything derived from a
|
|
// noescape parameter is assigned to a global, as this is likely
|
|
// undesired behavior in most cases.
|
|
thread_local_storage = data;
|
|
}
|
|
|
|
struct ObjConsumer {
|
|
void escape_through_member(const MyObj& in [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
member_view = in;
|
|
}
|
|
|
|
View member_view; // expected-note {{escapes to this field}}
|
|
};
|
|
|
|
// FIXME: Escaping through another param is not detected.
|
|
void escape_through_param(const MyObj& in, std::vector<View> &v) {
|
|
v.push_back(in);
|
|
}
|
|
|
|
View reassign_to_second(
|
|
const MyObj& a [[clang::noescape]],
|
|
const MyObj& b [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
View v = a;
|
|
v = b;
|
|
return v; // expected-note {{returned here}}
|
|
}
|
|
|
|
struct Container {
|
|
MyObj data;
|
|
const MyObj& getRef() const [[clang::lifetimebound]] { return data; }
|
|
};
|
|
|
|
View access_noescape_field(
|
|
const Container& c [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return c.data; // expected-note {{returned here}}
|
|
}
|
|
|
|
View access_noescape_through_getter(
|
|
Container& c [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return c.getRef(); // expected-note {{returned here}}
|
|
}
|
|
|
|
MyObj* return_ptr_from_noescape_ref(
|
|
MyObj& r [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return &r; // expected-note {{returned here}}
|
|
}
|
|
|
|
MyObj& return_ref_from_noescape_ptr(
|
|
MyObj* p [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return *p; // expected-note {{returned here}}
|
|
}
|
|
|
|
int* return_spaced_brackets(int* p [ [clang::noescape] /*some comment*/ ]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return p; // expected-note {{returned here}}
|
|
}
|
|
|
|
namespace callable_wrappers {
|
|
|
|
std::function<void()> escape_noescape_via_function(int &x [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}}
|
|
return [&]() { (void)x; }; // expected-note {{returned here}}
|
|
}
|
|
|
|
} // namespace callable_wrappers
|