Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 6 additions & 2 deletions flang/include/flang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ class CompilerInvocation : public CompilerInvocationBase {
bool debugModuleDir = false;
bool hermeticModuleFileOutput = false;

bool warnAsErr = false;

// Executable name
const char *argv0;

Expand All @@ -116,6 +114,9 @@ class CompilerInvocation : public CompilerInvocationBase {
// Fortran Dialect options
Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;

// Fortran Error options
size_t maxErrors = 0;
bool warnAsErr = false;
// Fortran Warning options
bool enableConformanceChecks = false;
bool enableUsageChecks = false;
Expand Down Expand Up @@ -189,6 +190,8 @@ class CompilerInvocation : public CompilerInvocationBase {
const bool &getHermeticModuleFileOutput() const {
return hermeticModuleFileOutput;
}
size_t &getMaxErrors() { return maxErrors; }
const size_t &getMaxErrors() const { return maxErrors; }

bool &getWarnAsErr() { return warnAsErr; }
const bool &getWarnAsErr() const { return warnAsErr; }
Expand Down Expand Up @@ -261,6 +264,7 @@ class CompilerInvocation : public CompilerInvocationBase {
hermeticModuleFileOutput = flag;
}

void setMaxErrors(size_t maxErrors) { this->maxErrors = maxErrors; }
void setWarnAsErr(bool flag) { warnAsErr = flag; }

void setUseAnalyzedObjectsForUnparse(bool flag) {
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Parser/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ class Messages {
void ResolveProvenances(const AllCookedSources &);
void Emit(llvm::raw_ostream &, const AllCookedSources &,
bool echoSourceLines = true,
const common::LanguageFeatureControl *hintFlags = nullptr) const;
const common::LanguageFeatureControl *hintFlags = nullptr,
size_t maxErrorsToEmit = 0) const;
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
bool AnyFatalError() const;

Expand Down
9 changes: 9 additions & 0 deletions flang/include/flang/Semantics/semantics.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ class SemanticsContext {
warnOnNonstandardUsage_ = x;
return *this;
}
SemanticsContext &set_maxErrors(size_t x) {
maxErrors_ = x;
return *this;
}
SemanticsContext &set_warningsAreErrors(bool x) {
warningsAreErrors_ = x;
return *this;
Expand All @@ -167,6 +171,8 @@ class SemanticsContext {
const DeclTypeSpec &MakeNumericType(TypeCategory, int kind = 0);
const DeclTypeSpec &MakeLogicalType(int kind = 0);

size_t maxErrors() const { return maxErrors_; }

bool AnyFatalError() const;

// Test or set the Error flag on a Symbol
Expand Down Expand Up @@ -213,6 +219,8 @@ class SemanticsContext {
return Warn(warning, *location_, std::forward<A>(args)...);
}

void EmitMessages(llvm::raw_ostream &);

const Scope &FindScope(parser::CharBlock) const;
Scope &FindScope(parser::CharBlock);
void UpdateScopeIndex(Scope &, parser::CharBlock);
Expand Down Expand Up @@ -322,6 +330,7 @@ class SemanticsContext {
Scope *currentHermeticModuleFileScope_{nullptr};
ScopeIndex scopeIndex_;
parser::Messages messages_;
size_t maxErrors_{0};
evaluate::FoldingContext foldingContext_;
ConstructStack constructStack_;
struct IndexVarInfo {
Expand Down
6 changes: 5 additions & 1 deletion flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,10 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
for (const auto &wArg : wArgs) {
if (wArg == "error") {
res.setWarnAsErr(true);
// -W(no-)<feature>
// -Wfatal-errors
} else if (wArg == "fatal-errors") {
res.setMaxErrors(1);
// -W[no-]<feature>
} else if (!features.EnableWarning(wArg)) {
const unsigned diagID = diags.getCustomDiagID(
clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
Expand Down Expand Up @@ -1775,6 +1778,7 @@ CompilerInvocation::getSemanticsCtx(
semanticsContext->set_moduleDirectory(getModuleDir())
.set_searchDirectories(fortranOptions.searchDirectories)
.set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
.set_maxErrors(getMaxErrors())
.set_warningsAreErrors(getWarnAsErr())
.set_moduleFileSuffix(getModuleFileSuffix())
.set_underscoring(getCodeGenOpts().Underscoring);
Expand Down
14 changes: 8 additions & 6 deletions flang/lib/Frontend/FrontendAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ bool FrontendAction::runParse(bool emitMessages) {
// combining them with messages from semantics.
const common::LanguageFeatureControl &features{
ci.getInvocation().getFortranOpts().features};
// Default maxErrors here because none are fatal.
ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources(),
/*echoSourceLine=*/true, &features);
}
Expand Down Expand Up @@ -228,15 +229,16 @@ template <unsigned N>
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 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);
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
/*echoSourceLines=*/true, &features, maxErrors);
return true;
}
if (instance->getParsing().parseTree().has_value() &&
Expand All @@ -245,9 +247,9 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
const unsigned diagID = instance->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(llvm::errs(),
instance->getAllCookedSources(),
/*echoSourceLine=*/true, &features);
instance->getParsing().messages().Emit(
llvm::errs(), instance->getAllCookedSources(),
/*echoSourceLine=*/true, &features, maxErrors);
instance->getParsing().EmitMessage(
llvm::errs(), instance->getParsing().finalRestingPlace(),
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
Expand Down
13 changes: 11 additions & 2 deletions flang/lib/Parser/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,22 +452,31 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) {
}

void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
bool echoSourceLines,
const common::LanguageFeatureControl *hintFlagPtr) const {
bool echoSourceLines, const common::LanguageFeatureControl *hintFlagPtr,
size_t maxErrorsToEmit) const {
std::vector<const Message *> sorted;
for (const auto &msg : messages_) {
sorted.push_back(&msg);
}
std::stable_sort(sorted.begin(), sorted.end(),
[](const Message *x, const Message *y) { return x->SortBefore(*y); });
const Message *lastMsg{nullptr};
size_t errorsEmitted{0};
for (const Message *msg : sorted) {
if (lastMsg && *msg == *lastMsg) {
// Don't emit two identical messages for the same location
continue;
}
msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
lastMsg = msg;
if (msg->IsFatal()) {
++errorsEmitted;
}
// If maxErrorsToEmit is 0, emit all errors, otherwise break after
// maxErrorsToEmit.
if (maxErrorsToEmit > 0 && errorsEmitted >= maxErrorsToEmit) {
break;
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Semantics/semantics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,10 @@ bool Semantics::Perform() {
void Semantics::EmitMessages(llvm::raw_ostream &os) {
// Resolve the CharBlock locations of the Messages to ProvenanceRanges
// so messages from parsing and semantics are intermixed in source order.
const common::LanguageFeatureControl &features{context_.languageFeatures()};
context_.messages().ResolveProvenances(context_.allCookedSources());
context_.messages().Emit(
os, context_.allCookedSources(), /*echoSourceLine=*/true, &features);
context_.messages().Emit(os, context_.allCookedSources(),
/*echoSourceLine=*/true, &context_.languageFeatures(),
/*maxErrorsToEmit=*/context_.maxErrors());
}

void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
Expand Down
16 changes: 16 additions & 0 deletions flang/test/Driver/fatal-errors-parsing.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
!RUN: not %flang_fc1 -fsyntax-only -Wfatal-errors %s 2>&1 | FileCheck %s --check-prefix=CHECK1
!RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK2

program p
contains
! CHECK1: fatal-errors-parsing.f90:{{.*}} error:
! CHECK2: fatal-errors-parsing.f90:{{.*}} error:
continue
end

subroutine s
contains
! CHECK1-NOT: error:
! CHECK2: fatal-errors-parsing.f90:{{.*}} error:
continue
end
40 changes: 40 additions & 0 deletions flang/test/Driver/fatal-errors-semantics.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
! RUN: not %flang_fc1 %s 2>&1 | FileCheck %s --check-prefix=CHECK1
! RUN: not %flang_fc1 -Wfatal-errors %s 2>&1 | FileCheck %s --check-prefix=CHECK2

module m
contains
subroutine s0(p)
real, pointer, intent(in) :: p
end
subroutine s1(p)
real, pointer, intent(in) :: p(:)
end
subroutine sa(p)
real, pointer, intent(in) :: p(..)
end
subroutine sao(p)
real, intent(in), optional, pointer :: p(..)
end
subroutine soa(a)
real, intent(in), optional, allocatable :: a(..)
end
subroutine test
real, pointer :: a0, a1(:)
!CHECK1: fatal-errors-semantics.f90:{{.*}} error:
!CHECK2: fatal-errors-semantics.f90:{{.*}} error:
call s0(null(a1))
!CHECK1: fatal-errors-semantics.f90:{{.*}} error:
!CHECK2-NOT: error:
call s1(null(a0))
!CHECK1: fatal-errors-semantics.f90:{{.*}} error:
!CHECK2-NOT: error:
call sa(null())
!CHECK1: fatal-errors-semantics.f90:{{.*}} error:
!CHECK2-NOT: error:
call sao(null())
!CHECK1: fatal-errors-semantics.f90:{{.*}} error:
!CHECK2-NOT: error:
call soa(null())
end
end

Loading