r193549 - Allow a new syntax in a module requires-declaration:

Richard Smith richard-llvm at metafoo.co.uk
Mon Oct 28 15:18:19 PDT 2013


Author: rsmith
Date: Mon Oct 28 17:18:19 2013
New Revision: 193549

URL: http://llvm.org/viewvc/llvm-project?rev=193549&view=rev
Log:
Allow a new syntax in a module requires-declaration:

  requires ! feature

The purpose of this is to allow (for instance) the module map for /usr/include
to exclude <tgmath.h> and <complex.h> when building in C++ (these headers are
instead provided by the C++ standard library in this case, and the glibc C
<tgmath.h> header would otherwise try to include <complex.h>, resulting in a
module cycle).

Added:
    cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_cxx.h
    cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_objc.h
    cfe/trunk/test/Modules/requires.mm
Modified:
    cfe/trunk/docs/Modules.rst
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/Basic/Module.h
    cfe/trunk/lib/Basic/Module.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/FrontendActions.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Index/index-module.m
    cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map
    cfe/trunk/test/Modules/requires.m

Modified: cfe/trunk/docs/Modules.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/docs/Modules.rst (original)
+++ cfe/trunk/docs/Modules.rst Mon Oct 28 17:18:19 2013
@@ -320,9 +320,12 @@ A *requires-declaration* specifies the r
     ``requires`` *feature-list*
 
   *feature-list*:
-    *identifier* (',' *identifier*)*
+    *feature* (',' *feature*)*
 
-The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module.
+  *feature*:
+    ``!``:sub:`opt` *identifier*
+
+The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. The optional ``!`` indicates that a feature is incompatible with the module.
 
 The following features are defined:
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Mon Oct 28 17:18:19 2013
@@ -136,7 +136,8 @@ def err_no_submodule_suggest : Error<
   "no submodule named %0 in module '%1'; did you mean '%2'?">;
 def warn_missing_submodule : Warning<"missing submodule '%0'">,
   InGroup<IncompleteUmbrella>;
-def err_module_unavailable : Error<"module '%0' requires feature '%1'">;
+def err_module_unavailable : Error<
+  "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
 def warn_module_config_macro_undef : Warning<
   "%select{definition|#undef}0 of configuration macro '%1' has no effect on "
   "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line "

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Mon Oct 28 17:18:19 2013
@@ -38,6 +38,7 @@ class FileEntry;
 class FileManager;
 class LangOptions;
 class TargetInfo;
+class IdentifierInfo;
   
 /// \brief Describes the name of a module.
 typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
@@ -89,12 +90,15 @@ public:
   /// \brief The headers that are private to this module.
   llvm::SmallVector<const FileEntry *, 2> PrivateHeaders;
 
+  /// \brief An individual requirement: a feature name and a flag indicating
+  /// the required state of that feature.
+  typedef std::pair<std::string, bool> Requirement;
+
   /// \brief The set of language features required to use this module.
   ///
-  /// If any of these features is not present, the \c IsAvailable bit
-  /// will be false to indicate that this (sub)module is not
-  /// available.
-  SmallVector<std::string, 2> Requires;
+  /// If any of these requirements are not available, the \c IsAvailable bit
+  /// will be false to indicate that this (sub)module is not available.
+  SmallVector<Requirement, 2> Requirements;
 
   /// \brief Whether this module is available in the current
   /// translation unit.
@@ -267,12 +271,12 @@ public:
   ///
   /// \param Target The target options used for the current translation unit.
   ///
-  /// \param Feature If this module is unavailable, this parameter
-  /// will be set to one of the features that is required for use of
-  /// this module (but is not available).
+  /// \param Req If this module is unavailable, this parameter
+  /// will be set to one of the requirements that is not met for use of
+  /// this module.
   bool isAvailable(const LangOptions &LangOpts, 
                    const TargetInfo &Target,
-                   StringRef &Feature) const;
+                   Requirement &Req) const;
 
   /// \brief Determine whether this module is a submodule.
   bool isSubModule() const { return Parent != 0; }
@@ -366,12 +370,16 @@ public:
   /// \param Feature The feature that is required by this module (and
   /// its submodules).
   ///
