summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Module.h12
-rw-r--r--clang/lib/Basic/Module.cpp5
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp3
-rw-r--r--clang/lib/Lex/ModuleMap.cpp12
-rw-r--r--clang/test/Modules/Inputs/submodules/module.map8
-rw-r--r--clang/test/Modules/missing-header.m13
-rw-r--r--clang/test/Modules/submodules.cpp5
7 files changed, 48 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 49be4ecb4d4..98f86df6d56 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -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.
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index d5c02d84058..6f29fae03a5 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -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;
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 1092c56ed59..3d65ae32c01 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -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)
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 27ba7620ff5..0e712b0dce6 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -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);
}
}
diff --git a/clang/test/Modules/Inputs/submodules/module.map b/clang/test/Modules/Inputs/submodules/module.map
index 15931031abb..8677ea0c80b 100644
--- a/clang/test/Modules/Inputs/submodules/module.map
+++ b/clang/test/Modules/Inputs/submodules/module.map
@@ -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/clang/test/Modules/missing-header.m b/clang/test/Modules/missing-header.m
new file mode 100644
index 00000000000..c2c1673ac5b
--- /dev/null
+++ b/clang/test/Modules/missing-header.m
@@ -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'
diff --git a/clang/test/Modules/submodules.cpp b/clang/test/Modules/submodules.cpp
index a18138c7099..7ef785c936c 100644
--- a/clang/test/Modules/submodules.cpp
+++ b/clang/test/Modules/submodules.cpp
@@ -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(); };
OpenPOWER on IntegriCloud