[cfe-commits] r167482 - in /cfe/trunk: include/clang/Basic/DiagnosticLexKinds.td include/clang/Lex/ModuleMap.h lib/Lex/HeaderSearch.cpp lib/Lex/ModuleMap.cpp test/Index/Inputs/Frameworks/module.map test/Modules/Inputs/NotAModule.framework/ test/Modules/Inputs/NotAModule.framework/Headers/ test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h test/Modules/Inputs/module.map test/Modules/inferred-frameworks.m

Douglas Gregor dgregor at apple.com
Tue Nov 6 11:39:40 PST 2012


Author: dgregor
Date: Tue Nov  6 13:39:40 2012
New Revision: 167482

URL: http://llvm.org/viewvc/llvm-project?rev=167482&view=rev
Log:
Introduce inferred framework modules into the module map file,
allowing a module map to be placed one level above the '.framework'
directories to specify that all .frameworks within that directory can
be inferred as framework modules. One can also specifically exclude
frameworks known not to work.

This makes explicit (and more restricted) behavior modules have had
"forever", where *any* .framework was assumed to be able to be built
as a module. That's not necessarily true, so we white-list directories
(with exclusions) when those directories have been audited.

Added:
    cfe/trunk/test/Index/Inputs/Frameworks/module.map
    cfe/trunk/test/Modules/Inputs/NotAModule.framework/
    cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/
    cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h
    cfe/trunk/test/Modules/inferred-frameworks.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/include/clang/Lex/ModuleMap.h
    cfe/trunk/lib/Lex/HeaderSearch.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/test/Modules/Inputs/module.map

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=167482&r1=167481&r2=167482&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Tue Nov  6 13:39:40 2012
@@ -491,15 +491,21 @@
 def err_mmap_missing_module_qualified : Error<
   "no module named '%0' in '%1'">;
 def err_mmap_top_level_inferred_submodule : Error<
-  "only submodules may be inferred with wildcard syntax">;
+  "only submodules and framework modules may be inferred with wildcard syntax">;
 def err_mmap_inferred_no_umbrella : Error<
   "inferred submodules require a module with an umbrella">;
+def err_mmap_inferred_framework_submodule : Error<
+  "inferred submodule cannot be a framework submodule">;
+def err_mmap_explicit_inferred_framework : Error<
+  "inferred framework modules cannot be 'explicit'">;
+def err_mmap_missing_exclude_name : Error<
+  "expected excluded module name">;
 def err_mmap_inferred_redef : Error<
   "redefinition of inferred submodule">;
 def err_mmap_expected_lbrace_wildcard : Error<
   "expected '{' to start inferred submodule">;
-def err_mmap_expected_wildcard_member : Error<
-  "expected module export wildcard">;
+def err_mmap_expected_inferred_member : Error<
+  "expected %select{module exclusion with 'exclude'|'export *'}0">;
 def err_mmap_expected_export_wildcard : Error<
   "only '*' can be exported from an inferred submodule">;
 def err_mmap_explicit_top_level : Error<

Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=167482&r1=167481&r2=167482&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Tue Nov  6 13:39:40 2012
@@ -91,7 +91,26 @@
   /// in the module map over to the module that includes them via its umbrella
   /// header.
   llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
-  
+
+  /// \brief A directory for which framework modules can be inferred.
+  struct InferredDirectory {
+    InferredDirectory() : InferModules(), InferSystemModules() { }
+
+    /// \brief Whether to infer modules from this directory.
+    unsigned InferModules : 1;
+
+    /// \brief Whether the modules we infer are [system] modules.
+    unsigned InferSystemModules : 1;
+
+    /// \brief The names of modules that cannot be inferred within this
+    /// directory.
+    llvm::SmallVector<std::string, 2> ExcludedModules;
+  };
+
+  /// \brief A mapping from directories to information about inferring
+  /// framework modules from within those directories.
+  llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories;
+
   friend class ModuleMapParser;
   
   /// \brief Resolve the given export declaration into an actual export
@@ -197,7 +216,23 @@
   std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, 
                                                bool IsFramework,
                                                bool IsExplicit);
