https://github.com/kparzysz created 
https://github.com/llvm/llvm-project/pull/196354

Utilize clang::ProcessWarningOptions function to process -Wno-... options.

This has the side effect that without additional changes it would cause driver 
warnings to become errors with -Werror. That would be a change from the 
existing behavior, so make sure that these warnings remain uneffected.

Modify the diagnostic emitter to add the disabling option at the end of the 
emitted diagnostic.

Fixes https://github.com/llvm/llvm-project/issues/195921

>From 7f7afd80e6f0778179ab70f71dd45a4373b39e2c Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <[email protected]>
Date: Wed, 6 May 2026 17:20:49 -0500
Subject: [PATCH] [flang] Implement -Wno-<warning> flags for driver diagnostics

Utilize clang::ProcessWarningOptions function to process -Wno-... options.

This has the side effect that without additional changes it would cause
driver warnings to become errors with -Werror. That would be a change
from the existing behavior, so make sure that these warnings remain
uneffected.

Modify the diagnostic emitter to add the disabling option at the end of
the emitted diagnostic.

Fixes https://github.com/llvm/llvm-project/issues/195921
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  7 +-
 .../include/flang/Support/Fortran-features.h  |  2 +-
 flang/lib/Frontend/CompilerInvocation.cpp     | 65 +++++++++++--------
 flang/lib/Frontend/TextDiagnosticBuffer.cpp   | 35 +++++++++-
 flang/test/Driver/fopenmp-version.F90         |  6 +-
 5 files changed, 80 insertions(+), 35 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 114ee475c371f..495254e89f520 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -167,10 +167,13 @@ def warn_drv_unsupported_option_for_runtime : Warning<
 def warn_drv_unsupported_openmp_library : Warning<
   "the library '%0=%1' is not supported, OpenMP will not be enabled">,
   InGroup<OptionIgnored>;
-def warn_openmp_incomplete : Warning<
+def warn_openmp_impl_incomplete : Warning<
   "OpenMP support for version %0 in flang is still incomplete">,
   InGroup<ExperimentalOption>;
-
+def warn_openmp_spec_incomplete : Warning<
+  "the specification for OpenMP version %0 is still under development; "
+  "the syntax and semantics of new features may be subject to change">,
+  InGroup<ExperimentalOption>;
 def err_drv_invalid_thread_model_for_target : Error<
   "invalid thread model '%0' in '%1' for this target">;
 def err_drv_invalid_linker_name : Error<
diff --git a/flang/include/flang/Support/Fortran-features.h 
b/flang/include/flang/Support/Fortran-features.h
index af72b71d9d1e6..1d07015334cfa 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -85,7 +85,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
     RealConstantWidening, VolatileOrAsynchronousTemporary, UnusedVariable,
     UsedUndefinedVariable, BadValueInDeadCode, AssumedTypeSizeDummy,
     MisplacedIgnoreTKR, NamelistParameter, ImpureFinalInPure,
-    IgnoredNoReallocateLHS, CLoc)
+    IgnoredNoReallocateLHS, CLoc, ExperimentalOption)
 
 using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
 using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index e7f4762e167fb..ea20ebbd7c2c1 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -41,6 +41,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/TargetParser/Host.h"
 #include "llvm/TargetParser/Triple.h"
 #include <algorithm>
@@ -601,8 +602,6 @@ static std::optional<const char *> parseConvertArg(const 
char *s) {
 
 static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
                               clang::DiagnosticsEngine &diags) {
-  unsigned numErrorsBefore = diags.getNumErrors();
-
   // By default the frontend driver creates a ParseSyntaxOnly action.
   opts.programAction = ParseSyntaxOnly;
 
@@ -910,7 +909,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, 
llvm::opt::ArgList &args,
   setUpFrontendBasedOnAction(opts);
   opts.dashX = dashX;
 
-  return diags.getNumErrors() == numErrorsBefore;
+  return !diags.hasUncompilableErrorOccurred();
 }
 
 // Generate the path to look for intrinsic modules
@@ -983,8 +982,6 @@ static void 
parsePreprocessorArgs(Fortran::frontend::PreprocessorOptions &opts,
 /// options accordingly. Returns false if new errors are generated.
 static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                           clang::DiagnosticsEngine &diags) {
-  unsigned numErrorsBefore = diags.getNumErrors();
-
   // -J/module-dir option
   std::vector<std::string> moduleDirList =
       args.getAllArgValues(clang::options::OPT_module_dir);
@@ -1026,7 +1023,7 @@ static bool parseSemaArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
       args.hasFlag(clang::options::OPT_fanalyzed_objects_for_unparse,
                    clang::options::OPT_fno_analyzed_objects_for_unparse, 
true));
 
-  return diags.getNumErrors() == numErrorsBefore;
+  return !diags.hasUncompilableErrorOccurred();
 }
 
 /// Parses all diagnostics related arguments and populates the variables
