[flang-commits] [flang] 443d695 - [flang][driver] Add support for fixed form detection
Andrzej Warzynski via flang-commits
flang-commits at lists.llvm.org
Tue Jan 19 05:00:31 PST 2021
Author: Faris Rehman
Date: 2021-01-19T12:58:01Z
New Revision: 443d6957ca712aacdfd72c3408a8837580f6a286
URL: https://github.com/llvm/llvm-project/commit/443d6957ca712aacdfd72c3408a8837580f6a286
DIFF: https://github.com/llvm/llvm-project/commit/443d6957ca712aacdfd72c3408a8837580f6a286.diff
LOG: [flang][driver] Add support for fixed form detection
Currently the new flang driver always runs in free form mode. This patch
adds support for fixed form mode detection based on the file extensions.
Like `f18`, `flang-new` will treat files ending with ".f", ".F" and
".ff" as fixed form. Additionally, ".for", ".FOR", ".fpp" and ".FPP"
file extensions are recognised as fixed form files. This is consistent
with gfortran [1]. In summary, files with the following extensions are
treated as fixed-form:
* ".f", ".F", ".ff", ".for", ".FOR", ".fpp", ".FPP"
For consistency with flang/test/lit.cfg.py and f18, this patch also adds
support for the following file extensions:
* ".ff", ".FOR", ".for", ".ff90", ".fpp", ".FPP"
This is added in flang/lib/Frontend/FrontendOptions.cpp. Additionally,
the following extensions are included:
* ".f03", ".F03", ".f08", ".F08"
This is for compatibility with gfortran [1] and other popular Fortran
compilers [2].
NOTE: internally Flang will only differentiate between fixed and free
form files. Currently Flang does not support switching between language
standards, so in this regard file extensions are irrelevant. More
specifically, both `file.f03` and `file.f18` are represented with
`Language::Fortran` (as opposed to e.g. `Language::Fortran03`).
Summary of changes:
- Set Fortran::parser::Options::sFixedForm according to the file type
- Add isFixedFormSuffix and isFreeFormSuffix helper functions to
FrontendTool/Utils.h
- Change FrontendOptions::GetInputKindForExtension to support the missing
file extensions that f18 supports and some additional ones
- FrontendActionTest.cpp is updated to make sure that the test input is
treated as free-form
[1] https://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-and-GCC.html
[2] https://github.com/llvm/llvm-project/blob/master/flang/docs/OptionComparison.md#notes
Differential Revision: https://reviews.llvm.org/D94228
Added:
flang/test/Flang-Driver/Inputs/fixed-form-test.f
flang/test/Flang-Driver/Inputs/free-form-test.f90
flang/test/Flang-Driver/fixed-free-detection.f90
Modified:
flang/include/flang/FrontendTool/Utils.h
flang/lib/Frontend/FrontendAction.cpp
flang/lib/Frontend/FrontendOptions.cpp
flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
flang/test/lit.cfg.py
flang/unittests/Frontend/FrontendActionTest.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/FrontendTool/Utils.h b/flang/include/flang/FrontendTool/Utils.h
index d62c03d8dc0b..7ee7568e21de 100644
--- a/flang/include/flang/FrontendTool/Utils.h
+++ b/flang/include/flang/FrontendTool/Utils.h
@@ -14,6 +14,8 @@
#ifndef LLVM_FLANG_FRONTENDTOOL_UTILS_H
#define LLVM_FLANG_FRONTENDTOOL_UTILS_H
+#include "llvm/ADT/StringRef.h"
+
namespace Fortran::frontend {
class CompilerInstance;
@@ -31,6 +33,14 @@ std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &ci);
/// \return - True on success.
bool ExecuteCompilerInvocation(CompilerInstance *flang);
+/// \param suffix The file extension
+/// \return True if the file extension should be processed as fixed form
+bool isFixedFormSuffix(llvm::StringRef suffix);
+
+/// \param suffix The file extension
+/// \return True if the file extension should be processed as free form
+bool isFreeFormSuffix(llvm::StringRef suffix);
+
} // end namespace Fortran::frontend
#endif // LLVM_FLANG_FRONTENDTOOL_UTILS_H
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 4d8a9d43d114..6da1e6191036 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -9,6 +9,7 @@
#include "flang/Frontend/FrontendAction.h"
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/FrontendActions.h"
+#include "flang/FrontendTool/Utils.h"
#include "llvm/Support/Errc.h"
using namespace Fortran::frontend;
@@ -51,6 +52,12 @@ llvm::Error FrontendAction::Execute() {
Fortran::parser::Options parserOptions =
this->instance().invocation().fortranOpts();
+ // Set the fixed form flag based on the file extension
+ auto pathDotIndex{currentInputPath.rfind(".")};
+ if (pathDotIndex != std::string::npos) {
+ std::string pathSuffix{currentInputPath.substr(pathDotIndex + 1)};
+ parserOptions.isFixedForm = isFixedFormSuffix(pathSuffix);
+ }
// Prescan. In case of failure, report and return.
ci.parsing().Prescan(currentInputPath, parserOptions);
diff --git a/flang/lib/Frontend/FrontendOptions.cpp b/flang/lib/Frontend/FrontendOptions.cpp
index 1757db3bb0d6..8c206b308176 100644
--- a/flang/lib/Frontend/FrontendOptions.cpp
+++ b/flang/lib/Frontend/FrontendOptions.cpp
@@ -7,15 +7,13 @@
//===----------------------------------------------------------------------===//
#include "flang/Frontend/FrontendOptions.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "flang/FrontendTool/Utils.h"
using namespace Fortran::frontend;
InputKind FrontendOptions::GetInputKindForExtension(llvm::StringRef extension) {
- return llvm::StringSwitch<InputKind>(extension)
- // TODO: Should match the list in flang/test/lit.cfg.py
- // FIXME: Currently this API allows at most 9 items per case.
- .Cases("f", "F", "f77", "f90", "F90", "f95", "F95", "ff95", "f18", "F18",
- Language::Fortran)
- .Default(Language::Unknown);
+ if (isFixedFormSuffix(extension) || isFreeFormSuffix(extension)) {
+ return Language::Fortran;
+ }
+ return Language::Unknown;
}
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 50c9fca0b882..6bc63b071a9c 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -84,4 +84,19 @@ bool ExecuteCompilerInvocation(CompilerInstance *flang) {
return success;
}
+bool isFixedFormSuffix(llvm::StringRef suffix) {
+ // Note: Keep this list in-sync with flang/test/lit.cfg.py
+ return suffix == "f" || suffix == "F" || suffix == "ff" || suffix == "for" ||
+ suffix == "FOR" || suffix == "fpp" || suffix == "FPP";
+}
+
+bool isFreeFormSuffix(llvm::StringRef suffix) {
+ // Note: Keep this list in-sync with flang/test/lit.cfg.py
+ // TODO: Add Cuda Fortan files (i.e. `*.cuf` and `*.CUF`).
+ return suffix == "f77" || suffix == "f90" || suffix == "F90" ||
+ suffix == "ff90" || suffix == "f95" || suffix == "F95" ||
+ suffix == "ff95" || suffix == "f03" || suffix == "F03" ||
+ suffix == "f08" || suffix == "F08" || suffix == "f18" || suffix == "F18";
+}
+
} // namespace Fortran::frontend
diff --git a/flang/test/Flang-Driver/Inputs/fixed-form-test.f b/flang/test/Flang-Driver/Inputs/fixed-form-test.f
new file mode 100644
index 000000000000..758ce2a0189a
--- /dev/null
+++ b/flang/test/Flang-Driver/Inputs/fixed-form-test.f
@@ -0,0 +1,2 @@
+ program FixedForm
+ end
diff --git a/flang/test/Flang-Driver/Inputs/free-form-test.f90 b/flang/test/Flang-Driver/Inputs/free-form-test.f90
new file mode 100644
index 000000000000..7933954f38ef
--- /dev/null
+++ b/flang/test/Flang-Driver/Inputs/free-form-test.f90
@@ -0,0 +1,2 @@
+program FreeForm
+end
diff --git a/flang/test/Flang-Driver/fixed-free-detection.f90 b/flang/test/Flang-Driver/fixed-free-detection.f90
new file mode 100644
index 000000000000..a24be5341db4
--- /dev/null
+++ b/flang/test/Flang-Driver/fixed-free-detection.f90
@@ -0,0 +1,40 @@
+! Ensure the driver correctly switches between fixed and free form based on the file extension.
+! This test exploits the fact that the preprocessor treats white-spaces
diff erently for free
+! and fixed form input files.
+
+! REQUIRES: new-flang-driver
+
+!--------------------------
+! FLANG DRIVER (flang-new)
+!--------------------------
+! RUN: %flang-new -E %S/Inputs/free-form-test.f90 2>&1 | FileCheck %s --check-prefix=FREEFORM
+! RUN: %flang-new -E %S/Inputs/fixed-form-test.f 2>&1 | FileCheck %s --check-prefix=FIXEDFORM
+! RUN: %flang-new -E %S/Inputs/free-form-test.f90 %S/Inputs/fixed-form-test.f 2>&1 | FileCheck %s --check-prefix=MULTIPLEFORMS
+
+!-----------------------------------------
+! FRONTEND FLANG DRIVER (flang-new -fc1)
+!-----------------------------------------
+! RUN: %flang-new -fc1 -E %S/Inputs/free-form-test.f90 2>&1 | FileCheck %s --check-prefix=FREEFORM
+! RUN: %flang-new -fc1 -E %S/Inputs/fixed-form-test.f 2>&1 | FileCheck %s --check-prefix=FIXEDFORM
+! RUN: %flang-new -fc1 -E %S/Inputs/free-form-test.f90 %S/Inputs/fixed-form-test.f 2>&1 | FileCheck %s --check-prefix=MULTIPLEFORMS
+
+!-------------------------------------
+! EXPECTED OUTPUT FOR A FREE FORM FILE
+!-------------------------------------
+! FREEFORM:program freeform
+! FREEFORM-NOT:programfixedform
+
+!---------------------------------------
+! EXPECTED OUTPUT FOR A FIXED FORM FILE
+!---------------------------------------
+! FIXEDFORM:programfixedform
+! FIXEDFORM-NOT:program freeform
+
+!------------------------------------------------
+! EXPECTED OUTPUT FOR 2 FILES OF DIFFERENT FORMS
+!------------------------------------------------
+! MULTIPLEFORMS:program freeform
+! MULTIPLEFORMS-NOT:programfixedform
+! MULTIPLEFORMS-NEXT:end
+! MULTIPLEFORMS-NEXT:programfixedform
+! MULTIPLEFORMS-NOT:program freeform
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 6d33c21f4863..c9992b75c218 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -26,8 +26,8 @@
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp', '.f', '.F', '.ff', '.FOR', '.for', '.f77', '.f90', '.F90',
- '.ff90', '.f95', '.F95', '.ff95', '.fpp', '.FPP', '.cuf',
- '.CUF', '.f18', '.F18', '.fir']
+ '.ff90', '.f95', '.F95', '.ff95', '.fpp', '.FPP', '.cuf'
+ '.CUF', '.f18', '.F18', '.fir', '.f03', '.F03', '.f08', '.F08']
config.substitutions.append(('%PATH%', config.environment['PATH']))
diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index fb4de6d307cd..2e8bacddaf58 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -40,7 +40,7 @@ class FrontendActionTest : public ::testing::Test {
// Generate a unique test file name.
const testing::TestInfo *const test_info =
testing::UnitTest::GetInstance()->current_test_info();
- inputFileName_ = std::string(test_info->name()) + "_test-file.f";
+ inputFileName_ = std::string(test_info->name()) + "_test-file.f90";
// Create the input file stream. Note that this stream is populated
// separately in every test (i.e. the input is test specific).
More information about the flang-commits
mailing list