Implement inference for the "Private" submodule corresponding to
private headers in a framework.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146082 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index f6df302..b6ad71a 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -118,17 +118,28 @@
         
         // For a framework module, the umbrella directory is the framework 
         // directory, so strip off the "Headers" or "PrivateHeaders".
-        // FIXME: Should we tack on an "explicit" for PrivateHeaders? That
-        // might be what we want, but it feels like a hack.
+        bool Explicit = UmbrellaModule->InferExplicitSubmodules;
         unsigned LastSkippedDir = SkippedDirs.size();
-        if (LastSkippedDir && UmbrellaModule->IsFramework)
+        if (LastSkippedDir && UmbrellaModule->IsFramework) {
+          if (llvm::sys::path::filename(SkippedDirs.back()->getName())
+                == "PrivateHeaders") {
+            // For private headers, add an explicit "Private" module.
+            // FIXME: This feels somewhat hackish. Do we want to introduce
+            // some kind of "umbrella directory" here?
+            Result = findOrCreateModule("Private", Result, 
+                                        /*IsFramework=*/false,
+                                        /*IsExplicit=*/true).first;
+            Explicit = true;
+          }
+          
           --LastSkippedDir;
+        }
         
         for (unsigned I = LastSkippedDir; I != 0; --I) {
           // Find or create the module that corresponds to this directory name.
           StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
-                                      UmbrellaModule->InferExplicitSubmodules).first;
+                                      Explicit).first;
           
           // Associate the module and the directory.
           UmbrellaDirs[SkippedDirs[I-1]] = Result;
@@ -142,7 +153,7 @@
         // Infer a submodule with the same name as this header file.
         StringRef Name = llvm::sys::path::stem(File->getName());
         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
-                                    UmbrellaModule->InferExplicitSubmodules).first;
+                                    Explicit).first;
         
         // If inferred submodules export everything they import, add a 
         // wildcard to the set of exports.
@@ -278,6 +289,41 @@
     }
   }
   
+  // Look for private headers.
+  Module *ModulePrivate = 0;
+  llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
+  llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
+  for (llvm::sys::fs::directory_iterator Dir(PrivateHeadersDirName.str(), EC),
+       DirEnd;
+       Dir != DirEnd && !EC; Dir.increment(EC)) {
+    // Check whether this entry has an extension typically associated with 
+    // headers.
+    if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
+           .Cases(".h", ".H", ".hh", ".hpp", true)
+           .Default(false))
+      continue;
+
+    if (const FileEntry *PrivateHeader = FileMgr.getFile(Dir->path())) {
+      // Create the "private" submodule, if we haven't done so already.
+      if (!ModulePrivate) {
+        ModulePrivate = findOrCreateModule("Private", Result, 
+                                           /*IsFramework=*/false, 
+                                           /*IsExplicit=*/true).first;
+      }
+      
+      Module *Sub = findOrCreateModule(llvm::sys::path::stem(Dir->path()),
+                                       ModulePrivate, /*IsFramework=*/false,
+                                       /*IsExplicit=*/true).first;
+      // header "the private header"
+      Sub->Headers.push_back(PrivateHeader);
+      
+      // export *
+      Sub->Exports.push_back(Module::ExportDecl(0, true));
+      
+      Headers[PrivateHeader] = Sub;
+    }
+  }
+  
   return Result;
 }
 
diff --git a/test/Modules/Inputs/Module.framework/PrivateHeaders/ModulePrivate.h b/test/Modules/Inputs/Module.framework/PrivateHeaders/ModulePrivate.h
new file mode 100644
index 0000000..0782336
--- /dev/null
+++ b/test/Modules/Inputs/Module.framework/PrivateHeaders/ModulePrivate.h
@@ -0,0 +1 @@
+int module_private;
diff --git a/test/Modules/auto-module-import.m b/test/Modules/auto-module-import.m
index 4ddd0e1..3703127 100644
--- a/test/Modules/auto-module-import.m
+++ b/test/Modules/auto-module-import.m
@@ -44,3 +44,7 @@
 #include <DependsOnModule/DependsOnModulePrivate.h> // expected-warning{{treating #include as an import of module 'DependsOnModule.Private.DependsOnModule'}}
 
 int getDependsOnModulePrivate() { return depends_on_module_private; }
+
+#include <Module/ModulePrivate.h> // expected-warning{{treating #include as an import of module 'Module.Private.ModulePrivate'}}
+
+int getModulePrivate() { return module_private; }