[cfe-commits] r146235 - in /cfe/trunk: include/clang/Basic/ lib/Lex/ test/Modules/ test/Modules/Inputs/NoUmbrella.framework/ test/Modules/Inputs/NoUmbrella.framework/Headers/ test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/

Douglas Gregor dgregor at apple.com
Thu Dec 8 18:04:43 PST 2011


Author: dgregor
Date: Thu Dec  8 20:04:43 2011
New Revision: 146235

URL: http://llvm.org/viewvc/llvm-project?rev=146235&view=rev
Log:
Implement the notion of umbrella directories, which implicity cover
all of the headers below that particular directory. Use umbrella
directories as a clean way to deal with (1) directories/frameworks
that don't have an umbrella header, but don't want to enumerate all of
their headers, and (2) PrivateHeaders, which we never want to
enumerate and want to keep separate from the main umbrella header. 

This also eliminates a little more of the "magic" for private headers,
and frameworks in general.

Added:
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h   (with props)
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h   (with props)
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h   (with props)
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h   (with props)
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map
    cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module_private.map
Modified:
    cfe/trunk/include/clang/Basic/Module.h
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/test/Modules/auto-module-import.m

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=146235&r1=146234&r2=146235&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Thu Dec  8 20:04:43 2011
@@ -194,6 +194,12 @@
     return Umbrella.dyn_cast<const FileEntry *>();
   }
 
+  /// \brief Determine whether this module has an umbrella directory that is
+  /// not based on an umbrella header.
+  bool hasUmbrellaDir() const {
+    return Umbrella && Umbrella.is<const DirectoryEntry *>();
+  }
+  
   /// \brief Print the module map for this module to the given stream. 
   ///
   void print(llvm::raw_ostream &OS, unsigned Indent = 0) const;

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=146235&r1=146234&r2=146235&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Thu Dec  8 20:04:43 2011
@@ -115,27 +115,9 @@
         // 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".
         bool Explicit = UmbrellaModule->InferExplicitSubmodules;
-        unsigned LastSkippedDir = SkippedDirs.size();
-        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) {
+        for (unsigned I = SkippedDirs.size(); 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,
@@ -294,41 +276,16 @@
   }
   
   // Look for private headers.
-  Module *ModulePrivate = 0;
   llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
   llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
-  llvm::SmallString<128> PrivateHeadersDirNameNative;
-  llvm::sys::path::native(PrivateHeadersDirName.str(),
-                          PrivateHeadersDirNameNative);
-  for (llvm::sys::fs::directory_iterator 
-         Dir(PrivateHeadersDirNameNative.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;
-    }
+  if (const DirectoryEntry *Dir = FileMgr.getDirectory(PrivateHeadersDirName)) {
+    Module *Private = findOrCreateModule("Private", Result, 
+                                         /*IsFramework=*/false, 
+                                         /*IsExplicit=*/true).first;
+    setUmbrellaDir(Private, Dir);
+    Private->InferSubmodules = true;
+    Private->InferExplicitSubmodules = true;
+    Private->InferExportWildcard = true;
   }
   
   return Result;
@@ -337,13 +294,7 @@
 void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
   Headers[UmbrellaHeader] = Mod;
   Mod->Umbrella = UmbrellaHeader;
-  
-  const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
-  if (Mod->IsFramework)
-    UmbrellaDir = SourceMgr->getFileManager().getDirectory(
-                    llvm::sys::path::parent_path(UmbrellaDir->getName()));
-    
-  UmbrellaDirs[UmbrellaDir] = Mod;
+  UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
 }
 
 void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
@@ -503,6 +454,8 @@
     void parseExportDecl();
     void parseInferredSubmoduleDecl(bool Explicit);
     
+    const DirectoryEntry *getOverriddenHeaderSearchDir();
+    
   public:
     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 
                              DiagnosticsEngine &Diags,
@@ -888,9 +841,13 @@
   if (llvm::sys::path::is_absolute(FileName)) {
     PathName = FileName;
     File = SourceMgr.getFileManager().getFile(PathName);
+  } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
+    PathName = Dir->getName();
+    llvm::sys::path::append(PathName, FileName);
+    File = SourceMgr.getFileManager().getFile(PathName);
   } else {
     // Search for the header file within the search directory.
-    PathName += Directory->getName();
+    PathName = Directory->getName();
     unsigned PathLength = PathName.size();
     
     if (ActiveModule->isPartOfFramework()) {
@@ -924,13 +881,6 @@
       HadError = true;
     } else if (Umbrella) {
       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 ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
         Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
           << OwningModule->getFullModuleName();
@@ -1141,6 +1091,22 @@
   }
 }
 
