https://github.com/AnonMiraj updated https://github.com/llvm/llvm-project/pull/212213
>From a61503b54e9568254885777cf89f5ca1586ec99f Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Mon, 27 Jul 2026 11:56:36 +0300 Subject: [PATCH 1/2] [clang] Cache the analysis-based warning policy in effect --- clang/include/clang/Basic/Diagnostic.h | 11 +++++ .../clang/Sema/AnalysisBasedWarnings.h | 7 +++ clang/lib/Sema/AnalysisBasedWarnings.cpp | 46 +++++++++++++++++-- clang/lib/Sema/Sema.cpp | 4 ++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 826b747f2c751..18cbd34c29ce5 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -583,6 +583,17 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { DiagSuppressionMapping; public: + /// Returns a cache key representing the diagnostic state at \p Loc. + const void *getDiagStateKeyForLoc(SourceLocation Loc) const { + return GetDiagStateForLoc(Loc); + } + + /// True if an active diagnostic suppression mapping makes severity dependent + /// on the file path. + bool hasDiagSuppressionMapping() const { + return static_cast<bool>(DiagSuppressionMapping); + } + explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, DiagnosticOptions &DiagOpts, DiagnosticConsumer *client = nullptr, diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h b/clang/include/clang/Sema/AnalysisBasedWarnings.h index 0ed61e56825be..c79e72bf3037f 100644 --- a/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -66,6 +66,10 @@ class AnalysisBasedWarnings { Policy PolicyOverrides; void clearOverrides(); + /// Caches results for getPolicyInEffectAt(). + /// Flushed whenever a diagnostic pragma changes severities. + llvm::DenseMap<const void *, Policy> PolicyCache[4]; + /// \name Statistics /// @{ @@ -129,6 +133,9 @@ class AnalysisBasedWarnings { // will override the policy used to issue warnings. Policy &getPolicyOverrides() { return PolicyOverrides; } + /// Drop cached getPolicyInEffectAt() results (diagnostic state changed). + void clearPolicyCache(); + void PrintStats() const; }; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index e070d9f1a9b85..f0674f80a825c 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2759,23 +2759,59 @@ sema::AnalysisBasedWarnings::Policy sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { using namespace diag; DiagnosticsEngine &D = S.getDiagnostics(); + + // This runs at the end of every function definition, and the checks below + // resolve Loc against the pragma diagnostic state (and system header/macro + // classification) once per queried diagnostic. Those inputs fully determine + // the result, so cache the policy on them instead (PolicyOverrides are + // transient per-function state and are applied after the cache lookup). + const bool Cacheable = !D.hasDiagSuppressionMapping(); + const void *StateKey = nullptr; + unsigned SysIdx = 0; + if (Cacheable) { + StateKey = D.getDiagStateKeyForLoc(Loc); + if (Loc.isValid() && D.hasSourceManager()) { + const SourceManager &SM = D.getSourceManager(); + SysIdx = (SM.isInSystemHeader(SM.getExpansionLoc(Loc)) ? 2u : 0u) | + (SM.isInSystemMacro(Loc) ? 1u : 0u); + } + auto It = PolicyCache[SysIdx].find(StateKey); + if (It != PolicyCache[SysIdx].end()) { + Policy P = It->second; + P.enableCheckUnreachable |= PolicyOverrides.enableCheckUnreachable; + P.enableThreadSafetyAnalysis |= + PolicyOverrides.enableThreadSafetyAnalysis; + P.enableConsumedAnalysis |= PolicyOverrides.enableConsumedAnalysis; + return P; + } + } + Policy P; // Note: The enabled checks should be kept in sync with the switch in // SemaPPCallbacks::PragmaDiagnostic(). P.enableCheckUnreachable = - PolicyOverrides.enableCheckUnreachable || areAnyEnabled(D, Loc, warn_unreachable, warn_unreachable_break, warn_unreachable_return, warn_unreachable_loop_increment); - P.enableThreadSafetyAnalysis = PolicyOverrides.enableThreadSafetyAnalysis || - areAnyEnabled(D, Loc, warn_double_lock); + P.enableThreadSafetyAnalysis = areAnyEnabled(D, Loc, warn_double_lock); - P.enableConsumedAnalysis = PolicyOverrides.enableConsumedAnalysis || - areAnyEnabled(D, Loc, warn_use_in_invalid_state); + P.enableConsumedAnalysis = areAnyEnabled(D, Loc, warn_use_in_invalid_state); + + if (Cacheable) + PolicyCache[SysIdx][StateKey] = P; + + P.enableCheckUnreachable |= PolicyOverrides.enableCheckUnreachable; + P.enableThreadSafetyAnalysis |= PolicyOverrides.enableThreadSafetyAnalysis; + P.enableConsumedAnalysis |= PolicyOverrides.enableConsumedAnalysis; return P; } +void sema::AnalysisBasedWarnings::clearPolicyCache() { + for (auto &M : PolicyCache) + M.clear(); +} + void sema::AnalysisBasedWarnings::clearOverrides() { PolicyOverrides.enableCheckUnreachable = false; PolicyOverrides.enableConsumedAnalysis = false; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 78fbc9e31842d..322ae410ed6cd 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -227,6 +227,10 @@ class SemaPPCallbacks : public PPCallbacks { } void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Severity Mapping, StringRef Str) override { + // The pragma changed diagnostic severities; drop any cached analysis + // warning policies derived from the previous state. + S->AnalysisWarnings.clearPolicyCache(); + // If one of the analysis-based diagnostics was enabled while processing // a function, we want to note it in the analysis-based warnings so they // can be run at the end of the function body even if the analysis warnings >From c5f626c2e6f28160df043263e179f5b257c13249 Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Tue, 28 Jul 2026 10:49:33 +0300 Subject: [PATCH 2/2] Don't cache when SourceLocation is invalid --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index f0674f80a825c..a70f1b0c77236 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2765,16 +2765,14 @@ sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { // classification) once per queried diagnostic. Those inputs fully determine // the result, so cache the policy on them instead (PolicyOverrides are // transient per-function state and are applied after the cache lookup). - const bool Cacheable = !D.hasDiagSuppressionMapping(); + const bool Cacheable = !D.hasDiagSuppressionMapping() && Loc.isValid(); const void *StateKey = nullptr; unsigned SysIdx = 0; if (Cacheable) { StateKey = D.getDiagStateKeyForLoc(Loc); - if (Loc.isValid() && D.hasSourceManager()) { - const SourceManager &SM = D.getSourceManager(); - SysIdx = (SM.isInSystemHeader(SM.getExpansionLoc(Loc)) ? 2u : 0u) | - (SM.isInSystemMacro(Loc) ? 1u : 0u); - } + const SourceManager &SM = D.getSourceManager(); + SysIdx = (SM.isInSystemHeader(SM.getExpansionLoc(Loc)) ? 2u : 0u) | + (SM.isInSystemMacro(Loc) ? 1u : 0u); auto It = PolicyCache[SysIdx].find(StateKey); if (It != PolicyCache[SysIdx].end()) { Policy P = It->second; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
