peterwaller-arm updated this revision to Diff 220856.
peterwaller-arm marked 14 inline comments as done.
peterwaller-arm edited the summary of this revision.
peterwaller-arm added a comment.

Thanks everyone for your comments.

Changes since last patch:

- Reintroduce handling of (no phase arg specified), -S, -emit-llvm, etc.

  The code implementing it was reordered for clarity.

  After internal discussion we concluded it was preferable to land these now 
even though they are unimplemented on the frontend side, in order to avoid 
giving assertion errors for unimplemented behaviour.

  It is planned that the frontend will emit sensible errors for unimplemented 
behaviour.

- Fixes to the cover letter for --driver-mode=fortran => --driver-mode=flang

- Add a test (flang-not-installed.f90) which demonstrates the error message if 
clang is invoked with no flang available, by unsetting PATH. This is a 
non-"-###" test which also does not depend on the presence of flang.
  - Since it uses shell syntax, it is marked unsupported on windows.

- In response to a private comment, Flang mode now coerces TY_PP_Fortran to 
TY_Fortran. This:
  - Leaves the legacy behaviour unchanged
  - Ensures that we do not emit a warning when passing TY_PP_Fortran inputs to 
-E
  - Should ensure that TY_PP_Fortran is treated exactly as a fortran file
  - Is consistent with f18's intent to not have any notion of preprocessed 
sources
  - Now the flang.f90 and flang.F90 <https://reviews.llvm.org/F90> tests are 
identical except for the filename

- Various minor whitespace changes and documentation fixes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63607/new/

https://reviews.llvm.org/D63607

Files:
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/ToolChain.h
  clang/include/clang/Driver/Types.h
  clang/lib/Driver/CMakeLists.txt
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Flang.cpp
  clang/lib/Driver/ToolChains/Flang.h
  clang/lib/Driver/Types.cpp
  clang/test/Driver/flang/Inputs/one.f90
  clang/test/Driver/flang/Inputs/other.c
  clang/test/Driver/flang/Inputs/two.f90
  clang/test/Driver/flang/flang-not-installed.f90
  clang/test/Driver/flang/flang.F90
  clang/test/Driver/flang/flang.f90
  clang/test/Driver/flang/multiple-inputs-mixed.f90
  clang/test/Driver/flang/multiple-inputs.f90
  clang/test/Driver/fortran.f95
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===================================================================
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,4 +1,4 @@
-config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.f95',
+config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
                    '.cu', '.rs', '.cl', '.hip']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
Index: clang/test/Driver/fortran.f95
===================================================================
--- clang/test/Driver/fortran.f95
+++ clang/test/Driver/fortran.f95
@@ -1,21 +1,22 @@
-// Check that the clang driver can invoke gcc to compile Fortran.
+! Check that the clang driver can invoke gcc to compile Fortran when in
+! --driver-mode=clang. This is legacy behaviour - see also --driver-mode=flang.
 
-// RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-OBJECT %s
-// CHECK-OBJECT: gcc
-// CHECK-OBJECT: "-c"
-// CHECK-OBJECT: "-x" "f95"
-// CHECK-OBJECT-NOT: cc1as
+! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -c %s -### 2>&1 \
+! RUN:   | FileCheck --check-prefix=CHECK-OBJECT %s
+! CHECK-OBJECT: gcc
+! CHECK-OBJECT: "-c"
+! CHECK-OBJECT: "-x" "f95"
+! CHECK-OBJECT-NOT: cc1as
 
-// RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-ASM %s
-// CHECK-ASM: gcc
-// CHECK-ASM: "-S"
-// CHECK-ASM: "-x" "f95"
-// CHECK-ASM-NOT: cc1
+! RUN: %clang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \
+! RUN:   | FileCheck --check-prefix=CHECK-ASM %s
+! CHECK-ASM: gcc
+! CHECK-ASM: "-S"
+! CHECK-ASM: "-x" "f95"
+! CHECK-ASM-NOT: cc1
 
