[clang] [flang] [flang/clang] Adding use of Clang's diagnostics in Flang (PR #130593)

via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 10 05:45:22 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Jean-Didier PAILLEUX (JDPailleux)

<details>
<summary>Changes</summary>

Hello,

Here's a proposal to support diagnostics in Flang using the `DiagnosticEngine` provided by Clang. The goal is to have a shared  diagnostic system between Clang and Flang. A small modification has been made to the tablegen to indicate whether or not a “Warning/Error” diagnostic is supported by Clang and/or Flang (by default for those already existing and unmodified, Clang is indicated as being the only compiler that supports the diagnostic). The addition of these 2 booleans was motivated by the fact that certain warning options (such as `-Wunused-dummy-argument`) are only supported by Flang and therefore cannot be used by Clang. In addition, this will make it possible to indicate warning options not yet supported by Flang. The Flang driver has been modified to support the correct `DiagnosticEngine`.


---

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


24 Files Affected:

- (modified) clang/include/clang/Basic/Diagnostic.td (+4-1) 
- (modified) clang/include/clang/Basic/DiagnosticCategories.h (+2-1) 
- (modified) clang/include/clang/Basic/DiagnosticIDs.h (+5) 
- (modified) clang/lib/Basic/DiagnosticIDs.cpp (+12-2) 
- (modified) clang/lib/Basic/Warnings.cpp (+9) 
- (modified) clang/test/TableGen/DiagnosticBase.inc (+3-1) 
- (modified) clang/tools/diagtool/DiagnosticNames.cpp (+2-1) 
- (modified) clang/utils/TableGen/ClangDiagnosticsEmitter.cpp (+4) 
- (modified) flang/include/flang/Frontend/CompilerInvocation.h (+8-2) 
- (modified) flang/include/flang/Semantics/semantics.h (+4-1) 
- (modified) flang/include/flang/Semantics/symbol.h (+3) 
- (modified) flang/lib/Frontend/CMakeLists.txt (+1) 
- (modified) flang/lib/Frontend/CompilerInstance.cpp (+2-1) 
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+29-21) 
- (added) flang/lib/Frontend/Warnings.cpp (+102) 
- (modified) flang/lib/Semantics/CMakeLists.txt (+3) 
- (modified) flang/lib/Semantics/semantics.cpp (+2-2) 
- (added) flang/test/Driver/w-arg-unknown.f90 (+7) 
- (removed) flang/test/Driver/werror-wrong.f90 (-6) 
- (modified) flang/test/Driver/wextra-ok.f90 (+2-2) 
- (modified) flang/tools/bbc/CMakeLists.txt (+5) 
- (modified) flang/tools/bbc/bbc.cpp (+13-1) 
- (modified) flang/tools/flang-driver/driver.cpp (+9-1) 
- (modified) flang/tools/flang-driver/fc1_main.cpp (+11-8) 


``````````diff
diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td
index 0b8b3af939ba0..b3a2e76ddc453 100644
--- a/clang/include/clang/Basic/Diagnostic.td
+++ b/clang/include/clang/Basic/Diagnostic.td
@@ -55,11 +55,14 @@ class DiagCategory<string Name> {
 }
 
 // Diagnostic Groups.
-class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}]> {
+class DiagGroup<string Name, list<DiagGroup> subgroups = [], code docs = [{}],
+                bit clangDiag = 1, bit flangDiag = 0> {
   string GroupName = Name;
   list<DiagGroup> SubGroups = subgroups;
   string CategoryName = "";
   code Documentation = docs;
+  bit IsClangDiag = clangDiag;
+  bit IsFlangDiag = flangDiag;
 }
 class InGroup<DiagGroup G> { DiagGroup Group = G; }
 //class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
diff --git a/clang/include/clang/Basic/DiagnosticCategories.h b/clang/include/clang/Basic/DiagnosticCategories.h
index 839f8dee3ca89..5e44889a2fcd8 100644
--- a/clang/include/clang/Basic/DiagnosticCategories.h
+++ b/clang/include/clang/Basic/DiagnosticCategories.h
@@ -21,7 +21,8 @@ namespace clang {
     };
 
     enum class Group {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs)    \
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs,    \
+                       IsClang, IsFlang)                                       \
       GroupName,
 #include "clang/Basic/DiagnosticGroups.inc"
 #undef CATEGORY
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index 017ef7065610f..e57500fb85d3c 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -365,6 +365,11 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
   /// Given a diagnostic group ID, return its documentation.
   static StringRef getWarningOptionDocumentation(diag::Group GroupID);
 
