Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1003,6 +1003,8 @@ def module_dependency_dir : Separate<["-"], "module-dependency-dir">, Flags<[CC1Option]>, HelpText<"Directory to dump module dependencies to">, MarshallingInfoString>; +def module_dir : Separate<["-"], "module-dir">, + Flags<[FlangOption,FC1Option]>, HelpText<"Add to the list of directories to be searched by an USE statement">; def dsym_dir : JoinedOrSeparate<["-"], "dsym-dir">, Flags<[NoXarchOption, RenderAsInput]>, HelpText<"Directory to output dSYM's (if any) to">, MetaVarName<"">; @@ -4102,7 +4104,7 @@ // Generic gfortran options. def A_DASH : Joined<["-"], "A-">, Group; -def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group; +def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined,FlangOption,FC1Option]>, Group; def cpp : Flag<["-"], "cpp">, Group; def nocpp : Flag<["-"], "nocpp">, Group; def static_libgfortran : Flag<["-"], "static-libgfortran">, Group; Index: clang/lib/Driver/ToolChains/Flang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Flang.cpp +++ clang/lib/Driver/ToolChains/Flang.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// - #include "Flang.h" #include "CommonArgs.h" @@ -21,7 +20,8 @@ void Flang::AddPreprocessingOptions(const ArgList &Args, ArgStringList &CmdArgs) const { - Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I}); + Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I, + options::OPT_J, options::OPT_module_dir}); } void Flang::ConstructJob(Compilation &C, const JobAction &JA, @@ -89,7 +89,7 @@ assert(Input.isFilename() && "Invalid input."); CmdArgs.push_back(Input.getFilename()); - const auto& D = C.getDriver(); + const auto &D = C.getDriver(); // TODO: Replace flang-new with flang once the new driver replaces the // throwaway driver const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC)); Index: flang/include/flang/Frontend/CompilerInstance.h =================================================================== --- flang/include/flang/Frontend/CompilerInstance.h +++ flang/include/flang/Frontend/CompilerInstance.h @@ -136,6 +136,11 @@ return invocation_->frontendOpts(); } + Fortran::parser::Options &fortranOpts() { return invocation_->fortranOpts(); } + const Fortran::parser::Options &fortranOpts() const { + return invocation_->fortranOpts(); + } + PreprocessorOptions &preprocessorOpts() { return invocation_->preprocessorOpts(); } Index: flang/include/flang/Frontend/PreprocessorOptions.h =================================================================== --- flang/include/flang/Frontend/PreprocessorOptions.h +++ flang/include/flang/Frontend/PreprocessorOptions.h @@ -30,6 +30,9 @@ // as there is no point creating a class for just one field. std::vector searchDirectoriesFromDashI; + // Module directory specified by -J + std::string moduleDirJ; + public: PreprocessorOptions() {} @@ -44,4 +47,4 @@ } // namespace Fortran::frontend -#endif // LLVM_FLANG_PREPROCESSOROPTIONS_H \ No newline at end of file +#endif // LLVM_FLANG_PREPROCESSOROPTIONS_H Index: flang/include/flang/Parser/parsing.h =================================================================== --- flang/include/flang/Parser/parsing.h +++ flang/include/flang/Parser/parsing.h @@ -32,6 +32,7 @@ int fixedFormColumns{72}; common::LanguageFeatureControl features; std::vector searchDirectories; + std::string moduleDirectory; std::vector predefinitions; bool instrumentedParse{false}; bool isModuleFile{false}; Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -178,9 +178,20 @@ } } - // Add the ordered list of -I's. + // Add the ordered list of -I's and -J to the search directories. for (const auto *currentArg : args.filtered(clang::driver::options::OPT_I)) opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue()); + for (const auto *currentArg : args.filtered(clang::driver::options::OPT_J)) { + opts.moduleDirJ = currentArg->getValue(); + opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue()); + } + + // Add the -J to the output module directory. + for (const auto *currentArg : + args.filtered(clang::driver::options::OPT_module_dir)) { + opts.moduleDirJ = currentArg->getValue(); + opts.searchDirectoriesFromDashI.emplace_back(currentArg->getValue()); + } } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &res, @@ -191,8 +202,7 @@ // Parse the arguments const llvm::opt::OptTable &opts = clang::driver::getDriverOptTable(); - const unsigned includedFlagsBitmask = - clang::driver::options::FC1Option; + const unsigned includedFlagsBitmask = clang::driver::options::FC1Option; unsigned missingArgIndex, missingArgCount; llvm::opt::InputArgList args = opts.ParseArgs( commandLineArgs, missingArgIndex, missingArgCount, includedFlagsBitmask); @@ -279,8 +289,10 @@ collectMacroDefinitions(preprocessorOptions, fortranOptions); + // Set up the search directories and output module directory properly. fortranOptions.searchDirectories.insert( fortranOptions.searchDirectories.end(), preprocessorOptions.searchDirectoriesFromDashI.begin(), preprocessorOptions.searchDirectoriesFromDashI.end()); + fortranOptions.moduleDirectory = preprocessorOptions.moduleDirJ; } Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -99,6 +99,12 @@ // Prepare semantics Fortran::semantics::SemanticsContext semanticsContext{ defaultKinds, features, ci.allCookedSources()}; + // Check if we have a module search directory, add it + // Also add the search directories + if (!ci.fortranOpts().moduleDirectory.empty()) + semanticsContext.set_moduleDirectory(ci.fortranOpts().moduleDirectory) + .set_searchDirectories(ci.fortranOpts().searchDirectories); + Fortran::semantics::Semantics semantics{ semanticsContext, parseTree, ci.parsing().cooked().AsCharBlock()}; Index: flang/test/Flang-Driver/driver-help-hidden.f90 =================================================================== --- flang/test/Flang-Driver/driver-help-hidden.f90 +++ flang/test/Flang-Driver/driver-help-hidden.f90 @@ -26,6 +26,7 @@ ! CHECK-NEXT: -fno-color-diagnostics Disable colors in diagnostics ! CHECK-NEXT: -help Display available options ! CHECK-NEXT: -I Add directory to the end of the list of include search paths +! CHECK-NEXT: -module-dir Add to the list of directories to be searched by an USE statement ! CHECK-NEXT: -o Write output to ! CHECK-NEXT: -test-io Run the InputOuputTest action. Use for development and testing only. ! CHECK-NEXT: -U Undefine macro Index: flang/test/Flang-Driver/driver-help.f90 =================================================================== --- flang/test/Flang-Driver/driver-help.f90 +++ flang/test/Flang-Driver/driver-help.f90 @@ -26,6 +26,7 @@ ! HELP-NEXT: -fno-color-diagnostics Disable colors in diagnostics ! HELP-NEXT: -help Display available options ! HELP-NEXT: -I Add directory to the end of the list of include search paths +! HELP-NEXT: -module-dir Add to the list of directories to be searched by an USE statement ! HELP-NEXT: -o Write output to ! HELP-NEXT: -U Undefine macro ! HELP-NEXT: --version Print version information @@ -41,6 +42,7 @@ ! HELP-FC1-NEXT: -E Only run the preprocessor ! HELP-FC1-NEXT: -help Display available options ! HELP-FC1-NEXT: -I Add directory to the end of the list of include search paths +! HELP-FC1-NEXT: -module-dir Add to the list of directories to be searched by an USE statement ! HELP-FC1-NEXT: -o Write output to ! HELP-FC1-NEXT: -U Undefine macro ! HELP-FC1-NEXT: --version Print version information Index: flang/test/Flang-Driver/include-module.f90 =================================================================== --- flang/test/Flang-Driver/include-module.f90 +++ flang/test/Flang-Driver/include-module.f90 @@ -1,4 +1,4 @@ -! Ensure argument -I works as expected with module files. +! Ensure argument -I, -J and -module-dir works as expected with module files. ! The module files for this test are not real module files. ! REQUIRES: new-flang-driver @@ -8,12 +8,20 @@ !-------------------------- ! RUN: not %flang-new -fsyntax-only -I %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED ! RUN: not %flang-new -fsyntax-only -I %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE +! RUN: not %flang-new -fsyntax-only -J %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED +! RUN: not %flang-new -fsyntax-only -J %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE +! RUN: not %flang-new -fsyntax-only -module-dir %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED +! RUN: not %flang-new -fsyntax-only -module-dir %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE !----------------------------------------- ! FRONTEND FLANG DRIVER (flang-new -fc1) !----------------------------------------- ! RUN: not %flang-new -fc1 -fsyntax-only -I %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED ! RUN: not %flang-new -fc1 -fsyntax-only -I %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE +! RUN: not %flang-new -fc1 -fsyntax-only -J %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED +! RUN: not %flang-new -fc1 -fsyntax-only -J %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE +! RUN: not %flang-new -fc1 -fsyntax-only -module-dir %S/Inputs -I %S/Inputs/module-dir %s 2>&1 | FileCheck %s --check-prefix=INCLUDED +! RUN: not %flang-new -fc1 -fsyntax-only -module-dir %S/Inputs %s 2>&1 | FileCheck %s --check-prefix=SINGLEINCLUDE !----------------------------------------- ! EXPECTED OUTPUT FOR MISSING MODULE FILE