[flang-commits] [flang] 2a7bb84 - [flang][driver] Add `-fno-analyzed-objects-for-unparse`

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Fri Jun 25 05:31:43 PDT 2021


Author: Andrzej Warzynski
Date: 2021-06-25T13:28:12+01:00
New Revision: 2a7bb8494e9c58b44ad7142d8d309455cd669603

URL: https://github.com/llvm/llvm-project/commit/2a7bb8494e9c58b44ad7142d8d309455cd669603
DIFF: https://github.com/llvm/llvm-project/commit/2a7bb8494e9c58b44ad7142d8d309455cd669603.diff

LOG: [flang][driver] Add `-fno-analyzed-objects-for-unparse`

This patch adds a new option for the new Flang driver:
`-fno-analyzed-objects-for-unparse`. The semantics are similar to
`-funparse-typed-exprs-to-f18-fc` from `f18`. For consistency, the
latter is replaced with `-fno-analyzed-objects-for-unparse`.

The new option controls the behaviour of the unparser (i.e. the action
corresponding to `-fdebug-unparse`). The default behaviour is to use the
analyzed objects when unparsing. The new flag can be used to turn this
off, so that the original parse-tree objects are used. The analyzed
objects are generated during the semantic checks [1].

This patch also updates the semantics of
`-fno-analyzed-objects-for-unparse`/`-funparse-typed-exprs-to-f18-fc`
in `f18`, so that this flag is always taken into account when `Unparse`
is used (this way the semantics in `f18` and `flang-new` are identical).

The added test file is based on example from Peter Steinfeld.

[1]
https://github.com/llvm/llvm-project/blob/main/flang/docs/Semantics.md

Differential Revision: https://reviews.llvm.org/D103612

Added: 
    flang/test/Driver/unparse-use-analyzed.f95

Modified: 
    clang/include/clang/Driver/Options.td
    flang/include/flang/Frontend/CompilerInvocation.h
    flang/lib/Frontend/CompilerInvocation.cpp
    flang/lib/Frontend/FrontendActions.cpp
    flang/lib/Frontend/FrontendOptions.cpp
    flang/test/Driver/driver-help.f90
    flang/tools/f18/f18.cpp
    flang/tools/f18/flang

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index cddc924dacd2e..0122afd2eeada 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4536,6 +4536,11 @@ def fget_symbols_sources : Flag<["-"], "fget-symbols-sources">, Group<Action_Gro
 
 def module_suffix : Separate<["-"], "module-suffix">,  Group<f_Group>, MetaVarName<"<suffix>">,
   HelpText<"Use <suffix> as the suffix for module files (the default value is `.mod`)">;
+def fanalyzed_objects_for_unparse : Flag<["-"],
+  "fanalyzed-objects-for-unparse">,  Group<f_Group>;
+def fno_analyzed_objects_for_unparse : Flag<["-"],
+  "fno-analyzed-objects-for-unparse">,  Group<f_Group>,
+  HelpText<"Do not use the analyzed objects when unparsing">;
 
 }
 

