-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[flang][driver] add -Wfatal-errors #147614
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
Conversation
clang-format simplify semantics remove line numbers from test fix error in semantics add newline to end of tests fix another error in semantics
|
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-driver Author: Andre Kuhlenschmidt (akuhlens) ChangesAdds the flag Full diff: https://github.com/llvm/llvm-project/pull/147614.diff 9 Files Affected:
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index 06978029435b7..d294955af780e 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -102,8 +102,6 @@ class CompilerInvocation : public CompilerInvocationBase {
bool debugModuleDir = false;
bool hermeticModuleFileOutput = false;
- bool warnAsErr = false;
-
// Executable name
const char *argv0;
@@ -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;
@@ -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; }
@@ -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) {
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 7371a46ad36ce..723180f63955c 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -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;
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index 730513dbe3232..3100aca353d81 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -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;
@@ -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
@@ -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);
@@ -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 {
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index e5c6b1d5c61ad..a92afeec170a2 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -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");
@@ -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);
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 5d788fe5619a2..2429e07e5b8c4 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -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);
}
@@ -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() &&
@@ -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);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index f2237da3857a2..dd329458ea6e6 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -452,8 +452,8 @@ 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);
@@ -461,6 +461,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
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
@@ -468,6 +469,14 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
}
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;
+ }
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index ed41c6fb16892..ab78605d01f4c 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -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) {
diff --git a/flang/test/Driver/fatal-errors-parsing.f90 b/flang/test/Driver/fatal-errors-parsing.f90
new file mode 100644
index 0000000000000..185a6e08481d7
--- /dev/null
+++ b/flang/test/Driver/fatal-errors-parsing.f90
@@ -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
diff --git a/flang/test/Driver/fatal-errors-semantics.f90 b/flang/test/Driver/fatal-errors-semantics.f90
new file mode 100644
index 0000000000000..54740dd6deec0
--- /dev/null
+++ b/flang/test/Driver/fatal-errors-semantics.f90
@@ -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
+
\ No newline at end of file
|
|
@llvm/pr-subscribers-flang-semantics Author: Andre Kuhlenschmidt (akuhlens) ChangesAdds the flag Full diff: https://github.com/llvm/llvm-project/pull/147614.diff 9 Files Affected:
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index 06978029435b7..d294955af780e 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -102,8 +102,6 @@ class CompilerInvocation : public CompilerInvocationBase {
bool debugModuleDir = false;
bool hermeticModuleFileOutput = false;
- bool warnAsErr = false;
-
// Executable name
const char *argv0;
@@ -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;
@@ -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; }
@@ -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) {
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 7371a46ad36ce..723180f63955c 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -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;
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index 730513dbe3232..3100aca353d81 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -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;
@@ -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
@@ -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);
@@ -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 {
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index e5c6b1d5c61ad..a92afeec170a2 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -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");
@@ -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);
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 5d788fe5619a2..2429e07e5b8c4 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -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);
}
@@ -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() &&
@@ -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);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index f2237da3857a2..dd329458ea6e6 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -452,8 +452,8 @@ 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);
@@ -461,6 +461,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
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
@@ -468,6 +469,14 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
}
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;
+ }
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index ed41c6fb16892..ab78605d01f4c 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -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) {
diff --git a/flang/test/Driver/fatal-errors-parsing.f90 b/flang/test/Driver/fatal-errors-parsing.f90
new file mode 100644
index 0000000000000..185a6e08481d7
--- /dev/null
+++ b/flang/test/Driver/fatal-errors-parsing.f90
@@ -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
diff --git a/flang/test/Driver/fatal-errors-semantics.f90 b/flang/test/Driver/fatal-errors-semantics.f90
new file mode 100644
index 0000000000000..54740dd6deec0
--- /dev/null
+++ b/flang/test/Driver/fatal-errors-semantics.f90
@@ -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
+
\ No newline at end of file
|
Adds the flag
-Wfatal-errorswhich truncates the error messages at 1 error.