+  /// \param RequiredState The required state of this feature: \c true
+  /// if it must be present, \c false if it must be absent.
+  ///
   /// \param LangOpts The set of language options that will be used to
   /// evaluate the availability of this feature.
   ///
   /// \param Target The target options that will be used to evaluate the
   /// availability of this feature.
-  void addRequirement(StringRef Feature, const LangOptions &LangOpts,
+  void addRequirement(StringRef Feature, bool RequiredState,
+                      const LangOptions &LangOpts,
                       const TargetInfo &Target);
 
   /// \brief Find the submodule with the given name.

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Mon Oct 28 17:18:19 2013
@@ -11,6 +11,7 @@
 // code.
 //
 //===----------------------------------------------------------------------===//
+
 #include "clang/Basic/Module.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
@@ -20,6 +21,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+
 using namespace clang;
 
 Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, 
@@ -65,16 +67,17 @@ static bool hasFeature(StringRef Feature
            .Default(Target.hasFeature(Feature));
 }
 
-bool 
+bool
 Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
-                    StringRef &Feature) const {
+                    Requirement &Req) const {
   if (IsAvailable)
     return true;
 
   for (const Module *Current = this; Current; Current = Current->Parent) {
-    for (unsigned I = 0, N = Current->Requires.size(); I != N; ++I) {
-      if (!hasFeature(Current->Requires[I], LangOpts, Target)) {
-        Feature = Current->Requires[I];
+    for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
+      if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
+              Current->Requirements[I].second) {
+        Req = Current->Requirements[I];
         return false;
       }
     }
@@ -143,12 +146,13 @@ ArrayRef<const FileEntry *> Module::getT
   return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
 }
 
-void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts,
+void Module::addRequirement(StringRef Feature, bool RequiredState,
+                            const LangOptions &LangOpts,
                             const TargetInfo &Target) {
-  Requires.push_back(Feature);
+  Requirements.push_back(Requirement(Feature, RequiredState));
 
   // If this feature is currently available, we're done.
-  if (hasFeature(Feature, LangOpts, Target))
+  if (hasFeature(Feature, LangOpts, Target) == RequiredState)
     return;
 
   if (!IsAvailable)
@@ -275,13 +279,15 @@ void Module::print(raw_ostream &OS, unsi
 
   OS << " {\n";
   
-  if (!Requires.empty()) {
+  if (!Requirements.empty()) {
     OS.indent(Indent + 2);
     OS << "requires ";
-    for (unsigned I = 0, N = Requires.size(); I != N; ++I) {
+    for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
       if (I)
         OS << ", ";
-      OS << Requires[I];
+      if (!Requirements[I].second)
+        OS << "!";
+      OS << Requirements[I].first;
     }
     OS << "\n";
   }

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Mon Oct 28 17:18:19 2013
@@ -1359,11 +1359,11 @@ CompilerInstance::loadModule(SourceLocat
     }
 
     // Check whether this module is available.
-    StringRef Feature;
-    if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) {
+    clang::Module::Requirement Requirement;
+    if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement)) {
       getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
         << Module->getFullModuleName()
-        << Feature
+        << Requirement.second << Requirement.first
         << SourceRange(Path.front().second, Path.back().second);
       LastModuleImportLoc = ImportLoc;
       LastModuleImportResult = ModuleLoadResult();

Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Mon Oct 28 17:18:19 2013
@@ -246,11 +246,11 @@ bool GenerateModuleAction::BeginSourceFi
   }
 
   // Check whether we can build this module at all.
-  StringRef Feature;
-  if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Feature)) {
+  clang::Module::Requirement Requirement;
+  if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement)) {
     CI.getDiagnostics().Report(diag::err_module_unavailable)
       << Module->getFullModuleName()
-      << Feature;
+      << Requirement.second << Requirement.first;
 
     return false;
   }

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Oct 28 17:18:19 2013
@@ -773,6 +773,7 @@ namespace clang {
       EndOfFile,
       HeaderKeyword,
       Identifier,
+      Exclaim,
       ExcludeKeyword,
       ExplicitKeyword,
       ExportKeyword,
@@ -967,6 +968,10 @@ retry:
     Tok.Kind = MMToken::Star;
     break;
       
+  case tok::exclaim:
+    Tok.Kind = MMToken::Exclaim;
+    break;
+      
   case tok::string_literal: {
     if (LToken.hasUDSuffix()) {
       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
@@ -1392,8 +1397,11 @@ void ModuleMapParser::parseExternModuleD
 ///     'requires' feature-list
 ///
 ///   feature-list:
-///     identifier ',' feature-list
-///     identifier
+///     feature ',' feature-list
+///     feature
+///
+///   feature:
+///     '!'[opt] identifier
 void ModuleMapParser::parseRequiresDecl() {
   assert(Tok.is(MMToken::RequiresKeyword));
 
@@ -1402,6 +1410,12 @@ void ModuleMapParser::parseRequiresDecl(
 
   // Parse the feature-list.
   do {
+    bool RequiredState = true;
+    if (Tok.is(MMToken::Exclaim)) {
+      RequiredState = false;
+      consumeToken();
+    }
+
     if (!Tok.is(MMToken::Identifier)) {
       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
       HadError = true;
@@ -1413,7 +1427,8 @@ void ModuleMapParser::parseRequiresDecl(
     consumeToken();
 
     // Add this feature.
-    ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
+    ActiveModule->addRequirement(Feature, RequiredState,
+                                 Map.LangOpts, *Map.Target);
 
     if (!Tok.is(MMToken::Comma))
       break;
@@ -2077,6 +2092,7 @@ bool ModuleMapParser::parseModuleMapFile
     case MMToken::Comma:
     case MMToken::ConfigMacros:
     case MMToken::Conflict:
+    case MMToken::Exclaim:
     case MMToken::ExcludeKeyword:
     case MMToken::ExportKeyword:
     case MMToken::HeaderKeyword:

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Oct 28 17:18:19 2013
@@ -3912,7 +3912,7 @@ bool ASTReader::ReadSubmoduleBlock(Modul
       if (!CurrentModule)
         break;
 
-      CurrentModule->addRequirement(Blob, Context.getLangOpts(),
+      CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(),
                                     Context.getTargetInfo());
       break;
     }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Oct 28 17:18:19 2013
@@ -2278,7 +2278,8 @@ void ASTWriter::WriteSubmodules(Module *
 
   Abbrev = new BitCodeAbbrev();
   Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));     // Feature
   unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev);
 
   Abbrev = new BitCodeAbbrev();
@@ -2342,12 +2343,12 @@ void ASTWriter::WriteSubmodules(Module *
     Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
     
     // Emit the requirements.
-    for (unsigned I = 0, N = Mod->Requires.size(); I != N; ++I) {
+    for (unsigned I = 0, N = Mod->Requirements.size(); I != N; ++I) {
       Record.clear();
       Record.push_back(SUBMODULE_REQUIRES);
+      Record.push_back(Mod->Requirements[I].second);
       Stream.EmitRecordWithBlob(RequiresAbbrev, Record,
-                                Mod->Requires[I].data(),
-                                Mod->Requires[I].size());
+                                Mod->Requirements[I].first);
     }
 
     // Emit the umbrella header, if there is one.

Modified: cfe/trunk/test/Index/index-module.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-module.m?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/test/Index/index-module.m (original)
+++ cfe/trunk/test/Index/index-module.m Mon Oct 28 17:18:19 2013
@@ -21,11 +21,13 @@ int glob;
 // CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_MODULE_H:.*/Modules/Inputs/DependsOnModule\.framework[/\\]Headers[/\\]DependsOnModule\.h]] | {{.*}} | hash loc: <invalid>
 // CHECK-DMOD-NEXT: [ppIncludedFile]: {{.*}}/Modules/Inputs/Module.framework{{[/\\]}}Headers{{[/\\]}}Module.h | name: "Module/Module.h" | hash loc: {{.*}}/Modules/Inputs/DependsOnModule.framework{{[/\\]}}Headers{{[/\\]}}DependsOnModule.h:1:1 | isImport: 0 | isAngled: 1 | isModule: 1
 // CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_OTHER_H:.*/Modules/Inputs/DependsOnModule\.framework[/\\]Headers[/\\]other\.h]] | {{.*}} | hash loc: <invalid>
+// CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_NOT_CXX_H:.*/Modules/Inputs/DependsOnModule\.framework[/\\]Headers[/\\]not_cxx\.h]] | {{.*}} | hash loc: <invalid>
 // CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_SUB_H:.*/Modules/Inputs/DependsOnModule\.framework[/\\]Frameworks[/\\]SubFramework\.framework[/\\]Headers[/\\]SubFramework\.h]] | {{.*}} | hash loc: <invalid>
 // CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_SUB_OTHER_H:.*/Modules/Inputs/DependsOnModule.framework[/\\]Frameworks/SubFramework\.framework/Headers/Other\.h]] | name: "SubFramework/Other.h" | hash loc: [[DMOD_SUB_H]]:1:1 | isImport: 0 | isAngled: 0
 // CHECK-DMOD-NEXT: [ppIncludedFile]: [[DMOD_PRIVATE_H:.*/Modules/Inputs/DependsOnModule.framework[/\\]PrivateHeaders[/\\]DependsOnModulePrivate.h]] | {{.*}} | hash loc: <invalid>
 // CHECK-DMOD-NEXT: [importedASTFile]: {{.*}}.cache{{[/\\]}}Module.pcm | loc: [[DMOD_MODULE_H]]:1:2 | name: "Module" | isImplicit: 1
 // CHECK-DMOD-NEXT: [indexDeclaration]: kind: variable | name: depends_on_module_other | {{.*}} | loc: [[DMOD_OTHER_H]]:1:5
+// CHECK-DMOD-NEXT: [indexDeclaration]: kind: variable | name: template | {{.*}} | loc: [[DMOD_NOT_CXX_H]]:1:12
 // CHECK-DMOD-NEXT: [importedASTFile]: {{.*}}.cache/DependsOnModule.pcm | loc: {{.*}}SubFramework.h:1:2 | name: "DependsOnModule.SubFramework.Other" | isImplicit: 1
 // CHECK-DMOD-NEXT: [indexDeclaration]: kind: variable | name: sub_framework | {{.*}} | loc: [[DMOD_SUB_H]]:2:8
 // CHECK-DMOD-NEXT: [indexDeclaration]: kind: variable | name: sub_framework_other | {{.*}} | loc: [[DMOD_SUB_OTHER_H]]:1:9

Added: cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_cxx.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_cxx.h?rev=193549&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_cxx.h (added)
+++ cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_cxx.h Mon Oct 28 17:18:19 2013
@@ -0,0 +1 @@
+extern int template;

Added: cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_objc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_objc.h?rev=193549&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_objc.h (added)
+++ cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/Headers/not_objc.h Mon Oct 28 17:18:19 2013
@@ -0,0 +1 @@
+int NSObject;

Modified: cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/DependsOnModule.framework/module.map Mon Oct 28 17:18:19 2013
@@ -8,6 +8,14 @@ framework module DependsOnModule {
     requires cplusplus
     header "cxx_other.h"
   }
+  explicit module NotCXX {
+    requires !cplusplus
+    header "not_cxx.h"
+  }
+  explicit module NotObjC {
+    requires !objc
+    header "not_objc.h"
+  }
 
   explicit framework module SubFramework {
     umbrella header "SubFramework.h"

Modified: cfe/trunk/test/Modules/requires.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/requires.m?rev=193549&r1=193548&r2=193549&view=diff
==============================================================================
--- cfe/trunk/test/Modules/requires.m (original)
+++ cfe/trunk/test/Modules/requires.m Mon Oct 28 17:18:19 2013
@@ -2,4 +2,5 @@
 // RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify
 
 @import DependsOnModule.CXX; // expected-error{{module 'DependsOnModule.CXX' requires feature 'cplusplus'}}
-
+ at import DependsOnModule.NotCXX;
+ at import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}

Added: cfe/trunk/test/Modules/requires.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/requires.mm?rev=193549&view=auto
==============================================================================
--- cfe/trunk/test/Modules/requires.mm (added)
+++ cfe/trunk/test/Modules/requires.mm Mon Oct 28 17:18:19 2013
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify
+
+ at import DependsOnModule.CXX;
+ at import DependsOnModule.NotCXX; // expected-error{{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}}
+ at import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}





More information about the cfe-commits mailing list