llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-temporal-safety @llvm/pr-subscribers-clang Author: NeKon69 <details> <summary>Changes</summary> Reuses the function for getting object information that was added in #<!-- -->199432 Comes as part of completing #<!-- -->186002 --- Patch is 85.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/200031.diff 6 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3-3) - (modified) clang/lib/Sema/SemaLifetimeSafety.h (+6-4) - (modified) clang/test/Sema/warn-lifetime-analysis-nocfg.cpp (+44-44) - (modified) clang/test/Sema/warn-lifetime-safety-cfg-bailout.cpp (+2-2) - (modified) clang/test/Sema/warn-lifetime-safety-suggestions.cpp (+6-6) - (modified) clang/test/Sema/warn-lifetime-safety.cpp (+142-141) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e330ea03d0544..c4f16ffcfb649 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10964,11 +10964,11 @@ def warn_dangling_reference_captured_by_unknown : Warning< // Diagnostics based on the Lifetime safety analysis. def warn_lifetime_safety_use_after_scope : Warning< - "object whose reference is captured does not live long enough">, + "%0 does not live long enough">, InGroup<LifetimeSafetyUseAfterScope>, DefaultIgnore; def warn_lifetime_safety_use_after_scope_moved : Warning< - "object whose reference is captured may not live long enough. " - "This could be false positive as the storage may have been moved later">, + "%0 may not live long enough. " + "This could be a false positive as the storage may have been moved later">, InGroup<LifetimeSafetyUseAfterScopeMoved>, DefaultIgnore; def warn_lifetime_safety_use_after_free : Warning< diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 0305510c1a233..2c4cfeab845c9 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -63,10 +63,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr, const Expr *MovedExpr, SourceLocation FreeLoc) override { - S.Diag(IssueExpr->getExprLoc(), - MovedExpr ? diag::warn_lifetime_safety_use_after_scope_moved - : diag::warn_lifetime_safety_use_after_scope) - << IssueExpr->getSourceRange(); + unsigned DiagID = MovedExpr + ? diag::warn_lifetime_safety_use_after_scope_moved + : diag::warn_lifetime_safety_use_after_scope; + + S.Diag(IssueExpr->getExprLoc(), DiagID) + << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange(); if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp index 9c53129ff707d..fa9cd33cc2d61 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -75,7 +75,7 @@ struct Y { }; void dangligGslPtrFromTemporary() { - MyIntPointer p = Y{}.a; // cfg-warning {{object whose reference is captured does not live long enough}} \ + MyIntPointer p = Y{}.a; // cfg-warning {{local temporary object does not live long enough}} \ // cfg-note {{destroyed here}} (void)p; // cfg-note {{later used here}} } @@ -145,32 +145,32 @@ MyLongPointerFromConversion global2; void initLocalGslPtrWithTempOwner() { MyIntPointer p = MyIntOwner{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p); // cfg-note {{later used here}} MyIntPointer pp = p = MyIntOwner{}; // expected-warning {{object backing the pointer 'p' will be}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p, pp); // cfg-note {{later used here}} p = MyIntOwner{}; // expected-warning {{object backing the pointer 'p' }} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p); // cfg-note {{later used here}} pp = p; // no warning use(p, pp); global = MyIntOwner{}; // expected-warning {{object backing the pointer 'global' }} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(global); // cfg-note {{later used here}} MyLongPointerFromConversion p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p2); // cfg-note {{later used here}} p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer 'p2' }} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} global2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer 'global2' }} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(global2, p2); // cfg-note 2 {{later used here}} } @@ -193,7 +193,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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} (void)it; // cfg-note {{later used here}} } @@ -241,11 +241,11 @@ int &danglingRawPtrFromLocal3() { // GH100384 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(c1); // cfg-note {{later used here}} c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(c1); // cfg-note {{later used here}} // no warning on constructing from gsl-pointer @@ -306,23 +306,23 @@ 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} // 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} // 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(sv); // cfg-note {{later used here}} } @@ -333,7 +333,7 @@ void testLoops() { for (auto i : getTempVec()) // ok ; for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} cfg-note {{later used here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} cfg-note {{later used here}} ; } @@ -395,18 +395,18 @@ void handleGslPtrInitsThroughReference2() { void handleTernaryOperator(bool cond) { std::basic_string<char> def; std::basic_string_view<char> v = cond ? def : ""; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(v); // cfg-note {{later used here}} } std::string operator+(std::string_view s1, std::string_view s2); void danglingStringviewAssignment(std::string_view a1, std::string_view a2) { a1 = std::string(); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(a1); // cfg-note {{later used here}} a2 = a1 + a1; // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(a2); // cfg-note {{later used here}} } @@ -601,7 +601,7 @@ struct UrlAnalyzed { std::string StrCat(std::string_view, std::string_view); void test1() { UrlAnalyzed url(StrCat("abc", "bcd")); // expected-warning {{object backing the pointer will be destroyed}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} \ + // cfg-warning {{local temporary object does not live long enough}} \ // cfg-note {{destroyed here}} use(url); // cfg-note {{later used here}} } @@ -610,7 +610,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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(svjkk1); // cfg-note {{later used here}} } } // namespace GH100549 @@ -844,7 +844,7 @@ namespace GH118064{ void test() { auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(y); // cfg-note {{later used here}} } } // namespace GH118064 @@ -859,10 +859,10 @@ 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t1); // cfg-note {{later used here}} t1 = Ref(std::string()); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t1); // cfg-note {{later used here}} return Ref(std::string()); // expected-warning {{returning address}} \ // cfg-warning {{stack memory associated with local temporary object is returned}} cfg-note {{returned here}} @@ -870,10 +870,10 @@ std::string_view test1_1() { std::string_view test1_2() { std::string_view t2 = TakeSv(std::string()); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t2); // cfg-note {{later used here}} t2 = TakeSv(std::string()); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t2); // cfg-note {{later used here}} return TakeSv(std::string()); // expected-warning {{returning address}} \ @@ -882,10 +882,10 @@ std::string_view test1_2() { std::string_view test1_3() { std::string_view t3 = TakeStrRef(std::string()); // expected-warning {{temporary}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t3); // cfg-note {{later used here}} t3 = TakeStrRef(std::string()); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t3); // cfg-note {{later used here}} return TakeStrRef(std::string()); // expected-warning {{returning address}} \ // cfg-warning {{stack memory associated with local temporary object is returned}} cfg-note {{returned here}} @@ -907,10 +907,10 @@ 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 {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(t1); // cfg-note {{later used here}} t1 = Foo<std::string>().get(); // expected-warning {{object backing}} \ - // cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + // cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} 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}} @@ -939,9 +939,9 @@ struct [[gsl::Pointer]] Pointer { Pointer(const Bar & bar [[clang::lifetimebound]]); }; Pointer test3(Bar bar) { - Pointer p = Pointer(Bar()); // expected-warning {{temporary}} cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + Pointer p = Pointer(Bar()); // expected-warning {{temporary}} cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p); // cfg-note {{later used here}} - p = Pointer(Bar()); // expected-warning {{object backing}} cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}} + p = Pointer(Bar()); // expected-warning {{object backing}} cfg-warning {{local temporary object does not live long enough}} cfg-note {{destroyed here}} use(p); ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/200031 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
