awarzynski created this revision. Herald added subscribers: dang, mgorny. Herald added a reviewer: sscalpone. Herald added a reviewer: jansvoboda11. awarzynski requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This patch adds the following compiler frontend driver options: - -fdebug-unparse (f18 spelling: -funparse) - -fdebug-unparse-with-symbols (f18 spelling: -funparse-with-symbols) The new driver will only accept the new spelling. `f18` will accept both the original and the new spelling. A new base class for frontend actions is added: `PrescanAndSemaAction`. This is added to reduce code duplication that otherwise these new options would lead to. Implementation from - `ParseSyntaxOnlyAction::ExecutionAction` is moved to: - `PrescanAndSemaAction::BeginSourceFileAction` This implementation is now shared between: - PrescanAndSemaAction - ParseSyntaxOnlyAction - DebugUnparseAction - DebugUnparseWithSymbolsAction All tests that don't require other yet unimplemented options are updated. This way `flang-new -fc1` is used instead of `f18` when `FLANG_BUILD_NEW_DRIVER` is set to `On`. In order to facilitate this, `%flang_fc1` is added in the LIT configuration (lit.cfg.py). `asFortran` from f18.cpp is duplicated as `getBasicAsFortran` in FrontendOptions.cpp. At this stage it's hard to find a good place to share this method. I suggest that we revisit this once a switch from `f18` to `flang-new` is complete. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D96483 Files: clang/include/clang/Driver/Options.td flang/include/flang/Frontend/FrontendActions.h flang/include/flang/Frontend/FrontendOptions.h flang/lib/Frontend/CMakeLists.txt flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/lib/Frontend/FrontendOptions.cpp flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp flang/lib/Parser/CMakeLists.txt flang/test/Flang-Driver/driver-help.f90 flang/test/Parser/continuation-in-if.f flang/test/Parser/pp-dir-comments.f90 flang/test/Semantics/canondo01.f90 flang/test/Semantics/canondo02.f90 flang/test/Semantics/canondo03.f90 flang/test/Semantics/canondo04.f90 flang/test/Semantics/canondo05.f90 flang/test/Semantics/critical04.f90 flang/test/Semantics/defined-ops.f90 flang/test/Semantics/doconcurrent02.f90 flang/test/Semantics/doconcurrent03.f90 flang/test/Semantics/doconcurrent04.f90 flang/test/Semantics/doconcurrent07.f90 flang/test/Semantics/label02.f90 flang/test/Semantics/label03.f90 flang/test/Semantics/label04.f90 flang/test/Semantics/label05.f90 flang/test/Semantics/label06.f90 flang/test/Semantics/label07.f90 flang/test/Semantics/label08.f90 flang/test/Semantics/label09.f90 flang/test/Semantics/label10.f90 flang/test/Semantics/label12.f90 flang/test/Semantics/label13.f90 flang/test/Semantics/label15.f90 flang/test/lit.cfg.py flang/tools/f18/f18.cpp
Index: flang/tools/f18/f18.cpp =================================================================== --- flang/tools/f18/f18.cpp +++ flang/tools/f18/f18.cpp @@ -538,9 +538,10 @@ options.instrumentedParse = true; } else if (arg == "-fdebug-no-semantics") { driver.debugNoSemantics = true; - } else if (arg == "-funparse") { + } else if (arg == "-funparse" || arg == "-fdebug_unparse") { driver.dumpUnparse = true; - } else if (arg == "-funparse-with-symbols") { + } else if (arg == "-funparse-with-symbols" || + arg == "-fdebug-unparse-with-symbols") { driver.dumpUnparseWithSymbols = true; } else if (arg == "-funparse-typed-exprs-to-f18-fc") { driver.unparseTypedExprsToF18_FC = true; Index: flang/test/lit.cfg.py =================================================================== --- flang/test/lit.cfg.py +++ flang/test/lit.cfg.py @@ -79,6 +79,14 @@ extra_args=["-intrinsic-module-directory "+config.flang_intrinsic_modules_dir], unresolved='fatal')) +if config.include_flang_new_driver_test: + tools.append(ToolSubst('%flang_fc1', command=FindTool('flang-new'), + extra_args=['-fc1'], unresolved='fatal')) +else: + tools.append(ToolSubst('%flang_fc1', command=FindTool('f18'), + extra_args=["-intrinsic-module-directory "+config.flang_intrinsic_modules_dir], + unresolved='fatal')) + if config.flang_standalone_build: llvm_config.add_tool_substitutions(tools, [config.flang_llvm_tools_dir]) else: Index: flang/test/Semantics/label15.f90 =================================================================== --- flang/test/Semantics/label15.f90 +++ flang/test/Semantics/label15.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s !CHECK-NOT: error: module mm Index: flang/test/Semantics/label13.f90 =================================================================== --- flang/test/Semantics/label13.f90 +++ flang/test/Semantics/label13.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: branch into loop body from outside ! CHECK: the loop branched into Index: flang/test/Semantics/label12.f90 =================================================================== --- flang/test/Semantics/label12.f90 +++ flang/test/Semantics/label12.f90 @@ -1,4 +1,4 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: expected end of statement subroutine s Index: flang/test/Semantics/label10.f90 =================================================================== --- flang/test/Semantics/label10.f90 +++ flang/test/Semantics/label10.f90 @@ -1,4 +1,4 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: '60' not a FORMAT ! CHECK: data transfer use of '60' Index: flang/test/Semantics/label09.f90 =================================================================== --- flang/test/Semantics/label09.f90 +++ flang/test/Semantics/label09.f90 @@ -1,4 +1,4 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '60' was not found subroutine s(a) Index: flang/test/Semantics/label08.f90 =================================================================== --- flang/test/Semantics/label08.f90 +++ flang/test/Semantics/label08.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: CYCLE construct-name is not in scope ! CHECK: IF construct name unexpected ! CHECK: unnamed IF statement Index: flang/test/Semantics/label07.f90 =================================================================== --- flang/test/Semantics/label07.f90 +++ flang/test/Semantics/label07.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '30' is not a branch target ! CHECK: Control flow use of '30' ! CHECK: Label '10' is not in scope Index: flang/test/Semantics/label06.f90 =================================================================== --- flang/test/Semantics/label06.f90 +++ flang/test/Semantics/label06.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '10' is not in scope ! CHECK: Label '20' was not found ! CHECK: Label '30' is not a branch target Index: flang/test/Semantics/label05.f90 =================================================================== --- flang/test/Semantics/label05.f90 +++ flang/test/Semantics/label05.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '50' was not found ! CHECK: Label '55' is not in scope ! CHECK: Label '70' is not a branch target Index: flang/test/Semantics/label04.f90 =================================================================== --- flang/test/Semantics/label04.f90 +++ flang/test/Semantics/label04.f90 @@ -1,5 +1,5 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: branch into loop body from outside ! CHECK: do 10 i = 1, m ! CHECK: the loop branched into Index: flang/test/Semantics/label03.f90 =================================================================== --- flang/test/Semantics/label03.f90 +++ flang/test/Semantics/label03.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: DO loop doesn't properly nest ! CHECK: DO loop conflicts ! CHECK: Label '30' cannot be found Index: flang/test/Semantics/label02.f90 =================================================================== --- flang/test/Semantics/label02.f90 +++ flang/test/Semantics/label02.f90 @@ -1,5 +1,5 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Label '0' is out of range ! CHECK: Label '100000' is out of range ! CHECK: Label '123456' is out of range Index: flang/test/Semantics/doconcurrent07.f90 =================================================================== --- flang/test/Semantics/doconcurrent07.f90 +++ flang/test/Semantics/doconcurrent07.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: exit from DO CONCURRENT construct subroutine do_concurrent_test1(n) Index: flang/test/Semantics/doconcurrent04.f90 =================================================================== --- flang/test/Semantics/doconcurrent04.f90 +++ flang/test/Semantics/doconcurrent04.f90 @@ -1,5 +1,5 @@ ! C1122 The index-name shall be a named scalar variable of type integer. -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Must have INTEGER type, but is REAL(4) subroutine do_concurrent_test1(n) Index: flang/test/Semantics/doconcurrent03.f90 =================================================================== --- flang/test/Semantics/doconcurrent03.f90 +++ flang/test/Semantics/doconcurrent03.f90 @@ -1,4 +1,4 @@ -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: Control flow escapes from DO CONCURRENT ! CHECK: branch into loop body from outside ! CHECK: the loop branched into Index: flang/test/Semantics/doconcurrent02.f90 =================================================================== --- flang/test/Semantics/doconcurrent02.f90 +++ flang/test/Semantics/doconcurrent02.f90 @@ -1,6 +1,6 @@ ! when the loops are not DO CONCURRENT -! RUN: not %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: image control statement not allowed in DO CONCURRENT ! CHECK-NOT: RETURN not allowed in DO CONCURRENT ! CHECK-NOT: call to impure procedure in DO CONCURRENT not allowed Index: flang/test/Semantics/defined-ops.f90 =================================================================== --- flang/test/Semantics/defined-ops.f90 +++ flang/test/Semantics/defined-ops.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s ! Check the analyzed form of a defined operator or assignment. Index: flang/test/Semantics/critical04.f90 =================================================================== --- flang/test/Semantics/critical04.f90 +++ flang/test/Semantics/critical04.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: Control flow escapes from CRITICAL subroutine test1(a, i) Index: flang/test/Semantics/canondo05.f90 =================================================================== --- flang/test/Semantics/canondo05.f90 +++ flang/test/Semantics/canondo05.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! RUN: %f18 -fopenmp -funparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: do *[1-9] Index: flang/test/Semantics/canondo04.f90 =================================================================== --- flang/test/Semantics/canondo04.f90 +++ flang/test/Semantics/canondo04.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: do [1-9] ! Figure out how to also execute this test. Index: flang/test/Semantics/canondo03.f90 =================================================================== --- flang/test/Semantics/canondo03.f90 +++ flang/test/Semantics/canondo03.f90 @@ -1,5 +1,5 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: 10 continue ! CHECK: end do Index: flang/test/Semantics/canondo02.f90 =================================================================== --- flang/test/Semantics/canondo02.f90 +++ flang/test/Semantics/canondo02.f90 @@ -1,5 +1,5 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: end do SUBROUTINE sub00(a,b,n,m) Index: flang/test/Semantics/canondo01.f90 =================================================================== --- flang/test/Semantics/canondo01.f90 +++ flang/test/Semantics/canondo01.f90 @@ -1,5 +1,5 @@ -! RUN: %f18 -funparse-with-symbols %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK: end do SUBROUTINE sub00(a,b,n,m) Index: flang/test/Parser/pp-dir-comments.f90 =================================================================== --- flang/test/Parser/pp-dir-comments.f90 +++ flang/test/Parser/pp-dir-comments.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s #define pmk #ifdef pmk // comment Index: flang/test/Parser/continuation-in-if.f =================================================================== --- flang/test/Parser/continuation-in-if.f +++ flang/test/Parser/continuation-in-if.f @@ -1,4 +1,4 @@ -! RUN: %f18 -funparse %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s ! CHECK: CALL foo("N","N") #ifdef transpose call foo('T', Index: flang/test/Flang-Driver/driver-help.f90 =================================================================== --- flang/test/Flang-Driver/driver-help.f90 +++ flang/test/Flang-Driver/driver-help.f90 @@ -46,6 +46,9 @@ ! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted) ! HELP-FC1-NEXT: -emit-obj Emit native object files ! HELP-FC1-NEXT: -E Only run the preprocessor +! HELP-FC1-NEXT: -fdebug-unparse-with-symbols +! HELP-FC1-NEXT: Unparse and stop. +! HELP-FC1-NEXT: -fdebug-unparse Unparse and stop. ! HELP-FC1-NEXT: -ffixed-form Process source files in fixed form ! HELP-FC1-NEXT: -ffixed-line-length=<value> ! HELP-FC1-NEXT: Use <value> as character line width in fixed mode Index: flang/lib/Parser/CMakeLists.txt =================================================================== --- flang/lib/Parser/CMakeLists.txt +++ flang/lib/Parser/CMakeLists.txt @@ -1,4 +1,3 @@ - add_flang_library(FortranParser Fortran-parsers.cpp char-buffer.cpp Index: flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp =================================================================== --- flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -37,6 +37,12 @@ case EmitObj: return std::make_unique<EmitObjAction>(); break; + case DebugUnparse: + return std::make_unique<DebugUnparseAction>(); + break; + case DebugUnparseWithSymbols: + return std::make_unique<DebugUnparseWithSymbolsAction>(); + break; default: break; // TODO: Index: flang/lib/Frontend/FrontendOptions.cpp =================================================================== --- flang/lib/Frontend/FrontendOptions.cpp +++ flang/lib/Frontend/FrontendOptions.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Frontend/FrontendOptions.h" +#include "flang/Evaluate/expression.h" using namespace Fortran::frontend; @@ -25,6 +26,34 @@ suffix == "f08" || suffix == "F08" || suffix == "f18" || suffix == "F18"; } +// TODO: This is a copy of `asFortran` from f18.cpp and is added here for +// compatiblity. It doesn't really belong here, but I couldn't find a better +// place. We should decide whether to add it to the Evaluate or Parse/Unparse +// APIs or some dedicated utility library in the driver. +Fortran::parser::AnalyzedObjectsAsFortran +Fortran::frontend::getBasicAsFortran() { + return Fortran::parser::AnalyzedObjectsAsFortran{ + [](llvm::raw_ostream &o, const Fortran::evaluate::GenericExprWrapper &x) { + if (x.v) { + x.v->AsFortran(o); + } else { + o << "(bad expression)"; + } + }, + [](llvm::raw_ostream &o, + const Fortran::evaluate::GenericAssignmentWrapper &x) { + if (x.v) { + x.v->AsFortran(o); + } else { + o << "(bad assignment)"; + } + }, + [](llvm::raw_ostream &o, const Fortran::evaluate::ProcedureRef &x) { + x.AsFortran(o << "CALL "); + }, + }; +} + InputKind FrontendOptions::GetInputKindForExtension(llvm::StringRef extension) { if (isFixedFormSuffix(extension) || isFreeFormSuffix(extension)) { return Language::Fortran; Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -9,10 +9,13 @@ #include "flang/Frontend/FrontendActions.h" #include "flang/Common/default-kinds.h" #include "flang/Frontend/CompilerInstance.h" +#include "flang/Frontend/FrontendOptions.h" #include "flang/Parser/parsing.h" #include "flang/Parser/provenance.h" #include "flang/Parser/source.h" +#include "flang/Parser/unparse.h" #include "flang/Semantics/semantics.h" +#include "flang/Semantics/unparse-with-symbols.h" using namespace Fortran::frontend; @@ -49,6 +52,75 @@ return true; } +bool PrescanAndSemaAction::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()}; + + // Prepare semantics + Fortran::semantics::Semantics semantics{ci.invocation().semanticsContext(), + parseTree, ci.parsing().cooked().AsCharBlock()}; + + // Run semantic checks + semantics.Perform(); + + // Report the diagnostics from the semantic checks + semantics.EmitMessages(ci.semaOutputStream()); + + if (semantics.AnyFatalError()) { + unsigned DiagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Semantic errors in %0"); + ci.diagnostics().Report(DiagID) << GetCurrentFileOrBufferName(); + + return false; + } + + return true; +} + void InputOutputTestAction::ExecuteAction() { CompilerInstance &ci = instance(); @@ -111,42 +183,25 @@ } } -void ParseSyntaxOnlyAction::ExecuteAction() { - CompilerInstance &ci = this->instance(); - - // 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; - } +void ParseSyntaxOnlyAction::ExecuteAction() {} - // Report the diagnostics from parsing - ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); - - auto &parseTree{*ci.parsing().parseTree()}; +void DebugUnparseAction::ExecuteAction() { + auto &parseTree{instance().parsing().parseTree()}; + Fortran::parser::AnalyzedObjectsAsFortran asFortran = + Fortran::frontend::getBasicAsFortran(); - // Prepare semantics - Fortran::semantics::Semantics semantics{ci.invocation().semanticsContext(), - parseTree, ci.parsing().cooked().AsCharBlock()}; - - // Run semantic checks - semantics.Perform(); + // TODO: Options should come from CompilerInvocation + Unparse(llvm::outs(), *parseTree, + /*encoding=*/Fortran::parser::Encoding::UTF_8, + /*capitalizeKeywords=*/true, /*backslashEscapes=*/false, + /*preStatement=*/nullptr, &asFortran); +} - // Report the diagnostics from the semantic checks - semantics.EmitMessages(ci.semaOutputStream()); +void DebugUnparseWithSymbolsAction::ExecuteAction() { + auto &parseTree{*instance().parsing().parseTree()}; - if (semantics.AnyFatalError()) { - unsigned DiagID = ci.diagnostics().getCustomDiagID( - clang::DiagnosticsEngine::Error, "Semantic errors in %0"); - ci.diagnostics().Report(DiagID) << GetCurrentFileOrBufferName(); - } + Fortran::semantics::UnparseWithSymbols( + llvm::outs(), parseTree, /*encoding=*/Fortran::parser::Encoding::UTF_8); } void EmitObjAction::ExecuteAction() { Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -110,6 +110,12 @@ case clang::driver::options::OPT_emit_obj: opts.programAction_ = EmitObj; break; + case clang::driver::options::OPT_fdebug_unparse: + opts.programAction_ = DebugUnparse; + break; + case clang::driver::options::OPT_fdebug_unparse_with_symbols: + opts.programAction_ = DebugUnparseWithSymbols; + break; // TODO: // case calng::driver::options::OPT_emit_llvm: Index: flang/lib/Frontend/CMakeLists.txt =================================================================== --- flang/lib/Frontend/CMakeLists.txt +++ flang/lib/Frontend/CMakeLists.txt @@ -14,6 +14,7 @@ LINK_LIBS FortranParser FortranSemantics + FortranEvaluate FortranCommon clangBasic clangDriver Index: flang/include/flang/Frontend/FrontendOptions.h =================================================================== --- flang/include/flang/Frontend/FrontendOptions.h +++ flang/include/flang/Frontend/FrontendOptions.h @@ -9,6 +9,7 @@ #define LLVM_FLANG_FRONTEND_FRONTENDOPTIONS_H #include "flang/Common/Fortran-features.h" +#include "flang/Parser/unparse.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" @@ -32,6 +33,13 @@ /// Emit a .o file. EmitObj, + /// Parse, unparse the parse-tree and output a Fortran source file + DebugUnparse, + + /// Parse, resolve the sybmols, unparse the parse-tree and then output a + /// Fortran source file + DebugUnparseWithSymbols, + /// TODO: RunPreprocessor, EmitLLVM, EmitLLVMOnly, /// EmitCodeGenOnly, EmitAssembly, (...) }; @@ -40,6 +48,10 @@ /// \return True if the file extension should be processed as fixed form bool isFixedFormSuffix(llvm::StringRef suffix); +// TODO: Find a more suitable location for this. Added for compability with +// f18.cpp (this is equivalent to `asFortran` defined there). +Fortran::parser::AnalyzedObjectsAsFortran getBasicAsFortran(); + /// \param suffix The file extension /// \return True if the file extension should be processed as free form bool isFreeFormSuffix(llvm::StringRef suffix); Index: flang/include/flang/Frontend/FrontendActions.h =================================================================== --- flang/include/flang/Frontend/FrontendActions.h +++ flang/include/flang/Frontend/FrontendActions.h @@ -37,7 +37,23 @@ void ExecuteAction() override; }; -class ParseSyntaxOnlyAction : public PrescanAction { +//===----------------------------------------------------------------------===// +// PrescanAndSema Actions +//===----------------------------------------------------------------------===// +class PrescanAndSemaAction : public FrontendAction { + void ExecuteAction() override = 0; + bool BeginSourceFileAction(CompilerInstance &ci) override; +}; + +class DebugUnparseWithSymbolsAction : public PrescanAndSemaAction { + void ExecuteAction() override; +}; + +class DebugUnparseAction : public PrescanAndSemaAction { + void ExecuteAction() override; +}; + +class ParseSyntaxOnlyAction : public PrescanAndSemaAction { void ExecuteAction() override; }; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -4237,6 +4237,18 @@ } +//===----------------------------------------------------------------------===// +// FC1 Options +//===----------------------------------------------------------------------===// +let Flags = [FC1Option, FlangOnlyOption] in { + +def fdebug_unparse : Flag<["-"], "fdebug-unparse">, Group<Action_Group>, + HelpText<"Unparse and stop.">; +def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, Group<Action_Group>, + HelpText<"Unparse and stop.">; + +} + //===----------------------------------------------------------------------===// // CC1 Options //===----------------------------------------------------------------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits