From 9887d79af5fecf1413515e909644f6a23f491b69 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 17 Oct 2014 01:42:53 +0000 Subject: [PATCH] PR21215: Support -fmodule-map-file being specified multiple times. Support loading multiple module map files from the same directory. llvm-svn: 220020 --- clang/include/clang/Lex/HeaderSearch.h | 6 +++++- clang/lib/Driver/Tools.cpp | 13 +++++-------- clang/lib/Lex/HeaderSearch.cpp | 20 +++++++++++--------- clang/test/Driver/modules.m | 5 +++++ clang/test/Modules/Inputs/modular_maps/c.h | 4 ++++ clang/test/Modules/Inputs/modular_maps/common.h | 2 +- clang/test/Modules/Inputs/modular_maps/modulec.map | 3 +++ clang/test/Modules/modular_maps.cpp | 8 +++++--- 8 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 clang/test/Modules/Inputs/modular_maps/c.h create mode 100644 clang/test/Modules/Inputs/modular_maps/modulec.map diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index ad76714..086d348 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -231,7 +231,11 @@ class HeaderSearch { /// \brief Describes whether a given directory has a module map in it. llvm::DenseMap DirectoryHasModuleMap; - + + /// \brief Set of module map files we've already loaded, and a flag indicating + /// whether they were valid or not. + llvm::DenseMap LoadedModuleMaps; + /// \brief Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet FrameworkNames; diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index da2b651..28cb4df 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -3826,13 +3826,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). - if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) - A->render(Args, CmdArgs); + Args.AddLastArg(CmdArgs, options::OPT_fmodule_name); - // -fmodule-map-file can be used to specify a file containing module + // -fmodule-map-file can be used to specify files containing module // definitions. - if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) - A->render(Args, CmdArgs); + Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file); // -fmodule-cache-path specifies where our module files should be written. SmallString<128> ModuleCachePath; @@ -3867,9 +3865,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(VFSDir)); } - if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path)) - if (HaveModules) - A->render(Args, CmdArgs); + if (HaveModules) + Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path); // Pass through all -fmodules-ignore-macro arguments. Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index bdec26fa..e16b537 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1146,27 +1146,27 @@ HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) { assert(File && "expected FileEntry"); - const DirectoryEntry *Dir = File->getDir(); - auto KnownDir = DirectoryHasModuleMap.find(Dir); - if (KnownDir != DirectoryHasModuleMap.end()) - return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; + // Check whether we've already loaded this module map, and mark it as being + // loaded in case we recursively try to load it from itself. + auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true)); + if (!AddResult.second) + return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; if (ModMap.parseModuleMapFile(File, IsSystem)) { - DirectoryHasModuleMap[Dir] = false; + LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } // Try to load a corresponding private module map. if (const FileEntry *PMMFile = - getPrivateModuleMap(File->getName(), Dir, FileMgr)) { + getPrivateModuleMap(File->getName(), File->getDir(), FileMgr)) { if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) { - DirectoryHasModuleMap[Dir] = false; + LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } } // This directory has a module map. - DirectoryHasModuleMap[Dir] = true; return LMM_NewlyLoaded; } @@ -1226,7 +1226,7 @@ HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, bool IsFramework) { auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) - return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap; + return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem); @@ -1235,6 +1235,8 @@ HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, // ^Dir ^ModuleMapFile if (Result == LMM_NewlyLoaded) DirectoryHasModuleMap[Dir] = true; + else if (Result == LMM_InvalidModuleMap) + DirectoryHasModuleMap[Dir] = false; return Result; } return LMM_InvalidModuleMap; diff --git a/clang/test/Driver/modules.m b/clang/test/Driver/modules.m index fbd41d8..dafb934 100644 --- a/clang/test/Driver/modules.m +++ b/clang/test/Driver/modules.m @@ -33,3 +33,8 @@ // RUN: %clang -fmodules-validate-system-headers -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_SYSTEM_HEADERS %s // MODULES_VALIDATE_SYSTEM_HEADERS: -fmodules-validate-system-headers + +// RUN: %clang -fmodules -fmodule-map-file=foo.map -fmodule-map-file=bar.map -### %s 2>&1 | FileCheck -check-prefix=CHECK-MODULE-MAP-FILES %s +// CHECK-MODULE-MAP-FILES: "-fmodules" +// CHECK-MODULE-MAP-FILES: "-fmodule-map-file=" "foo.map" +// CHECK-MODULE-MAP-FILES: "-fmodule-map-file=" "bar.map" diff --git a/clang/test/Modules/Inputs/modular_maps/c.h b/clang/test/Modules/Inputs/modular_maps/c.h new file mode 100644 index 0000000..6e3468e --- /dev/null +++ b/clang/test/Modules/Inputs/modular_maps/c.h @@ -0,0 +1,4 @@ +#ifndef C_H +#define C_H +const int c = 5; +#endif diff --git a/clang/test/Modules/Inputs/modular_maps/common.h b/clang/test/Modules/Inputs/modular_maps/common.h index f690bcb..349bf5f 100644 --- a/clang/test/Modules/Inputs/modular_maps/common.h +++ b/clang/test/Modules/Inputs/modular_maps/common.h @@ -1,4 +1,4 @@ #ifndef COMMON_H #define COMMON_H -const int c = 2; +const int x = 2; #endif diff --git a/clang/test/Modules/Inputs/modular_maps/modulec.map b/clang/test/Modules/Inputs/modular_maps/modulec.map new file mode 100644 index 0000000..c5a1ffe --- /dev/null +++ b/clang/test/Modules/Inputs/modular_maps/modulec.map @@ -0,0 +1,3 @@ +module C { + header "c.h" +} diff --git a/clang/test/Modules/modular_maps.cpp b/clang/test/Modules/modular_maps.cpp index 9c9aba8..484e727 100644 --- a/clang/test/Modules/modular_maps.cpp +++ b/clang/test/Modules/modular_maps.cpp @@ -1,8 +1,10 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulea.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/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 #include "common.h" #include "a.h" #include "b.h" // expected-error {{private header}} -const int v = a + c; -const int val = a + b + c; // expected-error {{undeclared identifier}} +@import C; +const int v = a + c + x; +const int val = a + b + c + x; // expected-error {{undeclared identifier}} -- 2.7.4