-                       
+
+  /// \brief Determine whether we can infer a framework module a framework
+  /// with the given name in the given
+  ///
+  /// \param ParentDir The directory that is the parent of the framework
+  /// directory.
+  ///
+  /// \param Name The name of the module.
+  ///
+  /// \param IsSystem Will be set to 'true' if the inferred module must be a
+  /// system module.
+  ///
+  /// \returns true if we are allowed to infer a framework module, and false
+  /// otherwise.
+  bool canInferFrameworkModule(const DirectoryEntry *ParentDir,
+                               StringRef Name, bool &IsSystem);
+
   /// \brief Infer the contents of a framework module map from the given
   /// framework directory.
   Module *inferFrameworkModule(StringRef ModuleName, 

Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=167482&r1=167481&r2=167482&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Tue Nov  6 13:39:40 2012
@@ -939,7 +939,33 @@
       TopFrameworkDir = Dir;
     }
   } while (true);
-  
+
+  // Determine whether we're allowed to infer a module map.
+  bool canInfer = false;
+  if (llvm::sys::path::has_parent_path(TopFrameworkDir->getName())) {
+    // Figure out the parent path.
+    StringRef Parent = llvm::sys::path::parent_path(TopFrameworkDir->getName());
+    if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
+      // If there's a module map file in the parent directory, it can
+      // explicitly allow us to infer framework modules.
+      switch (loadModuleMapFile(ParentDir)) {
+        case LMM_AlreadyLoaded:
+        case LMM_NewlyLoaded: {
+          StringRef Name = llvm::sys::path::stem(TopFrameworkDir->getName());
+          canInfer = ModMap.canInferFrameworkModule(ParentDir, Name, IsSystem);
+          break;
+        }
+        case LMM_InvalidModuleMap:
+        case LMM_NoDirectory:
+          break;
+      }
+    }
+  }
+
+  // If we're not allowed to infer a module map, we're done.
+  if (!canInfer)
+    return 0;
+
   // Try to infer a module map from the top-level framework directory.
   Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), 
                                                TopFrameworkDir,

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=167482&r1=167481&r2=167482&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Nov  6 13:39:40 2012
@@ -346,8 +346,32 @@
   return std::make_pair(Result, true);
 }
 
+bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
+                                        StringRef Name, bool &IsSystem) {
+  // Check whether we have already looked into the parent directory
+  // for a module map.
+  llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
+    inferred = InferredDirectories.find(ParentDir);
+  if (inferred == InferredDirectories.end())
+    return false;
+
+  if (!inferred->second.InferModules)
+    return false;
+
+  // We're allowed to infer for this directory, but make sure it's okay
+  // to infer this particular module.
+  bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
+                            inferred->second.ExcludedModules.end(),
+                            Name) == inferred->second.ExcludedModules.end();
+
+  if (canInfer && inferred->second.InferSystemModules)
+    IsSystem = true;
+
+  return canInfer;
+}
+
 Module *
