From: Richard Smith Date: Tue, 8 Apr 2014 13:13:04 +0000 (+0000) Subject: If a header is explicitly included in module A, and excluded from an umbrella X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=578bfcbda27c0d5dfe4df995fb01f7ceae424382;p=clang If a header is explicitly included in module A, and excluded from an umbrella directory in module B, don't include it in module B! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205762 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 1cd6d385b6..2fc1ca0c26 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/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/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 2657c9878b..3f1d2c6106 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/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/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index e78806dc50..646f8953b9 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/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::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 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_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/test/Modules/Inputs/exclude-header/module.map b/test/Modules/Inputs/exclude-header/module.map new file mode 100644 index 0000000000..2aa1024458 --- /dev/null +++ b/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/test/Modules/Inputs/exclude-header/x/a.h b/test/Modules/Inputs/exclude-header/x/a.h new file mode 100644 index 0000000000..389d285a45 --- /dev/null +++ b/test/Modules/Inputs/exclude-header/x/a.h @@ -0,0 +1 @@ +typedef int a; diff --git a/test/Modules/Inputs/exclude-header/x/bad.h b/test/Modules/Inputs/exclude-header/x/bad.h new file mode 100644 index 0000000000..179ef267be --- /dev/null +++ b/test/Modules/Inputs/exclude-header/x/bad.h @@ -0,0 +1 @@ +#error bad diff --git a/test/Modules/Inputs/exclude-header/y/b.h b/test/Modules/Inputs/exclude-header/y/b.h new file mode 100644 index 0000000000..a16836aac7 --- /dev/null +++ b/test/Modules/Inputs/exclude-header/y/b.h @@ -0,0 +1 @@ +typedef int b; diff --git a/test/Modules/exclude-header.c b/test/Modules/exclude-header.c new file mode 100644 index 0000000000..4134c82483 --- /dev/null +++ b/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;