peterwaller-arm updated this revision to Diff 226270.
peterwaller-arm added a comment.

I have rebased the patch for conflicts to master and all the tests are passing.

While doing so, I discovered that the test for flang-not-installed was not fit 
for purpose, because clang actually doesn't first check the PATH, it can find a 
flang binary which lives in the same directory as itself. I conclude that 
having such a test is more trouble than it is worth. Adding such a test would 
involve adding some questionable test-specific machinery. Therefore I've 
removed that test for now.

I'll leave the patch over the weekend in case anyone objects, otherwise I 
intend to submit early next week.


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.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/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
@@ -11,6 +11,7 @@
 #include "ToolChains/Arch/ARM.h"
 #include "ToolChains/Clang.h"
 #include "ToolChains/InterfaceStubs.h"
+#include "ToolChains/Flang.h"
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Config/config.h"
@@ -151,6 +152,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) {
@@ -254,6 +256,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);
 }
@@ -493,6 +501,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())
@@ -541,7 +550,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
@@ -4872,6 +4873,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,6 +134,7 @@
   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> IfsMerge;
@@ -141,6 +142,7 @@
   mutable std::unique_ptr<Tool> OffloadWrapper;
 
   Tool *getClang() const;
+  Tool *getFlang() const;
   Tool *getAssemble() const;
   Tool *getLink() const;
   Tool *getIfsMerge() 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