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

This patch adds support for the `-cpp` and `-nocpp` flags. The
implemented semantics match f18 (i.e. the "throwaway" driver), but are
different to gfortran. In Flang the preprocessor is always run and
`-cpp/-nocpp` are only used to control whether standard macro
predefinitions are added or not. In practice this is sufficient to model
gfortran`s `-cpp/-nocpp`.

In the absence of `-cpp/-nocpp`, the driver will use the extension of
the input file to decide whether to include the standard macro
predefinitions. gfortran's documentation [1] was used to decide which
file extension to use for this. The extension for:

- predefined-macros-compiler-version.f90

had to be updated accordingly.

The logic mentioned above was added in FrontendAction::BeginSourceFile.
That's relatively late in the driver set-up, but this roughly where the
name of the input file becomes available. The logic for deciding between
fixed and free form works in an a similar way and was also moved to
FrontendAction::BeginSourceFile for consistency (and to reduce
code-duplication).

[1] https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99292

Files:
  clang/include/clang/Driver/Options.td
  flang/include/flang/Frontend/CompilerInvocation.h
  flang/include/flang/Frontend/FrontendOptions.h
  flang/include/flang/Frontend/PreprocessorOptions.h
  flang/lib/Frontend/CompilerInstance.cpp
  flang/lib/Frontend/CompilerInvocation.cpp
  flang/lib/Frontend/FrontendAction.cpp
  flang/lib/Frontend/FrontendActions.cpp
  flang/lib/Frontend/FrontendOptions.cpp
  flang/test/Driver/cpp_nocpp.F90
  flang/test/Driver/driver-help-hidden.f90
  flang/test/Driver/driver-help.f90
  flang/test/Driver/predefined-macros-compiler-version.F90
  flang/test/Driver/predefined-macros-compiler-version.f90

Index: flang/test/Driver/predefined-macros-compiler-version.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/predefined-macros-compiler-version.f90
@@ -1,26 +0,0 @@
-! Check that the driver correctly defines macros with the compiler version
-
-! REQUIRES: new-flang-driver
-
-!--------------------------
-! FLANG DRIVER (flang-new)
-!--------------------------
-! RUN: %flang-new -E %s  2>&1 | FileCheck %s --ignore-case
-
-!-----------------------------------------
-! FRONTEND FLANG DRIVER (flang-new -fc1)
-!-----------------------------------------
-! RUN: %flang-new -fc1 -E %s  2>&1 | FileCheck %s --ignore-case
-
-!-----------------
-! EXPECTED OUTPUT
-!-----------------
-! CHECK: flang = 1
-! CHECK: flang_major = {{[1-9][0-9]*$}}
-! CHECK: flang_minor = {{[0-9]+$}}
-! CHECK: flang_patchlevel = {{[0-9]+$}}
-
-integer, parameter :: flang = __flang__
-integer, parameter :: flang_major = __flang_major__
-integer, parameter :: flang_minor = __flang_minor__
-integer, parameter :: flang_patchlevel = __flang_patchlevel__
Index: flang/test/Driver/driver-help.f90
===================================================================
--- flang/test/Driver/driver-help.f90
+++ flang/test/Driver/driver-help.f90
@@ -19,6 +19,7 @@
 ! HELP-EMPTY:
 ! HELP-NEXT:OPTIONS:
 ! HELP-NEXT: -###                   Print (but do not run) the commands to run for this compilation
+! HELP-NEXT: -cpp                   Always add standard macro predefinitions
 ! HELP-NEXT: -c                     Only run preprocess, compile, and assemble steps
 ! HELP-NEXT: -D <macro>=<value>     Define <macro> to <value> (or 1 if <value> omitted)
 ! HELP-NEXT: -E                     Only run the preprocessor
@@ -46,6 +47,7 @@
 ! HELP-NEXT: -help                  Display available options
 ! HELP-NEXT: -I <dir>               Add directory to the end of the list of include search paths
 ! HELP-NEXT: -module-dir <dir>      Put MODULE files in <dir>
+! HELP-NEXT: -nocpp                 Never add standard macro predefinitions
 ! HELP-NEXT: -o <file>              Write output to <file>
 ! HELP-NEXT: -U <macro>             Undefine macro <macro>
 ! HELP-NEXT: --version              Print version information
@@ -57,6 +59,7 @@
 ! HELP-FC1:USAGE: flang-new
 ! HELP-FC1-EMPTY:
 ! HELP-FC1-NEXT:OPTIONS:
+! HELP-FC1-NEXT: -cpp                   Always add standard macro predefinitions
 ! 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
@@ -95,6 +98,7 @@
 ! HELP-FC1-NEXT: -help                  Display available options
 ! HELP-FC1-NEXT: -I <dir>               Add directory to the end of the list of include search paths
 ! HELP-FC1-NEXT: -module-dir <dir>      Put MODULE files in <dir>
+! HELP-FC1-NEXT: -nocpp                 Never add standard macro predefinitions
 ! HELP-FC1-NEXT: -o <file>              Write output to <file>
 ! HELP-FC1-NEXT: -test-io               Run the InputOuputTest action. Use for development and testing only.
 ! HELP-FC1-NEXT: -U <macro>             Undefine macro <macro>
Index: flang/test/Driver/driver-help-hidden.f90
===================================================================
--- flang/test/Driver/driver-help-hidden.f90
+++ flang/test/Driver/driver-help-hidden.f90
@@ -19,6 +19,7 @@
 ! CHECK-EMPTY:
 ! CHECK-NEXT:OPTIONS:
 ! CHECK-NEXT: -###      Print (but do not run) the commands to run for this compilation
+! CHECK-NEXT: -cpp      Always add standard macro predefinitions
 ! CHECK-NEXT: -c        Only run preprocess, compile, and assemble steps
 ! CHECK-NEXT: -D <macro>=<value>     Define <macro> to <value> (or 1 if <value> omitted)
 ! CHECK-NEXT: -E        Only run the preprocessor
@@ -46,6 +47,7 @@
 ! CHECK-NEXT: -help     Display available options
 ! CHECK-NEXT: -I <dir>               Add directory to the end of the list of include search paths
 ! CHECK-NEXT: -module-dir <dir>      Put MODULE files in <dir>
+! CHECK-NEXT: -nocpp                 Never add standard macro predefinitions
 ! CHECK-NEXT: -o <file> Write output to <file>
 ! CHECK-NEXT: -U <macro>             Undefine macro <macro>
 ! CHECK-NEXT: --version Print version information
Index: flang/test/Driver/cpp_nocpp.F90
===================================================================
--- /dev/null
+++ flang/test/Driver/cpp_nocpp.F90
@@ -0,0 +1,18 @@
+!-----------
+! RUN lines
+!-----------
+! RUN: %flang_fc1 -E %s 2>&1 | FileCheck %s --check-prefix=DEFINED
+! RUN: %flang_fc1 -E -cpp %s 2>&1 | FileCheck %s --check-prefix=DEFINED
+! RUN: %flang_fc1 -E -nocpp %s 2>&1 | FileCheck %s --check-prefix=NOT_DEFINED
+
+!-----------------
+! EXPECTED OUTPUT
+!-----------------
+! DEFINED: flang = 1
+! DEFINED-NEXT: flang_major = {{[1-9][0-9]*$}}
+
+! NOT_DEFINED: flang = __flang__
+! NOT_DEFINED-NEXT: flang_major = __flang_major__
+
+integer, parameter :: flang = __flang__
+integer, parameter :: flang_major = __flang_major__
Index: flang/lib/Frontend/FrontendOptions.cpp
===================================================================
--- flang/lib/Frontend/FrontendOptions.cpp
+++ flang/lib/Frontend/FrontendOptions.cpp
@@ -26,6 +26,12 @@
       suffix == "f08" || suffix == "F08" || suffix == "f18" || suffix == "F18";
 }
 
+bool Fortran::frontend::mustBePreprocessed(llvm::StringRef suffix) {
+  return suffix == "F" || suffix == "FOR" || suffix == "FPP" ||
+      suffix == "F90" || suffix == "F95" || 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
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ flang/lib/Frontend/FrontendActions.cpp
@@ -10,6 +10,7 @@
 #include "flang/Common/default-kinds.h"
 #include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendOptions.h"
+#include "flang/Frontend/PreprocessorOptions.h"
 #include "flang/Lower/PFTBuilder.h"
 #include "flang/Parser/dump-parse-tree.h"
 #include "flang/Parser/parsing.h"
@@ -45,21 +46,9 @@
 
 bool PrescanAction::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);
@@ -78,22 +67,9 @@
 
 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);
 
Index: flang/lib/Frontend/FrontendAction.cpp
===================================================================
--- flang/lib/Frontend/FrontendAction.cpp
+++ flang/lib/Frontend/FrontendAction.cpp
@@ -67,6 +67,22 @@
     return false;
   }
 
+  auto &invoc = ci.invocation();
+
+  // Include standard macro predefinitions (use the file
+  // extension if the user didn't express any prefernce)
+  if ((invoc.preprocessorOpts().predefs_ == StdMacroPredefs::Include) ||
+      (invoc.preprocessorOpts().predefs_ == StdMacroPredefs::Unknown &&
+          currentInput().MustBePreprocessed())) {
+    invoc.setDefaultPredefinitions();
+  }
+
+  // Decide between fixed and free form (if the user didn't express any
+  // prefernce, use the file extension to decide)
+  if (invoc.frontendOpts().fortranForm_ == FortranForm::Unknown) {
+    invoc.fortranOpts().isFixedForm = currentInput().IsFixedForm();
+  }
+
   if (!BeginSourceFileAction(ci)) {
     BeginSourceFileCleanUp(*this, ci);
     return false;
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -323,6 +323,14 @@
   for (const auto *currentArg :
       args.filtered(clang::driver::options::OPT_fintrinsic_modules_path))
     opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue());
+
+  // -cpp/-nocpp
+  if (const auto *currentArg = args.getLastArg(
+          clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp))
+    opts.predefs_ =
+        (currentArg->getOption().matches(clang::driver::options::OPT_cpp))
+        ? StdMacroPredefs::Include
+        : StdMacroPredefs::Exclude;
 }
 
 /// Parses all semantic related arguments and populates the variables
Index: flang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- flang/lib/Frontend/CompilerInstance.cpp
+++ flang/lib/Frontend/CompilerInstance.cpp
@@ -142,7 +142,6 @@
 
   // Set some sane defaults for the frontend.
   invoc.SetDefaultFortranOpts();
-  invoc.setDefaultPredefinitions();
   // Update the fortran options based on user-based input.
   invoc.setFortranOpts();
   // Set the encoding to read all input files in based on user input.
Index: flang/include/flang/Frontend/PreprocessorOptions.h
===================================================================
--- flang/include/flang/Frontend/PreprocessorOptions.h
+++ flang/include/flang/Frontend/PreprocessorOptions.h
@@ -19,6 +19,20 @@
 
 namespace Fortran::frontend {
 
+/// Communicates whether to include standard macro predefinitions for the
+/// preprocessor
+enum class StdMacroPredefs : uint8_t {
+  /// Use the file extension to decide whether to include/exclude standard
+  /// macro predefintions
+  Unknown,
+
+  /// Include standard macro predefinitions
+  Include,
+
+  /// Exclude standard macro predefinitions
+  Exclude
+};
+
 /// This class is used for passing the various options used
 /// in preprocessor initialization to the parser options.
 class PreprocessorOptions {
@@ -32,6 +46,8 @@
   // Search directories specified by the user with -fintrinsic-modules-path
   std::vector<std::string> searchDirectoriesFromIntrModPath;
 
+  StdMacroPredefs predefs_ = StdMacroPredefs::Unknown;
+
 public:
   PreprocessorOptions() {}
 
Index: flang/include/flang/Frontend/FrontendOptions.h
===================================================================
--- flang/include/flang/Frontend/FrontendOptions.h
+++ flang/include/flang/Frontend/FrontendOptions.h
@@ -79,6 +79,10 @@
 /// \return True if the file extension should be processed as free form
 bool isFreeFormSuffix(llvm::StringRef suffix);
 
+/// \param suffix The file extension
+/// \return True if the file should be preprocessed
+bool mustBePreprocessed(llvm::StringRef suffix);
+
 enum class Language : uint8_t {
   Unknown,
 
@@ -137,6 +141,9 @@
   /// stdin this is never modified.
   bool isFixedForm_ = false;
 
+  ///
+  unsigned mustBePreprocessed_ : 1;
+
 public:
   FrontendInputFile() = default;
   FrontendInputFile(llvm::StringRef file, InputKind kind)
@@ -147,7 +154,9 @@
     auto pathDotIndex{file.rfind(".")};
     std::string pathSuffix{file.substr(pathDotIndex + 1)};
     isFixedForm_ = isFixedFormSuffix(pathSuffix);
+    mustBePreprocessed_ = mustBePreprocessed(pathSuffix);
   }
+
   FrontendInputFile(const llvm::MemoryBuffer *buffer, InputKind kind)
       : buffer_(buffer), kind_(kind) {}
 
@@ -157,6 +166,7 @@
   bool IsFile() const { return !IsBuffer(); }
   bool IsBuffer() const { return buffer_ != nullptr; }
   bool IsFixedForm() const { return isFixedForm_; }
+  bool MustBePreprocessed() const { return mustBePreprocessed_; }
 
   llvm::StringRef file() const {
     assert(IsFile());
Index: flang/include/flang/Frontend/CompilerInvocation.h
===================================================================
--- flang/include/flang/Frontend/CompilerInvocation.h
+++ flang/include/flang/Frontend/CompilerInvocation.h
@@ -132,6 +132,10 @@
 
   /// Set the Semantic Options
   void setSemanticsOpts(Fortran::parser::AllCookedSources &);
+
+  /// Updates this instance based on the extension of the input file (e.g. f90
+  /// s F90)
+  void updateBasedOnExtension(const FrontendInputFile &inputFile);
 };
 
 } // end namespace Fortran::frontend
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -4219,8 +4219,6 @@
 
 // Generic gfortran options.
 def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
-def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>;
-def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>;
 def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group>;
 
 // "f" options with values for gfortran.
@@ -4300,6 +4298,10 @@
 //===----------------------------------------------------------------------===//
 let Flags = [FC1Option, FlangOption, FlangOnlyOption] in {
 
+def cpp : Flag<["-"], "cpp">, Group<f_Group>,
+  HelpText<"Always add standard macro predefinitions">;
+def nocpp : Flag<["-"], "nocpp">, Group<f_Group>,
+  HelpText<"Never add standard macro predefinitions">;
 def module_dir : Separate<["-"], "module-dir">, MetaVarName<"<dir>">,
   HelpText<"Put MODULE files in <dir>">,
   DocBrief<[{This option specifies where to put .mod files for compiled modules.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to