llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Yuan Suo (suoyuan666) <details> <summary>Changes</summary> Initially, I planned to make all diagnostics in Checker.cpp use `buildOriginFlowChain`. However, after thinking about it, I think the current scope is more suitable for review. --- Patch is 84.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/212083.diff 12 Files Affected: - (modified) clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h (+16-7) - (modified) clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h (+1-1) - (modified) clang/lib/Analysis/LifetimeSafety/Checker.cpp (+19-16) - (modified) clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp (+7-2) - (modified) clang/lib/Sema/SemaLifetimeSafety.h (+31-13) - (modified) clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp (+15-8) - (modified) clang/test/Sema/LifetimeSafety/dangling-field.cpp (+18-9) - (modified) clang/test/Sema/LifetimeSafety/dangling-global.cpp (+1-1) - (modified) clang/test/Sema/LifetimeSafety/invalidations.cpp (+13-6) - (modified) clang/test/Sema/LifetimeSafety/nocfg.cpp (+65-28) - (modified) clang/test/Sema/LifetimeSafety/safety-c.c (+4-2) - (modified) clang/test/Sema/LifetimeSafety/safety.cpp (+167-85) ``````````diff diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h index a51ef2f7cc0ba..8e52363a41b4f 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h @@ -71,17 +71,20 @@ class LifetimeSafetySemaHelper { virtual void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, - const Expr *MovedExpr) {} + const Expr *MovedExpr, + llvm::ArrayRef<const Expr *> ExprChain) {} virtual void reportDanglingField(const Expr *IssueExpr, const FieldDecl *Field, const Expr *MovedExpr, - SourceLocation ExpiryLoc) {} + SourceLocation ExpiryLoc, + llvm::ArrayRef<const Expr *> ExprChain) {} virtual void reportDanglingGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, const Expr *MovedExpr, - SourceLocation ExpiryLoc) {} + SourceLocation ExpiryLoc, + llvm::ArrayRef<const Expr *> ExprChain) {} // Reports when a reference/iterator is used after the container operation // that invalidated it. @@ -95,16 +98,22 @@ class LifetimeSafetySemaHelper { llvm::ArrayRef<const Expr *> ExprChain) {} virtual void reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *Field, - const Expr *InvalidationExpr) {} + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) {} virtual void reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *Field, - const Expr *InvalidationExpr) {} + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) {} virtual void reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *Global, - const Expr *InvalidationExpr) {} + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) { + } virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *Global, - const Expr *InvalidationExpr) {} + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) { + } using EscapingTarget = llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>; diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index e13442facd82d..36c5e4242262e 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -51,7 +51,7 @@ class LoanPropagationAnalysis { const LoanID TargetLoan, const CFG *Cfg) const; - llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, + llvm::SmallVector<OriginID> buildOriginFlowChain(const Fact *F, const LoanID TargetLoan, const CFG *Cfg) const; diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index 53e5077131147..f099e400ee3b2 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -281,33 +281,35 @@ class LifetimeChecker { } else if (const auto *OEF = CausingFact.dyn_cast<const OriginEscapesFact *>()) { + llvm::SmallVector<const Expr *> ExprChain = + getExprChain(LoanPropagation.buildOriginFlowChain(OEF, LID, Cfg)); if (Warning.InvalidatedByExpr) { if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF)) { // Invalidated object escapes to a field. if (IssueExpr) // Invalidated object on stack escapes to a field. - SemaHelper->reportInvalidatedField(IssueExpr, - FieldEscape->getFieldDecl(), - Warning.InvalidatedByExpr); + SemaHelper->reportInvalidatedField( + IssueExpr, FieldEscape->getFieldDecl(), + Warning.InvalidatedByExpr, ExprChain); else if (InvalidatedPVD) // Invalidated parameter escapes to a field. - SemaHelper->reportInvalidatedField(InvalidatedPVD, - FieldEscape->getFieldDecl(), - Warning.InvalidatedByExpr); + SemaHelper->reportInvalidatedField( + InvalidatedPVD, FieldEscape->getFieldDecl(), + Warning.InvalidatedByExpr, ExprChain); } else if (const auto *GlobalEscape = dyn_cast<GlobalEscapeFact>(OEF)) { // Invalidated object escapes to global or static storage. if (IssueExpr) // Invalidated object on stack escapes to global or static // storage. - SemaHelper->reportInvalidatedGlobal(IssueExpr, - GlobalEscape->getGlobal(), - Warning.InvalidatedByExpr); + SemaHelper->reportInvalidatedGlobal( + IssueExpr, GlobalEscape->getGlobal(), + Warning.InvalidatedByExpr, ExprChain); else if (InvalidatedPVD) // Invalidated parameter escapes to global or static storage. - SemaHelper->reportInvalidatedGlobal(InvalidatedPVD, - GlobalEscape->getGlobal(), - Warning.InvalidatedByExpr); + SemaHelper->reportInvalidatedGlobal( + InvalidatedPVD, GlobalEscape->getGlobal(), + Warning.InvalidatedByExpr, ExprChain); } else if (isa<ReturnEscapeFact>(OEF)) { // FIXME: Diagnose invalidated return escapes separately. } else @@ -315,15 +317,16 @@ class LifetimeChecker { } else if (const auto *RetEscape = dyn_cast<ReturnEscapeFact>(OEF)) // Return stack address. SemaHelper->reportUseAfterReturn( - IssueExpr, RetEscape->getReturnExpr(), MovedExpr); + IssueExpr, RetEscape->getReturnExpr(), MovedExpr, ExprChain); else if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF)) // Dangling field. - SemaHelper->reportDanglingField( - IssueExpr, FieldEscape->getFieldDecl(), MovedExpr, ExpiryLoc); + SemaHelper->reportDanglingField(IssueExpr, + FieldEscape->getFieldDecl(), + MovedExpr, ExpiryLoc, ExprChain); else if (const auto *GlobalEscape = dyn_cast<GlobalEscapeFact>(OEF)) // Global escape. SemaHelper->reportDanglingGlobal(IssueExpr, GlobalEscape->getGlobal(), - MovedExpr, ExpiryLoc); + MovedExpr, ExpiryLoc, ExprChain); else llvm_unreachable("Unhandled OriginEscapesFact type"); } else diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp index 078892bd48c10..b2787c3abc987 100644 --- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp @@ -366,7 +366,12 @@ llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( } llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( - const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const { - return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); + const Fact *F, const LoanID TargetLoan, const CFG *Cfg) const { + if (const auto *UF = llvm::dyn_cast<UseFact>(F)) + return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); + if (const auto *OEF = llvm::dyn_cast<OriginEscapesFact>(F)) + return PImpl->buildOriginFlowChain(OEF, OEF->getEscapedOriginID(), + TargetLoan, Cfg); + llvm_unreachable("Unhandled Fact type"); } } // namespace clang::lifetimes::internal diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 1d9f94be7e22d..eaa5981639e80 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -128,7 +128,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { } void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr, - const Expr *MovedExpr) override { + const Expr *MovedExpr, + llvm::ArrayRef<const Expr *> ExprChain) override { unsigned DiagID = MovedExpr ? diag::warn_lifetime_safety_return_stack_addr_moved : diag::warn_lifetime_safety_return_stack_addr; @@ -139,14 +140,17 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); + + reportAliasingChain(ExprChain); + S.Diag(ReturnExpr->getExprLoc(), diag::note_lifetime_safety_returned_here) << ReturnExpr->getSourceRange(); } void reportDanglingField(const Expr *IssueExpr, const FieldDecl *DanglingField, - const Expr *MovedExpr, - SourceLocation ExpiryLoc) override { + const Expr *MovedExpr, SourceLocation ExpiryLoc, + llvm::ArrayRef<const Expr *> ExprChain) override { unsigned DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved : diag::warn_lifetime_safety_dangling_field; @@ -158,6 +162,9 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); + + reportAliasingChain(ExprChain); + S.Diag(DanglingField->getLocation(), diag::note_lifetime_safety_dangling_field_here) << DanglingField->getEndLoc(); @@ -165,8 +172,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { void reportDanglingGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, - const Expr *MovedExpr, - SourceLocation ExpiryLoc) override { + const Expr *MovedExpr, SourceLocation ExpiryLoc, + llvm::ArrayRef<const Expr *> ExprChain) override { unsigned DiagID = MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved : diag::warn_lifetime_safety_dangling_global; @@ -178,6 +185,9 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); + + reportAliasingChain(ExprChain); + if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) S.Diag(DanglingGlobal->getLocation(), diag::note_lifetime_safety_dangling_static_here) @@ -223,13 +233,15 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { void reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *DanglingField, - const Expr *InvalidationExpr) override { + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) override { std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr); S.Diag(IssueExpr->getExprLoc(), diag::warn_lifetime_safety_invalidated_field) << InvalidatedSubject << getDiagSubjectDescription(DanglingField) << IssueExpr->getSourceRange(); reportInvalidationSite(InvalidationExpr, InvalidatedSubject); + reportAliasingChain(ExprChain); S.Diag(DanglingField->getLocation(), diag::note_lifetime_safety_dangling_field_here) << DanglingField->getEndLoc(); @@ -237,27 +249,31 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { void reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *DanglingField, - const Expr *InvalidationExpr) override { + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) override { std::string InvalidatedSubject = getDiagSubjectDescription(PVD); S.Diag(PVD->getSourceRange().getBegin(), diag::warn_lifetime_safety_invalidated_field) << InvalidatedSubject << getDiagSubjectDescription(DanglingField) << PVD->getSourceRange(); reportInvalidationSite(InvalidationExpr, InvalidatedSubject); + reportAliasingChain(ExprChain); S.Diag(DanglingField->getLocation(), diag::note_lifetime_safety_dangling_field_here) << DanglingField->getEndLoc(); } - void reportInvalidatedGlobal(const Expr *IssueExpr, - const VarDecl *DanglingGlobal, - const Expr *InvalidationExpr) override { + void + reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal, + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) override { std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr); S.Diag(IssueExpr->getExprLoc(), diag::warn_lifetime_safety_invalidated_global) << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal) << IssueExpr->getSourceRange(); reportInvalidationSite(InvalidationExpr, InvalidatedSubject); + reportAliasingChain(ExprChain); if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) S.Diag(DanglingGlobal->getLocation(), diag::note_lifetime_safety_dangling_static_here) @@ -268,15 +284,17 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { << DanglingGlobal->getEndLoc(); } - void reportInvalidatedGlobal(const ParmVarDecl *PVD, - const VarDecl *DanglingGlobal, - const Expr *InvalidationExpr) override { + void + reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *DanglingGlobal, + const Expr *InvalidationExpr, + llvm::ArrayRef<const Expr *> ExprChain) override { std::string InvalidatedSubject = getDiagSubjectDescription(PVD); S.Diag(PVD->getSourceRange().getBegin(), diag::warn_lifetime_safety_invalidated_global) << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal) << PVD->getSourceRange(); reportInvalidationSite(InvalidationExpr, InvalidatedSubject); + reportAliasingChain(ExprChain); if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) S.Diag(DanglingGlobal->getLocation(), diag::note_lifetime_safety_dangling_static_here) diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp index 56ed4a6dc7106..3497598196ee5 100644 --- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp +++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp @@ -528,7 +528,8 @@ struct CaptureRefToView { CaptureRefToView test_ref_to_view() { MyObj obj; CaptureRefToView x(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct CaptureRefToPtr { @@ -539,7 +540,8 @@ struct CaptureRefToPtr { CaptureRefToPtr test_ref_to_ptr() { MyObj obj; CaptureRefToPtr x(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct CaptureViewToView { @@ -550,8 +552,9 @@ struct CaptureViewToView { CaptureViewToView test_view_to_view() { MyObj obj; View v(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - CaptureViewToView x(v); - return x; // expected-note {{returned here}} + CaptureViewToView x(v); // expected-note {{local variable 'v' aliases the storage of local variable 'obj'}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct CapturePtrToPtr { @@ -562,7 +565,8 @@ struct CapturePtrToPtr { CapturePtrToPtr test_ptr_to_ptr() { MyObj obj; CapturePtrToPtr x(&obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct CaptureRefToRef { @@ -573,7 +577,8 @@ struct CaptureRefToRef { CaptureRefToRef test_ref_to_ref() { MyObj obj; CaptureRefToRef x(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct BaseWithView { @@ -588,7 +593,8 @@ struct CaptureRefToBaseView : BaseWithView { CaptureRefToBaseView test_ref_to_base_view() { MyObj obj; CaptureRefToBaseView x(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } } // namespace capturing_constructor @@ -660,7 +666,8 @@ struct HasCtorField { HasCtorField test_dangling_field_ctor() { MyObj obj; HasCtorField x(obj); // expected-warning {{stack memory associated with local variable 'obj' is returned}} - return x; // expected-note {{returned here}} + return x; // expected-note {{returned here}} \ + // expected-note {{local variable 'x' aliases the storage of local variable 'obj'}} } struct HasSetterField { diff --git a/clang/test/Sema/LifetimeSafety/dangling-field.cpp b/clang/test/Sema/LifetimeSafety/dangling-field.cpp index bc73c4f7e8644..d3190d990d7a1 100644... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/212083 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
