https://github.com/AaronBallman updated https://github.com/llvm/llvm-project/pull/136323
>From 3beecb29772e13c6a1a41877e5e8cbbfb17a88f2 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Fri, 18 Apr 2025 12:26:36 -0400 Subject: [PATCH 1/5] Control analysis-based diagnostics with #pragma Previously, analysis-based diagnostics (like -Wconsumed) had to be enabled at file scope in order to be run at the end of each function body. This meant that they did not respect #pragma clang diagnostic enabling or disabling the diagnostic. Now, these pragmas can control the diagnostic emission. However, the behavior requires some explanation (which is why the documentation is being updated). Analysis-based warnings run at the end of a function body, so the diagnostic needs to be enabled after the closing } for the function in order to run the analysis at all. However, if the analysis emits a diagnostic for line in the function, the diagnostic still needs to be enabled on that specific line in order to be shown to the user. Fixes #42199 --- clang/docs/ReleaseNotes.rst | 3 + clang/docs/UsersManual.rst | 24 ++++++ .../clang/Sema/AnalysisBasedWarnings.h | 4 +- clang/lib/Sema/AnalysisBasedWarnings.cpp | 29 ++++--- clang/lib/Sema/SemaDecl.cpp | 8 +- clang/lib/Sema/SemaExpr.cpp | 3 +- clang/test/Analysis/pragma-diag-control.cpp | 77 +++++++++++++++++++ 7 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 clang/test/Analysis/pragma-diag-control.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f5cd1fbeabcfe..8d139123b47ce 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -395,6 +395,9 @@ Improvements to Clang's diagnostics constructors to initialize their non-modifiable members. The diagnostic is not new; being controlled via a warning group is what's new. Fixes #GH41104 +- Analysis-based diagnostics (like ``-Wconsumed`` or ``-Wunreachable-code``) + can now be correctly controlled by ``#pragma clang diagnostic``. #GH42199 + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 69256527f40c9..0ba4e2dedd4eb 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1202,6 +1202,30 @@ Clang also allows you to push and pop the current warning state. This is particularly useful when writing a header file that will be compiled by other people, because you don't know what warning flags they build with. +Note that the following diagnostic groups, which are ones based on analyzing +the control flow graph for a function, require the diagnostic group to be +enabled at the end of the function body (after the closing ``}``) in order to +run the analysis, in addition to requiring the diagnostic group to be enabled +at the line being diagnosed: + + * ``-Wconsumed`` + * ``-Wthread-safety-analysis`` + * ``-Wunreachable-code``, ``-Wunreachable-code-aggressive``, or warnings + controlled by either of those flags + +thus, it is generally better for a ``push`` and ``pop`` pair of pragmas +controlling behavior for an entire function be placed outside of the function +body rather than within it. e.g., + +.. code-block:: c + + #pragma clang diagnostic push + #pragma clang diagnostic warning "-Wwhatever" + int d() { + // Better to put the pragmas outside of the function rather than within it. + } + #pragma clang diagnostic pop + In the below example :option:`-Wextra-tokens` is ignored for only a single line of code, after which the diagnostics return to whatever state had previously existed. diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h b/clang/include/clang/Sema/AnalysisBasedWarnings.h index aafe227b84084..49023863f4503 100644 --- a/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -49,7 +49,6 @@ class AnalysisBasedWarnings { private: Sema &S; - Policy DefaultPolicy; class InterProceduralData; std::unique_ptr<InterProceduralData> IPData; @@ -103,7 +102,8 @@ class AnalysisBasedWarnings { // Issue warnings that require whole-translation-unit analysis. void IssueWarnings(TranslationUnitDecl *D); - Policy getDefaultPolicy() { return DefaultPolicy; } + // Gets the default policy which is in effect at the given source location. + Policy getPolicyInEffectAt(SourceLocation Loc); void PrintStats() const; }; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 34045a7274021..72962acee66d3 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2493,8 +2493,9 @@ class sema::AnalysisBasedWarnings::InterProceduralData { CalledOnceInterProceduralData CalledOnceData; }; -static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) { - return (unsigned)!D.isIgnored(diag, SourceLocation()); +static bool isEnabled(DiagnosticsEngine &D, unsigned diag, + SourceLocation Loc) { + return !D.isIgnored(diag, Loc); } sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) @@ -2504,24 +2505,28 @@ sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0), NumUninitAnalysisBlockVisits(0), MaxUninitAnalysisBlockVisitsPerFunction(0) { +} + +// We need this here for unique_ptr with forward declared class. +sema::AnalysisBasedWarnings::~AnalysisBasedWarnings() = default; +sema::AnalysisBasedWarnings::Policy +sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { using namespace diag; DiagnosticsEngine &D = S.getDiagnostics(); + Policy P; - DefaultPolicy.enableCheckUnreachable = - isEnabled(D, warn_unreachable) || isEnabled(D, warn_unreachable_break) || - isEnabled(D, warn_unreachable_return) || - isEnabled(D, warn_unreachable_loop_increment); + P.enableCheckUnreachable = isEnabled(D, warn_unreachable, Loc) || + isEnabled(D, warn_unreachable_break, Loc) || + isEnabled(D, warn_unreachable_return, Loc) || + isEnabled(D, warn_unreachable_loop_increment, Loc); - DefaultPolicy.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock); + P.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock, Loc); - DefaultPolicy.enableConsumedAnalysis = - isEnabled(D, warn_use_in_invalid_state); + P.enableConsumedAnalysis = isEnabled(D, warn_use_in_invalid_state, Loc); + return P; } -// We need this here for unique_ptr with forward declared class. -sema::AnalysisBasedWarnings::~AnalysisBasedWarnings() = default; - static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { for (const auto &D : fscope->PossiblyUnreachableDiags) S.Diag(D.Loc, D.PD); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 46933c5c43168..d28a2107d58a9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16150,7 +16150,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FSI->UsesFPIntrin && FD && !FD->hasAttr<StrictFPAttr>()) FD->addAttr(StrictFPAttr::CreateImplicit(Context)); - sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + SourceLocation AnalysisLoc; + if (Body) + AnalysisLoc = Body->getEndLoc(); + else if (FD) + AnalysisLoc = FD->getEndLoc(); + sema::AnalysisBasedWarnings::Policy WP = + AnalysisWarnings.getPolicyInEffectAt(AnalysisLoc); sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr; // If we skip function body, we can't tell if a function is a coroutine. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 9cd1a7e45fb64..a9f353be07ad2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16574,7 +16574,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); // Pop the block scope now but keep it alive to the end of this function. - AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + AnalysisBasedWarnings::Policy WP = + AnalysisWarnings.getPolicyInEffectAt(Body->getEndLoc()); PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy); BlockExpr *Result = new (Context) diff --git a/clang/test/Analysis/pragma-diag-control.cpp b/clang/test/Analysis/pragma-diag-control.cpp new file mode 100644 index 0000000000000..c41793c15bbcc --- /dev/null +++ b/clang/test/Analysis/pragma-diag-control.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Werror=unreachable-code-aggressive %s + +// Test that analysis-based warnings honor #pragma diagnostic controls. These +// diagnostics are triggered at the end of a function body, so the pragma needs +// to be enabled through to the closing curly brace in order for the diagnostic +// to be emitted. + +struct [[clang::consumable(unconsumed)]] Linear { + [[clang::return_typestate(unconsumed)]] + Linear() {} + [[clang::callable_when(consumed)]] + ~Linear() {} +}; + +int a() { + Linear l; + return 0; // No -Wconsumed diagnostic, analysis is not enabled. + return 1; // expected-error {{'return' will never be executed}} +} + +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconsumed" +int b() { + Linear l; + return 0; // expected-error {{invalid invocation of method '~Linear' on object 'l' while it is in the 'unconsumed' state}} + return 1; // expected-error {{'return' will never be executed}} +} +#pragma clang diagnostic pop + +int c() { +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconsumed" + Linear l; + return 0; // No -Wconsumed diagnostic, analysis is disabled before the closing brace + return 1; // expected-error {{'return' will never be executed}} +#pragma clang diagnostic pop +} + +int d() { +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconsumed" +#pragma clang diagnostic ignored "-Wunreachable-code-aggressive" + Linear l; + return 0; // expected-error {{invalid invocation of method '~Linear' on object 'l' while it is in the 'unconsumed' state}} + return 1; // Diagnostic is ignored +} +#pragma clang diagnostic pop + +int e() { +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconsumed" +#pragma clang diagnostic ignored "-Wunreachable-code-aggressive" + Linear l; + return 0; + return 1; + // Both diagnostics are ignored because analysis is disabled before the + // closing brace. +#pragma clang diagnostic pop +} + +int f() { + Linear l; + return 0; // No -Wconsumed diagnostic, analysis is not enabled at } so it never runs to produce the diagnostic + return 1; // Diagnostic ignores because it was disabled at the } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code-aggressive" +} +#pragma clang diagnostic pop + +int g() { + Linear l; + return 0; // No -Wconsumed diagnostic, the diagnostic generated at } is not enabled on this line. + return 1; // expected-error {{'return' will never be executed}} +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wconsumed" +} +#pragma clang diagnostic pop >From 17fcd1f225d15dd6f56b9ea951161696c11edc62 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Fri, 18 Apr 2025 13:10:08 -0400 Subject: [PATCH 2/5] Now with variadic goodness, as per review feedback --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 72962acee66d3..8b1e3b13831fa 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2493,11 +2493,16 @@ class sema::AnalysisBasedWarnings::InterProceduralData { CalledOnceInterProceduralData CalledOnceData; }; -static bool isEnabled(DiagnosticsEngine &D, unsigned diag, - SourceLocation Loc) { - return !D.isIgnored(diag, Loc); +static bool isEnabledImpl(DiagnosticsEngine &D, SourceLocation Loc, + unsigned Diag) { + return !D.isIgnored(Diag, Loc); } +template <typename... Ts> +static bool isEnabled(DiagnosticsEngine &D, SourceLocation Loc, Ts... Diags) { + return (isEnabledImpl(D, Loc, Diags) || ...); +}; + sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s), IPData(std::make_unique<InterProceduralData>()), NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0), @@ -2516,14 +2521,13 @@ sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { DiagnosticsEngine &D = S.getDiagnostics(); Policy P; - P.enableCheckUnreachable = isEnabled(D, warn_unreachable, Loc) || - isEnabled(D, warn_unreachable_break, Loc) || - isEnabled(D, warn_unreachable_return, Loc) || - isEnabled(D, warn_unreachable_loop_increment, Loc); + P.enableCheckUnreachable = + isEnabled(D, Loc, warn_unreachable, warn_unreachable_break, + warn_unreachable_return, warn_unreachable_loop_increment); - P.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock, Loc); + P.enableThreadSafetyAnalysis = isEnabled(D, Loc, warn_double_lock); - P.enableConsumedAnalysis = isEnabled(D, warn_use_in_invalid_state, Loc); + P.enableConsumedAnalysis = isEnabled(D, Loc, warn_use_in_invalid_state); return P; } >From 7e116dc273a423a04e22507edc7f957a2240d90d Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Fri, 18 Apr 2025 13:57:38 -0400 Subject: [PATCH 3/5] Implement Erich's suggestion --- clang/docs/UsersManual.rst | 24 ------------ .../clang/Sema/AnalysisBasedWarnings.h | 10 +++++ clang/lib/Sema/AnalysisBasedWarnings.cpp | 18 ++++++++- clang/lib/Sema/Sema.cpp | 37 +++++++++++++++++++ clang/test/Analysis/pragma-diag-control.cpp | 28 ++++++++------ 5 files changed, 80 insertions(+), 37 deletions(-) diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 0ba4e2dedd4eb..69256527f40c9 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1202,30 +1202,6 @@ Clang also allows you to push and pop the current warning state. This is particularly useful when writing a header file that will be compiled by other people, because you don't know what warning flags they build with. -Note that the following diagnostic groups, which are ones based on analyzing -the control flow graph for a function, require the diagnostic group to be -enabled at the end of the function body (after the closing ``}``) in order to -run the analysis, in addition to requiring the diagnostic group to be enabled -at the line being diagnosed: - - * ``-Wconsumed`` - * ``-Wthread-safety-analysis`` - * ``-Wunreachable-code``, ``-Wunreachable-code-aggressive``, or warnings - controlled by either of those flags - -thus, it is generally better for a ``push`` and ``pop`` pair of pragmas -controlling behavior for an entire function be placed outside of the function -body rather than within it. e.g., - -.. code-block:: c - - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wwhatever" - int d() { - // Better to put the pragmas outside of the function rather than within it. - } - #pragma clang diagnostic pop - In the below example :option:`-Wextra-tokens` is ignored for only a single line of code, after which the diagnostics return to whatever state had previously existed. diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h b/clang/include/clang/Sema/AnalysisBasedWarnings.h index 49023863f4503..4103c3f006a8f 100644 --- a/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -25,6 +25,7 @@ class QualType; class Sema; namespace sema { class FunctionScopeInfo; + class SemaPPCallbacks; } namespace sema { @@ -33,6 +34,7 @@ class AnalysisBasedWarnings { public: class Policy { friend class AnalysisBasedWarnings; + friend class SemaPPCallbacks; // The warnings to run. LLVM_PREFERRED_TYPE(bool) unsigned enableCheckFallThrough : 1; @@ -56,6 +58,9 @@ class AnalysisBasedWarnings { enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD; + Policy PolicyOverrides; + void clearOverrides(); + /// \name Statistics /// @{ @@ -105,6 +110,11 @@ class AnalysisBasedWarnings { // Gets the default policy which is in effect at the given source location. Policy getPolicyInEffectAt(SourceLocation Loc); + // Get the policies we may want to override due to things like #pragma clang + // diagnostic handling. If a caller sets any of these policies to true, that + // will override the policy used to issue warnings. + Policy &getPolicyOverrides() { return PolicyOverrides; } + void PrintStats() const; }; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 8b1e3b13831fa..cedb15b66ad48 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2521,16 +2521,27 @@ sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { DiagnosticsEngine &D = S.getDiagnostics(); Policy P; + // Note: The enabled checks should be kept in sync with the switch in + // SemaPPCallbacks::PragmaDiagnostic(). P.enableCheckUnreachable = + PolicyOverrides.enableCheckUnreachable || isEnabled(D, Loc, warn_unreachable, warn_unreachable_break, warn_unreachable_return, warn_unreachable_loop_increment); - P.enableThreadSafetyAnalysis = isEnabled(D, Loc, warn_double_lock); + P.enableThreadSafetyAnalysis = PolicyOverrides.enableThreadSafetyAnalysis || + isEnabled(D, Loc, warn_double_lock); - P.enableConsumedAnalysis = isEnabled(D, Loc, warn_use_in_invalid_state); + P.enableConsumedAnalysis = PolicyOverrides.enableConsumedAnalysis || + isEnabled(D, Loc, warn_use_in_invalid_state); return P; } +void sema::AnalysisBasedWarnings::clearOverrides() { + PolicyOverrides.enableCheckUnreachable = false; + PolicyOverrides.enableConsumedAnalysis = false; + PolicyOverrides.enableThreadSafetyAnalysis = false; +} + static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { for (const auto &D : fscope->PossiblyUnreachableDiags) S.Diag(D.Loc, D.PD); @@ -2880,6 +2891,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( AC.getCFG(); } + // Clear any of our policy overrides. + clearOverrides(); + // Collect statistics about the CFG if it was built. if (S.CollectStats && AC.isCFGBuilt()) { ++NumFunctionsAnalyzed; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d2da9cd1201c2..4039601612c62 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -202,6 +202,43 @@ class SemaPPCallbacks : public PPCallbacks { break; } } + void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, + diag::Severity Mapping, StringRef Str) override { + // 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 + // are disabled at that point. + SmallVector<diag::kind, 256> GroupDiags; + diag::Flavor Flavor = + Str[1] == 'W' ? diag::Flavor::WarningOrError : diag::Flavor::Remark; + StringRef Group = Str.substr(2); + + if (S->PP.getDiagnostics().getDiagnosticIDs()->getDiagnosticsInGroup( + Flavor, Group, GroupDiags)) + return; + + for (diag::kind K : GroupDiags) { + // Note: the cases in this switch should be kept in sync with the + // diagnostics in AnalysisBasedWarnings::getPolicyInEffectAt(). + AnalysisBasedWarnings::Policy &Override = + S->AnalysisWarnings.getPolicyOverrides(); + switch (K) { + default: break; + case diag::warn_unreachable: + case diag::warn_unreachable_break: + case diag::warn_unreachable_return: + case diag::warn_unreachable_loop_increment: + Override.enableCheckUnreachable = true; + break; + case diag::warn_double_lock: + Override.enableThreadSafetyAnalysis = true; + break; + case diag::warn_use_in_invalid_state: + Override.enableConsumedAnalysis = true; + break; + } + } + } }; } // end namespace sema diff --git a/clang/test/Analysis/pragma-diag-control.cpp b/clang/test/Analysis/pragma-diag-control.cpp index c41793c15bbcc..470960c030d0f 100644 --- a/clang/test/Analysis/pragma-diag-control.cpp +++ b/clang/test/Analysis/pragma-diag-control.cpp @@ -1,9 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Werror=unreachable-code-aggressive %s -// Test that analysis-based warnings honor #pragma diagnostic controls. These -// diagnostics are triggered at the end of a function body, so the pragma needs -// to be enabled through to the closing curly brace in order for the diagnostic -// to be emitted. +// Test that analysis-based warnings honor #pragma diagnostic controls. struct [[clang::consumable(unconsumed)]] Linear { [[clang::return_typestate(unconsumed)]] @@ -31,7 +28,7 @@ int c() { #pragma clang diagnostic push #pragma clang diagnostic error "-Wconsumed" Linear l; - return 0; // No -Wconsumed diagnostic, analysis is disabled before the closing brace + return 0; // expected-error {{invalid invocation of method '~Linear' on object 'l' while it is in the 'unconsumed' state}} return 1; // expected-error {{'return' will never be executed}} #pragma clang diagnostic pop } @@ -51,17 +48,15 @@ int e() { #pragma clang diagnostic error "-Wconsumed" #pragma clang diagnostic ignored "-Wunreachable-code-aggressive" Linear l; - return 0; - return 1; - // Both diagnostics are ignored because analysis is disabled before the - // closing brace. + return 0; // expected-error {{invalid invocation of method '~Linear' on object 'l' while it is in the 'unconsumed' state}} + return 1; // Diagnostic is ignored #pragma clang diagnostic pop } int f() { Linear l; - return 0; // No -Wconsumed diagnostic, analysis is not enabled at } so it never runs to produce the diagnostic - return 1; // Diagnostic ignores because it was disabled at the } + return 0; // No -Wconsumed diagnostic, analysis is not enabled + return 1; // expected-error {{'return' will never be executed}} #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code-aggressive" } @@ -75,3 +70,14 @@ int g() { #pragma clang diagnostic warning "-Wconsumed" } #pragma clang diagnostic pop + +int h() { +#pragma clang diagnostic push +#pragma clang diagnostic error "-Wconsumed" +#pragma clang diagnostic ignored "-Wunreachable-code-aggressive" +#pragma clang diagnostic pop + + Linear l; + return 0; // No -Wconsumed diagnostic, the diagnostic generated at } is not enabled on this line. + return 1; // expected-error {{'return' will never be executed}} +} >From 1644401eda879b94b483daec379cb37488b1a4ec Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Fri, 18 Apr 2025 13:59:15 -0400 Subject: [PATCH 4/5] Simplify based on review feedback --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index cedb15b66ad48..884b82fe0d765 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2493,14 +2493,9 @@ class sema::AnalysisBasedWarnings::InterProceduralData { CalledOnceInterProceduralData CalledOnceData; }; -static bool isEnabledImpl(DiagnosticsEngine &D, SourceLocation Loc, - unsigned Diag) { - return !D.isIgnored(Diag, Loc); -} - template <typename... Ts> static bool isEnabled(DiagnosticsEngine &D, SourceLocation Loc, Ts... Diags) { - return (isEnabledImpl(D, Loc, Diags) || ...); + return (!D.isIgnored(Diags, Loc) || ...); }; sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) >From cf27e93a961cdfb9a1e7329e66b8c54bfee01e9b Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Fri, 18 Apr 2025 14:13:53 -0400 Subject: [PATCH 5/5] Rename based on review feedback; NFC --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 884b82fe0d765..6dcec5008c4a6 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2494,7 +2494,8 @@ class sema::AnalysisBasedWarnings::InterProceduralData { }; template <typename... Ts> -static bool isEnabled(DiagnosticsEngine &D, SourceLocation Loc, Ts... Diags) { +static bool areAnyEnabled(DiagnosticsEngine &D, SourceLocation Loc, + Ts... Diags) { return (!D.isIgnored(Diags, Loc) || ...); }; @@ -2520,14 +2521,14 @@ sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) { // SemaPPCallbacks::PragmaDiagnostic(). P.enableCheckUnreachable = PolicyOverrides.enableCheckUnreachable || - isEnabled(D, Loc, warn_unreachable, warn_unreachable_break, - warn_unreachable_return, warn_unreachable_loop_increment); + areAnyEnabled(D, Loc, warn_unreachable, warn_unreachable_break, + warn_unreachable_return, warn_unreachable_loop_increment); P.enableThreadSafetyAnalysis = PolicyOverrides.enableThreadSafetyAnalysis || - isEnabled(D, Loc, warn_double_lock); + areAnyEnabled(D, Loc, warn_double_lock); P.enableConsumedAnalysis = PolicyOverrides.enableConsumedAnalysis || - isEnabled(D, Loc, warn_use_in_invalid_state); + areAnyEnabled(D, Loc, warn_use_in_invalid_state); return P; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits