-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[flang][driver] -Werror promotes warnings to error and interopts with -Wfatal-errors #148748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-flang-parser Author: Andre Kuhlenschmidt (akuhlens) ChangesThis PR changes how Flang:
clang
gfortran
Note, it should be a simple change to switch the text formatting back to the previous behavior if we prefer that, but my intuition was that it would behave this way and I was surprised when it didn't. Full diff: https://github.com/llvm/llvm-project/pull/148748.diff 7 Files Affected:
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
|
@llvm/pr-subscribers-flang-driver Author: Andre Kuhlenschmidt (akuhlens) ChangesThis PR changes how Flang:
clang
gfortran
Note, it should be a simple change to switch the text formatting back to the previous behavior if we prefer that, but my intuition was that it would behave this way and I was surprised when it didn't. Full diff: https://github.com/llvm/llvm-project/pull/148748.diff 7 Files Affected:
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
|
@llvm/pr-subscribers-flang-semantics Author: Andre Kuhlenschmidt (akuhlens) ChangesThis PR changes how Flang:
clang
gfortran
Note, it should be a simple change to switch the text formatting back to the previous behavior if we prefer that, but my intuition was that it would behave this way and I was surprised when it didn't. Full diff: https://github.com/llvm/llvm-project/pull/148748.diff 7 Files Affected:
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't display warnings with error:
on them. I understand that other compilers do that, but I think that it's confusing to users to have some diagnostic messages be errors in some contexts and not in others.
This PR changes how
-Werror
promotes warnings to errors so that it interoperates with-Wfatal-error
. In doing so it changes how warnings are presented when they are promoted. They now say "error" instead of "warning" and are highlighted in red. This new presentation is consistent with gfortran and clang.Flang:
clang
gfortran
Note, it should be a simple change to switch the text formatting back to the previous behavior if we prefer that, but my intuition was that it would behave this way and I was surprised when it didn't.