diff  --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index f449a69dfa8a0..ad25c39b48507 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -75,11 +75,39 @@ class CompilerInvocation : public CompilerInvocationBase {
 
   bool warnAsErr_ = false;
 
+  /// This flag controls the unparsing and is used to decide whether to print out
+  /// the semantically analyzed version of an object or expression or the plain
+  /// version that does not include any information from semantic analysis.
+  bool useAnalyzedObjectsForUnparse_ = true;
+
   // Fortran Dialect options
   Fortran::common::IntrinsicTypeDefaultKinds defaultKinds_;
 
   bool EnableConformanceChecks_ = false;
 
+  /// Used in e.g. unparsing to dump the analyzed rather than the original
+  /// parse-tree objects.
+  Fortran::parser::AnalyzedObjectsAsFortran AsFortran_{
+      [](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 ");
+      },
+  };
+
 public:
   CompilerInvocation() = default;
 
@@ -108,11 +136,21 @@ class CompilerInvocation : public CompilerInvocationBase {
   bool &warnAsErr() { return warnAsErr_; }
   const bool &warnAsErr() const { return warnAsErr_; }
 
+  bool &useAnalyzedObjectsForUnparse() { return useAnalyzedObjectsForUnparse_; }
+  const bool &useAnalyzedObjectsForUnparse() const {
+    return useAnalyzedObjectsForUnparse_;
+  }
+
   bool &enableConformanceChecks() { return EnableConformanceChecks_; }
   const bool &enableConformanceChecks() const {
     return EnableConformanceChecks_;
   }
 
+  Fortran::parser::AnalyzedObjectsAsFortran &asFortran() { return AsFortran_; }
+  const Fortran::parser::AnalyzedObjectsAsFortran &asFortran() const {
+    return AsFortran_;
+  }
+
   Fortran::common::IntrinsicTypeDefaultKinds &defaultKinds() {
     return defaultKinds_;
   }
@@ -142,6 +180,10 @@ class CompilerInvocation : public CompilerInvocationBase {
 
   void SetWarnAsErr(bool flag) { warnAsErr_ = flag; }
 
+  void SetUseAnalyzedObjectsForUnparse(bool flag) {
+    useAnalyzedObjectsForUnparse_ = flag;
+  }
+
   /// Set the Fortran options to predifined defaults. These defaults are
   /// consistend with f18/f18.cpp.
   // TODO: We should map frontendOpts_ to parserOpts_ instead. For that, we

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index dc771ecbc9a8f..6a2bf1947e350 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -404,6 +404,12 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     res.SetModuleFileSuffix(moduleSuffix->getValue());
   }
 
+  // -fno-analyzed-objects-for-unparse
+  if (args.hasArg(
+          clang::driver::options::OPT_fno_analyzed_objects_for_unparse)) {
+    res.SetUseAnalyzedObjectsForUnparse(false);
+  }
+
   return diags.getNumErrors() == numErrorsBefore;
 }
 

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index d3cce62681cc0..8ee42d73c6e46 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -242,28 +242,27 @@ void ParseSyntaxOnlyAction::ExecuteAction() {
 }
 
 void DebugUnparseNoSemaAction::ExecuteAction() {
+  auto &invoc = this->instance().invocation();
   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);
+      /*preStatement=*/nullptr,
+      invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr);
 }
 
 void DebugUnparseAction::ExecuteAction() {
+  auto &invoc = this->instance().invocation();
   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);
