]> granicus.if.org Git - clang/commitdiff
Add the notion of "framework" modules to module maps. Framework
authorDouglas Gregor <dgregor@apple.com>
Thu, 17 Nov 2011 22:09:43 +0000 (22:09 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 17 Nov 2011 22:09:43 +0000 (22:09 +0000)
modules (obviously) describe frameworks, and understand the header
layout of frameworks.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144921 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
include/clang/Lex/ModuleMap.h
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/DependsOnModule.framework/Headers/other.h [new file with mode: 0644]
test/Modules/Inputs/DependsOnModule.framework/module.map [new file with mode: 0644]

index 5925ef8bd6d096258026b84f811ea445da577385..0f9a8214c5505df7b4d80c347230de7170b9998a 100644 (file)
@@ -392,7 +392,7 @@ def note_mmap_prev_definition : Note<"previously defined here">;
 def err_mmap_header_conflict : Error<
   "header '%0' is already part of module '%1'">;
 def err_mmap_header_not_found : Error<
-  "%select{|umbrella }0 header '%1' not found">;
+  "%select{|umbrella }0header '%1' not found">;
 def err_mmap_umbrella_header_conflict : Error<
   "module '%0' already has an umbrella header ('%1')">;
 def err_mmap_umbrella_header_submodule : Error<
index b1eaebddb20a9cbd664abcbc6f87ae856046bed9..f4eb773e704e9da36519dddc883eacb2c94788ff 100644 (file)
@@ -59,19 +59,23 @@ public:
     /// \brief The headers that are part of this module.
     llvm::SmallVector<const FileEntry *, 2> Headers;
     
+    /// \brief Whether this is a framework module.
+    bool IsFramework;
+    
     /// \brief Whether this is an explicit submodule.
     bool IsExplicit;
     
     /// \brief Construct a top-level module.
-    explicit Module(StringRef Name, SourceLocation DefinitionLoc)
+    explicit Module(StringRef Name, SourceLocation DefinitionLoc,
+                    bool IsFramework)
       : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0),
-        IsExplicit(false) { }
+        IsFramework(IsFramework), IsExplicit(false) { }
     
     /// \brief Construct  a new module or submodule.
     Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, 
-           bool IsExplicit)
+           bool IsFramework, bool IsExplicit)
       : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), 
-        UmbrellaHeader(0), IsExplicit(IsExplicit) {
+        UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit) {
     }
      
     ~Module();
@@ -79,6 +83,18 @@ public:
     /// \brief Determine whether this module is a submodule.
     bool isSubModule() const { return Parent != 0; }
     
+    /// \brief Determine whether this module is a part of a framework,
+    /// either because it is a framework module or because it is a submodule
+    /// of a framework module.
+    bool isPartOfFramework() const {
+      for (const Module *Mod = this; Mod; Mod = Mod->Parent) 
+        if (Mod->IsFramework)
+          return true;
+      
+      return false;
+    }
+    
+    
     /// \brief Retrieve the full name of this module, including the path from
     /// its top-level module.
     std::string getFullModuleName() const;
index 393118110aff09e6c08e96b29a50ab8f007f7204..b8068cc05d8a39dd53add7b3c2b9e26d63677881 100644 (file)
@@ -162,7 +162,8 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
   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 indent(llvm::raw_ostream &OS, unsigned Spaces) {
 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 @@ namespace clang {
       HeaderKeyword,
       Identifier,
       ExplicitKeyword,
+      FrameworkKeyword,
       ModuleKeyword,
       UmbrellaKeyword,
       StringLiteral,
@@ -333,6 +337,7 @@ retry:
     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 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
 /// \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 @@ void ModuleMapParser::parseModuleDecl() {
   }
 
   // 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 @@ void ModuleMapParser::parseUmbrellaDecl() {
   // 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 @@ void ModuleMapParser::parseHeaderDecl() {
   // 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 @@ bool ModuleMapParser::parseModuleMapFile() {
       return HadError;
       
     case MMToken::ModuleKeyword:
+    case MMToken::FrameworkKeyword:
       parseModuleDecl();
       break;
       
diff --git a/test/Modules/Inputs/DependsOnModule.framework/Headers/other.h b/test/Modules/Inputs/DependsOnModule.framework/Headers/other.h
new file mode 100644 (file)
index 0000000..5ee3f92
--- /dev/null
@@ -0,0 +1 @@
+int depends_on_module_other;
diff --git a/test/Modules/Inputs/DependsOnModule.framework/module.map b/test/Modules/Inputs/DependsOnModule.framework/module.map
new file mode 100644 (file)
index 0000000..99ecac8
--- /dev/null
@@ -0,0 +1,4 @@
+framework module DependsOnModule {
+  umbrella "DependsOnModule.h"
+  header "other.h"
+}