-ModuleMap::inferFrameworkModule(StringRef ModuleName, 
+ModuleMap::inferFrameworkModule(StringRef ModuleName,
                                 const DirectoryEntry *FrameworkDir,
                                 bool IsSystem,
                                 Module *Parent) {
@@ -356,7 +380,54 @@
     return Mod;
   
   FileManager &FileMgr = SourceMgr->getFileManager();
-  
+
+  // If the framework has a parent path from which we're allowed to infer
+  // a framework module, do so.
+  if (!Parent) {
+    bool canInfer = false;
+    if (llvm::sys::path::has_parent_path(FrameworkDir->getName())) {
+      // Figure out the parent path.
+      StringRef Parent = llvm::sys::path::parent_path(FrameworkDir->getName());
+      if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
+        // Check whether we have already looked into the parent directory
+        // for a module map.
+        llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
+          inferred = InferredDirectories.find(ParentDir);
+        if (inferred == InferredDirectories.end()) {
+          // We haven't looked here before. Load a module map, if there is
+          // one.
+          SmallString<128> ModMapPath = Parent;
+          llvm::sys::path::append(ModMapPath, "module.map");
+          if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
+            parseModuleMapFile(ModMapFile);
+            inferred = InferredDirectories.find(ParentDir);
+          }
+
+          if (inferred == InferredDirectories.end())
+            inferred = InferredDirectories.insert(
+                         std::make_pair(ParentDir, InferredDirectory())).first;
+        }
+
+        if (inferred->second.InferModules) {
+          // We're allowed to infer for this directory, but make sure it's okay
+          // to infer this particular module.
+          StringRef Name = llvm::sys::path::filename(FrameworkDir->getName());
+          canInfer = std::find(inferred->second.ExcludedModules.begin(),
+                               inferred->second.ExcludedModules.end(),
+                               Name) == inferred->second.ExcludedModules.end();
+
+          if (inferred->second.InferSystemModules)
+            IsSystem = true;
+        }
+      }
+    }
+
+    // If we're not allowed to infer a framework module, don't.
+    if (!canInfer)
+      return 0;
+  }
+
+
   // Look for an umbrella header.
   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
   llvm::sys::path::append(UmbrellaName, "Headers");
@@ -582,7 +653,16 @@
       return StringRef(StringData, StringLength);
     }
   };
+
+  /// \brief The set of attributes that can be attached to a module.
+  struct Attributes {
+    Attributes() : IsSystem() { }
+
+    /// \brief Whether this is a system module.
+    unsigned IsSystem : 1;
+  };
   
+
   class ModuleMapParser {
     Lexer &L;
     SourceManager &SourceMgr;
@@ -628,8 +708,9 @@
     void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
     void parseExportDecl();
-    void parseInferredSubmoduleDecl(bool Explicit);
-    
+    void parseInferredModuleDecl(bool Framework, bool Explicit);
+    bool parseOptionalAttributes(Attributes &Attrs);
+
     const DirectoryEntry *getOverriddenHeaderSearchDir();
     
   public:
@@ -834,13 +915,6 @@
 ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 
 ///       { module-member* }
 ///
-///   attributes:
-///     attribute attributes
-///     attribute
-///
-///   attribute:
-///     [ identifier ]
-///
 ///   module-member:
 ///     requires-declaration
 ///     header-declaration
@@ -882,7 +956,7 @@
   // If we have a wildcard for the module name, this is an inferred submodule.
   // Parse it. 
   if (Tok.is(MMToken::Star))
-    return parseInferredSubmoduleDecl(Explicit);
+    return parseInferredModuleDecl(Framework, Explicit);
   
   // Parse the module name.
   ModuleId Id;
@@ -890,7 +964,7 @@
     HadError = true;
     return;
   }
