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 @@ -4521,6 +4521,10 @@ def fget_symbols_sources : Flag<["-"], "fget-symbols-sources">, Group, HelpText<"Dump symbols and their source code locations">; +def fno_unparse_typed_exprs : Flag<["-"], + "fno-unparse-typed-exprs">, Group, + HelpText<"Don't unparse typed expressions">; + } //===----------------------------------------------------------------------===// diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h --- a/flang/include/flang/Frontend/CompilerInvocation.h +++ b/flang/include/flang/Frontend/CompilerInvocation.h @@ -73,11 +73,34 @@ bool warnAsErr_ = false; + bool unparseTypedExprs_ = true; + // Fortran Dialect options Fortran::common::IntrinsicTypeDefaultKinds defaultKinds_; bool EnableConformanceChecks_ = false; + 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; @@ -103,11 +126,19 @@ bool &warnAsErr() { return warnAsErr_; } const bool &warnAsErr() const { return warnAsErr_; } + bool &unparseTypedExprs() { return unparseTypedExprs_; } + const bool &unaprseTypedExprsAsFortran() const { return unparseTypedExprs_; } + 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_; } @@ -133,6 +164,8 @@ void SetWarnAsErr(bool flag) { warnAsErr_ = flag; } + void SetUnparseTypedExprs(bool flag) { unparseTypedExprs_ = 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 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -392,6 +392,11 @@ res.SetDebugModuleDir(true); } + // -fno-unparse-typed-exprs + if (args.hasArg(clang::driver::options::OPT_fno_unparse_typed_exprs)) { + res.SetUnparseTypedExprs(false); + } + return diags.getNumErrors() == numErrorsBefore; } 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 @@ -242,28 +242,27 @@ } 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.unparseTypedExprs() ? &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.unparseTypedExprs() ? &invoc.asFortran() : nullptr); // Report fatal semantic errors reportFatalSemanticErrors(semantics(), this->instance().diagnostics(), @@ -307,20 +306,19 @@ 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 --- a/flang/lib/Frontend/FrontendOptions.cpp +++ b/flang/lib/Frontend/FrontendOptions.cpp @@ -32,34 +32,6 @@ 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/unparse-typed-exprs.f95 b/flang/test/Driver/unparse-typed-exprs.f95 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/unparse-typed-exprs.f95 @@ -0,0 +1,34 @@ +! Tests `-fno-unparse-typed-exprs-to-f18-fc` frontend option + +!-------------------------- +! RUN lines +!-------------------------- +! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s --check-prefix=UNPARSED_TYPED_EXPR +! RUN: %flang_fc1 -fdebug-unparse -fno-unparse-typed-exprs %s | FileCheck %s --check-prefix=AS_FORTRAN + +!-------------------------- +! EXPECTED OUTPUT: default +!-------------------------- +! UNPARSED_TYPED_EXPR: PROGRAM test_allocated +! UNPARSED_TYPED_EXPR-NEXT: INTEGER :: i = 4_4 +! UNPARSED_TYPED_EXPR-NEXT: REAL(KIND=4_4), ALLOCATABLE :: x(:) +! UNPARSED_TYPED_EXPR-NEXT: IF (.NOT.allocated(x)) ALLOCATE(x(i)) +! UNPARSED_TYPED_EXPR-NEXT: END PROGRAM test_allocated + +!------------------------------------- +! EXPECTED OUTPUT: unparsed as Fortran +!-------------------------------------- +! AS_FORTRAN: PROGRAM test_allocated +! AS_FORTRAN-NEXT: INTEGER :: i = 4 +! AS_FORTRAN-NEXT: REAL(KIND=4), ALLOCATABLE :: x(:) +! AS_FORTRAN-NEXT: IF (.NOT.allocated(x)) ALLOCATE(x(i)) +! AS_FORTRAN-NEXT: END PROGRAM test_allocated + +!-------------------------- +! INPUT +!-------------------------- +program test_allocated + integer :: i = 4 + real(4), allocatable :: x(:) + if (.not. allocated(x)) allocate(x(i)) +end program test_allocated diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -105,7 +105,7 @@ bool debugModuleWriter{false}; bool defaultReal8{false}; bool measureTree{false}; - bool unparseTypedExprsToF18_FC{false}; + bool unparseTypedExprs{true}; std::vector F18_FCArgs; const char *prefix{nullptr}; bool getDefinition{false}; @@ -322,7 +322,8 @@ 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.unparseTypedExprs ? &asFortran : nullptr); return {}; } if (driver.dumpPreFirTree) { @@ -353,11 +354,11 @@ options.features.IsEnabled( Fortran::common::LanguageFeature::BackslashEscapes), nullptr /* action before each statement */, - driver.unparseTypedExprsToF18_FC ? &asFortran : nullptr); + driver.unparseTypedExprs ? &asFortran : nullptr); } RunOtherCompiler(driver, tmpSourcePath.data(), relo.data()); - filesToDelete.emplace_back(tmpSourcePath); + // filesToDelete.emplace_back(tmpSourcePath); if (!driver.compileOnly && driver.outputPath.empty()) { filesToDelete.push_back(relo); } @@ -578,8 +579,8 @@ } 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-unparse-typed-exprs") { + driver.unparseTypedExprs = 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 --- 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-unparse-typed-exprs -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