Add the notion of "framework" modules to module maps. Framework
modules (obviously) describe frameworks, and understand the header
layout of frameworks.

llvm-svn: 144921
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 3931181..b8068cc 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -162,7 +162,8 @@
   if (!UmbrellaHeader)
     return 0;
   
-  Module *Result = new Module(ModuleName, SourceLocation());
+  Module *Result = new Module(ModuleName, SourceLocation(), 
+                              /*IsFramework=*/true);
   Result->UmbrellaHeader = UmbrellaHeader;
   Headers[UmbrellaHeader] = Result;
   UmbrellaDirs[FrameworkDir] = Result;
@@ -177,6 +178,8 @@
 static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M, 
                        unsigned Indent) {
   indent(OS, Indent);
+  if (M->IsFramework)
+    OS << "framework ";
   if (M->IsExplicit)
     OS << "explicit ";
   OS << M->Name << " {\n";
@@ -230,6 +233,7 @@
       HeaderKeyword,
       Identifier,
       ExplicitKeyword,
+      FrameworkKeyword,
       ModuleKeyword,
       UmbrellaKeyword,
       StringLiteral,
@@ -333,6 +337,7 @@
     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
                  .Case("header", MMToken::HeaderKeyword)
                  .Case("explicit", MMToken::ExplicitKeyword)
+                 .Case("framework", MMToken::FrameworkKeyword)
                  .Case("module", MMToken::ModuleKeyword)
                  .Case("umbrella", MMToken::UmbrellaKeyword)
                  .Default(MMToken::Identifier);
@@ -416,18 +421,26 @@
 /// \brief Parse a module declaration.
 ///
 ///   module-declaration:
-///     'module' identifier { module-member* }
+///     'framework'[opt] 'module' identifier { module-member* }
 ///
 ///   module-member:
 ///     umbrella-declaration
 ///     header-declaration
 ///     'explicit'[opt] module-declaration
 void ModuleMapParser::parseModuleDecl() {
-  assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
-  
-  // Parse 'explicit' keyword, if present.
+  assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
+         Tok.is(MMToken::FrameworkKeyword));
+
+  // Parse 'framework' or 'explicit' keyword, if present.
+  bool Framework = false;
   bool Explicit = false;
-  if (Tok.is(MMToken::ExplicitKeyword)) {
+
+  if (Tok.is(MMToken::FrameworkKeyword)) {
+    consumeToken();
+    Framework = true;
+  } 
+  // Parse 'explicit' keyword, if present.
+  else if (Tok.is(MMToken::ExplicitKeyword)) {
     consumeToken();
     Explicit = true;
   }
@@ -481,7 +494,8 @@
   }
 
   // Start defining this module.
-  ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
+  ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
+                            Explicit);
   ModuleSpace[ModuleName] = ActiveModule;
   
   bool Done = false;
@@ -562,11 +576,32 @@
   // Look for this file.
   llvm::SmallString<128> PathName;
   PathName += Directory->getName();
-  llvm::sys::path::append(PathName, FileName);
+  unsigned PathLength = PathName.size();
+  const FileEntry *File = 0;
+  if (ActiveModule->isPartOfFramework()) {
+    // Check whether this file is in the public headers.
+    llvm::sys::path::append(PathName, "Headers");
+    llvm::sys::path::append(PathName, FileName);
+    File = SourceMgr.getFileManager().getFile(PathName);
+
+    if (!File) {
+      // Check whether this file is in the private headers.
+      PathName.resize(PathLength);
+      llvm::sys::path::append(PathName, "PrivateHeaders");
+      llvm::sys::path::append(PathName, FileName);
+      File = SourceMgr.getFileManager().getFile(PathName);
+    }
+    
+    // FIXME: Deal with subframeworks.
+  } else {
+    // Lookup for normal headers.
+    llvm::sys::path::append(PathName, FileName);
+    File = SourceMgr.getFileManager().getFile(PathName);
+  }
   
   // 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 (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
+  if (File) {
     if (const Module *OwningModule = Map.Headers[File]) {
       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
         << FileName << OwningModule->getFullModuleName();
@@ -609,6 +644,10 @@
   // Look for this file.
   llvm::SmallString<128> PathName;
   PathName += Directory->getName();
+  
+  if (ActiveModule->isPartOfFramework())
+    llvm::sys::path::append(PathName, "Headers");
+
   llvm::sys::path::append(PathName, FileName);
   
   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
@@ -641,6 +680,7 @@
       return HadError;
       
     case MMToken::ModuleKeyword:
+    case MMToken::FrameworkKeyword:
       parseModuleDecl();
       break;