summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-04-21 22:39:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-04-21 22:39:18 +0000
commit81328ac3a5b1bfc24010ab5ada34a5ee8f4a32ae (patch)
tree5ed49bb35921cfb90bf187d18f46a5dc93578735 /clang/lib
parentc24d7974bcb9914540f6fcf331e53ae01e90ab05 (diff)
downloadbcm5719-llvm-81328ac3a5b1bfc24010ab5ada34a5ee8f4a32ae.tar.gz
bcm5719-llvm-81328ac3a5b1bfc24010ab5ada34a5ee8f4a32ae.zip
P0629R0: Switch to latest proposal for distinguishing module interface from implementation.
This switches from the prototype syntax in P0273R0 ('module' and 'module implementation') to the consensus syntax 'export module' and 'module'. In passing, drop the "module declaration must be first" enforcement, since EWG seems to have changed its mind on that. llvm-svn: 301056
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/Parser.cpp67
-rw-r--r--clang/lib/Sema/SemaDecl.cpp43
2 files changed, 55 insertions, 55 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index edbfc636bc4..38476ce7e15 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -534,23 +534,6 @@ void Parser::LateTemplateParserCleanupCallback(void *P) {
}
bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) {
- // C++ Modules TS: module-declaration must be the first declaration in the
- // file. (There can be no preceding preprocessor directives, but we expect
- // the lexer to check that.)
- if (Tok.is(tok::kw_module)) {
- Result = ParseModuleDecl();
- return false;
- } else if (getLangOpts().getCompilingModule() ==
- LangOptions::CMK_ModuleInterface) {
- // FIXME: We avoid providing this diagnostic when generating an object file
- // from an existing PCM file. This is not a good way to detect this
- // condition; we should provide a mechanism to indicate whether we've
- // already parsed a declaration in this translation unit and avoid calling
- // ParseFirstTopLevelDecl in that case.
- if (Actions.TUKind == TU_Module)
- Diag(Tok, diag::err_expected_module_interface_decl);
- }
-
// C11 6.9p1 says translation units must have at least one top-level
// declaration. C++ doesn't have this restriction. We also don't want to
// complain if we have a precompiled header, although technically if the PCH
@@ -583,6 +566,14 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
Result = ParseModuleImport(SourceLocation());
return false;
+ case tok::kw_export:
+ if (NextToken().isNot(tok::kw_module))
+ break;
+ LLVM_FALLTHROUGH;
+ case tok::kw_module:
+ Result = ParseModuleDecl();
+ return false;
+
case tok::annot_module_include:
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
@@ -2049,30 +2040,28 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
/// Parse a C++ Modules TS module declaration, which appears at the beginning
/// of a module interface, module partition, or module implementation file.
///
-/// module-declaration: [Modules TS + P0273R0]
-/// 'module' module-kind[opt] module-name attribute-specifier-seq[opt] ';'
-/// module-kind:
-/// 'implementation'
-/// 'partition'
+/// module-declaration: [Modules TS + P0273R0 + P0629R0]
+/// 'export'[opt] 'module' 'partition'[opt]
+/// module-name attribute-specifier-seq[opt] ';'
///
-/// Note that the module-kind values are context-sensitive keywords.
+/// Note that 'partition' is a context-sensitive keyword.
Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
- assert(Tok.is(tok::kw_module) && getLangOpts().ModulesTS &&
- "should not be parsing a module declaration");
+ SourceLocation StartLoc = Tok.getLocation();
+
+ Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export)
+ ? Sema::ModuleDeclKind::Module
+ : Sema::ModuleDeclKind::Implementation;
+
+ assert(Tok.is(tok::kw_module) && "not a module declaration");
SourceLocation ModuleLoc = ConsumeToken();
- // Check for a module-kind.
- Sema::ModuleDeclKind MDK = Sema::ModuleDeclKind::Module;
- if (Tok.is(tok::identifier) && NextToken().is(tok::identifier)) {
- if (Tok.getIdentifierInfo()->isStr("implementation"))
- MDK = Sema::ModuleDeclKind::Implementation;
- else if (Tok.getIdentifierInfo()->isStr("partition"))
- MDK = Sema::ModuleDeclKind::Partition;
- else {
- Diag(Tok, diag::err_unexpected_module_kind) << Tok.getIdentifierInfo();
- SkipUntil(tok::semi);
- return nullptr;
- }
+ if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) &&
+ Tok.getIdentifierInfo()->isStr("partition")) {
+ // If 'partition' is present, this must be a module interface unit.
+ if (MDK != Sema::ModuleDeclKind::Module)
+ Diag(Tok.getLocation(), diag::err_module_implementation_partition)
+ << FixItHint::CreateInsertion(ModuleLoc, "export ");
+ MDK = Sema::ModuleDeclKind::Partition;
ConsumeToken();
}
@@ -2080,14 +2069,14 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false))
return nullptr;
+ // We don't support any module attributes yet; just parse them and diagnose.
ParsedAttributesWithRange Attrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs);
- // We don't support any module attributes yet.
ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr);
ExpectAndConsumeSemi(diag::err_module_expected_semi);
- return Actions.ActOnModuleDecl(ModuleLoc, MDK, Path);
+ return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path);
}
/// Parse a module import declaration. This is essentially the same for
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6269c9fe391..6138cbb114e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15688,30 +15688,41 @@ static void checkModuleImportContext(Sema &S, Module *M,
}
}
-Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc,
+Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
+ SourceLocation ModuleLoc,
ModuleDeclKind MDK,
ModuleIdPath Path) {
- // 'module implementation' requires that we are not compiling a module of any
- // kind. 'module' and 'module partition' require that we are compiling a
- // module inteface (not a module map).
- auto CMK = getLangOpts().getCompilingModule();
- if (MDK == ModuleDeclKind::Implementation
- ? CMK != LangOptions::CMK_None
- : CMK != LangOptions::CMK_ModuleInterface) {
+ // A module implementation unit requires that we are not compiling a module
+ // of any kind. A module interface unit requires that we are not compiling a
+ // module map.
+ switch (getLangOpts().getCompilingModule()) {
+ case LangOptions::CMK_None:
+ // It's OK to compile a module interface as a normal translation unit.
+ break;
+
+ case LangOptions::CMK_ModuleInterface:
+ if (MDK != ModuleDeclKind::Implementation)
+ break;
+
+ // We were asked to compile a module interface unit but this is a module
+ // implementation unit. That indicates the 'export' is missing.
Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
- << (unsigned)MDK;
+ << FixItHint::CreateInsertion(ModuleLoc, "export ");
+ break;
+
+ case LangOptions::CMK_ModuleMap:
+ Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);
return nullptr;
}
// FIXME: Create a ModuleDecl and return it.
// FIXME: Most of this work should be done by the preprocessor rather than
- // here, in case we look ahead across something where the current
- // module matters (eg a #include).
+ // here, in order to support macro import.
- // The dots in a module name in the Modules TS are a lie. Unlike Clang's
- // hierarchical module map modules, the dots here are just another character
- // that can appear in a module name. Flatten down to the actual module name.
+ // 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
+ // module name.
std::string ModuleName;
for (auto &Piece : Path) {
if (!ModuleName.empty())
@@ -15736,8 +15747,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc,
case ModuleDeclKind::Module: {
// FIXME: Check we're not in a submodule.
- // We can't have imported a definition of this module or parsed a module
- // map defining it already.
+ // We can't have parsed or imported a definition of this module or parsed a
+ // module map defining it already.
if (auto *M = Map.findModule(ModuleName)) {
Diag(Path[0].second, diag::err_module_redefinition) << ModuleName;
if (M->DefinitionLoc.isValid())
OpenPOWER on IntegriCloud