+      /*preStatement=*/nullptr,
+      invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr);
 
   // Report fatal semantic errors
   reportFatalSemanticErrors(semantics(), this->instance().diagnostics(),
@@ -310,12 +309,11 @@ void DebugDumpAllAction::ExecuteAction() {
 
   // Dump parse tree
   auto &parseTree{instance().parsing().parseTree()};
-  Fortran::parser::AnalyzedObjectsAsFortran asFortran =
-      Fortran::frontend::getBasicAsFortran();
   llvm::outs() << "========================";
   llvm::outs() << " Flang: parse tree dump ";
   llvm::outs() << "========================\n";
-  Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran);
+  Fortran::parser::DumpTree(
+      llvm::outs(), parseTree, &ci.invocation().asFortran());
 
   auto &semantics = this->semantics();
   auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables(
@@ -343,20 +341,19 @@ void DebugDumpAllAction::ExecuteAction() {
 
 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);
+  Fortran::parser::DumpTree(
+      llvm::outs(), parseTree, &this->instance().invocation().asFortran());
 }
 
 void DebugDumpParseTreeAction::ExecuteAction() {
   auto &parseTree{instance().parsing().parseTree()};
-  Fortran::parser::AnalyzedObjectsAsFortran asFortran =
-      Fortran::frontend::getBasicAsFortran();
 
   // Dump parse tree
-  Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran);
+  Fortran::parser::DumpTree(
+      llvm::outs(), parseTree, &this->instance().invocation().asFortran());
+
   // Report fatal semantic errors
   reportFatalSemanticErrors(semantics(), this->instance().diagnostics(),
       GetCurrentFileOrBufferName());

diff  --git a/flang/lib/Frontend/FrontendOptions.cpp b/flang/lib/Frontend/FrontendOptions.cpp
index 94fff8799177a..dcad975284ad9 100644
--- a/flang/lib/Frontend/FrontendOptions.cpp
+++ b/flang/lib/Frontend/FrontendOptions.cpp
@@ -32,34 +32,6 @@ bool Fortran::frontend::mustBePreprocessed(llvm::StringRef suffix) {
       suffix == "F03" || suffix == "F08" || 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;

diff  --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 9fa35d28af3d7..db672364a2b6c 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -101,6 +101,8 @@
 ! HELP-FC1-NEXT:                        Specify where to find the compiled intrinsic modules
 ! HELP-FC1-NEXT: -flarge-sizes          Use INTEGER(KIND=8) for the result type in size-related intrinsics
 ! HELP-FC1-NEXT: -flogical-abbreviations Enable logical abbreviations
+! HELP-FC1-NEXT: -fno-analyzed-objects-for-unparse
+! HELP-FC1-NEXT:                        Do not use the analyzed objects when unparsing
 ! HELP-FC1-NEXT: -fopenacc              Enable OpenACC
 ! HELP-FC1-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
 ! HELP-FC1-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.

diff  --git a/flang/test/Driver/unparse-use-analyzed.f95 b/flang/test/Driver/unparse-use-analyzed.f95
new file mode 100644
index 0000000000000..08410077a2b82
--- /dev/null
+++ b/flang/test/Driver/unparse-use-analyzed.f95
@@ -0,0 +1,31 @@
+! Tests `-fno-analyzed-exprs-as-fortran` frontend option
+
+!--------------------------
+! RUN lines
+!--------------------------
+! RUN: %flang_fc1 -fdebug-unparse  %s | FileCheck %s --check-prefix=DEFAULT
+! RUN: %flang_fc1 -fdebug-unparse -fno-analyzed-objects-for-unparse %s | FileCheck %s --check-prefix=DISABLED
+
+!------------------------------------------------
+! EXPECTED OUTPUT: default - use analyzed objects
+!------------------------------------------------
+! DEFAULT: PROGRAM test
+! DEFAULT-NEXT:  REAL, PARAMETER :: val = 3.43e2_4
+! DEFAULT-NEXT:  PRINT *, 3.47e2_4
+! DEFAULT-NEXT: END PROGRAM
+
+!-----------------------------------------------------------
+! EXPECTED OUTPUT: disabled - don't use the analyzed objects
+!-----------------------------------------------------------
+! DISABLED: PROGRAM test
+! DISABLED-NEXT:  REAL, PARAMETER :: val = 343.0
+! DISABLED-NEXT:  PRINT *, val+4
+! DISABLED-NEXT: END PROGRAM
+
+!--------------------------
+! INPUT
+!--------------------------
+program test
+  real, parameter :: val = 343.0
+  print *, val + 4
+end program

diff  --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
index 9e414958ee783..71f7673c84075 100644
--- a/flang/tools/f18/f18.cpp
+++ b/flang/tools/f18/f18.cpp
@@ -105,7 +105,7 @@ struct DriverOptions {
   bool debugModuleWriter{false};
   bool defaultReal8{false};
   bool measureTree{false};
-  bool unparseTypedExprsToF18_FC{false};
+  bool useAnalyzedObjectsForUnparse{true};
   std::vector<std::string> F18_FCArgs;
   const char *prefix{nullptr};
   bool getDefinition{false};
@@ -322,7 +322,8 @@ std::string CompileFortran(std::string path, Fortran::parser::Options options,
     Unparse(llvm::outs(), parseTree, driver.encoding, true /*capitalize*/,
         options.features.IsEnabled(
             Fortran::common::LanguageFeature::BackslashEscapes),
-        nullptr /* action before each statement */, &asFortran);
+        nullptr /* action before each statement */,
+        driver.useAnalyzedObjectsForUnparse ? &asFortran : nullptr);
     return {};
   }
   if (driver.dumpPreFirTree) {
@@ -353,7 +354,7 @@ std::string CompileFortran(std::string path, Fortran::parser::Options options,
         options.features.IsEnabled(
             Fortran::common::LanguageFeature::BackslashEscapes),
         nullptr /* action before each statement */,
-        driver.unparseTypedExprsToF18_FC ? &asFortran : nullptr);
+        driver.useAnalyzedObjectsForUnparse ? &asFortran : nullptr);
   }
 
   RunOtherCompiler(driver, tmpSourcePath.data(), relo.data());
@@ -578,8 +579,8 @@ int main(int argc, char *const argv[]) {
     } 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;
+    } else if (arg == "-fno-analyzed-objects-for-unparse") {
+      driver.useAnalyzedObjectsForUnparse = false;
     } else if (arg == "-fparse-only" || arg == "-fsyntax-only") {
       driver.syntaxOnly = true;
     } else if (arg == "-c") {

diff  --git a/flang/tools/f18/flang b/flang/tools/f18/flang
index 81fac7b283459..846be4a18fdd8 100644
--- a/flang/tools/f18/flang
+++ b/flang/tools/f18/flang
@@ -8,7 +8,7 @@
 #===------------------------------------------------------------------------===#
 
 wd=$(cd $(dirname "$0")/.. && pwd)
-opts="-module-suffix .f18.mod "
+opts="-fno-analyzed-objects-for-unparse -module-suffix .f18.mod "
 if ! $wd/bin/f18 $opts "$@"
 then status=$?
      echo flang: in $PWD, f18 failed with exit status $status: $wd/bin/f18 $opts "$@" >&2


        


More information about the flang-commits mailing list