-// RUN: %clang -Wall -target x86_64-unknown-linux-gnu -integrated-as %s -o %t -### 2>&1 | FileCheck --check-prefix=CHECK-WARN %s
-// CHECK-WARN: gcc
-// CHECK-WARN-NOT: "-Wall"
-// CHECK-WARN: ld
-// CHECK-WARN-NOT: "-Wall"
+! RUN: %clang -Wall -target x86_64-unknown-linux-gnu -integrated-as %s -o %t -### 2>&1 | FileCheck --check-prefix=CHECK-WARN %s
+! CHECK-WARN: gcc
+! CHECK-WARN-NOT: "-Wall"
+! CHECK-WARN: ld
+! CHECK-WARN-NOT: "-Wall"
Index: clang/test/Driver/flang/multiple-inputs.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/multiple-inputs.f90
@@ -0,0 +1,7 @@
+! Check that flang driver can handle multiple inputs at once.
+
+! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/two.f90 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s
+! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang" "-fc1"
+! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90"
+! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang" "-fc1"
+! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/two.f90"
Index: clang/test/Driver/flang/multiple-inputs-mixed.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/multiple-inputs-mixed.f90
@@ -0,0 +1,7 @@
+! Check that flang can handle mixed C and fortran inputs.
+
+! RUN: %clang --driver-mode=flang -### -fsyntax-only %S/Inputs/one.f90 %S/Inputs/other.c 2>&1 | FileCheck --check-prefixes=CHECK-SYNTAX-ONLY %s
+! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}flang{{[^"/]*}}" "-fc1"
+! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/one.f90"
+! CHECK-SYNTAX-ONLY-LABEL: "{{[^"]*}}clang{{[^"/]*}}" "-cc1"
+! CHECK-SYNTAX-ONLY: "{{[^"]*}}/Inputs/other.c"
Index: clang/test/Driver/flang/flang.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/flang.f90
@@ -0,0 +1,51 @@
+! Check that flang -fc1 is invoked when in --driver-mode=flang.
+
+! This is a copy of flang.F90 because the driver has logic in it which
+! differentiates between F90 and f90 files. Flang will not treat these files
+! differently.
+
+! Test various output types:
+! * -E
+! * -fsyntax-only
+! * -emit-llvm -S
+! * -emit-llvm
+! * -S
+! * (no type specified, resulting in an object file)
+
+! All invocations should begin with flang -fc1, consume up to here.
+! ALL-LABEL: "{{[^"]*}}flang" "-fc1"
+
+! Check that f90 files are not treated as "previously preprocessed"
+! ... in --driver-mode=flang.
+! RUN: %clang --driver-mode=flang -### -E                  %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-E %s
+! CHECK-E-NOT: previously preprocessed input
+! CHECK-E-DAG: "-E"
+! CHECK-E-DAG: "-o" "-"
+
+! RUN: %clang --driver-mode=flang -### -emit-ast           %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-AST %s
+! CHECK-EMIT-AST-DAG: "-triple"
+! CHECK-EMIT-AST-DAG: "-emit-ast"
+! CHECK-EMIT-AST-DAG: "-o" "{{[^"]*}}.ast"
+
+! RUN: %clang --driver-mode=flang -### -fsyntax-only       %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-SYNTAX-ONLY %s
+! CHECK-SYNTAX-ONLY-NOT: "-o"
+! CHECK-SYNTAX-ONLY-DAG: "-fsyntax-only"
+
+! RUN: %clang --driver-mode=flang -### -emit-llvm -S       %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-LLVM-IR %s
+! CHECK-EMIT-LLVM-IR-DAG: "-emit-llvm"
+! CHECK-EMIT-LLVM-IR-DAG: "-o" "{{[^"]*}}.ll"
+
+! RUN: %clang --driver-mode=flang -### -emit-llvm          %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-LLVM-BC %s
+! CHECK-EMIT-LLVM-BC-DAG: "-emit-llvm-bc"
+! CHECK-EMIT-LLVM-BC-DAG: "-o" "{{[^"]*}}.bc"
+
+! RUN: %clang --driver-mode=flang -### -S                  %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-S %s
+! CHECK-S-DAG: "-S"
+! CHECK-S-DAG: "-o" "{{[^"]*}}.s"
+
+! RUN: %clang --driver-mode=flang -###                     %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-OBJ %s
+! CHECK-EMIT-OBJ-DAG: "-emit-obj"
+! CHECK-EMIT-OBJ-DAG: "-o" "{{[^"]*}}.o"
+
+! Should end in the input file.
+! ALL: "{{.*}}flang.f90"{{$}}
Index: clang/test/Driver/flang/flang.F90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/flang.F90
@@ -0,0 +1,51 @@
+! Check that flang -fc1 is invoked when in --driver-mode=flang.
+
+! This is a copy of flang.f90 because the driver has logic in it which
+! differentiates between F90 and f90 files. Flang will not treat these files
+! differently.
+
+! Test various output types:
+! * -E
+! * -fsyntax-only
+! * -emit-llvm -S
+! * -emit-llvm
+! * -S
+! * (no type specified, resulting in an object file)
+
+! All invocations should begin with flang -fc1, consume up to here.
+! ALL-LABEL: "{{[^"]*}}flang" "-fc1"
+
+! Check that f90 files are not treated as "previously preprocessed"
+! ... in --driver-mode=flang.
+! RUN: %clang --driver-mode=flang -### -E                  %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-E %s
+! CHECK-E-NOT: previously preprocessed input
+! CHECK-E-DAG: "-E"
+! CHECK-E-DAG: "-o" "-"
+
+! RUN: %clang --driver-mode=flang -### -emit-ast           %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-AST %s
+! CHECK-EMIT-AST-DAG: "-triple"
+! CHECK-EMIT-AST-DAG: "-emit-ast"
+! CHECK-EMIT-AST-DAG: "-o" "{{[^"]*}}.ast"
+
+! RUN: %clang --driver-mode=flang -### -fsyntax-only       %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-SYNTAX-ONLY %s
+! CHECK-SYNTAX-ONLY-NOT: "-o"
+! CHECK-SYNTAX-ONLY-DAG: "-fsyntax-only"
+
+! RUN: %clang --driver-mode=flang -### -emit-llvm -S       %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-LLVM-IR %s
+! CHECK-EMIT-LLVM-IR-DAG: "-emit-llvm"
+! CHECK-EMIT-LLVM-IR-DAG: "-o" "{{[^"]*}}.ll"
+
+! RUN: %clang --driver-mode=flang -### -emit-llvm          %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-LLVM-BC %s
+! CHECK-EMIT-LLVM-BC-DAG: "-emit-llvm-bc"
+! CHECK-EMIT-LLVM-BC-DAG: "-o" "{{[^"]*}}.bc"
+
+! RUN: %clang --driver-mode=flang -### -S                  %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-S %s
+! CHECK-S-DAG: "-S"
+! CHECK-S-DAG: "-o" "{{[^"]*}}.s"
+
+! RUN: %clang --driver-mode=flang -###                     %s 2>&1 | FileCheck --check-prefixes=ALL,CHECK-EMIT-OBJ %s
+! CHECK-EMIT-OBJ-DAG: "-emit-obj"
+! CHECK-EMIT-OBJ-DAG: "-o" "{{[^"]*}}.o"
+
+! Should end in the input file.
+! ALL: "{{.*}}flang.F90"{{$}}
Index: clang/test/Driver/flang/flang-not-installed.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/flang-not-installed.f90
@@ -0,0 +1,14 @@
+
+! Invoke clang in flang mode with an empty $PATH, mimicking the circumstances
+! where flang is unavailable. Check that a reasonable error is shown.
+
+! Note: can't use "not" here as usual, because PATH needs to be empty, so use
+! the shell primitive "!" instead to invert the error exit status. Braces are
+! required to only negate clang's exit status and not FileCheck's as well.
+
+! This test has not been run on windows. I assume it won't work due to the
+! shell syntax.
+! UNSUPPORTED: windows
+
+! RUN: { ! PATH="" %clang --driver-mode=flang -fsyntax-only %s 2>&1; } | FileCheck %s
+! CHECK: error: unable to execute command: Executable "flang{{[^"]*}}" doesn't exist
Index: clang/test/Driver/flang/Inputs/two.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/Inputs/two.f90
@@ -0,0 +1 @@
+! This file only exists to facilitate a driver -### test.
Index: clang/test/Driver/flang/Inputs/other.c
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/Inputs/other.c
@@ -0,0 +1 @@
+/* This file only exists to facilitate a driver -### test. */
Index: clang/test/Driver/flang/Inputs/one.f90
===================================================================
--- /dev/null
+++ clang/test/Driver/flang/Inputs/one.f90
@@ -0,0 +1 @@
+! This file only exists to facilitate a driver -### test.
Index: clang/lib/Driver/Types.cpp
===================================================================
--- clang/lib/Driver/Types.cpp
+++ clang/lib/Driver/Types.cpp
@@ -212,6 +212,16 @@
   }
 }
 
