[flang-commits] [flang] [flang][driver] -Werror promotes warnings to error and interopts with -Wfatal-errors (PR #148748)
Andre Kuhlenschmidt via flang-commits
flang-commits at lists.llvm.org
Wed Jul 16 11:30:59 PDT 2025
https://github.com/akuhlens updated https://github.com/llvm/llvm-project/pull/148748
>From b9cdd2e72c9c9e6b10098c4144b3e840122b56d6 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Mon, 14 Jul 2025 15:56:39 -0700
Subject: [PATCH 1/6] initial commit
---
flang/include/flang/Parser/message.h | 37 ++++++++++++++-------
flang/lib/Frontend/FrontendAction.cpp | 6 ++--
flang/lib/Parser/message.cpp | 37 +++++++++++++--------
flang/lib/Semantics/resolve-names.cpp | 3 +-
flang/lib/Semantics/semantics.cpp | 5 ++-
flang/test/Driver/color-diagnostics-scan.f | 16 ++++-----
flang/test/Driver/fatal-errors-warnings.f90 | 32 ++++++++++++++++++
7 files changed, 96 insertions(+), 40 deletions(-)
create mode 100644 flang/test/Driver/fatal-errors-warnings.f90
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index db1a0a65157e3..d1d313a70a016 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -56,13 +56,19 @@ class MessageFixedText {
CharBlock text() const { return text_; }
bool empty() const { return text_.empty(); }
- Severity severity() const { return severity_; }
+ Severity severity(bool warningsAreErrors = false) const {
+ if (warningsAreErrors) {
+ return Severity::Error;
+ }
+ return severity_;
+ }
MessageFixedText &set_severity(Severity severity) {
severity_ = severity;
return *this;
}
- bool IsFatal() const {
- return severity_ == Severity::Error || severity_ == Severity::Todo;
+ bool IsFatal(bool warningsAreErrors = false) const {
+ Severity sev{severity(warningsAreErrors)};
+ return sev == Severity::Error || sev == Severity::Todo;
}
private:
@@ -105,7 +111,7 @@ class MessageFormattedText {
public:
template <typename... A>
MessageFormattedText(const MessageFixedText &text, A &&...x)
- : severity_{text.severity()} {
+ : severity_{text.severity(false)} {
Format(&text, Convert(std::forward<A>(x))...);
}
MessageFormattedText(const MessageFormattedText &) = default;
@@ -113,14 +119,20 @@ class MessageFormattedText {
MessageFormattedText &operator=(const MessageFormattedText &) = default;
MessageFormattedText &operator=(MessageFormattedText &&) = default;
const std::string &string() const { return string_; }
- bool IsFatal() const {
- return severity_ == Severity::Error || severity_ == Severity::Todo;
+ Severity severity(bool warningsAreErrors = false) const {
+ if (warningsAreErrors) {
+ return Severity::Error;
+ }
+ return severity_;
}
- Severity severity() const { return severity_; }
MessageFormattedText &set_severity(Severity severity) {
severity_ = severity;
return *this;
}
+ bool IsFatal(bool warningsAreErrors = false) const {
+ Severity sev{severity(warningsAreErrors)};
+ return sev == Severity::Error || sev == Severity::Todo;
+ }
std::string MoveString() { return std::move(string_); }
bool operator==(const MessageFormattedText &that) const {
return severity_ == that.severity_ && string_ == that.string_;
@@ -281,8 +293,8 @@ class Message : public common::ReferenceCounted<Message> {
}
bool SortBefore(const Message &that) const;
- bool IsFatal() const;
- Severity severity() const;
+ bool IsFatal(bool warningsAreErrors = false) const;
+ Severity severity(bool warningsAreErrors = false) const;
Message &set_severity(Severity);
std::optional<common::LanguageFeature> languageFeature() const;
Message &set_languageFeature(common::LanguageFeature);
@@ -293,7 +305,8 @@ class Message : public common::ReferenceCounted<Message> {
const AllCookedSources &) const;
void Emit(llvm::raw_ostream &, const AllCookedSources &,
bool echoSourceLine = true,
- const common::LanguageFeatureControl *hintFlags = nullptr) const;
+ const common::LanguageFeatureControl *hintFlags = nullptr,
+ bool warningsAreErrors = false) const;
// If this Message or any of its attachments locates itself via a CharBlock,
// replace its location with the corresponding ProvenanceRange.
@@ -355,9 +368,9 @@ class Messages {
void Emit(llvm::raw_ostream &, const AllCookedSources &,
bool echoSourceLines = true,
const common::LanguageFeatureControl *hintFlags = nullptr,
- std::size_t maxErrorsToEmit = 0) const;
+ std::size_t maxErrorsToEmit = 0, bool warningsAreErrors = false) const;
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
- bool AnyFatalError() const;
+ bool AnyFatalError(bool warningsAreErrors = false) const;
private:
std::list<Message> messages_;
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 2429e07e5b8c4..d32f477445f93 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -238,7 +238,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
- /*echoSourceLines=*/true, &features, maxErrors);
+ /*echoSourceLines=*/true, &features, maxErrors,
+ instance->getInvocation().getWarnAsErr());
return true;
}
if (instance->getParsing().parseTree().has_value() &&
@@ -249,7 +250,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
- /*echoSourceLine=*/true, &features, maxErrors);
+ /*echoSourceLine=*/true, &features, maxErrors,
+ instance->getInvocation().getWarnAsErr());
instance->getParsing().EmitMessage(
llvm::errs(), instance->getParsing().finalRestingPlace(),
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 909fba948a45a..574e9f5d424f8 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -161,16 +161,21 @@ bool Message::SortBefore(const Message &that) const {
location_, that.location_);
}
-bool Message::IsFatal() const {
- return severity() == Severity::Error || severity() == Severity::Todo;
+bool Message::IsFatal(bool warningsAreErrors) const {
+ Severity sev{severity(warningsAreErrors)};
+ return sev == Severity::Error || sev == Severity::Todo;
}
-Severity Message::severity() const {
+Severity Message::severity(bool warningsAreErrors) const {
return common::visit(
common::visitors{
[](const MessageExpectedText &) { return Severity::Error; },
- [](const MessageFixedText &x) { return x.severity(); },
- [](const MessageFormattedText &x) { return x.severity(); },
+ [=](const MessageFixedText &x) {
+ return x.severity(warningsAreErrors);
+ },
+ [=](const MessageFormattedText &x) {
+ return x.severity(warningsAreErrors);
+ },
},
text_);
}
@@ -295,15 +300,16 @@ static constexpr int MAX_CONTEXTS_EMITTED{2};
static constexpr bool OMIT_SHARED_CONTEXTS{true};
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLine,
- const common::LanguageFeatureControl *hintFlagPtr) const {
+ bool echoSourceLine, const common::LanguageFeatureControl *hintFlagPtr,
+ bool warningsAreErrors) const {
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
const AllSources &sources{allCooked.allSources()};
const std::string text{ToString()};
+ Severity sev{severity(warningsAreErrors)};
const std::string hint{
HintLanguageControlFlag(hintFlagPtr, languageFeature_, usageWarning_)};
- sources.EmitMessage(o, provenanceRange, text + hint, Prefix(severity()),
- PrefixColor(severity()), echoSourceLine);
+ sources.EmitMessage(o, provenanceRange, text + hint, Prefix(sev),
+ PrefixColor(sev), echoSourceLine);
// Refers to whether the attachment in the loop below is a context, but can't
// be declared inside the loop because the previous iteration's
// attachment->attachmentIsContext_ indicates this.
@@ -453,7 +459,7 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) {
void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
bool echoSourceLines, const common::LanguageFeatureControl *hintFlagPtr,
- std::size_t maxErrorsToEmit) const {
+ std::size_t maxErrorsToEmit, bool warningsAreErrors) const {
std::vector<const Message *> sorted;
for (const auto &msg : messages_) {
sorted.push_back(&msg);
@@ -467,9 +473,9 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
// Don't emit two identical messages for the same location
continue;
}
- msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
+ msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr, warningsAreErrors);
lastMsg = msg;
- if (msg->IsFatal()) {
+ if (msg->IsFatal(warningsAreErrors)) {
++errorsEmitted;
}
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
@@ -491,9 +497,12 @@ void Messages::AttachTo(Message &msg, std::optional<Severity> severity) {
messages_.clear();
}
-bool Messages::AnyFatalError() const {
+bool Messages::AnyFatalError(bool warningsAreErrors) const {
+ if (messages_.empty()) {
+ return false;
+ }
for (const auto &msg : messages_) {
- if (msg.IsFatal()) {
+ if (msg.IsFatal(warningsAreErrors)) {
return true;
}
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 96faa5fd954cd..df898f6e5651e 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -7575,7 +7575,8 @@ bool DeclarationVisitor::OkToAddComponent(
if (msg) {
auto &said{Say2(name, std::move(*msg), *prev,
"Previous declaration of '%s'"_en_US)};
- if (msg->severity() == parser::Severity::Error) {
+ if (msg->severity(/*warningsAreErrors=*/false) ==
+ parser::Severity::Error) {
Resolve(name, *prev);
return false;
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index ab78605d01f4c..b15ed057b52f2 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -376,8 +376,7 @@ const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) {
}
bool SemanticsContext::AnyFatalError() const {
- return !messages_.empty() &&
- (warningsAreErrors_ || messages_.AnyFatalError());
+ return messages_.AnyFatalError(warningsAreErrors_);
}
bool SemanticsContext::HasError(const Symbol &symbol) {
return errorSymbols_.count(symbol) > 0;
@@ -658,7 +657,7 @@ void Semantics::EmitMessages(llvm::raw_ostream &os) {
context_.messages().ResolveProvenances(context_.allCookedSources());
context_.messages().Emit(os, context_.allCookedSources(),
/*echoSourceLine=*/true, &context_.languageFeatures(),
- /*maxErrorsToEmit=*/context_.maxErrors());
+ context_.maxErrors(), context_.warningsAreErrors());
}
void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
diff --git a/flang/test/Driver/color-diagnostics-scan.f b/flang/test/Driver/color-diagnostics-scan.f
index 29d4635b4fb03..2f647c923c2e6 100644
--- a/flang/test/Driver/color-diagnostics-scan.f
+++ b/flang/test/Driver/color-diagnostics-scan.f
@@ -3,24 +3,24 @@
! Windows command prompt doesn't support ANSI escape sequences.
! REQUIRES: shell
-! RUN: not %flang %s -E -Werror -fcolor-diagnostics 2>&1 \
+! RUN: %flang %s -E -fcolor-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: not %flang %s -E -Werror -fno-color-diagnostics 2>&1 \
+! RUN: %flang %s -E -fno-color-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: not %flang_fc1 -E -Werror %s -fcolor-diagnostics 2>&1 \
+! RUN: %flang_fc1 -E %s -fcolor-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: not %flang %s -E -Werror -fdiagnostics-color 2>&1 \
+! RUN: %flang %s -E -fdiagnostics-color 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: not %flang %s -E -Werror -fno-diagnostics-color 2>&1 \
+! RUN: %flang %s -E -fno-diagnostics-color 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: not %flang %s -E -Werror -fdiagnostics-color=always 2>&1 \
+! RUN: %flang %s -E -fdiagnostics-color=always 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: not %flang %s -E -Werror -fdiagnostics-color=never 2>&1 \
+! RUN: %flang %s -E -fdiagnostics-color=never 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: not %flang_fc1 -E -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
+! RUN: %flang_fc1 -E %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
! CHECK_CD: {{.*}}[0;1;35mwarning: {{.*}}[0mCharacter in fixed-form label field must be a digit
diff --git a/flang/test/Driver/fatal-errors-warnings.f90 b/flang/test/Driver/fatal-errors-warnings.f90
new file mode 100644
index 0000000000000..b4b23230587a4
--- /dev/null
+++ b/flang/test/Driver/fatal-errors-warnings.f90
@@ -0,0 +1,32 @@
+! RUN: not %flang_fc1 -Wfatal-errors -pedantic %s 2>&1 | FileCheck %s --check-prefix=CHECK1
+! RUN: not %flang_fc1 -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK2
+! RUN: not %flang_fc1 -Wfatal-errors -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK3
+
+module m
+ contains
+ subroutine foo(a)
+ real, intent(in), target :: a(:)
+ end subroutine
+end module
+
+program test
+ use m
+ real, target :: a(1)
+ real :: b(1)
+ call foo(a) ! ok
+ !CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK3: fatal-errors-warnings.f90:{{.*}} error:
+ call foo(b)
+ !CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK3-NOT: error:
+ !CHECK3-NOT: warning:
+ call foo((a))
+ !CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ call foo(a([1]))
+ !CHECK1: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ call foo(a(1))
+end
\ No newline at end of file
>From 31d79c710a3a0a727bcf2d94e73280a9f62bb0ca Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Tue, 15 Jul 2025 09:21:19 -0700
Subject: [PATCH 2/6] don't display warnings as errors
---
flang/lib/Parser/message.cpp | 6 +++++-
flang/test/Driver/color-diagnostics-scan.f | 16 ++++++++--------
flang/test/Driver/fatal-errors-warnings.f90 | 15 +++++++--------
3 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 574e9f5d424f8..6644fafffc1bc 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -473,7 +473,11 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
// Don't emit two identical messages for the same location
continue;
}
- msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr, warningsAreErrors);
+ // We think it is confusing to users to display warnings and other
+ // diagnostics as errors, instead we just treat them as errors for the
+ // purpose of failing.
+ msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr,
+ /*warningsAreErrors=*/false);
lastMsg = msg;
if (msg->IsFatal(warningsAreErrors)) {
++errorsEmitted;
diff --git a/flang/test/Driver/color-diagnostics-scan.f b/flang/test/Driver/color-diagnostics-scan.f
index 2f647c923c2e6..29d4635b4fb03 100644
--- a/flang/test/Driver/color-diagnostics-scan.f
+++ b/flang/test/Driver/color-diagnostics-scan.f
@@ -3,24 +3,24 @@
! Windows command prompt doesn't support ANSI escape sequences.
! REQUIRES: shell
-! RUN: %flang %s -E -fcolor-diagnostics 2>&1 \
+! RUN: not %flang %s -E -Werror -fcolor-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: %flang %s -E -fno-color-diagnostics 2>&1 \
+! RUN: not %flang %s -E -Werror -fno-color-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: %flang_fc1 -E %s -fcolor-diagnostics 2>&1 \
+! RUN: not %flang_fc1 -E -Werror %s -fcolor-diagnostics 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: %flang %s -E -fdiagnostics-color 2>&1 \
+! RUN: not %flang %s -E -Werror -fdiagnostics-color 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: %flang %s -E -fno-diagnostics-color 2>&1 \
+! RUN: not %flang %s -E -Werror -fno-diagnostics-color 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: %flang %s -E -fdiagnostics-color=always 2>&1 \
+! RUN: not %flang %s -E -Werror -fdiagnostics-color=always 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_CD
-! RUN: %flang %s -E -fdiagnostics-color=never 2>&1 \
+! RUN: not %flang %s -E -Werror -fdiagnostics-color=never 2>&1 \
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
-! RUN: %flang_fc1 -E %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
+! RUN: not %flang_fc1 -E -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
! CHECK_CD: {{.*}}[0;1;35mwarning: {{.*}}[0mCharacter in fixed-form label field must be a digit
diff --git a/flang/test/Driver/fatal-errors-warnings.f90 b/flang/test/Driver/fatal-errors-warnings.f90
index b4b23230587a4..2de09c3ed0778 100644
--- a/flang/test/Driver/fatal-errors-warnings.f90
+++ b/flang/test/Driver/fatal-errors-warnings.f90
@@ -1,4 +1,4 @@
-! RUN: not %flang_fc1 -Wfatal-errors -pedantic %s 2>&1 | FileCheck %s --check-prefix=CHECK1
+! RUN: %flang_fc1 -Wfatal-errors -pedantic %s 2>&1 | FileCheck %s --check-prefix=CHECK1
! RUN: not %flang_fc1 -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK2
! RUN: not %flang_fc1 -Wfatal-errors -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK3
@@ -15,18 +15,17 @@ program test
real :: b(1)
call foo(a) ! ok
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
- !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
- !CHECK3: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
+ !CHECK3: fatal-errors-warnings.f90:{{.*}} warning:
call foo(b)
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
- !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
!CHECK3-NOT: error:
!CHECK3-NOT: warning:
call foo((a))
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
- !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
+ !CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
call foo(a([1]))
- !CHECK1: fatal-errors-warnings.f90:{{.*}} error:
- !CHECK2: fatal-errors-warnings.f90:{{.*}} error:
- call foo(a(1))
+ !! Hard error instead of warning if uncommented.
+ !call foo(a(1))
end
\ No newline at end of file
>From 892e255be088b117b94203b66d75688fcd3ebc28 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Tue, 15 Jul 2025 11:07:22 -0700
Subject: [PATCH 3/6] add EffectiveSeverity(...)
---
flang/include/flang/Parser/message.h | 42 +++++++++++++++-----------
flang/lib/Frontend/FrontendAction.cpp | 11 +++----
flang/lib/Parser/message.cpp | 43 ++++++++++++++++-----------
flang/lib/Semantics/resolve-names.cpp | 3 +-
4 files changed, 54 insertions(+), 45 deletions(-)
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index d1d313a70a016..423856b084b92 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -56,18 +56,22 @@ class MessageFixedText {
CharBlock text() const { return text_; }
bool empty() const { return text_.empty(); }
- Severity severity(bool warningsAreErrors = false) const {
- if (warningsAreErrors) {
- return Severity::Error;
- }
- return severity_;
- }
+ Severity severity() const { return severity_; }
MessageFixedText &set_severity(Severity severity) {
severity_ = severity;
return *this;
}
+ // This is currently emulating how the frontend is currently handling other
+ // diagnostic messages. We may want to be more nuanced in the future.
+ Severity EffectiveSeverity(bool warningsAreErrors) const {
+ if (warningsAreErrors) {
+ return Severity::Error;
+ } else {
+ return severity_;
+ }
+ }
bool IsFatal(bool warningsAreErrors = false) const {
- Severity sev{severity(warningsAreErrors)};
+ Severity sev{EffectiveSeverity(warningsAreErrors)};
return sev == Severity::Error || sev == Severity::Todo;
}
@@ -111,7 +115,7 @@ class MessageFormattedText {
public:
template <typename... A>
MessageFormattedText(const MessageFixedText &text, A &&...x)
- : severity_{text.severity(false)} {
+ : severity_{text.severity()} {
Format(&text, Convert(std::forward<A>(x))...);
}
MessageFormattedText(const MessageFormattedText &) = default;
@@ -119,18 +123,20 @@ class MessageFormattedText {
MessageFormattedText &operator=(const MessageFormattedText &) = default;
MessageFormattedText &operator=(MessageFormattedText &&) = default;
const std::string &string() const { return string_; }
- Severity severity(bool warningsAreErrors = false) const {
- if (warningsAreErrors) {
- return Severity::Error;
- }
- return severity_;
- }
+ Severity severity() const { return severity_; }
MessageFormattedText &set_severity(Severity severity) {
severity_ = severity;
return *this;
}
+ Severity EffectiveSeverity(bool warningsAreErrors) const {
+ if (warningsAreErrors) {
+ return Severity::Error;
+ } else {
+ return severity_;
+ }
+ }
bool IsFatal(bool warningsAreErrors = false) const {
- Severity sev{severity(warningsAreErrors)};
+ Severity sev{EffectiveSeverity(warningsAreErrors)};
return sev == Severity::Error || sev == Severity::Todo;
}
std::string MoveString() { return std::move(string_); }
@@ -294,7 +300,8 @@ class Message : public common::ReferenceCounted<Message> {
bool SortBefore(const Message &that) const;
bool IsFatal(bool warningsAreErrors = false) const;
- Severity severity(bool warningsAreErrors = false) const;
+ Severity EffectiveSeverity(bool warningsAreErrors) const;
+ Severity severity() const;
Message &set_severity(Severity);
std::optional<common::LanguageFeature> languageFeature() const;
Message &set_languageFeature(common::LanguageFeature);
@@ -305,8 +312,7 @@ class Message : public common::ReferenceCounted<Message> {
const AllCookedSources &) const;
void Emit(llvm::raw_ostream &, const AllCookedSources &,
bool echoSourceLine = true,
- const common::LanguageFeatureControl *hintFlags = nullptr,
- bool warningsAreErrors = false) const;
+ const common::LanguageFeatureControl *hintFlags = nullptr) const;
// If this Message or any of its attachments locates itself via a CharBlock,
// replace its location with the corresponding ProvenanceRange.
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index d32f477445f93..58901c6000380 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -230,16 +230,14 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
const common::LanguageFeatureControl &features{
instance->getInvocation().getFortranOpts().features};
const size_t maxErrors{instance->getInvocation().getMaxErrors()};
- if (!instance->getParsing().messages().empty() &&
- (instance->getInvocation().getWarnAsErr() ||
- instance->getParsing().messages().AnyFatalError())) {
+ const bool warningsAreErrors{instance->getInvocation().getWarnAsErr()};
+ if (instance->getParsing().messages().AnyFatalError(warningsAreErrors)) {
const unsigned diagID = instance->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
- /*echoSourceLines=*/true, &features, maxErrors,
- instance->getInvocation().getWarnAsErr());
+ /*echoSourceLines=*/true, &features, maxErrors, warningsAreErrors);
return true;
}
if (instance->getParsing().parseTree().has_value() &&
@@ -250,8 +248,7 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
- /*echoSourceLine=*/true, &features, maxErrors,
- instance->getInvocation().getWarnAsErr());
+ /*echoSourceLine=*/true, &features, maxErrors, warningsAreErrors);
instance->getParsing().EmitMessage(
llvm::errs(), instance->getParsing().finalRestingPlace(),
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 6644fafffc1bc..80fe5b2a14ad2 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -161,25 +161,35 @@ bool Message::SortBefore(const Message &that) const {
location_, that.location_);
}
-bool Message::IsFatal(bool warningsAreErrors) const {
- Severity sev{severity(warningsAreErrors)};
- return sev == Severity::Error || sev == Severity::Todo;
-}
-
-Severity Message::severity(bool warningsAreErrors) const {
+Severity Message::EffectiveSeverity(bool warningsAreErrors) const {
return common::visit(
common::visitors{
[](const MessageExpectedText &) { return Severity::Error; },
[=](const MessageFixedText &x) {
- return x.severity(warningsAreErrors);
+ return x.EffectiveSeverity(warningsAreErrors);
},
[=](const MessageFormattedText &x) {
- return x.severity(warningsAreErrors);
+ return x.EffectiveSeverity(warningsAreErrors);
},
},
text_);
}
+bool Message::IsFatal(bool warningsAreErrors) const {
+ Severity sev{EffectiveSeverity(warningsAreErrors)};
+ return sev == Severity::Error || sev == Severity::Todo;
+}
+
+Severity Message::severity() const {
+ return common::visit(
+ common::visitors{
+ [](const MessageExpectedText &) { return Severity::Error; },
+ [](const MessageFixedText &x) { return x.severity(); },
+ [](const MessageFormattedText &x) { return x.severity(); },
+ },
+ text_);
+}
+
Message &Message::set_severity(Severity severity) {
common::visit(
common::visitors{
@@ -299,17 +309,18 @@ static std::string HintLanguageControlFlag(
static constexpr int MAX_CONTEXTS_EMITTED{2};
static constexpr bool OMIT_SHARED_CONTEXTS{true};
+// We think it is confusing to users to display warnings and other
+// diagnostics as errors. Don't use EffectiveSeverity() here.
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLine, const common::LanguageFeatureControl *hintFlagPtr,
- bool warningsAreErrors) const {
+ bool echoSourceLine,
+ const common::LanguageFeatureControl *hintFlagPtr) const {
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
const AllSources &sources{allCooked.allSources()};
const std::string text{ToString()};
- Severity sev{severity(warningsAreErrors)};
const std::string hint{
HintLanguageControlFlag(hintFlagPtr, languageFeature_, usageWarning_)};
- sources.EmitMessage(o, provenanceRange, text + hint, Prefix(sev),
- PrefixColor(sev), echoSourceLine);
+ sources.EmitMessage(o, provenanceRange, text + hint, Prefix(severity()),
+ PrefixColor(severity()), echoSourceLine);
// Refers to whether the attachment in the loop below is a context, but can't
// be declared inside the loop because the previous iteration's
// attachment->attachmentIsContext_ indicates this.
@@ -473,11 +484,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
// Don't emit two identical messages for the same location
continue;
}
- // We think it is confusing to users to display warnings and other
- // diagnostics as errors, instead we just treat them as errors for the
- // purpose of failing.
- msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr,
- /*warningsAreErrors=*/false);
+ msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
lastMsg = msg;
if (msg->IsFatal(warningsAreErrors)) {
++errorsEmitted;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index df898f6e5651e..96faa5fd954cd 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -7575,8 +7575,7 @@ bool DeclarationVisitor::OkToAddComponent(
if (msg) {
auto &said{Say2(name, std::move(*msg), *prev,
"Previous declaration of '%s'"_en_US)};
- if (msg->severity(/*warningsAreErrors=*/false) ==
- parser::Severity::Error) {
+ if (msg->severity() == parser::Severity::Error) {
Resolve(name, *prev);
return false;
}
>From 6bfd9255636df484d88fd46fbc84c368085501b6 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Tue, 15 Jul 2025 15:07:25 -0700
Subject: [PATCH 4/6] remove actual promotion
---
flang/include/flang/Parser/message.h | 28 +++++-----------------------
flang/lib/Parser/message.cpp | 26 +++++++-------------------
2 files changed, 12 insertions(+), 42 deletions(-)
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 423856b084b92..839bca158a78a 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -61,18 +61,9 @@ class MessageFixedText {
severity_ = severity;
return *this;
}
- // This is currently emulating how the frontend is currently handling other
- // diagnostic messages. We may want to be more nuanced in the future.
- Severity EffectiveSeverity(bool warningsAreErrors) const {
- if (warningsAreErrors) {
- return Severity::Error;
- } else {
- return severity_;
- }
- }
- bool IsFatal(bool warningsAreErrors = false) const {
- Severity sev{EffectiveSeverity(warningsAreErrors)};
- return sev == Severity::Error || sev == Severity::Todo;
+
+ bool IsFatal() const {
+ return severity() == Severity::Error || severity() == Severity::Todo;
}
private:
@@ -128,16 +119,8 @@ class MessageFormattedText {
severity_ = severity;
return *this;
}
- Severity EffectiveSeverity(bool warningsAreErrors) const {
- if (warningsAreErrors) {
- return Severity::Error;
- } else {
- return severity_;
- }
- }
bool IsFatal(bool warningsAreErrors = false) const {
- Severity sev{EffectiveSeverity(warningsAreErrors)};
- return sev == Severity::Error || sev == Severity::Todo;
+ return severity() == Severity::Error || severity() == Severity::Todo;
}
std::string MoveString() { return std::move(string_); }
bool operator==(const MessageFormattedText &that) const {
@@ -299,8 +282,7 @@ class Message : public common::ReferenceCounted<Message> {
}
bool SortBefore(const Message &that) const;
- bool IsFatal(bool warningsAreErrors = false) const;
- Severity EffectiveSeverity(bool warningsAreErrors) const;
+ bool IsFatal() const;
Severity severity() const;
Message &set_severity(Severity);
std::optional<common::LanguageFeature> languageFeature() const;
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 80fe5b2a14ad2..36d570408cdb9 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -161,23 +161,8 @@ bool Message::SortBefore(const Message &that) const {
location_, that.location_);
}
-Severity Message::EffectiveSeverity(bool warningsAreErrors) const {
- return common::visit(
- common::visitors{
- [](const MessageExpectedText &) { return Severity::Error; },
- [=](const MessageFixedText &x) {
- return x.EffectiveSeverity(warningsAreErrors);
- },
- [=](const MessageFormattedText &x) {
- return x.EffectiveSeverity(warningsAreErrors);
- },
- },
- text_);
-}
-
-bool Message::IsFatal(bool warningsAreErrors) const {
- Severity sev{EffectiveSeverity(warningsAreErrors)};
- return sev == Severity::Error || sev == Severity::Todo;
+bool Message::IsFatal() const {
+ return severity() == Severity::Error || severity() == Severity::Todo;
}
Severity Message::severity() const {
@@ -486,7 +471,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
}
msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
lastMsg = msg;
- if (msg->IsFatal(warningsAreErrors)) {
+ if (warningsAreErrors || msg->IsFatal()) {
++errorsEmitted;
}
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
@@ -512,8 +497,11 @@ bool Messages::AnyFatalError(bool warningsAreErrors) const {
if (messages_.empty()) {
return false;
}
+ if (warningsAreErrors) {
+ return true;
+ }
for (const auto &msg : messages_) {
- if (msg.IsFatal(warningsAreErrors)) {
+ if (msg.IsFatal()) {
return true;
}
}
>From 2693db8d3188c956204db8e70c8dc4ba97801875 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Tue, 15 Jul 2025 15:15:55 -0700
Subject: [PATCH 5/6] clean up removal
---
flang/include/flang/Parser/message.h | 9 ++++-----
flang/lib/Parser/message.cpp | 2 --
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 839bca158a78a..9192d23529913 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -61,9 +61,8 @@ class MessageFixedText {
severity_ = severity;
return *this;
}
-
bool IsFatal() const {
- return severity() == Severity::Error || severity() == Severity::Todo;
+ return severity_ == Severity::Error || severity_ == Severity::Todo;
}
private:
@@ -114,14 +113,14 @@ class MessageFormattedText {
MessageFormattedText &operator=(const MessageFormattedText &) = default;
MessageFormattedText &operator=(MessageFormattedText &&) = default;
const std::string &string() const { return string_; }
+ bool IsFatal() const {
+ return severity_ == Severity::Error || severity_ == Severity::Todo;
+ }
Severity severity() const { return severity_; }
MessageFormattedText &set_severity(Severity severity) {
severity_ = severity;
return *this;
}
- bool IsFatal(bool warningsAreErrors = false) const {
- return severity() == Severity::Error || severity() == Severity::Todo;
- }
std::string MoveString() { return std::move(string_); }
bool operator==(const MessageFormattedText &that) const {
return severity_ == that.severity_ && string_ == that.string_;
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 36d570408cdb9..064494de9b478 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -294,8 +294,6 @@ static std::string HintLanguageControlFlag(
static constexpr int MAX_CONTEXTS_EMITTED{2};
static constexpr bool OMIT_SHARED_CONTEXTS{true};
-// We think it is confusing to users to display warnings and other
-// diagnostics as errors. Don't use EffectiveSeverity() here.
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
bool echoSourceLine,
const common::LanguageFeatureControl *hintFlagPtr) const {
>From da3cddb3dc58580fb7d0ed12bb9cb608b8397dd1 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Wed, 16 Jul 2025 11:27:13 -0700
Subject: [PATCH 6/6] clarify code
---
flang/lib/Parser/message.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 064494de9b478..2a8101dd0b810 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -492,12 +492,17 @@ void Messages::AttachTo(Message &msg, std::optional<Severity> severity) {
}
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.
for (const auto &msg : messages_) {
if (msg.IsFatal()) {
return true;
More information about the flang-commits
mailing list