Author: Utkarsh Saxena
Date: 2026-06-25T14:58:28+02:00
New Revision: 75a256727cc5977775bc85f30fea9767f8e53b65

URL: 
https://github.com/llvm/llvm-project/commit/75a256727cc5977775bc85f30fea9767f8e53b65
DIFF: 
https://github.com/llvm/llvm-project/commit/75a256727cc5977775bc85f30fea9767f8e53b65.diff

LOG: [LifetimeSafety] Gate annotation suggestions behind `SuggestAnnotations` 
opt (#205764)

Annotations suggestions expectedly fire very often and they have
recently shown significant regressions after the
https://github.com/llvm/llvm-project/pull/204045. This now gates the
suggestions behind a dedicated `SuggestAnnotations` option, preventing
unnecessary work when the relevant diagnostics are disabled.

Added: 
    

Modified: 
    clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
    clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
    clang/lib/Analysis/LifetimeSafety/Checker.cpp
    clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
    clang/lib/Sema/AnalysisBasedWarnings.cpp
    clang/lib/Sema/SemaLifetimeSafety.h
    clang/test/Sema/LifetimeSafety/safety.cpp

Removed: 
    


################################################################################
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 *
   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..e070d9f1a9b85 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2929,7 +2929,9 @@ LifetimeSafetyTUAnalysis(Sema &S, TranslationUnitDecl *TU,
     AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
     AC.getCFGBuildOptions().setAllAlwaysAdd();
     if (AC.getCFG())
-      runLifetimeSafetyAnalysis(AC, &SemaHelper, LSStats, S.CollectStats);
+      runLifetimeSafetyAnalysis(AC, &SemaHelper,
+                                lifetimes::GetLifetimeSafetyOpts(S, FD),
+                                LSStats, S.CollectStats);
   }
 }
 
@@ -3159,13 +3161,12 @@ 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::runLifetimeSafetyAnalysis(AC, &LifetimeSafetySemaHelper,
-                                           LSStats, S.CollectStats);
+      lifetimes::runLifetimeSafetyAnalysis(
+          AC, &LifetimeSafetySemaHelper, lifetimes::GetLifetimeSafetyOpts(S, 
D),
+          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..a3d546792fe41 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -76,6 +76,26 @@ 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;
+}
+
+inline LifetimeSafetyOpts GetLifetimeSafetyOpts(Sema &S, const Decl *D) {
+  LifetimeSafetyOpts LSOpts;
+  LSOpts.MaxCFGBlocks = S.getLangOpts().LifetimeSafetyMaxCFGBlocks;
+  LSOpts.SuggestAnnotations = ShouldSuggestLifetimeAnnotations(S, D);
+  return LSOpts;
+}
+
 class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
 
 public:

diff  --git a/clang/test/Sema/LifetimeSafety/safety.cpp 
b/clang/test/Sema/LifetimeSafety/safety.cpp
index b59fac191dcfb..2c2d62b25b6c8 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -3955,3 +3955,9 @@ struct [[gsl::Pointer()]] PtrWithInt { int x; };
 PtrWithInt f() {
   return PtrWithInt{10};
 }
+
+// This would normally trigger a suggestion warning if 
-Wlifetime-safety-suggestions was on.
+// Since it is off, we expect NO warnings or notes here.
+View suggestion_disabled_test(View a) {
+  return a;
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to