-  
+
   if (ActiveModule) {
     if (Id.size() > 1) {
       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
@@ -933,47 +1007,8 @@
   SourceLocation ModuleNameLoc = Id.back().second;
   
   // Parse the optional attribute list.
-  bool IsSystem = false;
-  while (Tok.is(MMToken::LSquare)) {
-    // Consume the '['.
-    SourceLocation LSquareLoc = consumeToken();
-    
-    // Check whether we have an attribute name here.
-    if (!Tok.is(MMToken::Identifier)) {
-      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
-      skipUntil(MMToken::RSquare);
-      if (Tok.is(MMToken::RSquare))
-        consumeToken();
-      continue;
-    }
-    
-    // Decode the attribute name.
-    AttributeKind Attribute 
-      = llvm::StringSwitch<AttributeKind>(Tok.getString())
-        .Case("system", AT_system)
-        .Default(AT_unknown);
-    switch (Attribute) {
-    case AT_unknown:
-      Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
-        << Tok.getString();
-      break;
-        
-    case AT_system:
-      IsSystem = true;
-      break;
-    }
-    consumeToken();
-    
-    // Consume the ']'.
-    if (!Tok.is(MMToken::RSquare)) {
-      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
-      Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
-      skipUntil(MMToken::RSquare);
-    }
-
-    if (Tok.is(MMToken::RSquare))
-      consumeToken();
-  }
+  Attributes Attrs;
+  parseOptionalAttributes(Attrs);
   
   // Parse the opening brace.
   if (!Tok.is(MMToken::LBrace)) {
@@ -1016,7 +1051,7 @@
   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
                                         Explicit).first;
   ActiveModule->DefinitionLoc = ModuleNameLoc;
-  if (IsSystem)
+  if (Attrs.IsSystem)
     ActiveModule->IsSystem = true;
   
   bool Done = false;
@@ -1379,32 +1414,52 @@
   ActiveModule->UnresolvedExports.push_back(Unresolved);
 }
 
-void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
+/// \brief Parse an inferried module declaration (wildcard modules).
+///
+///   module-declaration:
+///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
+///       { inferred-module-member* }
+///
+///   inferred-module-member:
+///     'export' '*'
+///     'exclude' identifier
+void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
   assert(Tok.is(MMToken::Star));
   SourceLocation StarLoc = consumeToken();
   bool Failed = false;
-  
+
   // Inferred modules must be submodules.
-  if (!ActiveModule) {
+  if (!ActiveModule && !Framework) {
     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
     Failed = true;
   }
-  
-  // Inferred modules must have umbrella directories.
-  if (!Failed && !ActiveModule->getUmbrellaDir()) {
-    Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
-    Failed = true;
-  }
-  
-  // Check for redefinition of an inferred module.
-  if (!Failed && ActiveModule->InferSubmodules) {
-    Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
-    if (ActiveModule->InferredSubmoduleLoc.isValid())
-      Diags.Report(ActiveModule->InferredSubmoduleLoc,
-                   diag::note_mmap_prev_definition);
-    Failed = true;
+
+  if (ActiveModule) {
+    // Inferred modules must have umbrella directories.
+    if (!Failed && !ActiveModule->getUmbrellaDir()) {
+      Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
+      Failed = true;
+    }
+    
+    // Check for redefinition of an inferred module.
+    if (!Failed && ActiveModule->InferSubmodules) {
+      Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
+      if (ActiveModule->InferredSubmoduleLoc.isValid())
+        Diags.Report(ActiveModule->InferredSubmoduleLoc,
+                     diag::note_mmap_prev_definition);
+      Failed = true;
+    }
+
+    // Check for the 'framework' keyword, which is not permitted here.
+    if (Framework) {
+      Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
+      Framework = false;
+    }
+  } else if (Explicit) {
+    Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
+    Explicit = false;
   }
-  
+
   // If there were any problems with this inferred submodule, skip its body.
   if (Failed) {
     if (Tok.is(MMToken::LBrace)) {
@@ -1416,12 +1471,22 @@
     HadError = true;
     return;
   }
-  
-  // Note that we have an inferred submodule.
-  ActiveModule->InferSubmodules = true;
-  ActiveModule->InferredSubmoduleLoc = StarLoc;
-  ActiveModule->InferExplicitSubmodules = Explicit;
-  
+
+  // Parse optional attributes.
+  Attributes Attrs;
+  parseOptionalAttributes(Attrs);
+
+  if (ActiveModule) {
+    // Note that we have an inferred submodule.
+    ActiveModule->InferSubmodules = true;
+    ActiveModule->InferredSubmoduleLoc = StarLoc;
+    ActiveModule->InferExplicitSubmodules = Explicit;
+  } else {
+    // We'll be inferring framework modules for this directory.
+    Map.InferredDirectories[Directory].InferModules = true;
+    Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
+  }
+
   // Parse the opening brace.
   if (!Tok.is(MMToken::LBrace)) {
     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
@@ -1438,8 +1503,35 @@
     case MMToken::RBrace:
       Done = true;
       break;
-      
-    case MMToken::ExportKeyword: {
+
+    case MMToken::ExcludeKeyword: {
+      if (ActiveModule) {
+        Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
+          << (ActiveModule != nullptr);
+        consumeToken();
+        break;
+      }
+
+      consumeToken();
+      if (!Tok.is(MMToken::Identifier)) {
+        Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
+        break;
+      }
+
+      Map.InferredDirectories[Directory].ExcludedModules
+        .push_back(Tok.getString());
+      consumeToken();
+      break;
+    }
+
+    case MMToken::ExportKeyword:
+      if (!ActiveModule) {
+        Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
+          << (ActiveModule != nullptr);
+        consumeToken();
+        break;
+      }
+
       consumeToken();
       if (Tok.is(MMToken::Star)) 
         ActiveModule->InferExportWildcard = true;
@@ -1448,14 +1540,14 @@
                      diag::err_mmap_expected_export_wildcard);
       consumeToken();
       break;
-    }
-      
+
     case MMToken::ExplicitKeyword:
     case MMToken::ModuleKeyword:
     case MMToken::HeaderKeyword:
     case MMToken::UmbrellaKeyword:
     default:
-      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
+      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
+          << (ActiveModule != nullptr);
       consumeToken();
       break;        
     }
@@ -1470,6 +1562,66 @@
   }
 }
 
+/// \brief Parse optional attributes.
+///
+///   attributes:
+///     attribute attributes
+///     attribute
+///
+///   attribute:
+///     [ identifier ]
+///
+/// \param Attrs Will be filled in with the parsed attributes.
+///
+/// \returns true if an error occurred, false otherwise.
+bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
+  bool HadError = false;
+  
+  while (Tok.is(MMToken::LSquare)) {
+    // Consume the '['.
+    SourceLocation LSquareLoc = consumeToken();
+
+    // Check whether we have an attribute name here.
+    if (!Tok.is(MMToken::Identifier)) {
+      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
+      skipUntil(MMToken::RSquare);
+      if (Tok.is(MMToken::RSquare))
+        consumeToken();
+      HadError = true;
+    }
+
+    // Decode the attribute name.
+    AttributeKind Attribute
+      = llvm::StringSwitch<AttributeKind>(Tok.getString())
+          .Case("system", AT_system)
+          .Default(AT_unknown);
+    switch (Attribute) {
+    case AT_unknown:
+      Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
+        << Tok.getString();
+      break;
+
+    case AT_system:
+      Attrs.IsSystem = true;
+      break;
+    }
+    consumeToken();
+
+    // Consume the ']'.
+    if (!Tok.is(MMToken::RSquare)) {
+      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
+      Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
+      skipUntil(MMToken::RSquare);
+      HadError = true;
+    }
+
+    if (Tok.is(MMToken::RSquare))
+      consumeToken();
+  }
+
+  return HadError;
+}
+
 /// \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() {

