Diagnose attempts to build a preprocessed module that defines an unavailable submodule.

The errors we would otherwise get are incomprehensible, as we would enter the
module but not make its contents visible to itself.

llvm-svn: 304190
This commit is contained in:
Richard Smith 2017-05-30 05:22:59 +00:00
parent 08dfd53269
commit 51d09c512b
3 changed files with 32 additions and 0 deletions

View File

@ -525,6 +525,8 @@ def err_pp_module_begin_without_module_end : Error<
def err_pp_module_end_without_module_begin : Error<
"no matching '#pragma clang module begin' for this "
"'#pragma clang module end'">;
def note_pp_module_begin_here : Note<
"entering module '%0' due to this pragma">;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
def err_paste_at_start : Error<

View File

@ -1407,6 +1407,24 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
M = NewM;
}
// If the module isn't available, it doesn't make sense to enter it.
if (!M->isAvailable()) {
Module::Requirement Requirement;
Module::UnresolvedHeaderDirective MissingHeader;
(void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(),
Requirement, MissingHeader);
if (MissingHeader.FileNameLoc.isValid()) {
PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
<< MissingHeader.IsUmbrella << MissingHeader.FileName;
} else {
PP.Diag(M->DefinitionLoc, diag::err_module_unavailable)
<< M->getFullModuleName() << Requirement.second << Requirement.first;
}
PP.Diag(BeginLoc, diag::note_pp_module_begin_here)
<< M->getTopLevelModuleName();
return;
}
// Enter the scope of the submodule.
PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true);
PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second),

View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -x c++-module-map %s -fmodule-name=a -verify
module a {
module b {
requires cplusplus11
}
}
#pragma clang module contents
// expected-error@3 {{module 'a.b' requires feature 'cplusplus11'}}
#pragma clang module begin a.b // expected-note {{entering module 'a' due to this pragma}}
int f();
int g() { f(); }
#pragma clang module end // expected-error {{no matching '#pragma clang module begin'}}