Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions flang/include/flang/Parser/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -105,22 +111,28 @@ 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;
MessageFormattedText(MessageFormattedText &&) = default;
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_;
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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_;
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/Frontend/FrontendAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() &&
Expand All @@ -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);
Expand Down
41 changes: 27 additions & 14 deletions flang/lib/Parser/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -467,9 +473,13 @@ 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);
// 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()) {
if (msg->IsFatal(warningsAreErrors)) {
++errorsEmitted;
}
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
Expand All @@ -491,9 +501,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;
}
}
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 2 additions & 3 deletions flang/lib/Semantics/semantics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
31 changes: 31 additions & 0 deletions flang/test/Driver/fatal-errors-warnings.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
! 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

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:{{.*}} warning:
!CHECK3: fatal-errors-warnings.f90:{{.*}} warning:
call foo(b)
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
!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:{{.*}} warning:
call foo(a([1]))
!! Hard error instead of warning if uncommented.
!call foo(a(1))
end
Loading