+bool types::isFortran(ID Id) {
+  switch (Id) {
+  default:
+    return false;
+
+  case TY_Fortran: case TY_PP_Fortran:
+    return true;
+  }
+}
+
 bool types::isSrcFile(ID Id) {
   return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
 }
Index: clang/lib/Driver/ToolChains/Flang.h
===================================================================
--- /dev/null
+++ clang/lib/Driver/ToolChains/Flang.h
@@ -0,0 +1,46 @@
+//===--- Flang.h - Flang Tool and ToolChain Implementations ====-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+/// Flang compiler tool.
+class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
+public:
+  Flang(const ToolChain &TC);
+  ~Flang() override;
+
+  bool hasGoodDiagnostics() const override { return true; }
+  bool hasIntegratedAssembler() const override { return true; }
+  bool hasIntegratedCPP() const override { return true; }
+  bool canEmitIR() const override { return true; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+                    const InputInfo &Output, const InputInfoList &Inputs,
+                    const llvm::opt::ArgList &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
Index: clang/lib/Driver/ToolChains/Flang.cpp
===================================================================
--- /dev/null
+++ clang/lib/Driver/ToolChains/Flang.cpp
@@ -0,0 +1,79 @@
+//===-- Flang.cpp - Flang+LLVM ToolChain Implementations --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "Flang.h"
+#include "CommonArgs.h"
+
+#include "clang/Driver/Options.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+void Flang::ConstructJob(Compilation &C, const JobAction &JA,
+                         const InputInfo &Output, const InputInfoList &Inputs,
+                         const ArgList &Args, const char *LinkingOutput) const {
+  const auto &TC = getToolChain();
+  const llvm::Triple &Triple = TC.getEffectiveTriple();
+  const std::string &TripleStr = Triple.getTriple();
+
+  ArgStringList CmdArgs;
+
+  CmdArgs.push_back("-fc1");
+
+  CmdArgs.push_back("-triple");
+  CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+  if (isa<PreprocessJobAction>(JA)) {
+    CmdArgs.push_back("-E");
+  } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
+    if (JA.getType() == types::TY_Nothing) {
+      CmdArgs.push_back("-fsyntax-only");
+    } else if (JA.getType() == types::TY_AST) {
+      CmdArgs.push_back("-emit-ast");
+    } else if (JA.getType() == types::TY_LLVM_IR ||
+               JA.getType() == types::TY_LTO_IR) {
+      CmdArgs.push_back("-emit-llvm");
+    } else if (JA.getType() == types::TY_LLVM_BC ||
+               JA.getType() == types::TY_LTO_BC) {
+      CmdArgs.push_back("-emit-llvm-bc");
+    } else if (JA.getType() == types::TY_PP_Asm) {
+      CmdArgs.push_back("-S");
+    } else {
+      assert(false && "Unexpected output type!");
+    }
+  } else if (isa<AssembleJobAction>(JA)) {
+    CmdArgs.push_back("-emit-obj");
+  } else {
+    assert(false && "Unexpected action class for Flang tool.");
+  }
+
+  if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  const InputInfo &Input = Inputs[0];
+  assert(Input.isFilename() && "Invalid input.");
+  CmdArgs.push_back(Input.getFilename());
+
+  const auto& D = C.getDriver();
+  const char* Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));
+  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+Flang::Flang(const ToolChain &TC)
+    : Tool("flang", "flang frontend", TC, RF_Full) {}
+
+Flang::~Flang() {}
Index: clang/lib/Driver/ToolChain.cpp
===================================================================
--- clang/lib/Driver/ToolChain.cpp
+++ clang/lib/Driver/ToolChain.cpp
@@ -10,6 +10,7 @@
 #include "InputInfo.h"
 #include "ToolChains/Arch/ARM.h"
 #include "ToolChains/Clang.h"