+  /// Given a diagnostic group ID, return true if its a Flang warning.
+  static bool isFlangWarningOption(diag::Group Group);
+  /// Given a diagnostic group ID, return true if its a Clang warning.
+  static bool isClangWarningOption(diag::Group Group);
+
   void setGroupSeverity(StringRef Group, diag::Severity);
   void setGroupNoWarningsAsError(StringRef Group, bool);
 
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index ca5b8d2da769e..e275f7165b392 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -585,6 +585,8 @@ namespace {
     uint16_t Members;
     uint16_t SubGroups;
     StringRef Documentation;
+    bool IsClangDiag;
+    bool IsFlangDiag;
 
     StringRef getName() const { return DiagGroupNames[NameOffset]; }
   };
@@ -592,8 +594,9 @@ namespace {
 
 // Second the table of options, sorted by name for fast binary lookup.
 static const WarningOption OptionTable[] = {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs)        \
-  {FlagNameOffset, Members, SubGroups, Docs},
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs,        \
+                   IsClang, IsFlang)                                           \
+  {FlagNameOffset, Members, SubGroups, Docs, IsClang, IsFlang},
 #include "clang/Basic/DiagnosticGroups.inc"
 #undef DIAG_ENTRY
 };
@@ -607,6 +610,13 @@ StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
   return OptionTable[static_cast<int>(Group)].getName();
 }
 