+/// \brief If there is a specific header search directory due the presence
+/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
+const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
+  for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
+    // If we have an umbrella directory, use that.
+    if (Mod->hasUmbrellaDir())
+      return Mod->getUmbrellaDir();
+    
+    // If we have a framework directory, stop looking.
+    if (Mod->IsFramework)
+      return 0;
+  }
+  
+  return 0;
+}
+
 /// \brief Parse a module map file.
 ///
 ///   module-map-file:

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h Thu Dec  8 20:04:43 2011
@@ -0,0 +1 @@
+int no_umbrella_A;

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/A.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h Thu Dec  8 20:04:43 2011
@@ -0,0 +1 @@
+int no_umbrella_B;

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/Headers/B.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h Thu Dec  8 20:04:43 2011
@@ -0,0 +1 @@
+int no_umbrella_A_private;

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h Thu Dec  8 20:04:43 2011
@@ -0,0 +1 @@
+int no_umbrella_B_private;

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map Thu Dec  8 20:04:43 2011
@@ -0,0 +1,4 @@
+framework module NoUmbrella {
+  umbrella "Headers"
+  module * { }
+}
\ No newline at end of file

Added: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module_private.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module_private.map?rev=146235&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module_private.map (added)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module_private.map Thu Dec  8 20:04:43 2011
@@ -0,0 +1,4 @@
+explicit module NoUmbrella.Private {
+  umbrella "PrivateHeaders"
+  explicit module * { }
+}

Modified: cfe/trunk/test/Modules/auto-module-import.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/auto-module-import.m?rev=146235&r1=146234&r2=146235&view=diff
==============================================================================
--- cfe/trunk/test/Modules/auto-module-import.m (original)
+++ cfe/trunk/test/Modules/auto-module-import.m Thu Dec  8 20:04:43 2011
@@ -1,3 +1,4 @@
+// other file: expected-note{{'no_umbrella_A_private' declared here}}
 
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -Wauto-import -fmodule-cache-path %t -fauto-module-import -F %S/Inputs %s -verify
@@ -23,6 +24,10 @@
   double *sfo1 = sub_framework_other; // expected-error{{use of undeclared identifier 'sub_framework_other'}}
 }
 
+// Test umbrella-less submodule includes
+#include <NoUmbrella/A.h> // expected-warning{{treating #include as an import of module 'NoUmbrella.A'}}
+int getNoUmbrellaA() { return no_umbrella_A; } 
+
 // Test header cross-subframework include pattern.
 #include <DependsOnModule/../Frameworks/SubFramework.framework/Headers/Other.h> // expected-warning{{treating #include as an import of module 'DependsOnModule.SubFramework.Other'}}
 
@@ -48,3 +53,8 @@
 #include <Module/ModulePrivate.h> // expected-warning{{treating #include as an import of module 'Module.Private.ModulePrivate'}}
 
 int getModulePrivate() { return module_private; }
+
+#include <NoUmbrella/A_Private.h> // expected-warning{{treating #include as an import of module 'NoUmbrella.Private.A_Private'}}
+int getNoUmbrellaAPrivate() { return no_umbrella_A_private; }
+
+int getNoUmbrellaBPrivateFail() { return no_umbrella_B_private; } // expected-error{{use of undeclared identifier 'no_umbrella_B_private'; did you mean 'no_umbrella_A_private'?}}





More information about the cfe-commits mailing list