[flang] Implement -Wno-<warning> flags for driver diagnostics (#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
unaffected.

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

---------

Co-authored-by: Tarun Prabhu <tarun@lanl.gov>
This commit is contained in:
Krzysztof Parzyszek 2026-05-14 14:54:09 -05:00 committed by GitHub
parent b9bc518ac5
commit 42b4cb6aeb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 81 additions and 47 deletions

View file

@ -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<

View file

@ -36,7 +36,7 @@ page](https://llvm.org/releases/).
## New Compiler Flags
- The warning flags with prefixes -Wopen-mp and -Wopen-acc have been deprecated in favor of corrected spellings with the respective prefixes -Wopenmp and -Wopenacc. Removal of the deprecated options is planned for LLVM 25 (July 2027).
- The `-Werror` flag will cause all warnings to become errors. This includes warnings about support for OpenMP versions, which will now prevent the compilation from happening with the `-Werror` flag. These OpenMP warnings can be disabled with `-Wno-experimental-option`.
## Windows Support

View file

@ -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>;

View file

@ -40,6 +40,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
@ -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,35 @@ 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 +1633,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);
// -fno-ppc-native-vector-element-order
if (args.hasArg(clang::options::OPT_fno_ppc_native_vec_elem_order)) {
invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);

View file

@ -18,18 +18,39 @@
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
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);
llvm::raw_svector_ostream os(buf);
printWarningOption(os, level, info);
switch (level) {
default:
llvm_unreachable("Diagnostic not handled during diagnostic buffering!");

View file

@ -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]

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror -Wno-experimental-option
subroutine f00
!WARNING: 'variable-category' modifier is required

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -Werror -Wno-experimental-option
subroutine f00
!$omp target defaultmap(tofrom)

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror -Wno-experimental-option
subroutine f00(x)
integer :: x(10)

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror -Wno-experimental-option
subroutine f00(x)
integer :: x

View file

@ -1,4 +1,4 @@
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -Werror -fopenmp-version=52
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -Werror -fopenmp-version=52 -Wno-experimental-option
! Check for deprecation of master directive and its combined/composite variants

View file

@ -1,4 +1,4 @@
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52 -Werror
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52 -Werror -Wno-experimental-option
subroutine f00(x)
integer :: x

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror -Wno-experimental-option
! The directives to check:
! cancellation_point

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror -Wno-experimental-option
subroutine f00(x)
integer :: x

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=61 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=61 -Werror -Wno-experimental-option
subroutine f00(x)
integer, pointer :: x

View file

@ -1,4 +1,4 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror -Wno-experimental-option
subroutine f10(x)
integer :: x

View file

@ -1,4 +1,4 @@
!RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=60 -Werror %s | FileCheck --allow-empty %s
!RUN: %flang_fc1 -fsyntax-only -fopenmp -fopenmp-version=60 -Werror -Wno-experimental-option %s | FileCheck --allow-empty %s
!CHECK-NOT: deprecated
subroutine f00