+bool DiagnosticIDs::isFlangWarningOption(diag::Group Group) {
+  return OptionTable[static_cast<int>(Group)].IsFlangDiag;
+}
+
+bool DiagnosticIDs::isClangWarningOption(diag::Group Group) {
+  return OptionTable[static_cast<int>(Group)].IsClangDiag;
+}
 std::optional<diag::Group>
 DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
   const auto *Found = llvm::partition_point(
diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp
index 5f48e0ec81554..e6c1355650113 100644
--- a/clang/lib/Basic/Warnings.cpp
+++ b/clang/lib/Basic/Warnings.cpp
@@ -106,6 +106,15 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
       diag::Severity Mapping =
           isPositive ? diag::Severity::Warning : diag::Severity::Ignored;
 
+      // Check if the warning option is valid for Clang
+      std::optional<diag::Group> Group = DiagIDs->getGroupForWarningOption(Opt);
+      if (Group.has_value() && !DiagIDs->isClangWarningOption(Group.value())) {
+        const unsigned DiagID = Diags.getCustomDiagID(
+            DiagnosticsEngine::Error,
+            "Warning option \"%0\" is valid for Fortran but not for C++.");
+        Diags.Report(DiagID) << Opt;
+      }
+
       // -Wsystem-headers is a special case, not driven by the option table.  It
       // cannot be controlled with -Werror.
       if (Opt == "system-headers") {
diff --git a/clang/test/TableGen/DiagnosticBase.inc b/clang/test/TableGen/DiagnosticBase.inc
index 2fc7bb4266edb..359c6d1edd79a 100644
--- a/clang/test/TableGen/DiagnosticBase.inc
+++ b/clang/test/TableGen/DiagnosticBase.inc
@@ -55,11 +55,13 @@ class DiagCategory<string Name> {
 }
 
 // Diagnostic Groups.
-class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
+class DiagGroup<string Name, list<DiagGroup> subgroups = [], bit clangDiag = 1, bit flangDiag = 0> {
   string GroupName = Name;
   list<DiagGroup> SubGroups = subgroups;
   string CategoryName = "";
   code Documentation = [{}];
+  bit IsClangDiag = clangDiag;
+  bit IsFlangDiag = flangDiag;
 }
 class InGroup<DiagGroup G> { DiagGroup Group = G; }
 //class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp
index 4ac9825848ef3..95b9da461599b 100644
--- a/clang/tools/diagtool/DiagnosticNames.cpp
+++ b/clang/tools/diagtool/DiagnosticNames.cpp
@@ -62,7 +62,8 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
 
 // Second the table of options, sorted by name for fast binary lookup.
 static const GroupRecord OptionTable[] = {
-#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs)        \
+#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs,        \
+                   IsClang, IsFlang)                                           \
   {FlagNameOffset, Members, SubGroups},
 #include "clang/Basic/DiagnosticGroups.inc"
 #undef DIAG_ENTRY
diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 8f846a4744bbf..0c0962f6fceaa 100644
--- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -1890,6 +1890,10 @@ static void emitDiagTable(DiagsInGroupTy &DiagsInGroup,
 
     OS << "R\"(" << StringRef(Documentation).trim() << ")\"";
 
+    OS << ", /*IsClangDiag*/ "
+       << bool(GroupInfo.Defs.back()->getValueAsBit("IsClangDiag"));
+    OS << ", /*IsFlangDiag*/ "
+       << bool(GroupInfo.Defs.back()->getValueAsBit("IsFlangDiag"));
     OS << ")\n";
   }
   OS << "#endif // DIAG_ENTRY\n\n";
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index 9e6724be33033..9fdaeac3d999a 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -33,12 +33,18 @@ class TargetMachine;
 
 namespace Fortran::frontend {
 
+/// processWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+void processWarningOptions(clang::DiagnosticsEngine &Diags,
+                           const clang::DiagnosticOptions &Opts);
+
 /// Fill out Opts based on the options given in Args.
 ///
 /// When errors are encountered, return false and, if Diags is non-null,
 /// report the error(s).
 bool parseDiagnosticArgs(clang::DiagnosticOptions &opts,
-                         llvm::opt::ArgList &args);
+                         llvm::opt::ArgList &args,
+                         bool defaultDiagColor = true);
 
 class CompilerInvocationBase {
 public:
@@ -174,7 +180,7 @@ class CompilerInvocation : public CompilerInvocationBase {
   /// Creates and configures semantics context based on the compilation flags.
   std::unique_ptr<Fortran::semantics::SemanticsContext>
   getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
-                  const llvm::TargetMachine &);
+                  const llvm::TargetMachine &, clang::DiagnosticsEngine &diag);
 
   std::string &getModuleDir() { return moduleDir; }
   const std::string &getModuleDir() const { return moduleDir; }
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index 730513dbe3232..72ecd046f4048 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -19,6 +19,7 @@
 #include "flang/Parser/message.h"
 #include "flang/Support/Fortran-features.h"
 #include "flang/Support/LangOptions.h"
+#include "clang/Basic/Diagnostic.h"
 #include <iosfwd>
 #include <set>
 #include <string>
@@ -68,7 +69,7 @@ class SemanticsContext {
 public:
   SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
       const common::LanguageFeatureControl &, const common::LangOptions &,
-      parser::AllCookedSources &);
+      parser::AllCookedSources &, clang::DiagnosticsEngine &);
   ~SemanticsContext();
 
   const common::IntrinsicTypeDefaultKinds &defaultKinds() const {
@@ -82,6 +83,7 @@ class SemanticsContext {
   int doublePrecisionKind() const {
     return defaultKinds_.doublePrecisionKind();
   }
+  clang::DiagnosticsEngine &getDiagnostics() const { return diags_; }
   int quadPrecisionKind() const { return defaultKinds_.quadPrecisionKind(); }
   bool IsEnabled(common::LanguageFeature feature) const {
     return languageFeatures_.IsEnabled(feature);
@@ -305,6 +307,7 @@ class SemanticsContext {
   const common::IntrinsicTypeDefaultKinds &defaultKinds_;
   const common::LanguageFeatureControl &languageFeatures_;
   const common::LangOptions &langOpts_;
+  clang::DiagnosticsEngine &diags_;
   parser::AllCookedSources &allCookedSources_;
   std::optional<parser::CharBlock> location_;
   std::vector<std::string> searchDirectories_;
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 715811885c219..a14ca19241823 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -293,10 +293,13 @@ class EntityDetails : public WithBindName {
   void set_isDummy(bool value = true) { isDummy_ = value; }
   bool isFuncResult() const { return isFuncResult_; }
   void set_funcResult(bool x) { isFuncResult_ = x; }
+  bool isUsed() const { return isUsed_; }
+  void set_isUsed() { isUsed_ = true; }
 
 private:
   bool isDummy_{false};
   bool isFuncResult_{false};
+  bool isUsed_{false};
   const DeclTypeSpec *type_{nullptr};
   friend llvm::raw_ostream &operator<<(
       llvm::raw_ostream &, const EntityDetails &);
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 80d63fca6fb76..1d49b91db092a 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -11,6 +11,7 @@ add_flang_library(flangFrontend
   TextDiagnosticPrinter.cpp
   TextDiagnosticBuffer.cpp
   TextDiagnostic.cpp
+  Warnings.cpp
 
   DEPENDS
   CUFDialect
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index b1fa32ecb4cfc..6374a8b0d45bd 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -163,7 +163,8 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
   if (!setUpTargetMachine())
     return false;
   // Create the semantics context
-  semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine());
+  semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine(),
+                                      getDiagnostics());
   // Set options controlling lowering to FIR.
   invoc.setLoweringOptions();
 
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 8b07a50824899..cee4b7c053f9e 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -33,6 +33,7 @@
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
@@ -119,9 +120,26 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args,
 }
 
 bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts,
-                                            llvm::opt::ArgList &args) {
-  opts.ShowColors = parseShowColorsArgs(args);
-
+                                            llvm::opt::ArgList &args,
+                                            bool defaultDiagColor) {
+  opts.ShowColors = parseShowColorsArgs(args, defaultDiagColor);
+
+  for (llvm::opt::Arg *A : args.filtered(clang::driver::options::OPT_W_Group)) {
+    if (A->getOption().getKind() == llvm::opt::Option::FlagClass) {
+      // The argument is a pure flag (such as OPT_Wall).
+      opts.Warnings.push_back(
+          std::string(A->getOption().getName().drop_front(1)));
+    } else if (A->getOption().matches(
+                   clang::driver::options::OPT_W_value_Group)) {
+      // This is -Wfoo= where foo is the name of the diagnostic group.
+      // Add only the group name to the diagnostics.
+      opts.Warnings.push_back(
+          std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
+    } else {
+      // Otherwise, add its value for OPT_W_Joined.
+      opts.Warnings.push_back(A->getValue());
+    }
+  }
   return true;
 }
 
@@ -927,22 +945,11 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                           clang::DiagnosticsEngine &diags) {
   unsigned numErrorsBefore = diags.getNumErrors();
 
-  // -Werror option
-  // TODO: Currently throws a Diagnostic for anything other than -W<error>,
-  // this has to change when other -W<opt>'s are supported.
-  if (args.hasArg(clang::driver::options::OPT_W_Joined)) {
-    const auto &wArgs =
-        args.getAllArgValues(clang::driver::options::OPT_W_Joined);
-    for (const auto &wArg : wArgs) {
-      if (wArg == "error") {
-        res.setWarnAsErr(true);
-      } else {
-        const unsigned diagID =
-            diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                  "Only `-Werror` is supported currently.");
-        diags.Report(diagID);
-      }
-    }
+  // Handle warning Diagnostic for the frontend.
+  clang::DiagnosticOptions &diagOpts = res.getDiagnosticOpts();
+  for (const auto &warning : diagOpts.Warnings) {
+    if (warning == "error")
+      res.setWarnAsErr(true);
   }
 
   // Default to off for `flang -fc1`.
@@ -1030,6 +1037,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
   if (args.hasArg(clang::driver::options::OPT_pedantic)) {
     res.setEnableConformanceChecks();
     res.setEnableUsageChecks();
+    res.getDiagnosticOpts().Pedantic = true;
   }
 
   // -w
@@ -1650,12 +1658,12 @@ void CompilerInvocation::setFortranOpts() {
 std::unique_ptr<Fortran::semantics::SemanticsContext>
 CompilerInvocation::getSemanticsCtx(
     Fortran::parser::AllCookedSources &allCookedSources,
-    const llvm::TargetMachine &targetMachine) {
+    const llvm::TargetMachine &targetMachine, clang::DiagnosticsEngine &diags) {
   auto &fortranOptions = getFortranOpts();
 
   auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
       getDefaultKinds(), fortranOptions.features, getLangOpts(),
-      allCookedSources);
+      allCookedSources, diags);
 
   semanticsContext->set_moduleDirectory(getModuleDir())
       .set_searchDirectories(fortranOptions.searchDirectories)
diff --git a/flang/lib/Frontend/Warnings.cpp b/flang/lib/Frontend/Warnings.cpp
new file mode 100644
index 0000000000000..70e93efdd866d
--- /dev/null
+++ b/flang/lib/Frontend/Warnings.cpp
@@ -0,0 +1,102 @@
+//===--- Warnings.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w,
+// -Werror, ...
+//
+// Each warning option controls any number of actual warnings.
+// Given a warning option 'foo', the following are valid:
+//    -Wfoo, -Wno-foo, -Werror=foo
+//
+#include "clang/Basic/AllDiagnostics.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstring>
+
+namespace Fortran::frontend {
+
+// EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning
+// opts
+
+static void EmitUnknownDiagWarning(clang::DiagnosticsEngine &diags,
+                                   clang::diag::Flavor flavor,
+                                   llvm::StringRef prefix,
+                                   llvm::StringRef opt) {
+  llvm::StringRef suggestion =
+      clang::DiagnosticIDs::getNearestOption(flavor, opt);
+  diags.Report(clang::diag::warn_unknown_diag_option)
+      << (flavor == clang::diag::Flavor::WarningOrError ? 0 : 1)
+      << (prefix.str() += std::string(opt)) << !suggestion.empty()
+      << (prefix.str() += std::string(suggestion));
+}
+
+void processWarningOptions(clang::DiagnosticsEngine &diags,
+                           const clang::DiagnosticOptions &opts) {
+  diags.setIgnoreAllWarnings(opts.IgnoreWarnings);
+  diags.setShowColors(opts.ShowColors);
+
+  // If -pedantic or -pedantic-errors was specified, then we want to map all
+  // extension diagnostics onto WARNING or ERROR.
+  if (opts.PedanticErrors)
+    diags.setExtensionHandlingBehavior(clang::diag::Severity::Error);
+  else if (opts.Pedantic)
+    diags.setExtensionHandlingBehavior(clang::diag::Severity::Warning);
+  else
+    diags.setExtensionHandlingBehavior(clang::diag::Severity::Ignored);
+
+  llvm::SmallVector<clang::diag::kind, 10> _diags;
+  const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs =
+      diags.getDiagnosticIDs();
+  for (unsigned i = 0, e = opts.Warnings.size(); i != e; ++i) {
+    const auto flavor = clang::diag::Flavor::WarningOrError;
+    llvm::StringRef opt = opts.Warnings[i];
+
+    // Check to see if this warning starts with "no-", if so, this is a
+    // negative form of the option.
+    bool isPositive = !opt.consume_front("no-");
+
+    // Figure out how this option affects the warning.  If -Wfoo, map the
+    // diagnostic to a warning, if -Wno-foo, map it to ignore.
+    clang::diag::Severity mapping = isPositive ? clang::diag::Severity::Warning
+                                               : clang::diag::Severity::Ignored;
+
+    // -Werror/-Wno-error is a special case, not controlled by the option table.
+    // TODO: Adding support of "specifier" form of -Werror=foo.
+    if (opt == "error") {
+      diags.setWarningsAsErrors(isPositive);
+      continue;
+    }
+
+    if (std::optional<clang::diag::Group> group =
+            diagIDs->getGroupForWarningOption(opt)) {
+      if (!diagIDs->isFlangWarningOption(group.value())) {
+        // Warning option not supported by Flang
+        // FIXME : Updating diagnostic error message when all warning options
+        // will be supported
+        const unsigned diagID =
+            diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+                                  "Warning option \"%0\" not supported.");
+        diags.Report(diagID) << opt;
+      }
+    } else {
+      // Unkown warning option.
+...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/130593


More information about the cfe-commits mailing list