Added: cfe/trunk/test/Index/Inputs/Frameworks/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/Frameworks/module.map?rev=167482&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/Frameworks/module.map (added)
+++ cfe/trunk/test/Index/Inputs/Frameworks/module.map Tue Nov  6 13:39:40 2012
@@ -0,0 +1 @@
+framework module * { }

Added: cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h?rev=167482&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h (added)
+++ cfe/trunk/test/Modules/Inputs/NotAModule.framework/Headers/NotAModule.h Tue Nov  6 13:39:40 2012
@@ -0,0 +1,2 @@
+extern int not_a_module;
+

Modified: cfe/trunk/test/Modules/Inputs/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=167482&r1=167481&r2=167482&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/module.map Tue Nov  6 13:39:40 2012
@@ -113,3 +113,7 @@
 module import_decl {
   header "import-decl.h"
 }
+
+framework module * { 
+  exclude NotAModule
+}

Added: cfe/trunk/test/Modules/inferred-frameworks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/inferred-frameworks.m?rev=167482&view=auto
==============================================================================
--- cfe/trunk/test/Modules/inferred-frameworks.m (added)
+++ cfe/trunk/test/Modules/inferred-frameworks.m Tue Nov  6 13:39:40 2012
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c -Wauto-import -fmodule-cache-path %t -fmodules -F %S/Inputs %s -verify
+
+#include <NotAModule/NotAModule.h>
+
+ at __experimental_modules_import NotAModule; // expected-error{{module 'NotAModule' not found}}
+
+





More information about the cfe-commits mailing list