aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td4
-rw-r--r--include/clang/Lex/ModuleMap.h9
-rw-r--r--lib/Lex/ModuleMap.cpp40
-rw-r--r--test/Modules/Inputs/module.map38
-rw-r--r--test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h3
-rw-r--r--test/Modules/normal-module-map.cpp4
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;