Skip to content

Commit b3c72a9

Browse files
authored
[flang][driver] -Werror promotes warnings to error and interopts with -Wfatal-errors (#148748)
This PR changes how `-Werror` promotes warnings to errors so that it interoperates with `-Wfatal-error`. It maintains the property that warnings and other messages promoted to errors are displayed as there original message.
1 parent c372a2c commit b3c72a9

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

flang/include/flang/Parser/message.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ class Messages {
355355
void Emit(llvm::raw_ostream &, const AllCookedSources &,
356356
bool echoSourceLines = true,
357357
const common::LanguageFeatureControl *hintFlags = nullptr,
358-
std::size_t maxErrorsToEmit = 0) const;
358+
std::size_t maxErrorsToEmit = 0, bool warningsAreErrors = false) const;
359359
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
360-
bool AnyFatalError() const;
360+
bool AnyFatalError(bool warningsAreErrors = false) const;
361361

362362
private:
363363
std::list<Message> messages_;

flang/lib/Frontend/FrontendAction.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,14 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
230230
const common::LanguageFeatureControl &features{
231231
instance->getInvocation().getFortranOpts().features};
232232
const size_t maxErrors{instance->getInvocation().getMaxErrors()};
233-
if (!instance->getParsing().messages().empty() &&
234-
(instance->getInvocation().getWarnAsErr() ||
235-
instance->getParsing().messages().AnyFatalError())) {
233+
const bool warningsAreErrors{instance->getInvocation().getWarnAsErr()};
234+
if (instance->getParsing().messages().AnyFatalError(warningsAreErrors)) {
236235
const unsigned diagID = instance->getDiagnostics().getCustomDiagID(
237236
clang::DiagnosticsEngine::Error, message);
238237
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
239238
instance->getParsing().messages().Emit(
240239
llvm::errs(), instance->getAllCookedSources(),
241-
/*echoSourceLines=*/true, &features, maxErrors);
240+
/*echoSourceLines=*/true, &features, maxErrors, warningsAreErrors);
242241
return true;
243242
}
244243
if (instance->getParsing().parseTree().has_value() &&
@@ -249,7 +248,7 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
249248
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
250249
instance->getParsing().messages().Emit(
251250
llvm::errs(), instance->getAllCookedSources(),
252-
/*echoSourceLine=*/true, &features, maxErrors);
251+
/*echoSourceLine=*/true, &features, maxErrors, warningsAreErrors);
253252
instance->getParsing().EmitMessage(
254253
llvm::errs(), instance->getParsing().finalRestingPlace(),
255254
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);

flang/lib/Parser/message.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) {
453453

454454
void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
455455
bool echoSourceLines, const common::LanguageFeatureControl *hintFlagPtr,
456-
std::size_t maxErrorsToEmit) const {
456+
std::size_t maxErrorsToEmit, bool warningsAreErrors) const {
457457
std::vector<const Message *> sorted;
458458
for (const auto &msg : messages_) {
459459
sorted.push_back(&msg);
@@ -469,7 +469,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
469469
}
470470
msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
471471
lastMsg = msg;
472-
if (msg->IsFatal()) {
472+
if (warningsAreErrors || msg->IsFatal()) {
473473
++errorsEmitted;
474474
}
475475
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
@@ -491,7 +491,18 @@ void Messages::AttachTo(Message &msg, std::optional<Severity> severity) {
491491
messages_.clear();
492492
}
493493

494-
bool Messages::AnyFatalError() const {
494+
bool Messages::AnyFatalError(bool warningsAreErrors) const {
495+
// Short-circuit in the most common case.
496+
if (messages_.empty()) {
497+
return false;
498+
}
499+
// If warnings are errors and there are warnings or errors, this is fatal.
500+
// This preserves the compiler's current behavior of treating any non-fatal
501+
// message as a warning. We may want to refine this in the future.
502+
if (warningsAreErrors) {
503+
return true;
504+
}
505+
// Otherwise, check the message buffer for fatal errors.
495506
for (const auto &msg : messages_) {
496507
if (msg.IsFatal()) {
497508
return true;

flang/lib/Semantics/semantics.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ const DeclTypeSpec &SemanticsContext::MakeLogicalType(int kind) {
376376
}
377377

378378
bool SemanticsContext::AnyFatalError() const {
379-
return !messages_.empty() &&
380-
(warningsAreErrors_ || messages_.AnyFatalError());
379+
return messages_.AnyFatalError(warningsAreErrors_);
381380
}
382381
bool SemanticsContext::HasError(const Symbol &symbol) {
383382
return errorSymbols_.count(symbol) > 0;
@@ -658,7 +657,7 @@ void Semantics::EmitMessages(llvm::raw_ostream &os) {
658657
context_.messages().ResolveProvenances(context_.allCookedSources());
659658
context_.messages().Emit(os, context_.allCookedSources(),
660659
/*echoSourceLine=*/true, &context_.languageFeatures(),
661-
/*maxErrorsToEmit=*/context_.maxErrors());
660+
context_.maxErrors(), context_.warningsAreErrors());
662661
}
663662

664663
void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
! RUN: %flang_fc1 -Wfatal-errors -pedantic %s 2>&1 | FileCheck %s --check-prefix=CHECK1
2+
! RUN: not %flang_fc1 -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK2
3+
! RUN: not %flang_fc1 -Wfatal-errors -pedantic -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK3
4+
5+
module m
6+
contains
7+
subroutine foo(a)
8+
real, intent(in), target :: a(:)
9+
end subroutine
10+
end module
11+
12+
program test
13+
use m
14+
real, target :: a(1)
15+
real :: b(1)
16+
call foo(a) ! ok
17+
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
18+
!CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
19+
!CHECK3: fatal-errors-warnings.f90:{{.*}} warning:
20+
call foo(b)
21+
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
22+
!CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
23+
!CHECK3-NOT: error:
24+
!CHECK3-NOT: warning:
25+
call foo((a))
26+
!CHECK1: fatal-errors-warnings.f90:{{.*}} warning:
27+
!CHECK2: fatal-errors-warnings.f90:{{.*}} warning:
28+
call foo(a([1]))
29+
!! Hard error instead of warning if uncommented.
30+
!call foo(a(1))
31+
end

0 commit comments

Comments
 (0)