]> granicus.if.org Git - clang/commitdiff
If a header is explicitly included in module A, and excluded from an umbrella
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 8 Apr 2014 13:13:04 +0000 (13:13 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 8 Apr 2014 13:13:04 +0000 (13:13 +0000)
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

include/clang/Lex/ModuleMap.h
lib/Frontend/FrontendActions.cpp
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/exclude-header/module.map [new file with mode: 0644]
test/Modules/Inputs/exclude-header/x/a.h [new file with mode: 0644]
test/Modules/Inputs/exclude-header/x/bad.h [new file with mode: 0644]
test/Modules/Inputs/exclude-header/y/b.h [new file with mode: 0644]
test/Modules/exclude-header.c [new file with mode: 0644]

index 1cd6d385b6f01135f7193c368cc60f667bce5f60..2fc1ca0c26f04a3bc71c97471ef09167bda94a55 100644 (file)
@@ -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.
index 2657c9878b8e7db05440d622de2b4e0d234f48d4..3f1d2c6106f45eebdb99699ea44fe2031b2e96e5 100644 (file)
@@ -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);
       }
index e78806dc50b28d9ae79af3d489eddcdff9fd096c..646f8953b914e53596fd353c4c57f92f78c53e60 100644 (file)
@@ -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/test/Modules/Inputs/exclude-header/module.map b/test/Modules/Inputs/exclude-header/module.map
new file mode 100644 (file)
index 0000000..2aa1024
--- /dev/null
@@ -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 (file)
index 0000000..389d285
--- /dev/null
@@ -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 (file)
index 0000000..179ef26
--- /dev/null
@@ -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 (file)
index 0000000..a16836a
--- /dev/null
@@ -0,0 +1 @@
+typedef int b;
diff --git a/test/Modules/exclude-header.c b/test/Modules/exclude-header.c
new file mode 100644 (file)
index 0000000..4134c82
--- /dev/null
@@ -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;