https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/205764
>From 9ad57f3a6e129a25471d298edfc6c0fd82c8c634 Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <[email protected]> Date: Thu, 25 Jun 2026 10:10:35 +0000 Subject: [PATCH 1/3] suggesionsopt-in-suggestions --- .../Analysis/Analyses/LifetimeSafety/Checker.h | 3 ++- .../Analyses/LifetimeSafety/LifetimeSafety.h | 4 ++++ clang/lib/Analysis/LifetimeSafety/Checker.cpp | 14 ++++++++++---- .../lib/Analysis/LifetimeSafety/LifetimeSafety.cpp | 7 ++----- clang/lib/Sema/AnalysisBasedWarnings.cpp | 13 ++++++++++--- clang/lib/Sema/SemaLifetimeSafety.h | 13 +++++++++++++ 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h index 1ad3f9da61f60..99ad816311e74 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h @@ -29,7 +29,8 @@ void runLifetimeChecker(const LoanPropagationAnalysis &LoanPropagation, const MovedLoansAnalysis &MovedLoans, const LiveOriginsAnalysis &LiveOrigins, FactManager &FactMgr, AnalysisDeclContext &ADC, - LifetimeSafetySemaHelper *SemaHelper); + LifetimeSafetySemaHelper *SemaHelper, + const LifetimeSafetyOpts &LSOpts); } // namespace clang::lifetimes::internal diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h index 28886b826f72f..80a23f18baebd 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h @@ -38,6 +38,9 @@ struct LifetimeSafetyOpts { /// Maximum number of CFG blocks to analyze. Functions with larger CFGs will /// be skipped. size_t MaxCFGBlocks; + + /// Whether to suggest lifetime annotations. + bool SuggestAnnotations; }; /// Enum to track functions visible across or within TU. @@ -157,6 +160,7 @@ class LifetimeSafetySemaHelper { /// The main entry point for the analysis. void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetySemaHelper *SemaHelper, + const LifetimeSafetyOpts &Opts, LifetimeSafetyStats &Stats, bool CollectStats); namespace internal { diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index c258a1dc3596c..746ebbfb15c39 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -68,6 +68,7 @@ class LifetimeChecker { LifetimeSafetySemaHelper *SemaHelper; ASTContext &AST; const Decl *FD; + const LifetimeSafetyOpts &LSOpts; static SourceLocation GetFactLoc(llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> F) { @@ -87,10 +88,11 @@ class LifetimeChecker { const MovedLoansAnalysis &MovedLoans, const LiveOriginsAnalysis &LiveOrigins, FactManager &FM, AnalysisDeclContext &ADC, - LifetimeSafetySemaHelper *SemaHelper) + LifetimeSafetySemaHelper *SemaHelper, + const LifetimeSafetyOpts &LSOpts) : LoanPropagation(LoanPropagation), MovedLoans(MovedLoans), LiveOrigins(LiveOrigins), FactMgr(FM), SemaHelper(SemaHelper), - AST(ADC.getASTContext()), FD(ADC.getDecl()) { + AST(ADC.getASTContext()), FD(ADC.getDecl()), LSOpts(LSOpts) { for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) for (const Fact *F : FactMgr.getFacts(B)) if (const auto *EF = F->getAs<ExpireFact>()) @@ -398,6 +400,9 @@ class LifetimeChecker { void suggestAnnotations() { if (!SemaHelper) return; + if (!LSOpts.SuggestAnnotations) + return; + llvm::TimeTraceScope TimeTrace("SuggestAnnotations"); for (auto [Target, EscapeTarget] : AnnotationWarningsMap) { if (const auto *PVD = Target.dyn_cast<const ParmVarDecl *>()) suggestWithScopeForParmVar(PVD, EscapeTarget); @@ -535,9 +540,10 @@ void runLifetimeChecker(const LoanPropagationAnalysis &LP, const MovedLoansAnalysis &MovedLoans, const LiveOriginsAnalysis &LO, FactManager &FactMgr, AnalysisDeclContext &ADC, - LifetimeSafetySemaHelper *SemaHelper) { + LifetimeSafetySemaHelper *SemaHelper, + const LifetimeSafetyOpts &LSOpts) { llvm::TimeTraceScope TimeProfile("LifetimeChecker"); - LifetimeChecker Checker(LP, MovedLoans, LO, FactMgr, ADC, SemaHelper); + LifetimeChecker Checker(LP, MovedLoans, LO, FactMgr, ADC, SemaHelper, LSOpts); } } // namespace clang::lifetimes::internal diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp index 714f979fa5ee7..680095a54177c 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp @@ -96,7 +96,7 @@ void LifetimeSafetyAnalysis::run() { Factory.MovedLoansMapFactory); runLifetimeChecker(*LoanPropagation, *MovedLoans, *LiveOrigins, *FactMgr, AC, - SemaHelper); + SemaHelper, LSOpts); DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(), /*ShowColors=*/true)); @@ -122,11 +122,8 @@ void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM, void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetySemaHelper *SemaHelper, + const LifetimeSafetyOpts &LSOpts, LifetimeSafetyStats &Stats, bool CollectStats) { - LifetimeSafetyOpts LSOpts; - LSOpts.MaxCFGBlocks = - AC.getASTContext().getLangOpts().LifetimeSafetyMaxCFGBlocks; - internal::LifetimeSafetyAnalysis Analysis(AC, SemaHelper, LSOpts); Analysis.run(); if (CollectStats) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 52fe7765c6c6a..d39763a8732ca 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2928,8 +2928,12 @@ LifetimeSafetyTUAnalysis(Sema &S, TranslationUnitDecl *TU, AC.getCFGBuildOptions().AddInitializers = true; AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true; AC.getCFGBuildOptions().setAllAlwaysAdd(); - if (AC.getCFG()) - runLifetimeSafetyAnalysis(AC, &SemaHelper, LSStats, S.CollectStats); + if (AC.getCFG()) { + lifetimes::LifetimeSafetyOpts LSOpts; + LSOpts.MaxCFGBlocks = S.getLangOpts().LifetimeSafetyMaxCFGBlocks; + LSOpts.SuggestAnnotations = lifetimes::ShouldSuggestLifetimeAnnotations(S, FD); + runLifetimeSafetyAnalysis(AC, &SemaHelper, LSOpts, LSStats, S.CollectStats); + } } } @@ -3164,8 +3168,11 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( if (EnableLifetimeSafetyAnalysis) { if (AC.getCFG()) { lifetimes::LifetimeSafetySemaHelperImpl LifetimeSafetySemaHelper(S); + lifetimes::LifetimeSafetyOpts LSOpts; + LSOpts.MaxCFGBlocks = S.getLangOpts().LifetimeSafetyMaxCFGBlocks; + LSOpts.SuggestAnnotations = lifetimes::ShouldSuggestLifetimeAnnotations(S, D); lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetySemaHelper, - LSStats, S.CollectStats); + LSOpts, LSStats, S.CollectStats); } } // Check for violations of "called once" parameter properties. diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 7c78a6a1e8c31..c15c8609845b6 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -76,6 +76,19 @@ inline bool IsLifetimeSafetyEnabled(Sema &S, const Decl *D) { return false; } +inline bool ShouldSuggestLifetimeAnnotations(Sema &S, const Decl *D) { + DiagnosticsEngine &Diags = S.getDiagnostics(); + constexpr unsigned DiagIDs[] = { + diag::warn_lifetime_safety_intra_tu_param_suggestion, + diag::warn_lifetime_safety_cross_tu_param_suggestion, + diag::warn_lifetime_safety_intra_tu_this_suggestion, + diag::warn_lifetime_safety_cross_tu_this_suggestion}; + for (unsigned DiagID : DiagIDs) + if (!Diags.isIgnored(DiagID, D->getBeginLoc())) + return true; + return false; +} + class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { public: >From 761abd1fbf088a2e2799133c6abed50e3120d2ca Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <[email protected]> Date: Thu, 25 Jun 2026 10:12:51 +0000 Subject: [PATCH 2/3] add tests --- .../annotation-suggestions-disabled.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 clang/test/Sema/LifetimeSafety/annotation-suggestions-disabled.cpp diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions-disabled.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions-disabled.cpp new file mode 100644 index 0000000000000..ca5b3b7a65dd1 --- /dev/null +++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions-disabled.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference -fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety -Wno-dangling -I%S -verify %s + +#include "Inputs/lifetime-analysis.h" + +struct View; +struct [[gsl::Owner]] MyObj { + View getView() const [[clang::lifetimebound]]; +}; +struct [[gsl::Pointer()]] View { + View(const MyObj&); +}; + +// This would normally trigger a suggestion warning if -Wlifetime-safety-suggestions was on. +// Since it is off, we expect NO warnings or notes here. +// expected-no-diagnostics +View return_view_directly(View a) { + return a; +} >From 3fc00fec9e13fefe49768506f11a49a42f0211af Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <[email protected]> Date: Thu, 25 Jun 2026 10:14:52 +0000 Subject: [PATCH 3/3] format --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index d39763a8732ca..99ba7b2e0b24e 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2931,7 +2931,8 @@ LifetimeSafetyTUAnalysis(Sema &S, TranslationUnitDecl *TU, if (AC.getCFG()) { lifetimes::LifetimeSafetyOpts LSOpts; LSOpts.MaxCFGBlocks = S.getLangOpts().LifetimeSafetyMaxCFGBlocks; - LSOpts.SuggestAnnotations = lifetimes::ShouldSuggestLifetimeAnnotations(S, FD); + LSOpts.SuggestAnnotations = + lifetimes::ShouldSuggestLifetimeAnnotations(S, FD); runLifetimeSafetyAnalysis(AC, &SemaHelper, LSOpts, LSStats, S.CollectStats); } } @@ -3163,14 +3164,13 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( } } - // TODO: Enable lifetime safety analysis for other languages once it is - // stable. if (EnableLifetimeSafetyAnalysis) { if (AC.getCFG()) { lifetimes::LifetimeSafetySemaHelperImpl LifetimeSafetySemaHelper(S); lifetimes::LifetimeSafetyOpts LSOpts; LSOpts.MaxCFGBlocks = S.getLangOpts().LifetimeSafetyMaxCFGBlocks; - LSOpts.SuggestAnnotations = lifetimes::ShouldSuggestLifetimeAnnotations(S, D); + LSOpts.SuggestAnnotations = + lifetimes::ShouldSuggestLifetimeAnnotations(S, D); lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetySemaHelper, LSOpts, LSStats, S.CollectStats); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
