Author: PushkarSingh Date: 2026-09-04T07:20:48+02:00 New Revision: c0fb057aad586f4dbf4968f98262dcbeb9ee45ce
URL: https://github.com/llvm/llvm-project/commit/c0fb057aad586f4dbf4968f98262dcbeb9ee45ce DIFF: https://github.com/llvm/llvm-project/commit/c0fb057aad586f4dbf4968f98262dcbeb9ee45ce.diff LOG: [Lifetime Safety] Distinguish attributed/inferred lifetimebound diagnostics (#220248) Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaLifetimeSafety.h clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp clang/test/Sema/LifetimeSafety/nocfg.cpp clang/test/Sema/LifetimeSafety/safety-c.c clang/test/Sema/LifetimeSafety/safety.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6c4339b6175eb..c2bcf107df717 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11074,7 +11074,7 @@ def note_lifetime_safety_escapes_to_static_storage_here: Note<"escapes to this s def note_lifetime_safety_lifetimebound_here: Note<"'lifetimebound' attribute appears here on the definition">; def note_lifetime_safety_aliases_storage : Note<"%0 aliases the storage of %1">; def note_lifetime_safety_aliases_storage_lifetimebound : Note< - "%0 aliases the storage of %1 because %select{parameter %3|the implicit object parameter}2 is lifetimebound">; + "%0 aliases the storage of %1 because %select{parameter %3|the implicit object parameter}2 is %select{marked as|inferred as}4 lifetimebound">; def warn_lifetime_safety_intra_tu_param_suggestion : Warning<"parameter in intra-TU function should be marked " diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 71ec54dc8d377..d87c9003e83cf 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -700,17 +700,23 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { LastExpr = CurrExpr; if (ParamInfo) { bool IsImplicitObject = isa<const CXXMethodDecl *>(*ParamInfo); + bool IsInferred = true; std::string ParamName; if (!IsImplicitObject) { const auto *Param = cast<const ParmVarDecl *>(*ParamInfo); + if (const auto *Attr = Param->getAttr<LifetimeBoundAttr>()) + IsInferred = Attr->isImplicit(); ParamName = Param->getIdentifier() ? "'" + Param->getNameAsString() + "'" : "'<unnamed>'"; + } else if (const auto *Attr = getImplicitObjectParamLifetimeBoundAttr( + cast<const CXXMethodDecl *>(*ParamInfo))) { + IsInferred = Attr->isImplicit(); } S.Diag(CurrExpr->getBeginLoc(), diag::note_lifetime_safety_aliases_storage_lifetimebound) << CurrExpr->getSourceRange() << getDiagSubjectDescription(CurrExpr) - << IssueStr << IsImplicitObject << ParamName; + << IssueStr << IsImplicitObject << ParamName << IsInferred; } else S.Diag(CurrExpr->getBeginLoc(), diag::note_lifetime_safety_aliases_storage) diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp index ed462f77008a8..51d16ddcbf767 100644 --- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp +++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp @@ -278,21 +278,21 @@ View return_view_field(const ViewProvider& v) { // expected-warning {{paramet void test_get_on_temporary_pointer() { const ReturnsSelf* s_ref = &ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}. // expected-note@-1 {{temporary object is destroyed here}} - // expected-note@-2 {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note@-2 {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} (void)s_ref; // expected-note {{later used here}} } void test_get_on_temporary_ref() { const ReturnsSelf& s_ref = ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}. // expected-note@-1 {{temporary object is destroyed here}} - // expected-note@-2 {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note@-2 {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} (void)s_ref; // expected-note {{later used here}} } void test_getView_on_temporary() { View sv = ViewProvider{1}.getView(); // expected-warning {{temporary object does not live long enough}}. // expected-note@-1 {{temporary object is destroyed here}} - // expected-note@-2 {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note@-2 {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} (void)sv; // expected-note {{later used here}} } @@ -603,7 +603,7 @@ void uaf_via_inferred_lifetimebound() { { int local; f = return_lambda_capturing_param(local); // expected-warning {{local variable 'local' does not live long enough}} \ - // expected-note {{result of call to 'return_lambda_capturing_param' aliases the storage of local variable 'local' because parameter 'x' is lifetimebound}} + // expected-note {{result of call to 'return_lambda_capturing_param' aliases the storage of local variable 'local' because parameter 'x' is inferred as lifetimebound}} } // expected-note {{local variable 'local' is destroyed here}} (void)f; // expected-note {{later used here}} } @@ -627,7 +627,7 @@ void test_inference() { { MyObj obj; ptr = create_target(obj); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note {{result of call to 'create_target' aliases the storage of local variable 'obj' because parameter 'obj' is lifetimebound}} + // expected-note {{result of call to 'create_target' aliases the storage of local variable 'obj' because parameter 'obj' is inferred as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} (void)ptr; // expected-note {{later used here}} } @@ -642,7 +642,7 @@ View* MakeView(const MyObj& in) { // expected-warning {{parameter in intra-TU fu void test_new_allocation() { View* v = MakeView(MyObj{}); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'MakeView' aliases the storage of temporary object because parameter 'in' is lifetimebound}} + // expected-note {{result of call to 'MakeView' aliases the storage of temporary object because parameter 'in' is inferred as lifetimebound}} (void)v; // expected-note {{later used here}} } diff --git a/clang/test/Sema/LifetimeSafety/nocfg.cpp b/clang/test/Sema/LifetimeSafety/nocfg.cpp index 8d7140c7a1b6a..5c5f0e6f7ce52 100644 --- a/clang/test/Sema/LifetimeSafety/nocfg.cpp +++ b/clang/test/Sema/LifetimeSafety/nocfg.cpp @@ -194,7 +194,7 @@ struct Unannotated { void modelIterators() { std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} (void)it; // cfg-note {{later used here}} } @@ -243,12 +243,12 @@ int &danglingRawPtrFromLocal3() { std::string_view containerWithAnnotatedElements() { std::string_view c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(c1); // cfg-note {{later used here}} c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(c1); // cfg-note {{later used here}} // no warning on constructing from gsl-pointer @@ -310,28 +310,28 @@ std::string_view danglingRefToOptionalFromTemp4() { void danglingReferenceFromTempOwner() { int &&r = *std::optional<int>(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} // https://github.com/llvm/llvm-project/issues/175893 int &&r2 = *std::optional<int>(5); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} // https://github.com/llvm/llvm-project/issues/175893 int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'value' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'value' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} const int &r4 = std::vector<int>().at(3); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} int &&r5 = std::vector<int>().at(3); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'at' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(r, r2, r3, r4, r5); // cfg-note 5 {{later used here}} std::string_view sv = *getTempOptStr(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(sv); // cfg-note {{later used here}} } @@ -343,7 +343,7 @@ void testLoops() { ; for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} cfg-note {{later used here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} ; } @@ -621,7 +621,7 @@ std::string_view ReturnStringView(std::string_view abc [[clang::lifetimebound]]) void test() { std::string_view svjkk1 = ReturnStringView(StrCat("bar", "x")); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'ReturnStringView' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'ReturnStringView' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(svjkk1); // cfg-note {{later used here}} } } // namespace GH100549 @@ -656,7 +656,7 @@ class Wrapper2 { }; std::string_view test2() { StatusOr<Wrapper2<std::string_view>> k; - // We expect dangling issues as the conversion operator is lifetimebound。 + // We expect dangling issues as the conversion operator is marked as lifetimebound。 std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // expected-warning {{temporary whose address is used as value of}} return k.value(); // expected-warning {{address of stack memory associated}} \ @@ -856,7 +856,7 @@ namespace GH118064{ void test() { auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(y); // cfg-note {{later used here}} } } // namespace GH118064 @@ -872,11 +872,11 @@ std::string_view TakeStr(std::string abc [[clang::lifetimebound]]); std::string_view test1_1() { std::string_view t1 = Ref(std::string()); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'Ref' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'Ref' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t1); // cfg-note {{later used here}} t1 = Ref(std::string()); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'Ref' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'Ref' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t1); // cfg-note {{later used here}} return Ref(std::string()); // expected-warning {{returning address}} \ // cfg-warning {{stack memory associated with temporary object is returned}} cfg-note {{returned here}} @@ -885,11 +885,11 @@ std::string_view test1_1() { std::string_view test1_2() { std::string_view t2 = TakeSv(std::string()); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'TakeSv' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'TakeSv' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t2); // cfg-note {{later used here}} t2 = TakeSv(std::string()); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'TakeSv' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'TakeSv' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t2); // cfg-note {{later used here}} return TakeSv(std::string()); // expected-warning {{returning address}} \ @@ -899,11 +899,11 @@ std::string_view test1_2() { std::string_view test1_3() { std::string_view t3 = TakeStrRef(std::string()); // expected-warning {{temporary}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'TakeStrRef' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'TakeStrRef' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t3); // cfg-note {{later used here}} t3 = TakeStrRef(std::string()); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'TakeStrRef' aliases the storage of temporary object because parameter 'abc' is lifetimebound}} + // cfg-note {{result of call to 'TakeStrRef' aliases the storage of temporary object because parameter 'abc' is marked as lifetimebound}} use(t3); // cfg-note {{later used here}} return TakeStrRef(std::string()); // expected-warning {{returning address}} \ // cfg-warning {{stack memory associated with temporary object is returned}} cfg-note {{returned here}} @@ -926,11 +926,11 @@ struct Foo { std::string_view test2_1(Foo<std::string> r1, Foo<std::string_view> r2) { std::string_view t1 = Foo<std::string>().get(); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} use(t1); // cfg-note {{later used here}} t1 = Foo<std::string>().get(); // expected-warning {{object backing}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} use(t1); // cfg-note {{later used here}} return r1.get(); // expected-warning {{address of stack}} \ // cfg-warning {{stack memory associated with parameter 'r1' is returned}} cfg-note {{returned here}} @@ -1049,16 +1049,16 @@ void operator_star_arrow_reference() { auto temporary = []() { return std::vector<std::string>{{"1"}}; }; const char* x = temporary().begin()->data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} const char* y = (*temporary().begin()).data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} const std::string& z = (*temporary().begin()); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(p, q, r, x, y, z); // cfg-note 3 {{later used here}} } @@ -1071,16 +1071,16 @@ void operator_star_arrow_of_iterators_false_positive_no_cfg_analysis() { auto temporary = []() { return std::vector<std::pair<int, std::string>>{{1, "1"}}; }; const char* x = temporary().begin()->second.data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} const char* y = (*temporary().begin()).second.data(); // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'data' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} const std::string& z = (*temporary().begin()).second; // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'begin' aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} use(p, q, r, x, y, z); // cfg-note 3 {{later used here}} } @@ -1131,24 +1131,24 @@ void test1() { std::string_view k1 = S().sv; // OK std::string_view k2 = S().s; // expected-warning {{object backing the pointer will}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} std::string_view k3 = Q().get()->sv; // OK std::string_view k4 = Q().get()->s; // expected-warning {{object backing the pointer will}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} std::string_view lb1 = foo(S().s); // expected-warning {{object backing the pointer will}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is lifetimebound}} + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is marked as lifetimebound}} std::string_view lb2 = foo(Q().get()->s); // expected-warning {{object backing the pointer will}} \ // cfg-warning {{temporary object does not live long enough}} cfg-note {{destroyed here}} \ - // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is lifetimebound}} + // cfg-note {{result of call to 'get' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} \ + // cfg-note {{expression aliases the storage of temporary object because the implicit object parameter is inferred as lifetimebound}} \ + // cfg-note {{result of call to 'foo' aliases the storage of temporary object because parameter 'sv' is marked as lifetimebound}} use(k1, k2, k3, k4, lb1, lb2); // cfg-note 4 {{later used here}} } diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c b/clang/test/Sema/LifetimeSafety/safety-c.c index 9fe671f9ed577..171ac15341efe 100644 --- a/clang/test/Sema/LifetimeSafety/safety-c.c +++ b/clang/test/Sema/LifetimeSafety/safety-c.c @@ -63,7 +63,7 @@ void lifetimebound_call(void) { { int i; p = identity(&i); // expected-warning {{local variable 'i' does not live long enough}} \ - // expected-note {{result of call to 'identity' aliases the storage of local variable 'i' because parameter 'p' is lifetimebound}} + // expected-note {{result of call to 'identity' aliases the storage of local variable 'i' because parameter 'p' is marked as lifetimebound}} } // expected-note {{local variable 'i' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -94,8 +94,8 @@ void conditional_operator_lifetimebound(int cond) { { int a, b; p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note {{result of call to 'identity' aliases the storage of local variable 'a' because parameter 'p' is lifetimebound}} \ - // expected-note {{result of call to 'identity' aliases the storage of local variable 'b' because parameter 'p' is lifetimebound}} + // expected-note {{result of call to 'identity' aliases the storage of local variable 'a' because parameter 'p' is marked as lifetimebound}} \ + // expected-note {{result of call to 'identity' aliases the storage of local variable 'b' because parameter 'p' is marked as lifetimebound}} : &b); // expected-warning {{local variable 'b' does not live long enough}} } // expected-note {{local variable 'a' is destroyed here}} \ // expected-note {{local variable 'b' is destroyed here}} diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp index b49829775777d..1b269b265acb1 100644 --- a/clang/test/Sema/LifetimeSafety/safety.cpp +++ b/clang/test/Sema/LifetimeSafety/safety.cpp @@ -697,7 +697,7 @@ void test_lifetimebound_multi_level() { int** pp = &p; int*** ppp = &pp; // expected-warning {{local variable 'pp' does not live long enough}} result = return_inner_ptr_addr(ppp); // expected-note {{local variable 'ppp' aliases the storage of local variable 'pp'}} \ - // expected-note {{result of call to 'return_inner_ptr_addr' aliases the storage of local variable 'pp' because parameter 'ppp' is lifetimebound}} + // expected-note {{result of call to 'return_inner_ptr_addr' aliases the storage of local variable 'pp' because parameter 'ppp' is marked as lifetimebound}} } // expected-note {{local variable 'pp' is destroyed here}} (void)**result; // expected-note {{used here}} } @@ -822,7 +822,7 @@ void lifetimebound_simple_function() { { MyObj obj; v = Identity(obj); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'obj' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'obj' because parameter 'v' is marked as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -832,7 +832,7 @@ void lifetimebound_unnamed_param() { { MyObj obj; v = Unnamed(obj); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note {{result of call to 'Unnamed' aliases the storage of local variable 'obj' because parameter '<unnamed>' is lifetimebound}} + // expected-note {{result of call to 'Unnamed' aliases the storage of local variable 'obj' because parameter '<unnamed>' is marked as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -841,8 +841,8 @@ void lifetimebound_multiple_args_definite() { View v; { MyObj obj1, obj2; - v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj1' because parameter 'a' is lifetimebound}} \ - // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2' because parameter 'b' is lifetimebound}} + v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj1' because parameter 'a' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2' because parameter 'b' is marked as lifetimebound}} obj1, // expected-warning {{local variable 'obj1' does not live long enough}} obj2); // expected-warning {{local variable 'obj2' does not live long enough}} } // expected-note {{local variable 'obj1' is destroyed here}} \ @@ -857,8 +857,8 @@ void lifetimebound_multiple_args_potential(bool cond) { MyObj obj1; if (cond) { MyObj obj2; - v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj1' because parameter 'a' is lifetimebound}} \ - // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2' because parameter 'b' is lifetimebound}} + v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj1' because parameter 'a' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2' because parameter 'b' is marked as lifetimebound}} obj1, // expected-warning {{local variable 'obj1' does not live long enough}} obj2); // expected-warning {{local variable 'obj2' does not live long enough}} } // expected-note {{local variable 'obj2' is destroyed here}} @@ -884,7 +884,7 @@ void lifetimebound_mixed_args() { { MyObj obj1, obj2; v = SelectFirst(obj1, // expected-warning {{local variable 'obj1' does not live long enough}} \ - // expected-note {{result of call to 'SelectFirst' aliases the storage of local variable 'obj1' because parameter 'a' is lifetimebound}} + // expected-note {{result of call to 'SelectFirst' aliases the storage of local variable 'obj1' because parameter 'a' is marked as lifetimebound}} obj2); } // expected-note {{local variable 'obj1' is destroyed here}} v.use(); // expected-note {{later used here}} @@ -901,7 +901,7 @@ void lifetimebound_member_function() { { MyObj obj; v = obj.getView(); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note {{result of call to 'getView' aliases the storage of local variable 'obj' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'getView' aliases the storage of local variable 'obj' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -926,7 +926,7 @@ void lifetimebound_chained_calls() { { MyObj obj; v = Identity(Identity(Identity(obj))); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note 3 {{result of call to 'Identity' aliases the storage of local variable 'obj' because parameter 'v' is lifetimebound}} + // expected-note 3 {{result of call to 'Identity' aliases the storage of local variable 'obj' because parameter 'v' is marked as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -936,7 +936,7 @@ void lifetimebound_with_pointers() { { MyObj obj; ptr = GetPointer(obj); // expected-warning {{local variable 'obj' does not live long enough}} \ - // expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'obj' because parameter 'obj' is lifetimebound}} + // expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'obj' because parameter 'obj' is marked as lifetimebound}} } // expected-note {{local variable 'obj' is destroyed here}} (void)*ptr; // expected-note {{later used here}} } @@ -946,7 +946,7 @@ void chained_assignment_lifetimebound_call() { { MyObj s; p = Identity(obj = &s); // expected-warning {{does not live long enough}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 's' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'Identity' aliases the storage of local variable 's' because parameter 'v' is marked as lifetimebound}} } // expected-note {{local variable 's' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -964,7 +964,7 @@ void lifetimebound_partial_safety(bool cond) { if (cond) { MyObj temp_obj; - v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'temp_obj' because parameter 'b' is lifetimebound}} + v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'temp_obj' because parameter 'b' is marked as lifetimebound}} safe_obj, temp_obj); // expected-warning {{local variable 'temp_obj' does not live long enough}} } // expected-note {{local variable 'temp_obj' is destroyed here}} @@ -979,7 +979,7 @@ void lifetimebound_return_reference() { MyObj obj; View temp_v = obj; // expected-warning {{local variable 'obj' does not live long enough}} const MyObj& ref = GetObject(temp_v); // expected-note {{local variable 'temp_v' aliases the storage of local variable 'obj'}} \ - // expected-note {{result of call to 'GetObject' aliases the storage of local variable 'obj' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'GetObject' aliases the storage of local variable 'obj' because parameter 'v' is marked as lifetimebound}} ptr = &ref; } // expected-note {{local variable 'obj' is destroyed here}} (void)*ptr; // expected-note {{later used here}} @@ -1034,7 +1034,7 @@ void lifetimebound_make_unique() { { MyObj obj; ptr = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{local variable 'obj' does not live long enough}} \ - // tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj &>' aliases the storage of local variable 'obj' because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj &>' aliases the storage of local variable 'obj' because parameter 'args' is inferred as lifetimebound}} } // tu-note {{local variable 'obj' is destroyed here}} (void)ptr; // tu-note {{later used here}} } @@ -1052,7 +1052,7 @@ void non_lifetimebound_make_unique() { void lifetimebound_make_unique_temp() { std::unique_ptr<LifetimeBoundCtor> ptr = std::make_unique<LifetimeBoundCtor>(MyObj()); // tu-warning {{temporary object does not live long enough}} \ // tu-note {{temporary object is destroyed here}} \ - // tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj>' aliases the storage of temporary object because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj>' aliases the storage of temporary object because parameter 'args' is inferred as lifetimebound}} (void)ptr; // tu-note {{later used here}} } @@ -1090,7 +1090,7 @@ void lifetimebound_make_unique_multi_params() { { MyObj obj_short; ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long); // tu-warning {{local variable 'obj_short' does not live long enough}} \ - // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &>' aliases the storage of local variable 'obj_short' because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &>' aliases the storage of local variable 'obj_short' because parameter 'args' is inferred as lifetimebound}} } // tu-note {{local variable 'obj_short' is destroyed here}} (void)ptr; // tu-note {{later used here}} } @@ -1101,7 +1101,7 @@ void lifetimebound_make_unique_multi_params2() { { MyObj obj_short; ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1); // tu-warning {{local variable 'obj_short' does not live long enough}} \ - // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, int>' aliases the storage of local variable 'obj_short' because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, int>' aliases the storage of local variable 'obj_short' because parameter 'args' is inferred as lifetimebound}} } // tu-note {{local variable 'obj_short' is destroyed here}} (void)ptr; // tu-note {{later used here}} } @@ -1122,7 +1122,7 @@ void lifetimebound_make_unique_multi_params3_1() { { MyObj obj_short; ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \ - // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short' because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short' because parameter 'args' is inferred as lifetimebound}} } // tu-note {{local variable 'obj_short' is destroyed here}} (void)ptr; // tu-note {{later used here}} } @@ -1133,7 +1133,7 @@ void lifetimebound_make_unique_multi_params3_2() { { MyObj obj_short; ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \ - // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short' because parameter 'args' is lifetimebound}} + // tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short' because parameter 'args' is inferred as lifetimebound}} } // tu-note {{local variable 'obj_short' is destroyed here}} (void)ptr; // tu-note {{later used here}} } @@ -1248,8 +1248,8 @@ void conditional_operator_lifetimebound(bool cond) { { MyObj a, b; p = Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is lifetimebound}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is marked as lifetimebound}} : &b); // expected-warning {{local variable 'b' does not live long enough}} } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}} (void)*p; // expected-note 2 {{later used here}} @@ -1260,10 +1260,10 @@ void conditional_operator_lifetimebound_nested(bool cond) { { MyObj a, b; p = Identity(cond ? Identity(&a) // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is lifetimebound}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is lifetimebound}} + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is marked as lifetimebound}} : Identity(&b)); // expected-warning {{local variable 'b' does not live long enough}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is marked as lifetimebound}} } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}} (void)*p; // expected-note 2 {{later used here}} } @@ -1273,14 +1273,14 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) { { MyObj a, b, c, d; p = Identity(cond ? Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is lifetimebound}} \ - // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is lifetimebound}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c' because parameter 'v' is lifetimebound}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd' because parameter 'v' is lifetimebound}} + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a' because parameter 'v' is marked as lifetimebound}} \ + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'b' because parameter 'v' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c' because parameter 'v' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd' because parameter 'v' is marked as lifetimebound}} : &b) // expected-warning {{local variable 'b' does not live long enough}} : Identity(cond ? &c // expected-warning {{local variable 'c' does not live long enough}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c' because parameter 'v' is lifetimebound}} \ - // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd' because parameter 'v' is lifetimebound}} + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c' because parameter 'v' is marked as lifetimebound}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd' because parameter 'v' is marked as lifetimebound}} : &d)); // expected-warning {{local variable 'd' does not live long enough}} } // expected-note {{local variable 'a' is destroyed here}} expected-note {{local variable 'd' is destroyed here}} expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}} (void)*p; // expected-note 4 {{later used here}} @@ -1475,7 +1475,7 @@ void parentheses(bool cond) { { MyObj a; p = ((GetPointer((a)))); // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'a' because parameter 'obj' is lifetimebound}} + // expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'a' because parameter 'obj' is marked as lifetimebound}} } // expected-note {{local variable 'a' is destroyed here}} (void)*p; // expected-note {{later used here}} @@ -1507,7 +1507,7 @@ void use_temporary_after_destruction() { void passing_temporary_to_lifetime_bound_function() { View a = construct_view(non_trivially_destructed_temporary()); // expected-warning {{temporary object does not live long enough}} \ expected-note {{temporary object is destroyed here}} \ - expected-note {{result of call to 'construct_view' aliases the storage of temporary object because parameter 'obj' is lifetimebound}} + expected-note {{result of call to 'construct_view' aliases the storage of temporary object because parameter 'obj' is marked as lifetimebound}} use(a); // expected-note {{later used here}} } @@ -1549,7 +1549,7 @@ int **bit_cast_multilevel() { namespace FullExprCleanupLoc { void var_initializer() { View v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \ - // expected-note {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} .getView(); // expected-note {{temporary object is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -1557,7 +1557,7 @@ void var_initializer() { void expr_statement() { View v; v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \ - // expected-note {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'getView' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} .getView(); // expected-note {{temporary object is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -1601,7 +1601,7 @@ void foobar() { { StatusOr<MyObj> string_or = getStringOr(); view = string_or. // expected-warning {{local variable 'string_or' does not live long enough}} \ - // expected-note {{result of call to 'value' aliases the storage of local variable 'string_or' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'value' aliases the storage of local variable 'string_or' because the implicit object parameter is marked as lifetimebound}} value(); } // expected-note {{local variable 'string_or' is destroyed here}} (void)view; // expected-note {{later used here}} @@ -1677,7 +1677,7 @@ void test_user_defined_deref_uaf() { MyObj obj; SmartPtr<MyObj> smart_ptr(&obj); p = &(*smart_ptr); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'smart_ptr' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -1695,7 +1695,7 @@ void test_user_defined_deref_with_view() { MyObj obj; SmartPtr<MyObj> smart_ptr(&obj); v = *smart_ptr; // expected-warning {{local variable 'smart_ptr' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'smart_ptr' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -1706,7 +1706,7 @@ void test_user_defined_deref_arrow() { MyObj obj; SmartPtr<MyObj> smart_ptr(&obj); p = smart_ptr.operator->(); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'smart_ptr' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'smart_ptr' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -1717,7 +1717,7 @@ void test_user_defined_deref_chained() { MyObj obj; SmartPtr<SmartPtr<MyObj>> double_ptr; p = &(**double_ptr); // expected-warning {{local variable 'double_ptr' does not live long enough}} \ - // expected-note 2 {{expression aliases the storage of local variable 'double_ptr' because the implicit object parameter is lifetimebound}} + // expected-note 2 {{expression aliases the storage of local variable 'double_ptr' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'double_ptr' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -1904,15 +1904,15 @@ void wrong_use_of_move_is_permissive() { { MyObj a; v = std::move(a); // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a' because parameter 't' is lifetimebound}} + // expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a' because parameter 't' is inferred as lifetimebound}} } // expected-note {{local variable 'a' is destroyed here}} (void)v; // expected-note {{later used here}} const int* p; { MyObj a; p = std::move(a).getData(); // expected-warning {{local variable 'a' does not live long enough}} \ - // expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a' because parameter 't' is lifetimebound}} \ - // expected-note {{result of call to 'getData' aliases the storage of local variable 'a' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a' because parameter 't' is inferred as lifetimebound}} \ + // expected-note {{result of call to 'getData' aliases the storage of local variable 'a' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'a' is destroyed here}} (void)p; // expected-note {{later used here}} } @@ -1924,7 +1924,7 @@ void test_release_no_uaf() { { std::unique_ptr<int> p; r = p.get(); // expected-warning {{local variable 'p' may not live long enough. This could be a false positive as the storage may have been moved later}} \ - // expected-note {{result of call to 'get' aliases the storage of local variable 'p' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'get' aliases the storage of local variable 'p' because the implicit object parameter is inferred as lifetimebound}} take(p.release()); // expected-note {{potentially moved here}} } // expected-note {{local variable 'p' is destroyed here}} (void)*r; // expected-note {{later used here}} @@ -1947,10 +1947,10 @@ void bar() { { S s; x = s.x(); // expected-warning {{local variable 's' does not live long enough}} \ - // expected-note {{result of call to 'x' aliases the storage of local variable 's' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'x' aliases the storage of local variable 's' because the implicit object parameter is marked as lifetimebound}} View y = S().x(); // expected-warning {{temporary object does not live long enough}} \ expected-note {{temporary object is destroyed here}} \ - expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} (void)y; // expected-note {{used here}} } // expected-note {{local variable 's' is destroyed here}} (void)x; // expected-note {{used here}} @@ -2039,19 +2039,19 @@ const S& identity(const S& in [[clang::lifetimebound]]); void test_temporary() { const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} (void)x; // expected-note {{later used here}} const std::string& y = identity(S().x()); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} \ - // expected-note {{result of call to 'identity' aliases the storage of temporary object because parameter 'in' is lifetimebound}} + // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} \ + // expected-note {{result of call to 'identity' aliases the storage of temporary object because parameter 'in' is marked as lifetimebound}} (void)y; // expected-note {{later used here}} std::string_view z; { S s; const std::string& zz = s.x(); // expected-warning {{local variable 's' does not live long enough}} \ - // expected-note {{result of call to 'x' aliases the storage of local variable 's' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'x' aliases the storage of local variable 's' because the implicit object parameter is marked as lifetimebound}} z = zz; // expected-note {{expression aliases the storage of local variable 's'}} } // expected-note {{local variable 's' is destroyed here}} (void)z; // expected-note {{later used here}} @@ -2061,13 +2061,13 @@ void test_lifetime_extension_ok() { const S& x = S(); (void)x; const S& y = identity(S()); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'identity' aliases the storage of temporary object because parameter 'in' is lifetimebound}} + // expected-note {{result of call to 'identity' aliases the storage of temporary object because parameter 'in' is marked as lifetimebound}} (void)y; // expected-note {{later used here}} } const std::string& test_return() { const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'x' aliases the storage of temporary object because the implicit object parameter is marked as lifetimebound}} return x; // expected-note {{later used here}} } } // namespace reference_type_decl_ref_expr @@ -2085,7 +2085,7 @@ void uaf() { S str; S* p = &str; // expected-warning {{local variable 'str' does not live long enough}} view = p->s; // expected-note {{local variable 'p' aliases the storage of local variable 'str'}} \ - // expected-note {{expression aliases the storage of local variable 'str' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'str' because the implicit object parameter is inferred as lifetimebound}} } // expected-note {{local variable 'str' is destroyed here}} (void)view; // expected-note {{later used here}} } @@ -2112,7 +2112,7 @@ void uaf_union() { U u = U{"hello"}; U* up = &u; // expected-warning {{local variable 'u' does not live long enough}} view = up->s; // expected-note {{local variable 'up' aliases the storage of local variable 'u'}} \ - // expected-note {{expression aliases the storage of local variable 'u' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'u' because the implicit object parameter is inferred as lifetimebound}} } // expected-note {{local variable 'u' is destroyed here}} (void)view; // expected-note {{later used here}} } @@ -2248,11 +2248,11 @@ const T* MemberFuncsTpl<T>::memberC(const T& x [[clang::lifetimebound]]) { void test() { MemberFuncsTpl<MyObj> mtf; const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'memberA' aliases the storage of temporary object because parameter 'x' is lifetimebound}} + // expected-note {{result of call to 'memberA' aliases the storage of temporary object because parameter 'x' is marked as lifetimebound}} const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{temporary object does not live long enough}} // tu-note {{temporary object is destroyed here}} \ - // tu-note {{result of call to 'memberB' aliases the storage of temporary object because parameter 'x' is lifetimebound}} + // tu-note {{result of call to 'memberB' aliases the storage of temporary object because parameter 'x' is inferred as lifetimebound}} const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'memberC' aliases the storage of temporary object because parameter 'x' is lifetimebound}} + // expected-note {{result of call to 'memberC' aliases the storage of temporary object because parameter 'x' is marked as lifetimebound}} (void)pTMA; // expected-note {{later used here}} (void)pTMB; // tu-note {{later used here}} (void)pTMC; // expected-note {{later used here}} @@ -2288,8 +2288,8 @@ void test_optional_arrow() { { std::optional<std::string> opt; p = opt->data(); // expected-warning {{local variable 'opt' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is lifetimebound}} \ - // expected-note {{result of call to 'data' aliases the storage of local variable 'opt' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \ + // expected-note {{result of call to 'data' aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} } // expected-note {{local variable 'opt' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -2299,8 +2299,8 @@ void test_optional_arrow_lifetimebound() { { std::optional<MyObj> opt; v = opt->getView(); // expected-warning {{local variable 'opt' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is lifetimebound}} \ - // expected-note {{result of call to 'getView' aliases the storage of local variable 'opt' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} \ + // expected-note {{result of call to 'getView' aliases the storage of local variable 'opt' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'opt' is destroyed here}} v.use(); // expected-note {{later used here}} } @@ -2310,8 +2310,8 @@ void test_unique_ptr_arrow() { { std::unique_ptr<std::string> up; p = up->data(); // expected-warning {{local variable 'up' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'up' because the implicit object parameter is lifetimebound}} \ - // expected-note {{result of call to 'data' aliases the storage of local variable 'up' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'up' because the implicit object parameter is inferred as lifetimebound}} \ + // expected-note {{result of call to 'data' aliases the storage of local variable 'up' because the implicit object parameter is inferred as lifetimebound}} } // expected-note {{local variable 'up' is destroyed here}} (void)*p; // expected-note {{later used here}} } @@ -2701,8 +2701,8 @@ struct S { void indexing_with_static_operator() { S()(1, 2); - S& x = S()("1", // expected-note {{expression aliases the storage of temporary object because parameter 'a' is lifetimebound}} \ - // expected-note {{expression aliases the storage of temporary object because parameter 'b' is lifetimebound}} + S& x = S()("1", // expected-note {{expression aliases the storage of temporary object because parameter 'a' is marked as lifetimebound}} \ + // expected-note {{expression aliases the storage of temporary object because parameter 'b' is marked as lifetimebound}} 2, // expected-warning {{temporary object does not live long enough}} 3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{temporary object is destroyed here}} @@ -2728,7 +2728,7 @@ S getS(const std::string &s [[clang::lifetimebound]]); void from_free_function() { S s = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'getS' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getS' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} use(s); // expected-note {{later used here}} } @@ -2748,14 +2748,14 @@ void from_method() { Factory f; S s = f.make(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'make' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'make' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} use(s); // expected-note {{later used here}} } void from_static_method() { S s = Factory::create(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'create' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'create' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} use(s); // expected-note {{later used here}} } @@ -2764,7 +2764,7 @@ void from_lifetimebound_this_method() { { Factory f; value = f.makeThis(); // expected-warning {{local variable 'f' does not live long enough}} \ - // expected-note {{result of call to 'makeThis' aliases the storage of local variable 'f' because the implicit object parameter is lifetimebound}} + // expected-note {{result of call to 'makeThis' aliases the storage of local variable 'f' because the implicit object parameter is marked as lifetimebound}} } // expected-note {{local variable 'f' is destroyed here}} use(value); // expected-note {{later used here}} } @@ -2774,7 +2774,7 @@ void across_scope() { { std::string str{"abc"}; s = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \ - // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is marked as lifetimebound}} } // expected-note {{local variable 'str' is destroyed here}} use(s); // expected-note {{later used here}} } @@ -2797,7 +2797,7 @@ void assignment_propagation() { { std::string str{"abc"}; a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \ - // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is marked as lifetimebound}} b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}} } // expected-note {{local variable 'str' is destroyed here}} use(b); // expected-note {{later used here}} @@ -2808,7 +2808,7 @@ void chained_defaulted_assignment_propagation() { { std::string str{"abc"}; S a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \ - // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getS' aliases the storage of local variable 'str' because parameter 's' is marked as lifetimebound}} c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}} \ // expected-note {{expression aliases the storage of local variable 'str'}} } // expected-note {{local variable 'str' is destroyed here}} @@ -2825,7 +2825,7 @@ void no_annotation() { void mix_annotated_and_not() { S s1 = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'getS' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getS' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} S s2 = getSNoAnnotation(std::string("temp")); use(s1); // expected-note {{later used here}} use(s2); @@ -2837,7 +2837,7 @@ S multiple_lifetimebound_params() { std::string str{"abc"}; S s = getS2(str, std::string("temp")); // expected-warning {{stack memory associated with local variable 'str' is returned}} \ // expected-warning {{temporary object does not live long enough}} \ - // expected-note {{result of call to 'getS2' aliases the storage of temporary object because parameter 'b' is lifetimebound}} \ + // expected-note {{result of call to 'getS2' aliases the storage of temporary object because parameter 'b' is marked as lifetimebound}} \ // expected-note {{temporary object is destroyed here}} return s; // expected-note {{returned here}} \ // expected-note {{later used here}} @@ -2858,7 +2858,7 @@ T make(const std::string &s [[clang::lifetimebound]]); void from_template_instantiation() { S s = make<S>(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'make<track_origins_for_lifetimebound_record_type::S>' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'make<track_origins_for_lifetimebound_record_type::S>' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} use(s); // expected-note {{later used here}} } @@ -2922,7 +2922,7 @@ SAlias getSAlias(const std::string &s [[clang::lifetimebound]]); void from_typedef_return() { SAlias s = getSAlias(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'getSAlias' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getSAlias' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} use(s); // expected-note {{later used here}} } @@ -2997,7 +2997,7 @@ std::unique_ptr<S> getUniqueS(const std::string &s [[clang::lifetimebound]]); void owner_return_unique_ptr_s() { auto ptr = getUniqueS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \ // expected-note {{temporary object is destroyed here}} \ - // expected-note {{result of call to 'getUniqueS' aliases the storage of temporary object because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getUniqueS' aliases the storage of temporary object because parameter 's' is marked as lifetimebound}} (void)ptr; // expected-note {{later used here}} } @@ -3014,7 +3014,7 @@ void owner_outlives_lifetimebound_source() { { std::string local; ups = getUniqueS(local); // expected-warning {{local variable 'local' does not live long enough}} \ - // expected-note {{result of call to 'getUniqueS' aliases the storage of local variable 'local' because parameter 's' is lifetimebound}} + // expected-note {{result of call to 'getUniqueS' aliases the storage of local variable 'local' because parameter 's' is marked as lifetimebound}} } // expected-note {{local variable 'local' is destroyed here}} (void)ups; // expected-note {{later used here}} } @@ -3809,7 +3809,7 @@ void uaf_via_lifetimebound() { { int local; f = capture_lifetimebound_param(local); // expected-warning {{local variable 'local' does not live long enough}} \ - // expected-note {{result of call to 'capture_lifetimebound_param' aliases the storage of local variable 'local' because parameter 'x' is lifetimebound}} + // expected-note {{result of call to 'capture_lifetimebound_param' aliases the storage of local variable 'local' because parameter 'x' is marked as lifetimebound}} } // expected-note {{local variable 'local' is destroyed here}} (void)f; // expected-note {{later used here}} } @@ -3873,7 +3873,7 @@ void deref_use_after_scope() { { optional<MyObj> opt; p = &*opt; // expected-warning {{local variable 'opt' does not live long enough}} \ - // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is lifetimebound}} + // expected-note {{expression aliases the storage of local variable 'opt' because the implicit object parameter is inferred as lifetimebound}} } // expected-note {{local variable 'opt' is destroyed here}} (void)p->id; // expected-note {{later used here}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