+#include "ToolChains/Flang.h"
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Config/config.h"
@@ -150,6 +151,7 @@
       {"cpp", "--driver-mode=cpp"},
       {"cl", "--driver-mode=cl"},
       {"++", "--driver-mode=g++"},
+      {"flang", "--driver-mode=flang"},
   };
 
   for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
@@ -253,6 +255,12 @@
   return Clang.get();
 }
 
+Tool *ToolChain::getFlang() const {
+  if (!Flang)
+    Flang.reset(new tools::Flang(*this));
+  return Flang.get();
+}
+
 Tool *ToolChain::buildAssembler() const {
   return new tools::ClangAs(*this);
 }
@@ -474,6 +482,7 @@
 }
 
 Tool *ToolChain::SelectTool(const JobAction &JA) const {
+  if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
   if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
   Action::ActionClass AC = JA.getKind();
   if (AC == Action::AssembleJobClass && useIntegratedAs())
@@ -522,7 +531,15 @@
 }
 
 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
-  return types::lookupTypeForExtension(Ext);
+  types::ID id = types::lookupTypeForExtension(Ext);
+
+  // Flang always runs the preprocessor and has no notion of "preprocessed
+  // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
+  // them differently.
+  if (D.IsFlangMode() && id == types::TY_PP_Fortran)
+    id = types::TY_Fortran;
+
+  return id;
 }
 
 bool ToolChain::HasNativeLLVMSupport() const {
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -177,6 +177,7 @@
                    .Case("g++", GXXMode)
                    .Case("cpp", CPPMode)
                    .Case("cl", CLMode)
+                   .Case("flang", FlangMode)
                    .Default(None))
     Mode = *M;
   else
