diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4362,6 +4362,8 @@ def test_io : Flag<["-"], "test-io">, Group, HelpText<"Run the InputOuputTest action. Use for development and testing only.">; +def fdebug_unparse_no_sema : Flag<["-"], "fdebug-unparse-no-sema">, Group, + HelpText<"Unparse and stop (skips the semantic checks)">; def fdebug_unparse : Flag<["-"], "fdebug-unparse">, Group, HelpText<"Unparse and stop.">; def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, Group, @@ -4370,6 +4372,8 @@ HelpText<"Dump symbols after the semantic analysis">; def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group, HelpText<"Dump the parse tree">; +def fdebug_dump_parse_tree_no_sema : Flag<["-"], "fdebug-dump-parse-tree-no-sema">, Group, + HelpText<"Dump the parse tree (skips the semantic checks)">; def fdebug_dump_provenance : Flag<["-"], "fdebug-dump-provenance">, Group, HelpText<"Dump provenance">; def fdebug_dump_parsing_log : Flag<["-"], "fdebug-dump-parsing-log">, Group, diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -62,6 +62,22 @@ void ExecuteAction() override; }; +//===----------------------------------------------------------------------===// +// PrescanAndParse Actions +//===----------------------------------------------------------------------===// +class PrescanAndParseAction : public FrontendAction { + void ExecuteAction() override = 0; + bool BeginSourceFileAction(CompilerInstance &ci) override; +}; + +class DebugUnparseNoSemaAction : public PrescanAndParseAction { + void ExecuteAction() override; +}; + +class DebugDumpParseTreeNoSemaAction : public PrescanAndParseAction { + void ExecuteAction() override; +}; + //===----------------------------------------------------------------------===// // PrescanAndSema Actions //===----------------------------------------------------------------------===// diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -37,6 +37,10 @@ /// Parse, unparse the parse-tree and output a Fortran source file DebugUnparse, + /// Parse, unparse the parse-tree and output a Fortran source file, skip the + /// semantic checks + DebugUnparseNoSema, + /// Parse, resolve the sybmols, unparse the parse-tree and then output a /// Fortran source file DebugUnparseWithSymbols, @@ -47,6 +51,10 @@ /// Parse, run semantics and then output the parse tree DebugDumpParseTree, + /// Parse, run semantics and then output the parse tree, skip the semantic + /// checks + DebugDumpParseTreeNoSema, + /// Dump provenance DebugDumpProvenance, diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -124,6 +124,9 @@ case clang::driver::options::OPT_fdebug_unparse: opts.programAction_ = DebugUnparse; break; + case clang::driver::options::OPT_fdebug_unparse_no_sema: + opts.programAction_ = DebugUnparseNoSema; + break; case clang::driver::options::OPT_fdebug_unparse_with_symbols: opts.programAction_ = DebugUnparseWithSymbols; break; @@ -133,6 +136,9 @@ case clang::driver::options::OPT_fdebug_dump_parse_tree: opts.programAction_ = DebugDumpParseTree; break; + case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema: + opts.programAction_ = DebugDumpParseTreeNoSema; + break; case clang::driver::options::OPT_fdebug_dump_provenance: opts.programAction_ = DebugDumpProvenance; break; diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -76,6 +76,57 @@ return true; } +bool PrescanAndParseAction::BeginSourceFileAction(CompilerInstance &c1) { + CompilerInstance &ci = this->instance(); + + std::string currentInputPath{GetCurrentFileOrBufferName()}; + + Fortran::parser::Options parserOptions = ci.invocation().fortranOpts(); + + if (ci.invocation().frontendOpts().fortranForm_ == FortranForm::Unknown) { + // Switch between fixed and free form format based on the input file + // extension. + // + // Ideally we should have all Fortran options set before entering this + // method (i.e. before processing any specific input files). However, we + // can't decide between fixed and free form based on the file extension + // earlier than this. + parserOptions.isFixedForm = currentInput().IsFixedForm(); + } + + // Prescan. In case of failure, report and return. + ci.parsing().Prescan(currentInputPath, parserOptions); + + if (ci.parsing().messages().AnyFatalError()) { + const unsigned diagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Could not scan %0"); + ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); + ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); + + return false; + } + + // Parse. In case of failure, report and return. + ci.parsing().Parse(llvm::outs()); + + if (ci.parsing().messages().AnyFatalError()) { + unsigned diagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Could not parse %0"); + ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); + + ci.parsing().messages().Emit( + llvm::errs(), this->instance().allCookedSources()); + return false; + } + + // Report the diagnostics from parsing + ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); + + auto &parseTree{*ci.parsing().parseTree()}; + + return true; +} + bool PrescanAndSemaAction::BeginSourceFileAction(CompilerInstance &c1) { CompilerInstance &ci = this->instance(); @@ -135,6 +186,7 @@ // Report the diagnostics from the semantic checks semantics.EmitMessages(ci.semaOutputStream()); + return true; } @@ -209,6 +261,19 @@ GetCurrentFileOrBufferName()); } +void DebugUnparseNoSemaAction::ExecuteAction() { + auto &parseTree{instance().parsing().parseTree()}; + + Fortran::parser::AnalyzedObjectsAsFortran asFortran = + Fortran::frontend::getBasicAsFortran(); + + // TODO: Options should come from CompilerInvocation + Unparse(llvm::outs(), *parseTree, + /*encoding=*/Fortran::parser::Encoding::UTF_8, + /*capitalizeKeywords=*/true, /*backslashEscapes=*/false, + /*preStatement=*/nullptr, &asFortran); +} + void DebugUnparseAction::ExecuteAction() { auto &parseTree{instance().parsing().parseTree()}; Fortran::parser::AnalyzedObjectsAsFortran asFortran = @@ -246,6 +311,15 @@ semantics, this->instance().diagnostics(), GetCurrentFileOrBufferName()); } +void DebugDumpParseTreeNoSemaAction::ExecuteAction() { + auto &parseTree{instance().parsing().parseTree()}; + Fortran::parser::AnalyzedObjectsAsFortran asFortran = + Fortran::frontend::getBasicAsFortran(); + + // Dump parse tree + Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran); +} + void DebugDumpParseTreeAction::ExecuteAction() { auto &parseTree{instance().parsing().parseTree()}; Fortran::parser::AnalyzedObjectsAsFortran asFortran = diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -40,6 +40,9 @@ case DebugUnparse: return std::make_unique(); break; + case DebugUnparseNoSema: + return std::make_unique(); + break; case DebugUnparseWithSymbols: return std::make_unique(); break; @@ -49,6 +52,9 @@ case DebugDumpParseTree: return std::make_unique(); break; + case DebugDumpParseTreeNoSema: + return std::make_unique(); + break; case DebugDumpProvenance: return std::make_unique(); break; diff --git a/flang/test/Parser/omp-allocate-unparse.f90 b/flang/test/Parser/omp-allocate-unparse.f90 --- a/flang/test/Parser/omp-allocate-unparse.f90 +++ b/flang/test/Parser/omp-allocate-unparse.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-no-semantics -funparse -fopenmp %s | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s ! Check Unparsing of OpenMP Allocate directive program allocate_unparse diff --git a/flang/test/Parser/omp-atomic-unparse.f90 b/flang/test/Parser/omp-atomic-unparse.f90 --- a/flang/test/Parser/omp-atomic-unparse.f90 +++ b/flang/test/Parser/omp-atomic-unparse.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-no-semantics -funparse -fopenmp %s | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s program main implicit none