[Modules TS] Diagnose missing/duplicate module-declaration.

llvm-svn: 315397
This commit is contained in:
Richard Smith 2017-10-11 00:36:56 +00:00
parent 922973a466
commit 18057cb34c
5 changed files with 44 additions and 6 deletions

View File

@ -8997,6 +8997,11 @@ def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">;
def err_module_not_defined : Error< def err_module_not_defined : Error<
"definition of module '%0' is not available; use -fmodule-file= to specify " "definition of module '%0' is not available; use -fmodule-file= to specify "
"path to precompiled module interface">; "path to precompiled module interface">;
def err_module_redeclaration : Error<
"translation unit contains multiple module declarations">;
def note_prev_module_declaration : Note<"previous module declaration is here">;
def err_module_declaration_missing : Error<
"missing 'export module' declaration in module interface unit">;
def err_module_private_specialization : Error< def err_module_private_specialization : Error<
"%select{template|partial|member}0 specialization cannot be " "%select{template|partial|member}0 specialization cannot be "
"declared __module_private__">; "declared __module_private__">;

View File

@ -930,6 +930,17 @@ void Sema::ActOnEndOfTranslationUnit() {
} }
if (TUKind == TU_Module) { if (TUKind == TU_Module) {
// If we are building a module interface unit, we need to have seen the
// module declaration by now.
if (getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface &&
ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) {
// FIXME: Make a better guess as to where to put the module declaration.
Diag(getSourceManager().getLocForStartOfFile(
getSourceManager().getMainFileID()),
diag::err_module_declaration_missing);
}
// If we are building a module, resolve all of the exported declarations // If we are building a module, resolve all of the exported declarations
// now. // now.
if (Module *CurrentModule = PP.getCurrentModule()) { if (Module *CurrentModule = PP.getCurrentModule()) {

View File

@ -16176,9 +16176,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
return nullptr; return nullptr;
} }
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
// FIXME: Most of this work should be done by the preprocessor rather than // FIXME: Most of this work should be done by the preprocessor rather than
// here, in order to support macro import. // here, in order to support macro import.
// Only one module-declaration is permitted per source file.
if (ModuleScopes.back().Module->Kind == Module::ModuleInterfaceUnit) {
Diag(ModuleLoc, diag::err_module_redeclaration);
Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module),
diag::note_prev_module_declaration);
return nullptr;
}
// Flatten the dots in a module name. Unlike Clang's hierarchical module map // Flatten the dots in a module name. Unlike Clang's hierarchical module map
// modules, the dots here are just another character that can appear in a // modules, the dots here are just another character that can appear in a
// module name. // module name.
@ -16189,8 +16199,6 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
ModuleName += Piece.first->getName(); ModuleName += Piece.first->getName();
} }
// FIXME: If we've already seen a module-declaration, report an error.
// If a module name was explicitly specified on the command line, it must be // If a module name was explicitly specified on the command line, it must be
// correct. // correct.
if (!getLangOpts().CurrentModule.empty() && if (!getLangOpts().CurrentModule.empty() &&
@ -16205,8 +16213,6 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
auto &Map = PP.getHeaderSearchInfo().getModuleMap(); auto &Map = PP.getHeaderSearchInfo().getModuleMap();
Module *Mod; Module *Mod;
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
switch (MDK) { switch (MDK) {
case ModuleDeclKind::Interface: { case ModuleDeclKind::Interface: {
// We can't have parsed or imported a definition of this module or parsed a // We can't have parsed or imported a definition of this module or parsed a
@ -16240,7 +16246,9 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
/*IsIncludeDirective=*/false); /*IsIncludeDirective=*/false);
if (!Mod) { if (!Mod) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
return nullptr; // Create an empty module interface unit for error recovery.
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
ModuleScopes.front().Module);
} }
break; break;
} }

View File

@ -17,7 +17,7 @@ module A;
#endif #endif
#else #else
#ifdef BUILT_AS_INTERFACE #ifdef BUILT_AS_INTERFACE
// FIXME: Diagnose missing module declaration (at end of TU) // expected-error@1 {{missing 'export module' declaration in module interface unit}}
#endif #endif
#endif #endif

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -DFOO=export -DBAR=export
// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -DFOO=export -DBAR=
// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -DFOO=export -emit-module-interface -o %t
// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -fmodule-file=%t -DFOO=
// RUN: %clang_cc1 -std=c++17 -fmodules-ts %s -fmodule-file=%t -DBAR=export
// RUN: %clang_cc1 -std=c++17 -fmodules-ts -verify %s -fmodule-file=%t -DFOO= -DBAR=export
#ifdef FOO
FOO module foo; // expected-note {{previous module declaration is here}}
#endif
#ifdef BAR
BAR module bar; // expected-error {{translation unit contains multiple module declarations}}
#endif