llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangd

@llvm/pr-subscribers-clang-tools-extra

Author: Anonmiraj (AnonMiraj)

<details>
<summary>Changes</summary>

The original PR caused a huge 
[regression](https://llvm-compile-time-tracker.com/compare.php?from=aa1058e34a6127df91898829b0e60cbae3111cbf&amp;to=e046dce4a4c80610b49d67bc02c85f86b1a6353d&amp;stat=instructions:u)

The problem was that `areAllIgnored` ends up being called once per declared 
entity, and each call walks all 26 diagnostics in `-Wdocumentation` and 
`-Wdocumentation-pedantic`. So now the result is cached and it's a performance 
[improvement](https://llvm-compile-time-tracker.com/compare.php?from=5d063386f51b7d9925df7db5f05ec2f0a33f63c4&amp;to=e8f7f96262a312739a990d1747a332ba6f1859b3&amp;stat=instructions%3Au)
 again.

The cache is keyed on the diagnostic state plus whether the location is in a 
system header, because both change the answer. Keying it on the state alone is 
wrong: a declaration coming from a system header would cache "off" and silence 
the comments in the user's own code after it. There is a test for that.

Also, Claude noticed that a similar thing is done in 
`DoEmitAvailabilityWarning`, so i moved it out in the NFC to reuse it.

closes https://github.com/llvm/llvm-project/issues/165515
Assisted-By: Opus 5.

---

Patch is 39.41 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/221605.diff


28 Files Affected:

- (modified) clang-tools-extra/clang-doc/tool/ClangDocMain.cpp (+2-1) 
- (modified) clang-tools-extra/clangd/Compiler.cpp (+2-1) 
- (modified) clang-tools-extra/clangd/index/IndexAction.cpp (+2-1) 
- (modified) clang/docs/ReleaseNotes.md (+6) 
- (modified) clang/include/clang/Basic/CommentOptions.h (+8) 
- (modified) clang/include/clang/Basic/Diagnostic.h (+33) 
- (modified) clang/include/clang/Basic/DiagnosticIDs.h (+6) 
- (modified) clang/include/clang/Basic/LangOptions.def (-2) 
- (modified) clang/include/clang/Options/Options.td (+7-1) 
- (modified) clang/include/clang/Sema/Sema.h (+28) 
- (modified) clang/lib/AST/ASTContext.cpp (+1-1) 
- (modified) clang/lib/Basic/Diagnostic.cpp (+7) 
- (modified) clang/lib/Basic/DiagnosticIDs.cpp (+112-84) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+2) 
- (modified) clang/lib/ExtractAPI/ExtractAPIConsumer.cpp (+3) 
- (modified) clang/lib/Frontend/ASTUnit.cpp (+6) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+1) 
- (modified) clang/lib/Frontend/FrontendActions.cpp (+6) 
- (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+1-3) 
- (modified) clang/lib/Sema/Sema.cpp (+74-4) 
- (modified) clang/lib/Sema/SemaAvailability.cpp (+2-14) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+1-5) 
- (added) clang/test/AST/ast-dump-comment-retention.cpp (+28) 
- (added) clang/test/Sema/Inputs/documentation-system-header-doc.h (+2) 
- (added) clang/test/Sema/Inputs/documentation-system-header.h (+2) 
- (added) clang/test/Sema/warn-documentation-comment-retention.cpp (+38) 
- (added) clang/test/Sema/warn-documentation-system-header-retained.cpp (+11) 
- (added) clang/test/Sema/warn-documentation-system-header.cpp (+14) 


``````````diff
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp 
b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 00290d7cdc74b..0b81a3cb20351 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -285,7 +285,8 @@ Example usage for a project using a compile commands 
database:
     llvm::outs() << "Emiting docs in " << Format << " format.\n";
     auto G = ExitOnErr(doc::findGeneratorByName(Format));
 
