diff options
-rw-r--r-- | include/clang/Basic/DiagnosticLexKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 9 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 40 | ||||
-rw-r--r-- | test/Modules/Inputs/module.map | 38 | ||||
-rw-r--r-- | test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h | 3 | ||||
-rw-r--r-- | test/Modules/normal-module-map.cpp | 4 |
6 files changed, 76 insertions, 22 deletions
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 48110fc5c5..5925ef8bd6 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -397,5 +397,7 @@ def err_mmap_umbrella_header_conflict : Error< "module '%0' already has an umbrella header ('%1')">; def err_mmap_umbrella_header_submodule : Error< "submodule '%0' can not have an umbrella header">; - +def err_mmap_umbrella_clash : Error< + "umbrella header for module '%0' already covers this directory">; + } diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 6ca37f1005..74cca6b881 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -27,6 +27,7 @@ namespace clang { +class DirectoryEntry; class FileEntry; class FileManager; class DiagnosticConsumer; @@ -96,6 +97,14 @@ private: /// that header. llvm::DenseMap<const FileEntry *, Module *> Headers; + /// \brief Mapping from directories with umbrella headers to the module + /// that is generated from the umbrella header. + /// + /// This mapping is used to map headers that haven't explicitly been named + /// in the module map over to the module that includes them via its umbrella + /// header. + llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; + friend class ModuleMapParser; public: diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index bc43e01ac5..f6751b78f1 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -81,6 +81,41 @@ ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) { if (Known != Headers.end()) return Known->second; + const DirectoryEntry *Dir = File->getDir(); + llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir + = UmbrellaDirs.find(Dir); + if (KnownDir != UmbrellaDirs.end()) + return KnownDir->second; + + // Walk up the directory hierarchy looking for umbrella headers. + llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; + StringRef DirName = Dir->getName(); + do { + // Retrieve our parent path. + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.empty()) + break; + + // Resolve the parent path to a directory entry. + Dir = SourceMgr->getFileManager().getDirectory(DirName); + if (!Dir) + break; + + KnownDir = UmbrellaDirs.find(Dir); + if (KnownDir != UmbrellaDirs.end()) { + Module *Result = KnownDir->second; + + // Record each of the directories we stepped through as being part of + // the module we found, since the umbrella header covers them all. + for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) + UmbrellaDirs[SkippedDirs[I]] = Result; + + return Result; + } + + SkippedDirs.push_back(Dir); + } while (true); + return 0; } @@ -493,10 +528,15 @@ void ModuleMapParser::parseUmbrellaDecl() { Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) << FileName << OwningModule->getFullModuleName(); HadError = true; + } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { + Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) + << OwningModule->getFullModuleName(); + HadError = true; } else { // Record this umbrella header. ActiveModule->UmbrellaHeader = File; Map.Headers[File] = ActiveModule; + Map.UmbrellaDirs[Directory] = ActiveModule; } } else { Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index aefaf9d73a..b14ab24a8a 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -1,19 +1,19 @@ -module diamond_top { umbrella "diamond_top.h" } -module diamond_left { umbrella "diamond_left.h" } -module diamond_right { umbrella "diamond_right.h" } -module diamond_bottom { umbrella "diamond_bottom.h" } -module irgen { umbrella "irgen.h" } -module lookup_left_objc { umbrella "lookup_left.h" } -module lookup_right_objc { umbrella "lookup_right.h" } -module lookup_left_cxx { umbrella "lookup_left.hpp" } -module lookup_right_cxx { umbrella "lookup_right.hpp" } -module module_private_left { umbrella "module_private_left.h" } -module module_private_right { umbrella "module_private_right.h" } -module macros { umbrella "macros.h" } -module category_top { umbrella "category_top.h" } -module category_left { umbrella "category_left.h" } -module category_right { umbrella "category_right.h" } -module category_bottom { umbrella "category_bottom.h" } -module redeclarations_left { umbrella "redeclarations_left.h" } -module redeclarations_right { umbrella "redeclarations_right.h" } -module load_failure { umbrella "load_failure.h" } +module diamond_top { header "diamond_top.h" } +module diamond_left { header "diamond_left.h" } +module diamond_right { header "diamond_right.h" } +module diamond_bottom { header "diamond_bottom.h" } +module irgen { header "irgen.h" } +module lookup_left_objc { header "lookup_left.h" } +module lookup_right_objc { header "lookup_right.h" } +module lookup_left_cxx { header "lookup_left.hpp" } +module lookup_right_cxx { header "lookup_right.hpp" } +module module_private_left { header "module_private_left.h" } +module module_private_right { header "module_private_right.h" } +module macros { header "macros.h" } +module category_top { header "category_top.h" } +module category_left { header "category_left.h" } +module category_right { header "category_right.h" } +module category_bottom { header "category_bottom.h" } +module redeclarations_left { header "redeclarations_left.h" } +module redeclarations_right { header "redeclarations_right.h" } +module load_failure { header "load_failure.h" } diff --git a/test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h b/test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h index 5d201f58d2..7462376558 100644 --- a/test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h +++ b/test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h @@ -1 +1,4 @@ int umbrella; + +#include "umbrella_sub.h" + diff --git a/test/Modules/normal-module-map.cpp b/test/Modules/normal-module-map.cpp index c8338b7061..c87657f5a9 100644 --- a/test/Modules/normal-module-map.cpp +++ b/test/Modules/normal-module-map.cpp @@ -4,10 +4,10 @@ // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify -#include "Umbrella/Umbrella.h" +#include "Umbrella/umbrella_sub.h" int getUmbrella() { - return umbrella; + return umbrella + umbrella_sub; } __import_module__ Umbrella2; |