Implement inferred submodules support, which (when requested)
implicitly generates submodules corresponding to the headers that fall
within a module.

llvm-svn: 145887
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 164eb27..498061f 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -93,15 +93,67 @@
     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 {
+
+  // Keep walking up the directory hierarchy, looking for a directory with
+  // an umbrella header.
+  do {    
+    llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
+      = UmbrellaDirs.find(Dir);
+    if (KnownDir != UmbrellaDirs.end()) {
+      Module *Result = KnownDir->second;
+      Module *TopModule = Result->getTopLevelModule();
+      if (TopModule->InferSubmodules) {
+        // Infer submodules for each of the directories we found between
+        // the directory of the umbrella header and the directory where 
+        // the actual header is located.
+        
+        // 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.
+        unsigned LastSkippedDir = SkippedDirs.size();
+        if (LastSkippedDir && TopModule->IsFramework)
+          --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,
+                                      TopModule->InferExplicitSubmodules).first;
+          
+          // Associate the module and the directory.
+          UmbrellaDirs[SkippedDirs[I-1]] = Result;
+
+          // If inferred submodules export everything they import, add a 
+          // wildcard to the set of exports.
+          if (TopModule->InferExportWildcard && Result->Exports.empty())
+            Result->Exports.push_back(Module::ExportDecl(0, true));
+        }
+        
+        // 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,
+                                    TopModule->InferExplicitSubmodules).first;
+        
+        // If inferred submodules export everything they import, add a 
+        // wildcard to the set of exports.
+        if (TopModule->InferExportWildcard && Result->Exports.empty())
+          Result->Exports.push_back(Module::ExportDecl(0, true));
+      } else {
+        // 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;
+      }
+      
+      Headers[File] = Result;
+      return Result;
+    }
+    
+    SkippedDirs.push_back(Dir);
+    
     // Retrieve our parent path.
     DirName = llvm::sys::path::parent_path(DirName);
     if (DirName.empty())
@@ -109,23 +161,7 @@
     
     // 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);
+  } while (Dir);
   
   return 0;
 }
@@ -205,10 +241,31 @@
   // export *
   Result->Exports.push_back(Module::ExportDecl(0, true));
   
+  // module * { export * }
+  Result->InferSubmodules = true;
+  Result->InferExportWildcard = true;
+  
   Modules[ModuleName] = Result;
   return Result;
 }
 
+void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
+  Headers[UmbrellaHeader] = Mod;
+  Mod->UmbrellaHeader = UmbrellaHeader;
+  
+  const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
+  if (Mod->IsFramework)
+    UmbrellaDir = SourceMgr->getFileManager().getDirectory(
+                    llvm::sys::path::parent_path(UmbrellaDir->getName()));
+    
+  UmbrellaDirs[UmbrellaDir] = Mod;
+}
+
+void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
+  Mod->Headers.push_back(Header);
+  Headers[Header] = Mod;
+}
+
 const FileEntry *
 ModuleMap::getContainingModuleMapFile(Module *Module) {
   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
@@ -683,19 +740,25 @@
   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
   // Come up with a lazy way to do this.
   if (File) {
+    const DirectoryEntry *UmbrellaDir = File->getDir();
+    if (ActiveModule->IsFramework) {
+      // For framework modules, use the framework directory as the umbrella
+      // directory.
+      UmbrellaDir = SourceMgr.getFileManager().getDirectory(
+                      llvm::sys::path::parent_path(UmbrellaDir->getName()));
+    }
+    
     if (const Module *OwningModule = Map.Headers[File]) {
       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
         << FileName << OwningModule->getFullModuleName();
       HadError = true;
-    } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
+    } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
       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;
+      Map.setUmbrellaHeader(ActiveModule, File);
     }
   } else {
     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
@@ -743,8 +806,7 @@
       HadError = true;
     } else {
       // Record this file.
-      ActiveModule->Headers.push_back(File);      
-      Map.Headers[File] = ActiveModule;
+      Map.addHeader(ActiveModule, File);
     }
   } else {
     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)