-    ArgumentsAdjuster ArgAdjuster;
+    ArgumentsAdjuster ArgAdjuster = getInsertArgumentAdjuster(
+        "-fretain-comments", tooling::ArgumentInsertPosition::END);
     if (!DoxygenOnly)
       ArgAdjuster = combineAdjusters(
           getInsertArgumentAdjuster("-fparse-all-comments",
diff --git a/clang-tools-extra/clangd/Compiler.cpp 
b/clang-tools-extra/clangd/Compiler.cpp
index 4644cd75c0833..aaeaab30b96db 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -121,7 +121,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, 
clang::DiagnosticConsumer &D,
   // createInvocationFromCommandLine sets DisableFree.
   CI->getFrontendOpts().DisableFree = false;
   CI->getLangOpts().CommentOpts.ParseAllComments = true;
-  CI->getLangOpts().RetainCommentsFromSystemHeaders = true;
+  CI->getLangOpts().CommentOpts.RetainComments = true;
+  CI->getLangOpts().CommentOpts.RetainCommentsFromSystemHeaders = true;
 
   disableUnsupportedOptions(*CI);
   return CI;
diff --git a/clang-tools-extra/clangd/index/IndexAction.cpp 
b/clang-tools-extra/clangd/index/IndexAction.cpp
index 489c61f1ff424..21e055b82d722 100644
--- a/clang-tools-extra/clangd/index/IndexAction.cpp
+++ b/clang-tools-extra/clangd/index/IndexAction.cpp
@@ -167,7 +167,8 @@ class IndexAction : public ASTFrontendAction {
   bool BeginInvocation(CompilerInstance &CI) override {
     // We want all comments, not just the doxygen ones.
     CI.getLangOpts().CommentOpts.ParseAllComments = true;
-    CI.getLangOpts().RetainCommentsFromSystemHeaders = true;
+    CI.getLangOpts().CommentOpts.RetainComments = true;
+    CI.getLangOpts().CommentOpts.RetainCommentsFromSystemHeaders = true;
     // Index the whole file even if there are warnings and -Werror is set.
     // Avoids some analyses too. Set in two places as we're late to the party.
     CI.getDiagnosticOpts().IgnoreWarnings = true;
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bf295981710ac..9142fcddb363a 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -433,6 +433,12 @@ features cannot lower the translation-unit ABI level;
 
 - Improved how Unicode characters are displayed in diagnostic messages.
 
+- Clang no longer retains source comments in the AST when nothing will read 
them
+  back. Comments are now collected only when they may be consumed (e.g. with
+  ``-fparse-all-comments``, when ``-Wdocumentation`` is enabled, when emitting 
a
+  PCH/module, or during code completion), reducing memory overhead for typical
+  compilations.
+
 - `-Wtautological-pointer-compare` and `-Wpointer-bool-conversion` now
   diagnose a reference to a function (e.g. of type `void (&)()`) compared
   against or converted to a null pointer, the same as a bare function name.
diff --git a/clang/include/clang/Basic/CommentOptions.h 
b/clang/include/clang/Basic/CommentOptions.h
index 7d142fc32f511..73e7cba91cca8 100644
--- a/clang/include/clang/Basic/CommentOptions.h
+++ b/clang/include/clang/Basic/CommentOptions.h
@@ -30,6 +30,14 @@ struct CommentOptions {
   /// Treat ordinary comments as documentation comments.
   bool ParseAllComments = false;
 
+  /// Force the front end to retain all documentation comments in the AST, even
+  /// when no comment consuming diagnostic or language option is enabled. Tools
+  /// that query comments after parsing set this.
+  bool RetainComments = false;
+
+  /// Retain documentation comments from system headers in the AST.
+  bool RetainCommentsFromSystemHeaders = false;
+
   CommentOptions() = default;
 };
 
diff --git a/clang/include/clang/Basic/Diagnostic.h 
b/clang/include/clang/Basic/Diagnostic.h
index 834f026aff62d..2d3f48f602bed 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -589,6 +589,12 @@ class DiagnosticsEngine : public 
RefCountedBase<DiagnosticsEngine> {
     return GetDiagStateForLoc(Loc);
   }
 
+  /// Returns whether \p Loc is in a system header and/or a system macro, as a
+  /// value in [0, 4). Severity depends on this through
+  /// DiagnosticIDs::shouldSuppressAsSystemWarning(), so a cache keyed on
+  /// getDiagStateKeyForLoc() must take it into account as well.
+  unsigned getDiagStateSystemClassForLoc(SourceLocation Loc) const;
+
   /// True if an active diagnostic suppression mapping makes severity dependent
   /// on the file path.
   bool hasDiagSuppressionMapping() const {
@@ -974,6 +980,16 @@ class DiagnosticsEngine : public 
RefCountedBase<DiagnosticsEngine> {
            diag::Severity::Ignored;
   }
 
+  bool areAllIgnored(StringRef Group, SourceLocation Loc) const {
+    llvm::SmallVector<diag::kind> diagsInGroup;
+    bool Failed = Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError,
+                                               Group, diagsInGroup);
+    assert(!Failed && "Incorrect group name?");
+    (void)Failed;
+    return Diags->getDiagnosticListHighestSeverity(diagsInGroup, Loc, *this) ==
+           diag::Severity::Ignored;
+  }
+
   /// Based on the way the client configured the DiagnosticsEngine
   /// object, classify the specified diagnostic ID into a Level, consumable by
   /// the DiagnosticConsumer.
@@ -1140,6 +1156,23 @@ class IgnoreAllWarningDiagRAII {
   ~IgnoreAllWarningDiagRAII() { Diag.setIgnoreAllWarnings(OldValue); }
 };
 
+/// RAII class that temporarily forces warnings in system headers and system
+/// macros to be shown on a DiagnosticsEngine and restores the previous state 
on
+/// destruction.  Use it to ask what a diagnostic's severity would be if the
+/// location were not in a system header.
+class ForceSystemWarningsRAII {
+  DiagnosticsEngine &Diag;
+  bool OldValue;
+
+public:
+  explicit ForceSystemWarningsRAII(DiagnosticsEngine &Diag, bool Force = true)
+      : Diag(Diag), OldValue(Diag.getForceSystemWarnings()) {
+    if (Force)
+      Diag.setForceSystemWarnings(true);
+  }
+  ~ForceSystemWarningsRAII() { Diag.setForceSystemWarnings(OldValue); }
+};
+
 /// The streaming interface shared between DiagnosticBuilder and
 /// PartialDiagnostic. This class is not intended to be constructed directly
 /// but only as base class of DiagnosticBuilder and PartialDiagnostic builder.
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h 
b/clang/include/clang/Basic/DiagnosticIDs.h
index 148d772a9e593..1bb0529c3ff26 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -516,6 +516,12 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> 
{
   getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
                         const DiagnosticsEngine &Diag) const LLVM_READONLY;
 
+  /// Given a collection of diagnostic IDs, get the 'highest' severity of them
+  /// at the provided location for this DiagnosticsEngine.
+  diag::Severity getDiagnosticListHighestSeverity(
+      llvm::ArrayRef<diag::kind> DiagIDs, SourceLocation Loc,
+      const DiagnosticsEngine &Diag) const LLVM_READONLY;
+
   Class getDiagClass(unsigned DiagID) const;
 
   /// Whether the diagnostic may leave the AST in a state where some
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index ad993ce7e5d95..1422125b77741 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -405,8 +405,6 @@ LANGOPT(ApplePragmaPack, 1, 0, NotCompatible, "Apple 
gcc-compatible #pragma pack
 
 LANGOPT(XLPragmaPack, 1, 0, NotCompatible, "IBM XL #pragma pack handling")
 
-LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, Compatible, "retain 
documentation comments from system headers in the AST")
-
 LANGOPT(APINotes, 1, 0, NotCompatible, "use external API notes")
 LANGOPT(APINotesModules, 1, 0, NotCompatible, "use module-based external API 
notes")
 LANGOPT(SwiftVersionIndependentAPINotes, 1, 0, NotCompatible, "use external 
API notes capturing all versions")
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 9ef012dfe1d03..f97a2a54e665d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2221,6 +2221,12 @@ defm define_target_os_macros : 
OptInCC1FFlag<"define-target-os-macros",
 def fparse_all_comments : Flag<["-"], "fparse-all-comments">, 
Group<f_clang_Group>,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag<LangOpts<"CommentOpts.ParseAllComments">>;
+def fretain_comments : Flag<["-"], "fretain-comments">, Group<f_clang_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Retain documentation comments in the AST even when no diagnostic 
or "
+           "language option would otherwise require them (e.g. for tools that "
+           "query comments after parsing)">,
+  MarshallingInfoFlag<LangOpts<"CommentOpts.RetainComments">>;
 def frecord_command_line : Flag<["-"], "frecord-command-line">,
   DocBrief<[{Generate a section named ".GCC.command.line" containing the
 driver command-line. After linking, the section may contain multiple command
@@ -3942,7 +3948,7 @@ defm implicit_modules : BoolFOption<"implicit-modules",
           [NoXarchOption], [ClangOption, CLOption]>>;
 def fretain_comments_from_system_headers : Flag<["-"], 
"fretain-comments-from-system-headers">, Group<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
-  MarshallingInfoFlag<LangOpts<"RetainCommentsFromSystemHeaders">>;
+  MarshallingInfoFlag<LangOpts<"CommentOpts.RetainCommentsFromSystemHeaders">>;
 def fmodule_header : Flag <["-"], "fmodule-header">, Group<f_Group>,
   Visibility<[ClangOption, CLOption]>,
   HelpText<"Build a C++20 Header Unit from a header">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9b07b591b8c07..928dbcd3ac589 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1126,6 +1126,34 @@ class Sema final : public SemaBase {
 
   void ActOnComment(SourceRange Comment);
 
+  /// Returns true if any of the documentation warnings is enabled at \p Loc.
+  bool areDocumentationDiagsEnabled(SourceLocation Loc);
+
+  /// Discard the areDocumentationDiagsEnabled() cache, for when a
+  /// `#pragma clang diagnostic` has changed diagnostic severities.
+  void clearDocumentationDiagsCache();
+
+private:
+  /// The uncached answer for both documentation groups at \p Loc.
+  bool computeDocumentationDiagsAt(SourceLocation Loc) const;
+
+  /// Caches results for areDocumentationDiagsEnabled().
+  /// Flushed whenever a diagnostic pragma changes severities.
+  /// Level one is keyed on the diagnostic state alone.
+  const void *DocDiagsStateKey = nullptr;
+  bool DocDiagsEnabledIgnoringSystem = false;
+
+  /// Level two, for when the location does matter. Bit i of each mask is a
+  /// getDiagStateSystemClassForLoc() value; bit 0 is unused.
+  uint8_t DocDiagsExactComputed = 0;
+  uint8_t DocDiagsExactEnabled = 0;
+
+public:
+  /// Returns true if a comment at \p Loc should be retained in the AST
+  /// (some consumer such as -Wdocumentation, -fparse-all-comments, code
+  /// completion, or AST-file serialization may read it back).
+  bool shouldRetainCommentsInAST(SourceLocation Loc);
+
   /// Retrieve the parser's current scope.
   ///
   /// This routine must only be used when it is certain that semantic analysis
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b7e771595e86e..cf1c68d0d4443 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -357,7 +357,7 @@ RawComment 
*ASTContext::getRawCommentNoCache(RawCommentLookupKey Key) const {
 }
 
 void ASTContext::addComment(const RawComment &RC) {
-  assert(LangOpts.RetainCommentsFromSystemHeaders ||
+  assert(LangOpts.CommentOpts.RetainCommentsFromSystemHeaders ||
          !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
   Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc);
 }
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 48dd9559ab8e6..995fd6dff2254 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -596,6 +596,13 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind 
DiagId,
   return LastSup > LastEmit;
 }
 
+unsigned
+DiagnosticsEngine::getDiagStateSystemClassForLoc(SourceLocation Loc) const {
+  const SourceManager &SM = getSourceManager();
+  return (SM.isInSystemHeader(SM.getExpansionLoc(Loc)) ? 2u : 0u) |
+         (SM.isInSystemMacro(Loc) ? 1u : 0u);
+}
+
 bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,
                                                SourceLocation DiagLoc) const {
   if (!hasSourceManager() || !DiagSuppressionMapping)
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp 
b/clang/lib/Basic/DiagnosticIDs.cpp
index 3709528e497d2..ef9db935ca752 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -541,103 +541,131 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, 
SourceLocation Loc,
 diag::Severity
 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
                                      const DiagnosticsEngine &Diag) const {
-  bool IsCustomDiag = DiagnosticIDs::IsCustomDiag(DiagID);
-  assert(getDiagClass(DiagID) != CLASS_NOTE);
-
-  // Specific non-error diagnostics may be mapped to various levels from 
ignored
-  // to error.  Errors can only be mapped to fatal.
-  diag::Severity Result = diag::Severity::Fatal;
+  return getDiagnosticListHighestSeverity({DiagID}, Loc, Diag);
+}
 
-  // Get the mapping information, or compute it lazily.
+diag::Severity DiagnosticIDs::getDiagnosticListHighestSeverity(
+    llvm::ArrayRef<diag::kind> DiagIDs, SourceLocation Loc,
+    const DiagnosticsEngine &Diag) const {
   DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
-  DiagnosticMapping Mapping = State->getOrAddMapping((diag::kind)DiagID);
-
-  // TODO: Can a null severity really get here?
-  if (Mapping.getSeverity() != diag::Severity())
-    Result = Mapping.getSeverity();
-
-  // Upgrade ignored diagnostics if -Weverything is enabled.
-  if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
-      !Mapping.isUser() &&
-      (IsCustomDiag || getDiagClass(DiagID) != CLASS_REMARK))
-    Result = diag::Severity::Warning;
-
-  // Ignore -pedantic diagnostics inside __extension__ blocks.
-  // (The diagnostics controlled by -pedantic are the extension diagnostics
-  // that are not enabled by default.)
-  bool EnabledByDefault = false;
-  bool IsExtensionDiag = isExtensionDiag(DiagID, EnabledByDefault);
-  if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
-    return diag::Severity::Ignored;
-
-  // For extension diagnostics that haven't been explicitly mapped, check if we
-  // should upgrade the diagnostic. Skip if the user explicitly suppressed it
-  // (e.g. -Wno-foo).
-  if (IsExtensionDiag &&
-      !(Mapping.isUser() && Result == diag::Severity::Ignored)) {
-    if (Mapping.hasNoWarningAsError())
-      Result = std::max(Result,
-                        std::min(State->ExtBehavior, diag::Severity::Warning));
-    else
-      Result = std::max(Result, State->ExtBehavior);
-  }
-
-  // At this point, ignored errors can no longer be upgraded.
-  if (Result == diag::Severity::Ignored)
-    return Result;
 
-  // Honor -w: this disables all messages which are not Error/Fatal by
-  // default (disregarding attempts to upgrade severity from Warning to Error),
-  // as well as disabling all messages which are currently mapped to Warning
-  // (whether by default or downgraded from Error via e.g. -Wno-error or 
#pragma
-  // diagnostic.)
-  // FIXME: Should -w be ignored for custom warnings without a group?
-  if (State->IgnoreAllWarnings) {
-    if ((!IsCustomDiag || CustomDiagInfo->getDescription(DiagID).GetGroup()) &&
-        (Result == diag::Severity::Warning ||
-         (Result >= diag::Severity::Error &&
-          !isDefaultMappingAsError((diag::kind)DiagID))))
+  auto checkSingleDiag = [&](diag::kind DiagID) -> diag::Severity {
+    bool IsCustomDiag = DiagnosticIDs::IsCustomDiag(DiagID);
+    assert(getDiagClass(DiagID) != CLASS_NOTE);
+
+    // Specific non-error diagnostics may be mapped to various levels from
+    // ignored to error.  Errors can only be mapped to fatal.
+    diag::Severity Result = diag::Severity::Fatal;
+
+    // Get the mapping information, or compute it lazily.
+    DiagnosticMapping Mapping = State->getOrAddMapping((diag::kind)DiagID);
+
+    // TODO: Can a null severity really get here?
+    if (Mapping.getSeverity() != diag::Severity())
+      Result = Mapping.getSeverity();
+
+    // Upgrade ignored diagnostics if -Weverything is enabled.
+    if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
+        !Mapping.isUser() &&
+        (IsCustomDiag || getDiagClass(DiagID) != CLASS_REMARK))
+      Result = diag::Severity::Warning;
+
+    // Ignore -pedantic diagnostics inside __extension__ blocks.
+    // (The diagnostics controlled by -pedantic are the extension diagnostics
+    // that are not enabled by default.)
+    bool EnabledByDefault = false;
+    bool IsExtensionDiag = isExtensionDiag(DiagID, EnabledByDefault);
+    if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
       return diag::Severity::Ignored;
-  }
 
-  // If -Werror is enabled, map warnings to errors unless explicitly disabled.
-  if (Result == diag::Severity::Warning) {
-    if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
+    // For extension diagnostics that haven't been explicitly mapped, check if
+    // we should upgrade the diagnostic. Skip if the user explicitly
+    // suppressed it (e.g. -Wno-foo).
+    if (IsExtensionDiag &&
+        !(Mapping.isUser() && Result == diag::Severity::Ignored)) {
+      if (Mapping.hasNoWarningAsError())
+        Result = std::max(
+            Result, std::min(State->ExtBehavior, diag::Severity::Warning));
+      else
+        Result = std::max(Result, State->ExtBehavior);
+    }
+
+    // At this point, ignored errors can no longer be upgraded.
+    if (Result == diag::Severity::Ignored)
+      return Result;
+
+    // Honor -w: this disables all messages which are not Error/Fatal by
+    // default (disregarding attempts to upgrade severity from Warning to
+    // Error), as well as disabling all messages which are currently mapped to
+    // Warning (whether by default or downgraded from Error via e.g.
+    // -Wno-error or #pragma diagnostic.)
+    // FIXME: Should -w be ignored for custom warnings without a group?
+    if (State->IgnoreAllWarnings) {
+      if ((!IsCustomDiag ||
+           CustomDiagInfo->getDescription(DiagID).GetGroup()) &&
+          (Result == diag::Severity::Warning ||
+           (Result >= diag::Severity::Error &&
+            !isDefaultMappingAsError((diag::kind)DiagID))))
+        return diag::Severity::Ignored;
+    }
+
+    // If -Werror is enabled, map warnings to errors unless explicitly
+    // disabled.
+    if (Result == diag::Severity::Warning) {
+      if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
+        Result = diag::Severity::Error;
+    }
+
+    // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
+    // disabled.
+    if (Result == diag::Severity::Error) {
+      if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
+        Result = diag::Severity::Fatal;
+    }
+
+    // If explicitly requested, map fatal errors to errors.
+    if (Result == diag::Severity::Fatal &&
+        DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
       Result = diag::Severity::Error;
-  }
 
-  // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
-  // disabled.
-  if (Result == diag::Severity::Error) {
-    if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
-      Result = diag::Severity::Fatal;
-  }
+    // Rest of the mappings are only applicable for diagnostics associated
+    // with a S...
[truncated]

``````````

</details>


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

Reply via email to