]> granicus.if.org Git - clang/commitdiff
A module with an umbrella header assumes that all of the headers in
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Nov 2011 23:02:25 +0000 (23:02 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Nov 2011 23:02:25 +0000 (23:02 +0000)
the umbrella header's directory and its subdirectories are part of the
module (that's why it's an umbrella). Make sure that these headers are
considered to be part of the module for lookup purposes.

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

include/clang/Basic/DiagnosticLexKinds.td
include/clang/Lex/ModuleMap.h
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/module.map
test/Modules/Inputs/normal-module-map/Umbrella/Umbrella.h
test/Modules/normal-module-map.cpp

index 48110fc5c5232931010b724c0b0a9c3776049bb0..5925ef8bd6d096258026b84f811ea445da577385 100644 (file)
@@ -397,5 +397,7 @@ def err_mmap_umbrella_header_conflict : Error<
   "module '%0' already has an umbrella header ('%1')">;
 def err_mmap_umbrella_header_submodule : Error<
   "submodule '%0' can not have an umbrella header">;
-  
+def err_mmap_umbrella_clash : Error<
+  "umbrella header for module '%0' already covers this directory">;
+
 }
index 6ca37f1005fc8ee765db252c67291f1a13dfca58..74cca6b881688c1f54a0e2425ef153d833e7898b 100644 (file)
@@ -27,6 +27,7 @@
 
 namespace clang {
   
+class DirectoryEntry;
 class FileEntry;
 class FileManager;
 class DiagnosticConsumer;
@@ -96,6 +97,14 @@ private:
   /// that header.
   llvm::DenseMap<const FileEntry *, Module *> Headers;
   
+  /// \brief Mapping from directories with umbrella headers to the module
+  /// that is generated from the umbrella header.
+  ///
+  /// This mapping is used to map headers that haven't explicitly been named
+  /// in the module map over to the module that includes them via its umbrella
+  /// header.
+  llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
+  
   friend class ModuleMapParser;
   
 public:
index bc43e01ac5c0c80683820d849063ef5e600bee3f..f6751b78f1e627fea93d078a923c11319ac79c27 100644 (file)
@@ -81,6 +81,41 @@ ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
   if (Known != Headers.end())
     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 {
+    // Retrieve our parent path.
+    DirName = llvm::sys::path::parent_path(DirName);
+    if (DirName.empty())
+      break;
+    
+    // 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);
+  
   return 0;
 }
 
@@ -493,10 +528,15 @@ void ModuleMapParser::parseUmbrellaDecl() {
       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
         << FileName << OwningModule->getFullModuleName();
       HadError = true;
+    } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
+      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;
     }
   } else {
     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
index aefaf9d73a16e4888261f24e5b1a00fe9d315d71..b14ab24a8a2eef94fd644ef21bc7659f0f01da58 100644 (file)
@@ -1,19 +1,19 @@
-module diamond_top { umbrella "diamond_top.h" }
-module diamond_left { umbrella "diamond_left.h" }
-module diamond_right { umbrella "diamond_right.h" }
-module diamond_bottom { umbrella "diamond_bottom.h" }
-module irgen { umbrella "irgen.h" }
-module lookup_left_objc { umbrella "lookup_left.h" }
-module lookup_right_objc { umbrella "lookup_right.h" }
-module lookup_left_cxx { umbrella "lookup_left.hpp" }
-module lookup_right_cxx { umbrella "lookup_right.hpp" }
-module module_private_left { umbrella "module_private_left.h" }
-module module_private_right { umbrella "module_private_right.h" }
-module macros { umbrella "macros.h" }
-module category_top { umbrella "category_top.h" }
-module category_left { umbrella "category_left.h" }
-module category_right { umbrella "category_right.h" }
-module category_bottom { umbrella "category_bottom.h" }
-module redeclarations_left { umbrella "redeclarations_left.h" }
-module redeclarations_right { umbrella "redeclarations_right.h" }
-module load_failure { umbrella "load_failure.h" }
+module diamond_top { header "diamond_top.h" }
+module diamond_left { header "diamond_left.h" }
+module diamond_right { header "diamond_right.h" }
+module diamond_bottom { header "diamond_bottom.h" }
+module irgen { header "irgen.h" }
+module lookup_left_objc { header "lookup_left.h" }
+module lookup_right_objc { header "lookup_right.h" }
+module lookup_left_cxx { header "lookup_left.hpp" }
+module lookup_right_cxx { header "lookup_right.hpp" }
+module module_private_left { header "module_private_left.h" }
+module module_private_right { header "module_private_right.h" }
+module macros { header "macros.h" }
+module category_top { header "category_top.h" }
+module category_left { header "category_left.h" }
+module category_right { header "category_right.h" }
+module category_bottom { header "category_bottom.h" }
+module redeclarations_left { header "redeclarations_left.h" }
+module redeclarations_right { header "redeclarations_right.h" }
+module load_failure { header "load_failure.h" }
index 5d201f58d2c787faed0349d274cb08aecd9d48f2..746237655855e2c86c7393f0213b34adcbd89696 100644 (file)
@@ -1 +1,4 @@
 int umbrella;
+
+#include "umbrella_sub.h"
+
index c8338b7061d1f5469c6a57a2baa1912a24a5af4c..c87657f5a9ba32b3f3ff10e754da5722e13fec0f 100644 (file)
@@ -4,10 +4,10 @@
 // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map
 // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map
 // RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify
-#include "Umbrella/Umbrella.h"
+#include "Umbrella/umbrella_sub.h"
 
 int getUmbrella() { 
-  return umbrella; 
+  return umbrella + umbrella_sub
 }
 
 __import_module__ Umbrella2;