[clang] 6bf5580 - [clang][driver] Add basic --driver-mode=flang support for fortran
Peter Waller via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 30 03:43:26 PDT 2019
Author: Peter Waller
Date: 2019-10-30T10:42:22Z
New Revision: 6bf55804924d5a1d902925ad080b1a2b57c5c75c
URL: https://github.com/llvm/llvm-project/commit/6bf55804924d5a1d902925ad080b1a2b57c5c75c
DIFF: https://github.com/llvm/llvm-project/commit/6bf55804924d5a1d902925ad080b1a2b57c5c75c.diff
LOG: [clang][driver] Add basic --driver-mode=flang support for fortran
This patch adds a new Flang mode. When in Flang mode, the driver will
invoke flang for fortran inputs instead of falling back to the GCC
toolchain as it would otherwise do.
The behaviour of other driver modes are left unmodified to preserve
backwards compatibility.
It is intended that a soon to be implemented binary in the flang project
will import libclangDriver and run the clang driver in the new flang
mode.
Please note that since the binary invoked by the driver is under
development, there will no doubt be further tweaks necessary in future
commits.
* Initial support is added for basic driver phases
* -E, -fsyntax-only, -emit-llvm -S, -emit-llvm, -S, (none specified)
* -### tests are added for all of the above
* This is more than is supported by f18 so far, which will emit errors
for those options which are unimplemented.
* A test is added that ensures that clang gives a reasonable error
message if flang is not available in the path (without -###).
* Test that the driver accepts multiple inputs in --driver-mode=flang.
* Test that a combination of C and Fortran inputs run both clang and
flang in --driver-mode=flang.
* clang/test/Driver/fortran.f95 is fixed to use the correct fortran
comment character.
Differential revision: https://reviews.llvm.org/D63607
Added:
clang/lib/Driver/ToolChains/Flang.cpp
clang/lib/Driver/ToolChains/Flang.h
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
Modified:
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/Types.cpp
clang/test/Driver/fortran.f95
clang/test/Driver/lit.local.cfg
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 5e7283e31ee0..64f1eb8cb5d7 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -65,7 +65,8 @@ class Driver {
GCCMode,
GXXMode,
CPPMode,
- CLMode
+ CLMode,
+ FlangMode
} Mode;
enum SaveTempsMode {
@@ -180,6 +181,10 @@ class Driver {
/// 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 @@ class Driver {
/// 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; }
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index c40af1e6e01f..26d8d43dd2fc 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -134,6 +134,7 @@ class ToolChain {
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 @@ class ToolChain {
mutable std::unique_ptr<Tool> OffloadWrapper;
Tool *getClang() const;
+ Tool *getFlang() const;
Tool *getAssemble() const;
Tool *getLink() const;
Tool *getIfsMerge() const;
diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h
index a605450e6e3d..c7c38fa52593 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -84,6 +84,9 @@ namespace types {
/// 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.
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 84fd58cf6819..e175e88c4ebb 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -43,6 +43,7 @@ add_clang_library(clangDriver
ToolChains/Cuda.cpp
ToolChains/Darwin.cpp
ToolChains/DragonFly.cpp
+ ToolChains/Flang.cpp
ToolChains/FreeBSD.cpp
ToolChains/Fuchsia.cpp
ToolChains/Gnu.cpp
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 4c59bf0a5e20..3fb38a79051c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -178,6 +178,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
.Case("g++", GXXMode)
.Case("cpp", CPPMode)
.Case("cl", CLMode)
+ .Case("flang", FlangMode)
.Default(None))
Mode = *M;
else
@@ -4876,6 +4877,19 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
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.
///
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 357a5106ab39..a014c611ee22 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/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 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"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 @@ Tool *ToolChain::getClang() const {
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 @@ bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
}
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 @@ std::string ToolChain::GetLinkerPath() const {
}
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
diff erently.
+ if (D.IsFlangMode() && id == types::TY_PP_Fortran)
+ id = types::TY_Fortran;
+
+ return id;
}
bool ToolChain::HasNativeLLVMSupport() const {
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
new file mode 100644
index 000000000000..9b9eb81fa111
--- /dev/null
+++ b/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() {}
diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
new file mode 100644
index 000000000000..19e3a8c28f7e
--- /dev/null
+++ b/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
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index a30710645af3..0e14e3d63fab 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -212,6 +212,16 @@ bool types::isHIP(ID Id) {
}
}
+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;
}
diff --git a/clang/test/Driver/flang/Inputs/one.f90 b/clang/test/Driver/flang/Inputs/one.f90
new file mode 100644
index 000000000000..3c234da8c26c
--- /dev/null
+++ b/clang/test/Driver/flang/Inputs/one.f90
@@ -0,0 +1 @@
+! This file only exists to facilitate a driver -### test.
diff --git a/clang/test/Driver/flang/Inputs/other.c b/clang/test/Driver/flang/Inputs/other.c
new file mode 100644
index 000000000000..719903ec38ba
--- /dev/null
+++ b/clang/test/Driver/flang/Inputs/other.c
@@ -0,0 +1 @@
+/* This file only exists to facilitate a driver -### test. */
diff --git a/clang/test/Driver/flang/Inputs/two.f90 b/clang/test/Driver/flang/Inputs/two.f90
new file mode 100644
index 000000000000..3c234da8c26c
--- /dev/null
+++ b/clang/test/Driver/flang/Inputs/two.f90
@@ -0,0 +1 @@
+! This file only exists to facilitate a driver -### test.
diff --git a/clang/test/Driver/flang/flang.F90 b/clang/test/Driver/flang/flang.F90
new file mode 100644
index 000000000000..37553c7c2760
--- /dev/null
+++ b/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
+!
diff erentiates between F90 and f90 files. Flang will not treat these files
+!
diff erently.
+
+! 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"{{$}}
diff --git a/clang/test/Driver/flang/flang.f90 b/clang/test/Driver/flang/flang.f90
new file mode 100644
index 000000000000..56c1ace6f860
--- /dev/null
+++ b/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
+!
diff erentiates between F90 and f90 files. Flang will not treat these files
+!
diff erently.
+
+! 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"{{$}}
diff --git a/clang/test/Driver/flang/multiple-inputs-mixed.f90 b/clang/test/Driver/flang/multiple-inputs-mixed.f90
new file mode 100644
index 000000000000..98d8cab00bdf
--- /dev/null
+++ b/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"
diff --git a/clang/test/Driver/flang/multiple-inputs.f90 b/clang/test/Driver/flang/multiple-inputs.f90
new file mode 100644
index 000000000000..34592a3dc3a3
--- /dev/null
+++ b/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"
diff --git a/clang/test/Driver/fortran.f95 b/clang/test/Driver/fortran.f95
index 47c6e7b50c95..03ff99f9fbfb 100644
--- a/clang/test/Driver/fortran.f95
+++ b/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"
diff --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg
index 4a4ef2af23b5..ad3f0e92cacd 100644
--- a/clang/test/Driver/lit.local.cfg
+++ b/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,
More information about the cfe-commits
mailing list