diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3357,7 +3357,7 @@ MarshallingInfoStringVector>; def image__base : Separate<["-"], "image_base">; def include_ : JoinedOrSeparate<["-", "--"], "include">, Group, EnumName<"include">, - MetaVarName<"">, HelpText<"Include file before parsing">, Flags<[CC1Option]>; + MetaVarName<"">, HelpText<"Include file before parsing">, Flags<[CC1Option, FC1Option]>; def include_pch : Separate<["-"], "include-pch">, Group, Flags<[CC1Option]>, HelpText<"Include precompiled header file">, MetaVarName<"">, MarshallingInfoString>; diff --git a/flang/include/flang/Frontend/PreprocessorOptions.h b/flang/include/flang/Frontend/PreprocessorOptions.h --- a/flang/include/flang/Frontend/PreprocessorOptions.h +++ b/flang/include/flang/Frontend/PreprocessorOptions.h @@ -47,6 +47,8 @@ std::vector searchDirectoriesFromDashI; // Search directories specified by the user with -fintrinsic-modules-path std::vector searchDirectoriesFromIntrModPath; + // Includes specified by the user with -include + std::vector includes; PPMacrosFlag macrosFlag = PPMacrosFlag::Unknown; diff --git a/flang/include/flang/Parser/parsing.h b/flang/include/flang/Parser/parsing.h --- a/flang/include/flang/Parser/parsing.h +++ b/flang/include/flang/Parser/parsing.h @@ -34,6 +34,7 @@ std::vector searchDirectories; std::vector intrinsicModuleDirectories; std::vector predefinitions; + std::vector includes; bool instrumentedParse{false}; bool isModuleFile{false}; bool needProvenanceRangeToCharBlockMappings{false}; diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -543,6 +543,11 @@ args.filtered(clang::driver::options::OPT_fintrinsic_modules_path)) opts.searchDirectoriesFromIntrModPath.emplace_back(currentArg->getValue()); + // Add the ordered list of -include's + for (const auto *currentArg : + args.filtered(clang::driver::options::OPT_include)) + opts.includes.emplace_back(currentArg->getValue()); + // -cpp/-nocpp if (const auto *currentArg = args.getLastArg( clang::driver::options::OPT_cpp, clang::driver::options::OPT_nocpp)) @@ -914,6 +919,11 @@ preprocessorOptions.searchDirectoriesFromIntrModPath.begin(), preprocessorOptions.searchDirectoriesFromIntrModPath.end()); + // Adding includes specified by -include + fortranOptions.includes.insert(fortranOptions.includes.end(), + preprocessorOptions.includes.begin(), + preprocessorOptions.includes.end()); + // Add the default intrinsic module directory fortranOptions.intrinsicModuleDirectories.emplace_back(getIntrinsicDir()); diff --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp --- a/flang/lib/Parser/parsing.cpp +++ b/flang/lib/Parser/parsing.cpp @@ -84,6 +84,24 @@ prescanner.AddCompilerDirectiveSentinel("$omp"); prescanner.AddCompilerDirectiveSentinel("$"); // OMP conditional line } + + // Prescan -include's + for (auto include : options.includes) { + const SourceFile *includeFile = + allSources.Open(include, fileError, "."s /*prepend to search path*/); + + if (!fileError.str().empty()) { + ProvenanceRange range{allSources.AddCompilerInsertion(include)}; + messages_.Say(range, "%s"_err_en_US, fileError.str()); + return sourceFile; + } + CHECK(includeFile); + + ProvenanceRange range{ + allSources.AddIncludedFile(*includeFile, ProvenanceRange{})}; + prescanner.Prescan(range); + } + ProvenanceRange range{allSources.AddIncludedFile( *sourceFile, ProvenanceRange{}, options.isModuleFile)}; prescanner.Prescan(range); diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -144,6 +144,7 @@ ! HELP-FC1-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages ! HELP-FC1-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. ! HELP-FC1-NEXT: -help Display available options +! HELP-FC1-NEXT: -include Include file before parsing ! HELP-FC1-NEXT: -init-only Only execute frontend initialization ! HELP-FC1-NEXT: -I Add directory to the end of the list of include search paths ! HELP-FC1-NEXT: -load Load the named plugin (dynamic shared object) diff --git a/flang/test/Driver/include-file.f90 b/flang/test/Driver/include-file.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/include-file.f90 @@ -0,0 +1,13 @@ +! Ensure argument -include works as expected with an included header file. + +! RUN: %flang_fc1 -E -include "%S/Inputs/basic-header-one.h" %s 2>&1 | FileCheck %s --check-prefix=INCLUDED +! RUN: not %flang_fc1 -E -include does-not-exist.h %s 2>&1 | FileCheck %s --check-prefix=MISSING + +! INCLUDED: program MainDirectoryOne +! INCLUDED-NOT: program X + +! MISSING: error: Source file 'does-not-exist.h' was not found +! MISSING-NOT: program + +program X +end