summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Lex/ModuleMap.h5
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp2
-rw-r--r--clang/lib/Lex/ModuleMap.cpp23
-rw-r--r--clang/test/Modules/Inputs/exclude-header/module.map3
-rw-r--r--clang/test/Modules/Inputs/exclude-header/x/a.h1
-rw-r--r--clang/test/Modules/Inputs/exclude-header/x/bad.h1
-rw-r--r--clang/test/Modules/Inputs/exclude-header/y/b.h1
-rw-r--r--clang/test/Modules/exclude-header.c11
8 files changed, 40 insertions, 7 deletions
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 1cd6d385b6f..2fc1ca0c26f 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -242,6 +242,11 @@ public:
/// marked 'unavailable'.
bool isHeaderInUnavailableModule(const FileEntry *Header) const;
+ /// \brief Determine whether the given header is unavailable as part
+ /// of the specified module.
+ bool isHeaderUnavailableInModule(const FileEntry *Header,
+ Module *RequestingModule) const;
+
/// \brief Retrieve a module with the given name.
///
/// \param Name The name of the module to look up.
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 2657c9878b8..3f1d2c6106f 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -213,7 +213,7 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
// If this header is marked 'unavailable' in this module, don't include
// it.
if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
- if (ModMap.isHeaderInUnavailableModule(Header))
+ if (ModMap.isHeaderUnavailableInModule(Header, Module))
continue;
Module->addTopHeader(Header);
}
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index e78806dc50b..646f8953b91 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -396,30 +396,41 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
}
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
+ return isHeaderUnavailableInModule(Header, 0);
+}
+
+bool ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
+ Module *RequestingModule) const {
HeadersMap::const_iterator Known = Headers.find(Header);
if (Known != Headers.end()) {
for (SmallVectorImpl<KnownHeader>::const_iterator
I = Known->second.begin(),
E = Known->second.end();
I != E; ++I) {
- if (I->isAvailable())
+ if (I->isAvailable() && (!RequestingModule ||
+ I->getModule()->isSubModuleOf(RequestingModule)))
return false;
}
return true;
}
-
+
const DirectoryEntry *Dir = Header->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
StringRef DirName = Dir->getName();
+ auto IsUnavailable = [&](const Module *M) {
+ return !M->isAvailable() && (!RequestingModule ||
+ M->isSubModuleOf(RequestingModule));
+ };
+
// Keep walking up the directory hierarchy, looking for a directory with
// an umbrella header.
- do {
+ do {
llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
= UmbrellaDirs.find(Dir);
if (KnownDir != UmbrellaDirs.end()) {
Module *Found = KnownDir->second;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
// Search up the module stack until we find a module with an umbrella
@@ -438,7 +449,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
Found = lookupModuleQualified(Name, Found);
if (!Found)
return false;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
}
@@ -452,7 +463,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
return false;
}
- return !Found->isAvailable();
+ return IsUnavailable(Found);
}
SkippedDirs.push_back(Dir);
diff --git a/clang/test/Modules/Inputs/exclude-header/module.map b/clang/test/Modules/Inputs/exclude-header/module.map
new file mode 100644
index 00000000000..2aa1024458b
--- /dev/null
+++ b/clang/test/Modules/Inputs/exclude-header/module.map
@@ -0,0 +1,3 @@
+module x { umbrella "x" exclude header "x/bad.h" exclude header "y/b.h" module * {} }
+module y { umbrella "y" module * {} }
+module bad { header "x/bad.h" }
diff --git a/clang/test/Modules/Inputs/exclude-header/x/a.h b/clang/test/Modules/Inputs/exclude-header/x/a.h
new file mode 100644
index 00000000000..389d285a458
--- /dev/null
+++ b/clang/test/Modules/Inputs/exclude-header/x/a.h
@@ -0,0 +1 @@
+typedef int a;
diff --git a/clang/test/Modules/Inputs/exclude-header/x/bad.h b/clang/test/Modules/Inputs/exclude-header/x/bad.h
new file mode 100644
index 00000000000..179ef267be2
--- /dev/null
+++ b/clang/test/Modules/Inputs/exclude-header/x/bad.h
@@ -0,0 +1 @@
+#error bad
diff --git a/clang/test/Modules/Inputs/exclude-header/y/b.h b/clang/test/Modules/Inputs/exclude-header/y/b.h
new file mode 100644
index 00000000000..a16836aac77
--- /dev/null
+++ b/clang/test/Modules/Inputs/exclude-header/y/b.h
@@ -0,0 +1 @@
+typedef int b;
diff --git a/clang/test/Modules/exclude-header.c b/clang/test/Modules/exclude-header.c
new file mode 100644
index 00000000000..4134c82483d
--- /dev/null
+++ b/clang/test/Modules/exclude-header.c
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c -fmodules -fmodules-cache-path=%t -I %S/Inputs/exclude-header %s -verify
+
+@import x;
+
+a var_a;
+b var_b1; // expected-error {{unknown type name 'b'}}
+
+@import y;
+
+b var_b2;
OpenPOWER on IntegriCloud