// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety-lifetimebound-violation -Wno-dangling -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; }; bool cond(); View not_lb(const MyObj &obj); View lb(const MyObj &obj [[clang::lifetimebound]]); View return_through_unannotated_passthrough( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} return not_lb(obj); } View return_through_lifetimebound_passthrough( const MyObj &obj [[clang::lifetimebound]]) { return lb(obj); } View lose_lb(const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} return not_lb(obj); } View return_through_alias(const MyObj &obj [[clang::lifetimebound]]) { const MyObj &alias = obj; return alias; } View return_alias_through_unannotated_passthrough( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} const MyObj &alias = obj; return not_lb(alias); } View global_view; View assign_param_to_global( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} global_view = obj; // Wrong kind of escape. return View(); // Unrelated view. } struct EnclosingState { View member; View assign_param_to_field( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} member = obj; // Wrong kind of escape. return View(); // Unrelated view. } }; View not_lb_view(View v); View lb_view(View v [[clang::lifetimebound]]); View return_through_two_lifetimebound_calls( const MyObj &obj [[clang::lifetimebound]]) { return lb_view(lb(obj)); } View return_through_nested_broken_chain( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} return not_lb_view(lb_view(View(obj))); } View return_constructed_view_through_unannotated_forwarder( const MyObj &obj [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} return not_lb_view(View(obj)); } View return_constructed_view_through_lifetimebound_forwarder( const MyObj &obj [[clang::lifetimebound]]) { return lb_view(View(obj)); } View verify_each_annotated_param_independently( const MyObj &a [[clang::lifetimebound]], const MyObj &b [[clang::lifetimebound]], // expected-warning {{could not verify that the return value can be lifetime bound to 'b'}} const MyObj &c [[clang::lifetimebound]]) { // expected-warning {{could not verify that the return value can be lifetime bound to 'c'}} return cond() ? a : not_lb(b); } View unnamed_lifetimebound_param( [[clang::lifetimebound]] const MyObj &) { // expected-warning {{could not verify that the return value can be lifetime bound to an unnamed parameter}} return View(); } View annotated_decl_but_not_def_not_returned(const MyObj &obj [[clang::lifetimebound]]); // expected-warning {{could not verify that the return value can be lifetime bound to 'obj'}} View annotated_decl_but_not_def_not_returned(const MyObj &obj) { return not_lb(obj); } struct BadThisReturn { MyObj data; View get() const [[clang::lifetimebound]] { // expected-warning {{could not verify that the return value can be lifetime bound to the implicit this parameter}} return not_lb(data); } }; struct GoodThisReturn { MyObj data; View get() const [[clang::lifetimebound]] { return data; } }; struct RedeclaredThis { MyObj data; View get() const [[clang::lifetimebound]]; // expected-warning {{could not verify that the return value can be lifetime bound to the implicit this parameter}} }; View RedeclaredThis::get() const { return not_lb(data); } struct ThisAndParam { MyObj data; View get(const MyObj &obj [[clang::lifetimebound]]) const [[clang::lifetimebound]] { // expected-warning {{could not verify that the return value can be lifetime bound to the implicit this parameter}} return lb(obj); } }; struct ThisAndMixedParams { MyObj data; View get( const MyObj &a [[clang::lifetimebound]], const MyObj &b, const MyObj &c [[clang::lifetimebound]]) const // expected-warning {{could not verify that the return value can be lifetime bound to 'c'}} [[clang::lifetimebound]] { // expected-warning {{could not verify that the return value can be lifetime bound to the implicit this parameter}} return cond() ? lb(a) : not_lb(b); } }; struct AssignmentCorr { AssignmentCorr& operator=(const AssignmentCorr& other) { return *this; } }; struct AssignementIncorr { AssignementIncorr& operator=(const AssignementIncorr& other) { AssignementIncorr tmp; return tmp; } }; void implicit_lifetimebound_in_nested_std_namespace() { (void)std::basic_string_view("hello"); }