@@ -4783,6 +4784,19 @@
   return true;
 }
 
+bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
+  // Say "no" if there is not exactly one input of a type flang understands.
+  if (JA.size() != 1 ||
+      !types::isFortran((*JA.input_begin())->getType()))
+    return false;
+
+  // And say "no" if this is not a kind of action flang understands.
+  if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+    return false;
+
+  return true;
+}
+
 /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
 /// grouped values as integers. Numbers which are not provided are set to 0.
 ///
Index: clang/lib/Driver/CMakeLists.txt
===================================================================
--- clang/lib/Driver/CMakeLists.txt
+++ clang/lib/Driver/CMakeLists.txt
@@ -42,6 +42,7 @@
   ToolChains/Cuda.cpp
   ToolChains/Darwin.cpp
   ToolChains/DragonFly.cpp
+  ToolChains/Flang.cpp
   ToolChains/FreeBSD.cpp
   ToolChains/Fuchsia.cpp
   ToolChains/Gnu.cpp
Index: clang/include/clang/Driver/Types.h
===================================================================
--- clang/include/clang/Driver/Types.h
+++ clang/include/clang/Driver/Types.h
@@ -84,6 +84,9 @@
   /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
   bool isObjC(ID Id);
 
+  /// isFortran - Is this a Fortran input.
+  bool isFortran(ID Id);
+
   /// isSrcFile - Is this a source file, i.e. something that still has to be
   /// preprocessed. The logic behind this is the same that decides if the first
   /// compilation phase is a preprocessing one.
Index: clang/include/clang/Driver/ToolChain.h
===================================================================
--- clang/include/clang/Driver/ToolChain.h
+++ clang/include/clang/Driver/ToolChain.h
@@ -134,11 +134,13 @@
   path_list ProgramPaths;
 
   mutable std::unique_ptr<Tool> Clang;
+  mutable std::unique_ptr<Tool> Flang;
   mutable std::unique_ptr<Tool> Assemble;
   mutable std::unique_ptr<Tool> Link;
   mutable std::unique_ptr<Tool> OffloadBundler;
 
   Tool *getClang() const;
+  Tool *getFlang() const;
   Tool *getAssemble() const;
   Tool *getLink() const;
   Tool *getClangAs() const;
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -65,7 +65,8 @@
     GCCMode,
     GXXMode,
     CPPMode,
-    CLMode
+    CLMode,
+    FlangMode
   } Mode;
 
   enum SaveTempsMode {
@@ -180,6 +181,10 @@
   /// Whether the driver should follow cl.exe like behavior.
   bool IsCLMode() const { return Mode == CLMode; }
 
+  /// Whether the driver should invoke flang for fortran inputs.
+  /// Other modes fall back to calling gcc which in turn calls gfortran.
+  bool IsFlangMode() const { return Mode == FlangMode; }
+
   /// Only print tool bindings, don't build any jobs.
   unsigned CCCPrintBindings : 1;
 
@@ -534,6 +539,10 @@
   /// handle this action.
   bool ShouldUseClangCompiler(const JobAction &JA) const;
 
+  /// ShouldUseFlangCompiler - Should the flang compiler be used to
+  /// handle this action.
+  bool ShouldUseFlangCompiler(const JobAction &JA) const;
+
   /// Returns true if we are performing any kind of LTO.
   bool isUsingLTO() const { return LTOMode != LTOK_None; }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to