diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/Module.h | 12 | ||||
-rw-r--r-- | clang/lib/Basic/Module.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 12 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/submodules/module.map | 8 | ||||
-rw-r--r-- | clang/test/Modules/missing-header.m | 13 | ||||
-rw-r--r-- | clang/test/Modules/submodules.cpp | 5 |
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(); }; |