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
229 lines
8.6 KiB
C++
229 lines
8.6 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety -Wno-dangling -verify %s
|
|
// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety -Wno-dangling -verify=expected,tu %s
|
|
|
|
#include "Inputs/lifetime-analysis.h"
|
|
|
|
template<int N> struct Dummy {};
|
|
static std::string kGlobal = "GLOBAL";
|
|
void takeString(std::string&& s);
|
|
|
|
std::string_view construct_view(const std::string& str [[clang::lifetimebound]]);
|
|
|
|
struct CtorInit {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
CtorInit(std::string s) : view(s) {} // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
};
|
|
|
|
struct CtorSet {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
CtorSet(std::string s) { view = s; } // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
};
|
|
|
|
struct CtorInitLifetimeBound {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
};
|
|
|
|
struct CtorInitButMoved {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
CtorInitButMoved(std::string s)
|
|
: view(s) { // expected-warning-re {{stack memory associated with parameter 's' may escape to the field 'view' which will dangle. {{.*}} may have been moved}}
|
|
takeString(std::move(s)); // expected-note {{potentially moved here}}
|
|
}
|
|
};
|
|
|
|
struct CtorInitButMovedOwned {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
std::string owned;
|
|
CtorInitButMovedOwned(std::string s)
|
|
: view(s), // expected-warning-re {{stack memory associated with parameter 's' may escape to the field 'view' which will dangle. {{.*}} may have been moved}}
|
|
owned(std::move(s)) {} // expected-note {{potentially moved here}}
|
|
};
|
|
|
|
struct CtorInitButMovedOwnedOrderedCorrectly {
|
|
std::string owned;
|
|
std::string_view view;
|
|
CtorInitButMovedOwnedOrderedCorrectly(std::string s)
|
|
:owned(std::move(s)), view(owned) {}
|
|
};
|
|
|
|
struct CtorInitMultipleViews {
|
|
std::string_view view1; // expected-note {{this field dangles}}
|
|
std::string_view view2; // expected-note {{this field dangles}}
|
|
CtorInitMultipleViews(std::string s) : view1(s), // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view1' which will dangle}}
|
|
view2(s) {} // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view2' which will dangle}}
|
|
};
|
|
|
|
struct CtorInitMultipleParams {
|
|
std::string_view view1; // expected-note {{this field dangles}}
|
|
std::string_view view2; // expected-note {{this field dangles}}
|
|
CtorInitMultipleParams(std::string s1, std::string s2) : view1(s1), // expected-warning {{stack memory associated with parameter 's1' escapes to the field 'view1' which will dangle}}
|
|
view2(s2) {} // expected-warning {{stack memory associated with parameter 's2' escapes to the field 'view2' which will dangle}}
|
|
};
|
|
|
|
struct CtorRefField {
|
|
const std::string& str; // expected-note {{this field dangles}}
|
|
const std::string_view& view; // expected-note {{this field dangles}}
|
|
CtorRefField(std::string s, std::string_view v) : str(s), // expected-warning {{stack memory associated with parameter 's' escapes to the field 'str' which will dangle}}
|
|
view(v) {} // expected-warning {{stack memory associated with parameter 'v' escapes to the field 'view' which will dangle}}
|
|
CtorRefField(Dummy<1> ok, const std::string& s, const std::string_view& v): str(s), view(v) {}
|
|
};
|
|
|
|
struct CtorPointerField {
|
|
const char* ptr; // expected-note {{this field dangles}}
|
|
CtorPointerField(std::string s) : ptr(s.data()) {} // expected-warning {{stack memory associated with parameter 's' escapes to the field 'ptr' which will dangle}}
|
|
CtorPointerField(Dummy<1> ok, const std::string& s) : ptr(s.data()) {}
|
|
CtorPointerField(Dummy<2> ok, std::string_view view) : ptr(view.data()) {}
|
|
};
|
|
|
|
struct MemberSetters {
|
|
std::string_view view; // expected-note 6 {{this field dangles}}
|
|
const char* p; // expected-note 6 {{this field dangles}}
|
|
|
|
void setWithParam(std::string s) {
|
|
view = s; // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
p = s.data(); // expected-warning {{stack memory associated with parameter 's' escapes to the field 'p' which will dangle}}
|
|
}
|
|
|
|
void setWithParamAndReturn(std::string s) {
|
|
view = s; // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
p = s.data(); // expected-warning {{stack memory associated with parameter 's' escapes to the field 'p' which will dangle}}
|
|
return;
|
|
}
|
|
|
|
void setWithParamOk(const std::string& s) {
|
|
view = s;
|
|
p = s.data();
|
|
}
|
|
|
|
void setWithParamOkAndReturn(const std::string& s) {
|
|
view = s;
|
|
p = s.data();
|
|
return;
|
|
}
|
|
|
|
void setWithLocal() {
|
|
std::string s;
|
|
view = s; // expected-warning {{stack memory associated with local variable 's' escapes to the field 'view' which will dangle}}
|
|
p = s.data(); // expected-warning {{stack memory associated with local variable 's' escapes to the field 'p' which will dangle}}
|
|
}
|
|
|
|
void setWithLocalButMoved() {
|
|
std::string s;
|
|
view = s; // expected-warning-re {{stack memory associated with local variable 's' may escape to the field 'view' which will dangle. {{.*}} may have been moved}}
|
|
p = s.data(); // expected-warning-re {{stack memory associated with local variable 's' may escape to the field 'p' which will dangle. {{.*}} may have been moved}}
|
|
takeString(std::move(s)); // expected-note 2 {{potentially moved here}}
|
|
}
|
|
|
|
void setWithGlobal() {
|
|
view = kGlobal;
|
|
p = kGlobal.data();
|
|
}
|
|
|
|
void setWithLocalThenWithGlobal() {
|
|
std::string local;
|
|
view = local;
|
|
p = local.data();
|
|
|
|
view = kGlobal;
|
|
p = kGlobal.data();
|
|
}
|
|
|
|
void setWithGlobalThenWithLocal() {
|
|
view = kGlobal;
|
|
p = kGlobal.data();
|
|
|
|
std::string local;
|
|
view = local; // expected-warning {{stack memory associated with local variable 'local' escapes to the field 'view' which will dangle}}
|
|
p = local.data(); // expected-warning {{stack memory associated with local variable 'local' escapes to the field 'p' which will dangle}}
|
|
}
|
|
|
|
void use_after_scope() {
|
|
{
|
|
std::string local;
|
|
view = local; // expected-warning {{stack memory associated with local variable 'local' escapes to the field 'view' which will dangle}}
|
|
p = local.data(); // expected-warning {{stack memory associated with local variable 'local' escapes to the field 'p' which will dangle}}
|
|
}
|
|
(void)view;
|
|
(void)p;
|
|
}
|
|
|
|
void use_after_scope_saved_after_reassignment() {
|
|
{
|
|
std::string local;
|
|
view = local;
|
|
p = local.data();
|
|
}
|
|
(void)view;
|
|
(void)p;
|
|
|
|
view = kGlobal;
|
|
p = kGlobal.data();
|
|
}
|
|
};
|
|
|
|
// FIXME: Detect escape to field of field.
|
|
struct IndirectEscape{
|
|
struct {
|
|
const char *p;
|
|
} b;
|
|
|
|
void foo() {
|
|
std::string s;
|
|
b.p = s.data();
|
|
}
|
|
};
|
|
|
|
// FIXME: Detect escape to field of field.
|
|
struct IndirectEscape2 {
|
|
struct {
|
|
const char *p;
|
|
};
|
|
|
|
void foo() {
|
|
std::string s;
|
|
p = s.data();
|
|
}
|
|
};
|
|
|
|
namespace DanglingPointerFieldInBaseClass {
|
|
struct BaseWithPointer {
|
|
std::string_view view; // expected-note {{this field dangles}}
|
|
};
|
|
|
|
struct DerivedWithCtor : BaseWithPointer {
|
|
DerivedWithCtor(std::string s) {
|
|
view = s; // expected-warning {{stack memory associated with parameter 's' escapes to the field 'view' which will dangle}}
|
|
}
|
|
};
|
|
} // namespace DanglingPointerFieldInBaseClass
|
|
|
|
namespace callable_wrappers {
|
|
|
|
struct HasCallback {
|
|
std::function<void()> callback; // expected-note {{this field dangles}}
|
|
|
|
void set_callback() {
|
|
int local;
|
|
callback = [&local]() { (void)local; }; // expected-warning {{stack memory associated with local variable 'local' escapes to the field 'callback' which will dangle}}
|
|
}
|
|
};
|
|
|
|
} // namespace callable_wrappers
|
|
|
|
namespace MakeUnique {
|
|
struct MyObj {};
|
|
|
|
struct LifetimeBoundCtor {
|
|
LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);
|
|
};
|
|
|
|
struct HasUniquePtrField {
|
|
std::unique_ptr<LifetimeBoundCtor> field; // tu-note {{this field dangles}}
|
|
|
|
void setWithParam(MyObj obj) {
|
|
field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{stack memory associated with parameter 'obj' escapes to the field 'field' which will dangle}}
|
|
}
|
|
};
|
|
} // namespace MakeUnique
|