awarzynski created this revision.
Herald added a reviewer: sscalpone.
Herald added subscribers: jansvoboda11, dang.
awarzynski requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added subscribers: cfe-commits, sstefan1.
Herald added a project: clang.

This patch adds two debugging options in the new Flang driver
(`flang-new`):

- `-fdebug-unparse-no-sema`
- `-fdebug-dump-parse-tree-no-sema`

Each of these options combines two options from the "throwaway"
driver (left: `f18`, right: `flang-new`):

- `-fdebug-uparse -fdebug-no-semantics` --> `-fdebug-unparse-no-sema`
- `-fdebug-dump-parse-tree -fdebug-no-semantics` --> 
`-fdebug-dump-parse-tree-no-sema`

There are no plans to implement `-fdebug-no-semantics` in the new
driver. Such option is deemed too powerful. Also, it only makes sense
when combined with specific frontend actions (`-fdebug-unparse` and
`-fdebug-dump-parse-tree`). Instead,

- dedicated `FrontendAction`s (available in the new driver), and
- specialised action options

feel like a much safer and future-proof approach.

In terms of the implementation, new actions are introduced via a new
abstract frontend action: `PrescanAndParseAction`. This action will only

- run the prescanner and the parser.

Until now, we've only had actions that would:

- only run the prescanner (`PrescanAction`)
- run the prescanner, parser and do the semantic checks (`PrescanAndSemaAction`)

New actions require finer granularity, hence the new abstract class.
Apart from the semantic checks removed at the end, the implementation of
`PrescanAndParseAction::BeginSourceFileAction` is similar to
`PrescanAndSemaAction::BeginSourceFileAction`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99645

Files:
  clang/include/clang/Driver/Options.td
  flang/include/flang/Frontend/FrontendActions.h
  flang/include/flang/Frontend/FrontendOptions.h
  flang/lib/Frontend/CompilerInvocation.cpp
  flang/lib/Frontend/FrontendActions.cpp
  flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  flang/test/Parser/omp-allocate-unparse.f90
  flang/test/Parser/omp-atomic-unparse.f90

Index: flang/test/Parser/omp-atomic-unparse.f90
===================================================================
--- flang/test/Parser/omp-atomic-unparse.f90
+++ 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
Index: flang/test/Parser/omp-allocate-unparse.f90
===================================================================
--- flang/test/Parser/omp-allocate-unparse.f90
+++ 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
Index: flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -40,6 +40,9 @@
   case DebugUnparse:
     return std::make_unique<DebugUnparseAction>();
     break;
+  case DebugUnparseNoSema:
+    return std::make_unique<DebugUnparseNoSemaAction>();
+    break;
   case DebugUnparseWithSymbols:
     return std::make_unique<DebugUnparseWithSymbolsAction>();
     break;
@@ -49,6 +52,9 @@
   case DebugDumpParseTree:
     return std::make_unique<DebugDumpParseTreeAction>();
     break;
+  case DebugDumpParseTreeNoSema:
+    return std::make_unique<DebugDumpParseTreeNoSemaAction>();
+    break;
   case DebugDumpProvenance:
     return std::make_unique<DebugDumpProvenanceAction>();
     break;
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ 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 =
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ 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;
Index: flang/include/flang/Frontend/FrontendOptions.h
===================================================================
--- flang/include/flang/Frontend/FrontendOptions.h
+++ 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,
 
Index: flang/include/flang/Frontend/FrontendActions.h
===================================================================
--- flang/include/flang/Frontend/FrontendActions.h
+++ 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
 //===----------------------------------------------------------------------===//
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -4362,6 +4362,8 @@
 
 def test_io : Flag<["-"], "test-io">, Group<Action_Group>,
   HelpText<"Run the InputOuputTest action. Use for development and testing only.">;
+def fdebug_unparse_no_sema : Flag<["-"], "fdebug-unparse-no-sema">, Group<Action_Group>,
+  HelpText<"Unparse and stop (skips the semantic checks)">;
 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>,
@@ -4370,6 +4372,8 @@
   HelpText<"Dump symbols after the semantic analysis">;
 def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group<Action_Group>,
   HelpText<"Dump the parse tree">;
+def fdebug_dump_parse_tree_no_sema : Flag<["-"], "fdebug-dump-parse-tree-no-sema">, Group<Action_Group>,
+  HelpText<"Dump the parse tree (skips the semantic checks)">;
 def fdebug_dump_provenance : Flag<["-"], "fdebug-dump-provenance">, Group<Action_Group>,
   HelpText<"Dump provenance">;
 def fdebug_dump_parsing_log : Flag<["-"], "fdebug-dump-parsing-log">, Group<Action_Group>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to