@@ -1034,8 +1031,6 @@ static bool parseSemaArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
 /// FC1 driver entry point for parsing diagnostic arguments.
 static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                           clang::DiagnosticsEngine &diags) {
-  unsigned numErrorsBefore = diags.getNumErrors();
-
   auto &features{res.getFrontendOpts().features};
   // The order of these flags (-pedantic -W<feature> -w) is important and is
   // chosen to match clang's behavior.
@@ -1092,15 +1087,13 @@ static bool parseDiagArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
   diags.getDiagnosticOptions().ShowColors = showColors;
   res.getDiagnosticOpts().ShowColors = showColors;
   res.getFrontendOpts().showColors = showColors;
-  return diags.getNumErrors() == numErrorsBefore;
+  return !diags.hasUncompilableErrorOccurred();
 }
 
 /// Parses all Dialect related arguments and populates the variables
 /// options accordingly. Returns false if new errors are generated.
 static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                              clang::DiagnosticsEngine &diags) {
-  unsigned numErrorsBefore = diags.getNumErrors();
-
   // -fd-lines-as-code
   if (args.hasArg(clang::options::OPT_fd_lines_as_code)) {
     if (res.getFrontendOpts().fortranForm == FortranForm::FreeForm) {
@@ -1213,7 +1206,7 @@ static bool parseDialectArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
     diags.Report(diagID);
   }
 
-  return diags.getNumErrors() == numErrorsBefore;
+  return !diags.hasUncompilableErrorOccurred();
 }
 
 /// Parses all OpenMP related arguments if the -fopenmp option is present,
@@ -1232,7 +1225,6 @@ static bool parseOpenMPArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
     res.getLangOpts().OpenMPSimd = 1;
   }
 
-  unsigned numErrorsBefore = diags.getNumErrors();
   llvm::Triple t(res.getTargetOpts().triple);
 
   constexpr unsigned newestFullySupported = 31;
@@ -1258,27 +1250,15 @@ static bool parseOpenMPArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
       diags.Report(diagID) << value << arg->getAsString(args) << 
versions.str();
     };
 
-    auto reportFutureVersion = [&](llvm::StringRef value) {
-      const unsigned diagID = diags.getCustomDiagID(
-          clang::DiagnosticsEngine::Warning,
-          "The specification for OpenMP version %0 is still under development; 
"
-          "the syntax and semantics of new features may be subject to change");
-      std::string buffer;
-      llvm::raw_string_ostream versions(buffer);
-      llvm::interleaveComma(ompVersions, versions);
-
-      diags.Report(diagID) << value;
-    };
-
     llvm::StringRef value = arg->getValue();
     if (!value.getAsInteger(/*radix=*/10, version)) {
       if (llvm::is_contained(ompVersions, version)) {
         res.getLangOpts().OpenMPVersion = version;
 
         if (version > latestFinalized)
-          reportFutureVersion(value);
+          diags.Report(clang::diag::warn_openmp_spec_incomplete) << version;
         else if (version > newestFullySupported)
-          diags.Report(clang::diag::warn_openmp_incomplete) << version;
+          diags.Report(clang::diag::warn_openmp_impl_incomplete) << version;
       } else if (llvm::is_contained(oldVersions, version)) {
         const unsigned diagID =
             diags.getCustomDiagID(clang::DiagnosticsEngine::Warning,
@@ -1382,7 +1362,7 @@ static bool parseOpenMPArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
         res.getLangOpts().OMPTargetTriples.push_back(tt);
     }
   }
-  return diags.getNumErrors() == numErrorsBefore;
+  return !diags.hasUncompilableErrorOccurred();
 }
 
 /// Parses signed integer overflow options and populates the
@@ -1588,11 +1568,34 @@ static bool parseLangOptionsArgs(CompilerInvocation 
&invoc,
   return success;
 }
 
