]> granicus.if.org Git - clang/commitdiff
Don't build modules with (submodules with) missing headers
authorBen Langmuir <blangmuir@apple.com>
Fri, 18 Apr 2014 22:07:31 +0000 (22:07 +0000)
committerBen Langmuir <blangmuir@apple.com>
Fri, 18 Apr 2014 22:07:31 +0000 (22:07 +0000)
Unless they are in submodules that aren't available anyway, due to
requirements not being met.  Also, mark children as unavailable when the
parent is.

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

include/clang/Basic/Module.h
lib/Basic/Module.cpp
lib/Frontend/FrontendActions.cpp
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/submodules/module.map
test/Modules/missing-header.m [new file with mode: 0644]
test/Modules/submodules.cpp

index 49be4ecb4d484caf29d2bd1dca0cec1d5f18d955..98f86df6d561e54fe08105afe770498f47e12a82 100644 (file)
@@ -123,8 +123,13 @@ public:
   /// 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.
+  /// \brief Whether this module is missing a feature from \c Requirements.
+  unsigned IsMissingRequirement : 1;
+
+  /// \brief Whether this module is available in the current translation unit.
+  ///
+  /// If the module is missing headers or does not meet all requirements then
+  /// this bit will be 0.
   unsigned IsAvailable : 1;
 
   /// \brief Whether this module was loaded from a module file.
@@ -407,6 +412,9 @@ public:
                       const LangOptions &LangOpts,
                       const TargetInfo &Target);
 
+  /// \brief Mark this module and all of its submodules as unavailable.
+  void markUnavailable();
+
   /// \brief Find the submodule with the given name.
   ///
   /// \returns The submodule if found, or NULL otherwise.
index d5c02d84058f546ee17e4691923b349e5c44e2da..6f29fae03a51b530f2bddb0820e276bd0c113af0 100644 (file)
@@ -160,6 +160,11 @@ void Module::addRequirement(StringRef Feature, bool RequiredState,
   if (hasFeature(Feature, LangOpts, Target) == RequiredState)
     return;
 
+  IsMissingRequirement = true;
+  markUnavailable();
+}
+
+void Module::markUnavailable() {
   if (!IsAvailable)
     return;
 
index 1092c56ed59806f2a63a582129fe2d324683ba92..3d65ae32c019349d963e61fa95a73597226ddfba 100644 (file)
@@ -288,7 +288,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
   if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
                            MissingHeader)) {
     if (MissingHeader.FileNameLoc.isValid()) {
-      CI.getDiagnostics().Report(diag::err_module_header_missing)
+      CI.getDiagnostics().Report(MissingHeader.FileNameLoc,
+                                 diag::err_module_header_missing)
         << MissingHeader.IsUmbrella << MissingHeader.FileName;
     } else {
       CI.getDiagnostics().Report(diag::err_module_unavailable)
index 27ba7620ff51c18a6427de2b61b5f9f1710e14b7..0e712b0dce6e655d5c3dea2d34c5fa7bb9a7f431 100644 (file)
@@ -1477,6 +1477,15 @@ void ModuleMapParser::parseModuleDecl() {
     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
   }
 
+  // If the module meets all requirements but is still unavailable, mark the
+  // whole tree as unavailable to prevent it from building.
+  if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
+      ActiveModule->Parent) {
+    ActiveModule->getTopLevelModule()->markUnavailable();
+    ActiveModule->getTopLevelModule()->MissingHeaders.append(
+      ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
+  }
+
   // We're done parsing this module. Pop back to the previous module.
   ActiveModule = PreviousActiveModule;
 }
@@ -1705,9 +1714,8 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
 
     // If we find a module that has a missing header, we mark this module as
     // unavailable and store the header directive for displaying diagnostics.
-    // Other submodules in the same module can still be used.
     Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
-    ActiveModule->IsAvailable = false;
+    ActiveModule->markUnavailable();
     ActiveModule->MissingHeaders.push_back(Header);
   }
 }
index 15931031abbac40848ff73162533be842e354340..8677ea0c80b7f8706180b54308e67776325c63fe 100644 (file)
@@ -15,3 +15,11 @@ module missing_headers {
   module missing { header "missing.h" }
   module not_missing { header "not_missing.h" }
 }
+
+module missing_unavailable_headers {
+  module missing {
+    requires !objc
+    header "missing.h"
+  }
+  module not_missing { }
+}
diff --git a/test/Modules/missing-header.m b/test/Modules/missing-header.m
new file mode 100644 (file)
index 0000000..c2c1673
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: not %clang_cc1 -x objective-c -fmodules-cache-path=%t -fmodules -I %S/Inputs/submodules %s 2>&1 | FileCheck %s
+
+// FIXME: cannot use -verify, because the error from inside the module build has
+// a different source manager than the verifier.
+
+@import missing_unavailable_headers; // OK
+@import missing_unavailable_headers.not_missing; // OK
+// CHECK-NOT: missing_unavailable_headers
+
+@import missing_headers;
+// CHECK: module.map:15:27: error: header 'missing.h' not found
+// CHECK: could not build module 'missing_headers'
index a18138c70994c414cd3469d44a1fee1cd80bfb98..7ef785c936c4f6ad6acd915c2bf9938620bb984d 100644 (file)
@@ -32,8 +32,3 @@ extern MyTypeA import_self_test_a; // expected-error {{must be imported from mod
 // expected-note@import-self-a.h:1 {{here}}
 extern MyTypeC import_self_test_c;
 extern MyTypeD import_self_test_d;
-
-// expected-error@Inputs/submodules/module.map:15{{header 'missing.h' not found}}
-@import missing_headers.missing;
-@import missing_headers.not_missing;
-void f() { NotMissingFunction(); };