diff options
-rw-r--r-- | clang/include/clang/Driver/CC1Options.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Lex/HeaderSearch.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Lex/HeaderSearchOptions.h | 10 | ||||
-rw-r--r-- | clang/include/clang/Lex/ModuleMap.h | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 26 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/modular_maps-moduleb-cwd.map | 4 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/modular_maps/modulea-cwd.map | 7 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/modular_maps/modulec-cwd.map | 3 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/relative-dep-gen-cwd.modulemap | 4 | ||||
-rw-r--r-- | clang/test/Modules/modular_maps.cpp | 9 | ||||
-rw-r--r-- | clang/test/Modules/relative-dep-gen.cpp | 9 |
13 files changed, 97 insertions, 28 deletions
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index fbab14b51be..10bda46012d 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -337,6 +337,9 @@ def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">, def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, MetaVarName<"<name>">, HelpText<"Specify the name of the module whose implementation file this is">; +def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">, + HelpText<"Use the current working directory as the home directory of " + "module maps specified by -fmodule-map-file=<FILE>">; let Group = Action_Group in { diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 190a0c98339..158f67d40b4 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -640,7 +640,8 @@ private: }; LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, - bool IsSystem); + bool IsSystem, + const DirectoryEntry *Dir); /// \brief Try to load the module map file in the given directory. /// diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h index 4e6e46939f7..775943de816 100644 --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -101,6 +101,15 @@ public: /// \brief Interpret module maps. This option is implied by full modules. unsigned ModuleMaps : 1; + /// \brief Set the 'home directory' of a module map file to the current + /// working directory (or the home directory of the module map file that + /// contained the 'extern module' directive importing this module map file + /// if any) rather than the directory containing the module map file. + // + /// The home directory is where we look for files named in the module map + /// file. + unsigned ModuleMapFileHomeIsCwd : 1; + /// \brief The interval (in seconds) between pruning operations. /// /// This operation is expensive, because it requires Clang to walk through @@ -158,6 +167,7 @@ public: public: HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0), + ModuleMapFileHomeIsCwd(0), ModuleCachePruneInterval(7*24*60*60), ModuleCachePruneAfter(31*24*60*60), BuildSessionTimestamp(0), diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index aad83c1fce2..b31158b9d29 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -454,8 +454,12 @@ public: /// \param IsSystem Whether this module map file is in a system header /// directory, and therefore should be considered a system module. /// + /// \param HomeDir The directory in which relative paths within this module + /// map file will be resolved. + /// /// \returns true if an error occurred, false otherwise. - bool parseModuleMapFile(const FileEntry *File, bool IsSystem); + bool parseModuleMapFile(const FileEntry *File, bool IsSystem, + const DirectoryEntry *HomeDir); /// \brief Dump the contents of the module map, for debugging purposes. void dump(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f01663858e0..59095941a83 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1003,6 +1003,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); // -fmodules implies -fmodule-maps Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules); + Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd); Opts.ModuleCachePruneInterval = getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60); Opts.ModuleCachePruneAfter = diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index a3f3737521e..02fd87c8226 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1113,11 +1113,10 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const { return ModMap.findModuleForHeader(File); } -static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath, - const DirectoryEntry *Directory, +static const FileEntry *getPrivateModuleMap(const FileEntry *File, FileManager &FileMgr) { - StringRef Filename = llvm::sys::path::filename(ModuleMapPath); - SmallString<128> PrivateFilename(Directory->getName()); + StringRef Filename = llvm::sys::path::filename(File->getName()); + SmallString<128> PrivateFilename(File->getDir()->getName()); if (Filename == "module.map") llvm::sys::path::append(PrivateFilename, "module_private.map"); else if (Filename == "module.modulemap") @@ -1128,7 +1127,25 @@ static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath, } bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { - switch (loadModuleMapFileImpl(File, IsSystem)) { + // Find the directory for the module. For frameworks, that may require going + // up from the 'Modules' directory. + const DirectoryEntry *Dir = nullptr; + if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) + Dir = FileMgr.getDirectory("."); + else { + Dir = File->getDir(); + StringRef DirName(Dir->getName()); + if (llvm::sys::path::filename(DirName) == "Modules") { + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.endswith(".framework")) + Dir = FileMgr.getDirectory(DirName); + // FIXME: This assert can fail if there's a race between the above check + // and the removal of the directory. + assert(Dir && "parent must exist"); + } + } + + switch (loadModuleMapFileImpl(File, IsSystem, Dir)) { case LMM_AlreadyLoaded: case LMM_NewlyLoaded: return false; @@ -1140,7 +1157,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { } HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) { +HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, + const DirectoryEntry *Dir) { assert(File && "expected FileEntry"); // Check whether we've already loaded this module map, and mark it as being @@ -1149,15 +1167,14 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) { if (!AddResult.second) return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - if (ModMap.parseModuleMapFile(File, IsSystem)) { + if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) { LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } // Try to load a corresponding private module map. - if (const FileEntry *PMMFile = - getPrivateModuleMap(File->getName(), File->getDir(), FileMgr)) { - if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) { + if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) { + if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) { LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } @@ -1231,7 +1248,8 @@ HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { - LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem); + LoadModuleMapResult Result = + loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir); // Add Dir explicitly in case ModuleMapFile is in a subdirectory. // E.g. Foo.framework/Modules/module.modulemap // ^Dir ^ModuleMapFile diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 9ac554ae96c..c5e317a0ba6 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/LiteralSupport.h" @@ -648,7 +649,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, bool IsFrameworkDir = Parent.endswith(".framework"); if (const FileEntry *ModMapFile = HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { - parseModuleMapFile(ModMapFile, IsSystem); + parseModuleMapFile(ModMapFile, IsSystem, ParentDir); inferred = InferredDirectories.find(ParentDir); } @@ -1024,7 +1025,8 @@ namespace clang { /// \brief The current module map file. const FileEntry *ModuleMapFile; - /// \brief The directory that this module map resides in. + /// \brief The directory that file names in this module map file should + /// be resolved relative to. const DirectoryEntry *Directory; /// \brief The directory containing Clang-supplied headers. @@ -1591,7 +1593,11 @@ void ModuleMapParser::parseExternModuleDecl() { FileNameRef = ModuleMapFileName.str(); } if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) - Map.parseModuleMapFile(File, /*IsSystem=*/false); + Map.parseModuleMapFile( + File, /*IsSystem=*/false, + Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd + ? Directory + : File->getDir()); } /// \brief Parse a requires declaration. @@ -2333,7 +2339,8 @@ bool ModuleMapParser::parseModuleMapFile() { } while (true); } -bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) { +bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, + const DirectoryEntry *Dir) { llvm::DenseMap<const FileEntry *, bool>::iterator Known = ParsedModuleMap.find(File); if (Known != ParsedModuleMap.end()) @@ -2346,17 +2353,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) { if (!Buffer) return ParsedModuleMap[File] = true; - // Find the directory for the module. For frameworks, that may require going - // up from the 'Modules' directory. - const DirectoryEntry *Dir = File->getDir(); - StringRef DirName(Dir->getName()); - if (llvm::sys::path::filename(DirName) == "Modules") { - DirName = llvm::sys::path::parent_path(DirName); - if (DirName.endswith(".framework")) - Dir = SourceMgr.getFileManager().getDirectory(DirName); - assert(Dir && "parent must exist"); - } - // Parse this module map file. Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, diff --git a/clang/test/Modules/Inputs/modular_maps-moduleb-cwd.map b/clang/test/Modules/Inputs/modular_maps-moduleb-cwd.map new file mode 100644 index 00000000000..1ff307f4b3d --- /dev/null +++ b/clang/test/Modules/Inputs/modular_maps-moduleb-cwd.map @@ -0,0 +1,4 @@ +module B { + header "Inputs/modular_maps/common.h" + private header "Inputs/modular_maps/b.h" +} diff --git a/clang/test/Modules/Inputs/modular_maps/modulea-cwd.map b/clang/test/Modules/Inputs/modular_maps/modulea-cwd.map new file mode 100644 index 00000000000..10be5237fc7 --- /dev/null +++ b/clang/test/Modules/Inputs/modular_maps/modulea-cwd.map @@ -0,0 +1,7 @@ +module A { + header "Inputs/modular_maps/common.h" + header "Inputs/modular_maps/a.h" +} + +extern module B "Inputs/modular_maps-moduleb-cwd.map" + diff --git a/clang/test/Modules/Inputs/modular_maps/modulec-cwd.map b/clang/test/Modules/Inputs/modular_maps/modulec-cwd.map new file mode 100644 index 00000000000..ca38b542df4 --- /dev/null +++ b/clang/test/Modules/Inputs/modular_maps/modulec-cwd.map @@ -0,0 +1,3 @@ +module C { + header "Inputs/modular_maps/c.h" +} diff --git a/clang/test/Modules/Inputs/relative-dep-gen-cwd.modulemap b/clang/test/Modules/Inputs/relative-dep-gen-cwd.modulemap new file mode 100644 index 00000000000..b8678d309d6 --- /dev/null +++ b/clang/test/Modules/Inputs/relative-dep-gen-cwd.modulemap @@ -0,0 +1,4 @@ +module "relative-dep-gen" { + header "Inputs/relative-dep-gen-1.h" + header "Inputs/relative-dep-gen-2.h" +} diff --git a/clang/test/Modules/modular_maps.cpp b/clang/test/Modules/modular_maps.cpp index 484e727c13e..3b6afc7552d 100644 --- a/clang/test/Modules/modular_maps.cpp +++ b/clang/test/Modules/modular_maps.cpp @@ -1,6 +1,15 @@ // RUN: rm -rf %t +// // RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulea.map -fmodule-map-file=%S/Inputs/modular_maps/modulec.map -I %S/Inputs/modular_maps %s -verify // RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulec.map -fmodule-map-file=%S/Inputs/modular_maps/modulea.map -I %S/Inputs/modular_maps %s -verify +// +// RUN: cd %S +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulea.map -fmodule-map-file=Inputs/modular_maps/modulec.map -I Inputs/modular_maps %s -verify +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulec.map -fmodule-map-file=Inputs/modular_maps/modulea.map -I Inputs/modular_maps %s -verify +// +// RUN: cd %S +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulea-cwd.map -fmodule-map-file=Inputs/modular_maps/modulec-cwd.map -I Inputs/modular_maps %s -verify -fmodule-map-file-home-is-cwd +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulec-cwd.map -fmodule-map-file=Inputs/modular_maps/modulea-cwd.map -I Inputs/modular_maps %s -verify -fmodule-map-file-home-is-cwd #include "common.h" #include "a.h" diff --git a/clang/test/Modules/relative-dep-gen.cpp b/clang/test/Modules/relative-dep-gen.cpp index 9a52f34a016..c8171777154 100644 --- a/clang/test/Modules/relative-dep-gen.cpp +++ b/clang/test/Modules/relative-dep-gen.cpp @@ -3,6 +3,7 @@ // RUN: cd %S // RUN: rm -rf %t // RUN: mkdir %t +// // RUN: %clang_cc1 -cc1 -fmodule-name=relative-dep-gen -emit-module -x c++ Inputs/relative-dep-gen.modulemap -dependency-file %t/build.d -MT mod.pcm -o %t/mod.pcm // RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen.modulemap -fmodule-file=%t/mod.pcm -dependency-file %t/use-explicit.d -MT use.o relative-dep-gen.cpp -fsyntax-only // RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen.modulemap -dependency-file %t/use-implicit.d relative-dep-gen.cpp -MT use.o -fsyntax-only @@ -10,6 +11,14 @@ // RUN: FileCheck --check-prefix=CHECK-BUILD %s < %t/build.d // RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-explicit.d // RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-implicit.d +// +// RUN: %clang_cc1 -cc1 -fmodule-name=relative-dep-gen -emit-module -x c++ Inputs/relative-dep-gen-cwd.modulemap -dependency-file %t/build-cwd.d -MT mod.pcm -o %t/mod-cwd.pcm -fmodule-map-file-home-is-cwd +// RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen-cwd.modulemap -fmodule-file=%t/mod-cwd.pcm -dependency-file %t/use-explicit-cwd.d -MT use.o relative-dep-gen.cpp -fsyntax-only -fmodule-map-file-home-is-cwd +// RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen-cwd.modulemap -dependency-file %t/use-implicit-cwd.d relative-dep-gen.cpp -MT use.o -fsyntax-only -fmodule-map-file-home-is-cwd +// +// RUN: FileCheck --check-prefix=CHECK-BUILD %s < %t/build-cwd.d +// RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-explicit-cwd.d +// RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-implicit-cwd.d #include "Inputs/relative-dep-gen-1.h" |