[flang-commits] [flang] [Flang] Support -Werror=<name> and -Wno-error=<name> (PR #205413)
Steve Scalpone via flang-commits
flang-commits at lists.llvm.org
Mon Jun 29 03:53:36 PDT 2026
https://github.com/sscalpone updated https://github.com/llvm/llvm-project/pull/205413
>From b755de484134d144473b0dbb16cf954d0b1d30b7 Mon Sep 17 00:00:00 2001
From: Steve Scalpone <sscalpone at nvidia.com>
Date: Tue, 23 Jun 2026 12:19:32 -0700
Subject: [PATCH] [Flang] Support -Werror=<name> and -Wno-error=<name>
Allow per-warning control of warnings-as-errors, matching Clang/GCC
behavior. Global -Werror and -Wno-error continue to work; individual
Flang warning groups can be promoted or exempted with -Werror=<name>
and -Wno-error=<name>.
parseDiagArgs no longer rejects these options when they target Clang
diagnostic groups (e.g. -Wno-error=experimental-option for OpenMP).
---
flang/docs/FlangDriver.md | 17 ++++--
flang/docs/ReleaseNotes.md | 2 +-
flang/include/flang/Parser/message.h | 3 +-
.../include/flang/Support/Fortran-features.h | 12 +++++
flang/lib/Frontend/CompilerInvocation.cpp | 26 +++++++---
flang/lib/Frontend/FrontendAction.cpp | 3 +-
flang/lib/Frontend/ParserActions.cpp | 5 +-
flang/lib/Parser/message.cpp | 31 ++++++-----
flang/lib/Semantics/semantics.cpp | 2 +-
flang/lib/Support/Fortran-features.cpp | 49 +++++++++++++++++
.../Driver/Inputs/werror-unknown-scanning.f90 | 2 +
flang/test/Driver/werror-unknown.f90 | 30 +++++++++++
flang/test/Driver/wno-error.f90 | 52 +++++++++++++++++++
.../unittests/Common/FortranFeaturesTest.cpp | 15 ++++++
14 files changed, 220 insertions(+), 29 deletions(-)
create mode 100644 flang/test/Driver/Inputs/werror-unknown-scanning.f90
create mode 100644 flang/test/Driver/werror-unknown.f90
create mode 100644 flang/test/Driver/wno-error.f90
diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index 4edc99944ad44..69eaed8108408 100644
--- a/flang/docs/FlangDriver.md
+++ b/flang/docs/FlangDriver.md
@@ -601,9 +601,20 @@ floating point and so always acts as though these flags were specified.
GCC/GFortran will also set flush-to-zero mode: linking `crtfastmath.o`, the same
as Flang.
-The only GCC/GFortran warning option currently supported is `-Werror`. Passing
-any unsupported GCC/GFortran warning flags into Flang's compiler driver will
-result in warnings being emitted.
+Flang supports a subset of GCC/GFortran and Clang warning options. The
+`-Werror` flag causes all warnings to become errors. `-Wno-error` disables
+that behavior. Per-warning control is also available: `-Werror=<name>` promotes
+a specific warning group to an error (even without global `-Werror`), and
+`-Wno-error=<name>` keeps that group as a warning even when `-Werror` is in
+effect. For example, `-Werror -Wno-error=experimental-option` still emits
+OpenMP experimental-feature warnings but does not fail the compilation because
+of them.
+
+Flang-specific warnings (such as `-Wportability` or `-Wunused-variable`) use
+Flang warning group names. Some diagnostics (including OpenMP
+`-Wexperimental-option`) are handled by Clang's diagnostic engine and use the
+same spellings. Passing unsupported GCC/GFortran warning flags into Flang's
+compiler driver will result in warnings being emitted.
### Comparison with nvfortran
nvfortran defines `-fast` as
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 0ccb34be20571..a9e31d59a115f 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -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`.
+- 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 downgraded back to warnings with `-Wno-error=experimental-option`, or disabled entirely with `-Wno-experimental-option`.
## Windows Support
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index c70c335133ba8..ebb5b4353035d 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -380,7 +380,8 @@ class Messages {
const common::LanguageFeatureControl *hintFlags = nullptr,
std::size_t maxErrorsToEmit = 0, bool warningsAreErrors = false) const;
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
- bool AnyFatalError(bool warningsAreErrors = false) const;
+ bool AnyFatalError(bool warningsAreErrors = false,
+ const common::LanguageFeatureControl *control = nullptr) const;
private:
template <typename... A>
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index ebc6f495e59ba..82516ed14610a 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -11,6 +11,7 @@
#include "Fortran.h"
#include "flang/Common/enum-set.h"
+#include <optional>
#include <string_view>
#include <vector>
@@ -140,6 +141,13 @@ class LanguageFeatureControl {
// Take a string from the Cli and apply it to the LanguageFeatureControl.
// Return true if the option was recognized (and hence applied).
bool EnableWarning(std::string_view input);
+ // Apply -Werror=<name> or -Wno-error=<name> to a Flang warning group.
+ // Return true if the option was recognized.
+ bool SetWarningErrorTreatment(std::string_view specifier, bool asError);
+ // Return true if a non-fatal diagnostic should be treated as an error.
+ bool ShouldPromoteWarningToError(bool globalWarnAsErr,
+ std::optional<LanguageFeature> languageFeature,
+ std::optional<UsageWarning> usageWarning) const;
// The add and replace functions are not currently used but are provided
// to allow a flexible many-to-one mapping from Cli spellings to enum values.
// Taking a string by value because the functions own this string after the
@@ -193,6 +201,10 @@ class LanguageFeatureControl {
bool warnAllLanguage_{false};
UsageWarnings warnUsage_;
bool warnAllUsage_{false};
+ LanguageFeatures warnAsErrorLanguage_;
+ UsageWarnings warnAsErrorUsage_;
+ LanguageFeatures warnNotAsErrorLanguage_;
+ UsageWarnings warnNotAsErrorUsage_;
bool disableAllWarnings_{false};
};
} // namespace Fortran::common
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 14cb5af7c81e5..61bad89c116a6 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1062,17 +1062,31 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
}
// -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::options::OPT_W_Joined)) {
const auto &wArgs = args.getAllArgValues(clang::options::OPT_W_Joined);
// TODO: Consider using std::string_view instead of llvm::StringRef
// when moving to C++20:
for (const llvm::StringRef wArg : wArgs) {
- if (wArg == "error") {
- res.setWarnAsErr(true);
- // -Wfatal-errors
- } else if (wArg == "fatal-errors") {
+ llvm::StringRef opt{wArg};
+ const bool isPositive{!opt.consume_front("no-")};
+ if (opt.starts_with("error")) {
+ if (opt.size() == 5) {
+ res.setWarnAsErr(isPositive);
+ } else if (opt.size() > 6 && opt[5] == '=') {
+ const llvm::StringRef specifier{opt.substr(6)};
+ if (!features.SetWarningErrorTreatment(specifier, isPositive)) {
+ // Unknown Flang warning groups are handled by Clang's
+ // ProcessWarningOptions (e.g. -Wno-error=experimental-option).
+ }
+ } else {
+ const unsigned diagID =
+ diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "Unknown diagnostic option: -W%0");
+ diags.Report(diagID) << wArg;
+ }
+ continue;
+ }
+ if (opt == "fatal-errors") {
res.setMaxErrors(1);
// -W[no-]<feature>
} else if (features.EnableWarning(wArg)) {
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 7d201881cbba7..6f0b1c6904a21 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -232,7 +232,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
instance->getInvocation().getFortranOpts().features};
const size_t maxErrors{instance->getInvocation().getMaxErrors()};
const bool warningsAreErrors{instance->getInvocation().getWarnAsErr()};
- if (instance->getParsing().messages().AnyFatalError(warningsAreErrors)) {
+ if (instance->getParsing().messages().AnyFatalError(warningsAreErrors,
+ &features)) {
const unsigned diagID = instance->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
diff --git a/flang/lib/Frontend/ParserActions.cpp b/flang/lib/Frontend/ParserActions.cpp
index 1722c7a9cf9d0..f191623b38c03 100644
--- a/flang/lib/Frontend/ParserActions.cpp
+++ b/flang/lib/Frontend/ParserActions.cpp
@@ -96,8 +96,9 @@ void debugMeasureParseTree(CompilerInstance &ci, llvm::StringRef filename) {
if ((ci.getParsing().parseTree().has_value() &&
!ci.getParsing().consumedWholeFile()) ||
(!ci.getParsing().messages().empty() &&
- (ci.getInvocation().getWarnAsErr() ||
- ci.getParsing().messages().AnyFatalError()))) {
+ ci.getParsing().messages().AnyFatalError(
+ ci.getInvocation().getWarnAsErr(),
+ &ci.getInvocation().getFortranOpts().features))) {
unsigned diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, "Could not parse %0");
ci.getDiagnostics().Report(diagID) << filename;
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index d68489a192081..e9964cd28866a 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -169,6 +169,19 @@ bool Message::SortBefore(const Message &that) const {
location_, that.location_);
}
+static bool ShouldTreatMessageAsFatal(const Message &msg,
+ bool globalWarningsAreErrors,
+ const common::LanguageFeatureControl *control) {
+ if (msg.IsFatal()) {
+ return true;
+ }
+ if (control) {
+ return control->ShouldPromoteWarningToError(
+ globalWarningsAreErrors, msg.languageFeature(), msg.usageWarning());
+ }
+ return globalWarningsAreErrors;
+}
+
bool Message::IsFatal() const { return IsFatalSeverity(severity()); }
Severity Message::severity() const {
@@ -500,7 +513,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
}
msgsWithLastLocation.push_back(msg);
msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
- if (warningsAreErrors || msg->IsFatal()) {
+ if (ShouldTreatMessageAsFatal(*msg, warningsAreErrors, hintFlagPtr)) {
++errorsEmitted;
}
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
@@ -522,20 +535,10 @@ void Messages::AttachTo(Message &msg, std::optional<Severity> severity) {
messages_.clear();
}
-bool Messages::AnyFatalError(bool warningsAreErrors) const {
- // Short-circuit in the most common case.
- if (messages_.empty()) {
- return false;
- }
- // If warnings are errors and there are warnings or errors, this is fatal.
- // This preserves the compiler's current behavior of treating any non-fatal
- // message as a warning. We may want to refine this in the future.
- if (warningsAreErrors) {
- return true;
- }
- // Otherwise, check the message buffer for fatal errors.
+bool Messages::AnyFatalError(bool warningsAreErrors,
+ const common::LanguageFeatureControl *control) const {
for (const auto &msg : messages_) {
- if (msg.IsFatal()) {
+ if (ShouldTreatMessageAsFatal(msg, warningsAreErrors, control)) {
return true;
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index 33c54c81f8abd..2e4daef8f807c 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -416,7 +416,7 @@ const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) {
}
bool SemanticsContext::AnyFatalError() const {
- return messages_.AnyFatalError(warningsAreErrors_);
+ return messages_.AnyFatalError(warningsAreErrors_, &languageFeatures_);
}
bool SemanticsContext::HasError(const Symbol &symbol) {
return errorSymbols_.count(symbol) > 0;
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index a8fa4ac4a7afe..4abf53e35272a 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -259,6 +259,55 @@ bool LanguageFeatureControl::EnableWarning(std::string_view input) {
return false;
}
+bool LanguageFeatureControl::SetWarningErrorTreatment(
+ std::string_view specifier, bool asError) {
+ if (auto warning{FindWarning(specifier)}) {
+ if (std::holds_alternative<LanguageFeature>(warning->first)) {
+ auto feature{std::get<LanguageFeature>(warning->first)};
+ if (asError) {
+ warnNotAsErrorLanguage_.reset(feature);
+ warnAsErrorLanguage_.set(feature);
+ } else {
+ warnAsErrorLanguage_.reset(feature);
+ warnNotAsErrorLanguage_.set(feature);
+ }
+ } else {
+ auto usageWarning{std::get<UsageWarning>(warning->first)};
+ if (asError) {
+ warnNotAsErrorUsage_.reset(usageWarning);
+ warnAsErrorUsage_.set(usageWarning);
+ } else {
+ warnAsErrorUsage_.reset(usageWarning);
+ warnNotAsErrorUsage_.set(usageWarning);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool LanguageFeatureControl::ShouldPromoteWarningToError(bool globalWarnAsErr,
+ std::optional<LanguageFeature> languageFeature,
+ std::optional<UsageWarning> usageWarning) const {
+ if (languageFeature) {
+ if (warnNotAsErrorLanguage_.test(*languageFeature)) {
+ return false;
+ }
+ if (warnAsErrorLanguage_.test(*languageFeature)) {
+ return true;
+ }
+ }
+ if (usageWarning) {
+ if (warnNotAsErrorUsage_.test(*usageWarning)) {
+ return false;
+ }
+ if (warnAsErrorUsage_.test(*usageWarning)) {
+ return true;
+ }
+ }
+ return globalWarnAsErr;
+}
+
void LanguageFeatureControl::ReplaceCliCanonicalSpelling(
LanguageFeature f, std::string input) {
cliOptions_.erase(languageFeatureCliCanonicalSpelling_[EnumToInt(f)]);
diff --git a/flang/test/Driver/Inputs/werror-unknown-scanning.f90 b/flang/test/Driver/Inputs/werror-unknown-scanning.f90
new file mode 100644
index 0000000000000..6aba8346a6f9c
--- /dev/null
+++ b/flang/test/Driver/Inputs/werror-unknown-scanning.f90
@@ -0,0 +1,2 @@
+ xy z=1
+ end
diff --git a/flang/test/Driver/werror-unknown.f90 b/flang/test/Driver/werror-unknown.f90
new file mode 100644
index 0000000000000..c049b0be11e27
--- /dev/null
+++ b/flang/test/Driver/werror-unknown.f90
@@ -0,0 +1,30 @@
+! Verify unknown, malformed, and -Werror= / -Wno-error= for another warning group.
+!
+! Unknown Flang groups fall through to Clang's ProcessWarningOptions and are
+! accepted without "Unknown diagnostic option". Malformed -Werror= is rejected.
+! Scanning warnings come from -ffixed-form on %S/Inputs/werror-unknown-scanning.f90.
+
+!--- unknown Flang groups: no driver diagnostic --------------------------------
+! RUN: %flang_fc1 -fsyntax-only -Werror=not-a-flang-warning %s 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-UNKNOWN
+! RUN: %flang_fc1 -fsyntax-only -Wno-error=not-a-flang-warning %s 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-UNKNOWN
+
+!--- malformed -Werror= spelling -----------------------------------------------
+! RUN: not %flang_fc1 -fsyntax-only -Werror= %s 2>&1 | FileCheck %s --check-prefix=MALFORMED
+
+!--- scanning warning group ----------------------------------------------------
+! RUN: %flang_fc1 -fsyntax-only -ffixed-form %S/Inputs/werror-unknown-scanning.f90 -Werror -Wno-error=scanning 2>&1 | FileCheck %s --check-prefixes=SCAN-WARN,NO-ERROR
+! RUN: not %flang_fc1 -fsyntax-only -ffixed-form %S/Inputs/werror-unknown-scanning.f90 -Werror=scanning 2>&1 | FileCheck %s --check-prefixes=SCAN-ERROR,SCAN-WARN
+! RUN: not %flang_fc1 -fsyntax-only -ffixed-form %S/Inputs/werror-unknown-scanning.f90 -Werror 2>&1 | FileCheck %s --check-prefixes=SCAN-ERROR,SCAN-WARN
+
+! NO-UNKNOWN-NOT: Unknown diagnostic option
+! NO-UNKNOWN-NOT: not-a-flang-warning
+
+! MALFORMED: Unknown diagnostic option: -Werror=
+
+! FileCheck scans forward: SCAN-ERROR before SCAN-WARN.
+! SCAN-ERROR: Could not scan
+! SCAN-WARN: Statement should not begin with a continuation line [-Wscanning]
+! NO-ERROR-NOT: error:
+
+program werrorUnknown
+end
diff --git a/flang/test/Driver/wno-error.f90 b/flang/test/Driver/wno-error.f90
new file mode 100644
index 0000000000000..9ab04c7856209
--- /dev/null
+++ b/flang/test/Driver/wno-error.f90
@@ -0,0 +1,52 @@
+! Verify -Werror / -Werror= / -Wno-error / -Wno-error= for Flang warning groups.
+!
+! Portability warning from -pedantic on ichar('ab').
+! Redundant-attribute warning from duplicate SAVE on integer, save, save :: x.
+! Use -Wno-redundant-attribute on portability-only runs so they stay isolated.
+
+!--- Baseline (no -pedantic) --------------------------------------------------
+! RUN: %flang_fc1 -fsyntax-only -Wno-redundant-attribute %s 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-DIAG
+
+!--- -Werror=portability without -pedantic: no warning, so no error -----------
+! RUN: %flang_fc1 -fsyntax-only -Wno-redundant-attribute -Werror=portability %s 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-DIAG
+
+!--- -pedantic and redundant-attribute both emit warnings --------------------
+! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,REDUNDANT-WARN,NO-ERROR
+
+!--- combinations that promote the portability warning to an error ------------
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror=portability %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Wno-error -Werror=portability %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror -Wno-error -Werror=portability %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+
+!--- combinations that leave the portability warning non-fatal ----------------
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Wno-error %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Wno-error=portability %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror -Wno-error=portability %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror -Wno-error %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Werror=portability -Wno-error=portability %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Wno-redundant-attribute -Wno-error=portability -Werror %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,NO-ERROR
+
+!--- per-group control with both portability and redundant-attribute warnings --
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror -Wno-error=portability %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,REDUNDANT-WARN
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror -Wno-error=redundant-attribute %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+! RUN: %flang_fc1 -fsyntax-only -pedantic -Werror -Wno-error=portability -Wno-error=redundant-attribute %s 2>&1 | FileCheck %s --check-prefixes=PEDANTIC-WARN,REDUNDANT-WARN,NO-ERROR
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror=redundant-attribute -Wno-error=portability %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,REDUNDANT-WARN
+! RUN: not %flang_fc1 -fsyntax-only -pedantic -Werror=portability -Wno-error=redundant-attribute %s 2>&1 | FileCheck %s --check-prefixes=IS-ERROR,PEDANTIC-WARN
+
+! NO-DIAG-NOT: portability
+! NO-DIAG-NOT: warning
+! NO-DIAG-NOT: error
+
+! FileCheck scans forward: IS-ERROR before PEDANTIC-WARN; REDUNDANT-WARN before
+! PEDANTIC-WARN when both warnings appear (redundant-attribute is emitted first).
+! IS-ERROR: Semantic errors in
+! REDUNDANT-WARN: Attribute 'SAVE' cannot be used more than once [-Wredundant-attribute]
+! PEDANTIC-WARN: should have length one [-Wportability]
+! NO-ERROR-NOT: error:
+
+subroutine wnoErrorTest
+ integer, save, save :: x
+ x = 1
+ print *, ichar('ab')
+end
diff --git a/flang/unittests/Common/FortranFeaturesTest.cpp b/flang/unittests/Common/FortranFeaturesTest.cpp
index dfd88cb8abecd..53c60a82b1a86 100644
--- a/flang/unittests/Common/FortranFeaturesTest.cpp
+++ b/flang/unittests/Common/FortranFeaturesTest.cpp
@@ -563,4 +563,19 @@ TEST(FortranFeaturesTest, HintLanguageControlFlag) {
control.getDefaultCliSpelling(UsageWarning::Portability), "portability");
}
+TEST(FortranFeaturesTest, WarningErrorTreatment) {
+ LanguageFeatureControl control{};
+ EXPECT_TRUE(control.SetWarningErrorTreatment("portability", false));
+ EXPECT_FALSE(control.ShouldPromoteWarningToError(
+ /*globalWarnAsErr=*/true, std::nullopt, UsageWarning::Portability));
+ EXPECT_TRUE(control.ShouldPromoteWarningToError(
+ /*globalWarnAsErr=*/true, std::nullopt, UsageWarning::Bounds));
+
+ EXPECT_TRUE(control.SetWarningErrorTreatment("benign-name-clash", true));
+ EXPECT_TRUE(control.ShouldPromoteWarningToError(/*globalWarnAsErr=*/false,
+ LanguageFeature::BenignNameClash, std::nullopt));
+ EXPECT_FALSE(control.ShouldPromoteWarningToError(/*globalWarnAsErr=*/false,
+ LanguageFeature::RedundantAttribute, std::nullopt));
+}
+
} // namespace Fortran::common::details
More information about the flang-commits
mailing list