From facfcadbbc6732591cf76f5b5777b13289f6166a Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Mon, 30 Dec 2024 09:39:08 -0800 Subject: [PATCH] [flang] Detect and report parsing failure The flang-new driver doesn't check for the case of the parser failing to consume the entire input file. This is of course never an ideal outcome, and usually signals a need to improve error recovery, but it is better for the compiler to admit failure rather than to silently proceed with compilation of what may well be an incomplete parse tree. --- flang/lib/Frontend/FrontendAction.cpp | 13 +++++++++++++ flang/lib/Frontend/FrontendActions.cpp | 8 +++++--- flang/test/Integration/debug-local-var-2.f90 | 2 +- flang/test/Parser/at-process.f | 4 +++- flang/test/Parser/unparseable.f90 | 5 +++++ 5 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 flang/test/Parser/unparseable.f90 diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp index 041182bdf6178..9a555bc7cd23b 100644 --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -232,6 +232,19 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) { instance->getAllCookedSources()); return true; } + if (instance->getParsing().parseTree().has_value() && + !instance->getParsing().consumedWholeFile()) { + // Parsing failed without error. + const unsigned diagID = instance->getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, message); + instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); + instance->getParsing().messages().Emit(llvm::errs(), + instance->getAllCookedSources()); + instance->getParsing().EmitMessage( + llvm::errs(), instance->getParsing().finalRestingPlace(), + "parser FAIL (final position)", "error: ", llvm::raw_ostream::RED); + return true; + } return false; } diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 77631f70dfd19..48029fe53299d 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -566,9 +566,11 @@ void DebugMeasureParseTreeAction::executeAction() { // Parse. In case of failure, report and return. ci.getParsing().Parse(llvm::outs()); - if (!ci.getParsing().messages().empty() && - (ci.getInvocation().getWarnAsErr() || - ci.getParsing().messages().AnyFatalError())) { + if ((ci.getParsing().parseTree().has_value() && + !ci.getParsing().consumedWholeFile()) || + (!ci.getParsing().messages().empty() && + (ci.getInvocation().getWarnAsErr() || + ci.getParsing().messages().AnyFatalError()))) { unsigned diagID = ci.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not parse %0"); ci.getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); diff --git a/flang/test/Integration/debug-local-var-2.f90 b/flang/test/Integration/debug-local-var-2.f90 index 5a675cbe1786d..fe4144a3dd46e 100644 --- a/flang/test/Integration/debug-local-var-2.f90 +++ b/flang/test/Integration/debug-local-var-2.f90 @@ -107,4 +107,4 @@ function fn2(a2, b2, c2) result (res2) end function end program -LINEONLY-NOT: DILocalVariable +! LINEONLY-NOT: DILocalVariable diff --git a/flang/test/Parser/at-process.f b/flang/test/Parser/at-process.f index 41b95044bfdc5..4f54c6b65638b 100644 --- a/flang/test/Parser/at-process.f +++ b/flang/test/Parser/at-process.f @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s ! Test ignoring @PROCESS directive in fixed source form @@ -18,3 +18,5 @@ subroutine f() !CHECK: Character in fixed-form label field must be a digit @precoss + +!CHECK: at-process.f:14:1: error: parser FAIL (final position) diff --git a/flang/test/Parser/unparseable.f90 b/flang/test/Parser/unparseable.f90 new file mode 100644 index 0000000000000..9e7a890b67a34 --- /dev/null +++ b/flang/test/Parser/unparseable.f90 @@ -0,0 +1,5 @@ +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s +! CHECK: unparseable.f90:5:1: error: parser FAIL (final position) +module m +end +select type (barf)