+// Copied from clang/lib/Frontend/CompilerInvocation.cpp.
+static void addDiagnosticArgs(llvm::opt::ArgList &Args,
+    llvm::opt::OptSpecifier Group, llvm::opt::OptSpecifier GroupWithValue,
+    std::vector<std::string> &Diagnostics) {
+  for (auto *A : Args.filtered(Group)) {
+    if (A->getOption().getKind() == llvm::opt::Option::FlagClass) {
+      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
+      // its name (minus the "W" or "R" at the beginning) to the diagnostics.
+      Diagnostics.push_back(
+          std::string(A->getOption().getName().drop_front(1)));
+    } else if (A->getOption().matches(GroupWithValue)) {
+      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
+      // group. Add only the group name to the diagnostics.
+      Diagnostics.push_back(
+          std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
+    } else {
+      // Otherwise, add its value (for OPT_W_Joined and similar).
+      Diagnostics.push_back(A->getValue());
+    }
+  }
+}
+
 bool CompilerInvocation::createFromArgs(
     CompilerInvocation &invoc, llvm::ArrayRef<const char *> commandLineArgs,
     clang::DiagnosticsEngine &diags, const char *argv0) {
 
   bool success = true;
+  clang::DiagnosticOptions &diagOpts = diags.getDiagnosticOptions();
 
   // Set the default triple for this CompilerInvocation. This might be
   // overridden by users with `-triple` (see the call to `ParseTargetArgs`
@@ -1629,6 +1632,12 @@ bool CompilerInvocation::createFromArgs(
     success = false;
   }
 
+  // Handle -Wno-<warning> flags.
+  addDiagnosticArgs(args, clang::options::OPT_W_Group,
+      clang::options::OPT_W_value_Group, diagOpts.Warnings);
+  auto vfs = llvm::vfs::getRealFileSystem();
+  clang::ProcessWarningOptions(diags, diagOpts, *vfs, /*ReportDiags=*/false);
+
   // -flang-experimental-hlfir
   if (args.hasArg(clang::options::OPT_flang_experimental_hlfir) ||
       args.hasArg(clang::options::OPT_emit_hlfir)) {
diff --git a/flang/lib/Frontend/TextDiagnosticBuffer.cpp 
b/flang/lib/Frontend/TextDiagnosticBuffer.cpp
index 1f3b86f92dc74..140b99aed5c1c 100644
--- a/flang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ b/flang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -21,15 +21,48 @@
 
 using namespace Fortran::frontend;
 
+static void printWarningOption(llvm::raw_ostream &os,
+    clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
+  auto &diagIDs = *info.getDiags()->getDiagnosticIDs();
+
+  if (level == clang::DiagnosticsEngine::Warning) {
+    llvm::StringRef opt = diagIDs.getWarningOptionForDiag(info.getID());
+    if (!opt.empty()) {
+      os << " [-W" << opt;
+      llvm::StringRef optValue = info.getFlagValue();
+      if (!optValue.empty())
+        os << "=" << optValue;
+      os << ']';
+    }
+  }
+}
+
 /// HandleDiagnostic - Store the errors, warnings, and notes that are
 /// reported.
 void TextDiagnosticBuffer::HandleDiagnostic(
     clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
-  // Default implementation (warnings_/errors count).
+  // Default implementation (warnings/errors count).
   DiagnosticConsumer::HandleDiagnostic(level, info);
 
   llvm::SmallString<100> buf;
   info.FormatDiagnostic(buf);
+
+  // This function dealing with diagnostics emitted directly through the
+  // diagnostic engine, e.g. in CompilerInvocation. With -Werror any warning
+  // emitted there would become an error, and prevented any part of compilation
+  // from happening. In case of OpenMP, this would cause the warning about an
+  // incomplete implementation to completely skip the compilation, which is
+  // undesirable.
+  // Downgrade -Werror'ed warnings back to warnings to avoid this situation.
+  const clang::DiagnosticsEngine &diags = *info.getDiags();
+  if (level == clang::DiagnosticsEngine::Error) {
+    if (!diags.getDiagnosticIDs()->isDefaultMappingAsError(info.getID()))
+      level = clang::DiagnosticsEngine::Warning;
+  }
+
+  llvm::raw_svector_ostream os(buf);
+  printWarningOption(os, level, info);
+
   switch (level) {
   default:
     llvm_unreachable("Diagnostic not handled during diagnostic buffering!");
diff --git a/flang/test/Driver/fopenmp-version.F90 
b/flang/test/Driver/fopenmp-version.F90
index 59406d3dd32c8..9106b62f90b42 100644
--- a/flang/test/Driver/fopenmp-version.F90
+++ b/flang/test/Driver/fopenmp-version.F90
@@ -16,14 +16,14 @@
 
 
 !RUN: %flang -c -fopenmp -fopenmp-version=25 %s 2>&1 | FileCheck 
--check-prefix=WARN-ASSUMED %s
-
 !WARN-ASSUMED: warning: OpenMP version 25 is no longer supported, assuming 
version 31
 
 
 !RUN: not %flang -c -fopenmp -fopenmp-version=29 %s 2>&1 | FileCheck 
--check-prefix=ERR-BAD %s
-
 !ERR-BAD: error: '29' is not a valid OpenMP version in '-fopenmp-version=29', 
valid versions are 31, 40, 45, 50, 51, 52, 60, 61
 
 !RUN: %flang -c -fopenmp -fopenmp-version=61 %s 2>&1 | FileCheck 
--check-prefix=FUTURE %s
+!FUTURE: the specification for OpenMP version 61 is still under development; 
the syntax and semantics of new features may be subject to change 
[-Wexperimental-option]
 
-!FUTURE: The specification for OpenMP version 61 is still under development; 
the syntax and semantics of new features may be subject to change
+!RUN: %flang -c -fopenmp -fopenmp-version=60 %s 2>&1 | FileCheck 
--check-prefix=IMPL %s
+!IMPL: OpenMP support for version 60 in flang is still incomplete 
[-Wexperimental-option]

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

Reply via email to