Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 3f972b5

Browse files
committed
[Modules TS] Diagnose attempts to enter module implementation units without the module interface being available.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315381 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 6bbe311 commit 3f972b5

File tree

8 files changed

+38
-21
lines changed

8 files changed

+38
-21
lines changed

include/clang/Basic/DiagnosticSemaKinds.td

+3
Original file line numberDiff line numberDiff line change
@@ -8994,6 +8994,9 @@ def err_module_redefinition : Error<
89948994
"redefinition of module '%0'">;
89958995
def note_prev_module_definition : Note<"previously defined here">;
89968996
def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">;
8997+
def err_module_not_defined : Error<
8998+
"definition of module '%0' is not available; use -fmodule-file= to specify "
8999+
"path to precompiled module interface">;
89979000
def err_module_private_specialization : Error<
89989001
"%select{template|partial|member}0 specialization cannot be "
89999002
"declared __module_private__">;

include/clang/Sema/Sema.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,8 @@ class Sema {
15331533
TypeDiagnoser *Diagnoser);
15341534

15351535
struct ModuleScope {
1536-
clang::Module *Module;
1536+
clang::Module *Module = nullptr;
1537+
bool ModuleInterface = false;
15371538
VisibleModuleSet OuterVisibleModules;
15381539
};
15391540
/// The modules we're currently parsing.
@@ -2051,9 +2052,9 @@ class Sema {
20512052
SourceLocation SemiLoc);
20522053

20532054
enum class ModuleDeclKind {
2054-
Module, ///< 'module X;'
2055+
Interface, ///< 'export module X;'
2056+
Implementation, ///< 'module X;'
20552057
Partition, ///< 'module partition X;'
2056-
Implementation, ///< 'module implementation X;'
20572058
};
20582059

20592060
/// The parser has processed a module-declaration that begins the definition

lib/Parse/Parser.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2048,7 +2048,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
20482048
SourceLocation StartLoc = Tok.getLocation();
20492049

20502050
Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export)
2051-
? Sema::ModuleDeclKind::Module
2051+
? Sema::ModuleDeclKind::Interface
20522052
: Sema::ModuleDeclKind::Implementation;
20532053

20542054
assert(Tok.is(tok::kw_module) && "not a module declaration");
@@ -2057,7 +2057,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
20572057
if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) &&
20582058
Tok.getIdentifierInfo()->isStr("partition")) {
20592059
// If 'partition' is present, this must be a module interface unit.
2060-
if (MDK != Sema::ModuleDeclKind::Module)
2060+
if (MDK != Sema::ModuleDeclKind::Interface)
20612061
Diag(Tok.getLocation(), diag::err_module_implementation_partition)
20622062
<< FixItHint::CreateInsertion(ModuleLoc, "export ");
20632063
MDK = Sema::ModuleDeclKind::Partition;

lib/Sema/SemaDecl.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -16168,6 +16168,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
1616816168
// implementation unit. That indicates the 'export' is missing.
1616916169
Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
1617016170
<< FixItHint::CreateInsertion(ModuleLoc, "export ");
16171+
MDK = ModuleDeclKind::Interface;
1617116172
break;
1617216173

1617316174
case LangOptions::CMK_ModuleMap:
@@ -16207,7 +16208,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
1620716208
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
1620816209

1620916210
switch (MDK) {
16210-
case ModuleDeclKind::Module: {
16211+
case ModuleDeclKind::Interface: {
1621116212
// We can't have parsed or imported a definition of this module or parsed a
1621216213
// module map defining it already.
1621316214
if (auto *M = Map.findModule(ModuleName)) {
@@ -16237,14 +16238,16 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
1623716238
PP.getIdentifierInfo(ModuleName), Path[0].second);
1623816239
Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible,
1623916240
/*IsIncludeDirective=*/false);
16240-
// FIXME: Produce an error in this case.
16241-
if (!Mod)
16241+
if (!Mod) {
16242+
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
1624216243
return nullptr;
16244+
}
1624316245
break;
1624416246
}
1624516247

1624616248
// Switch from the global module to the named module.
1624716249
ModuleScopes.back().Module = Mod;
16250+
ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation;
1624816251
VisibleModules.setVisible(Mod, ModuleLoc);
1624916252

1625016253
// From now on, we have an owning module for all declarations we see.
@@ -16430,8 +16433,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
1643016433
// C++ Modules TS draft:
1643116434
// An export-declaration shall appear in the purview of a module other than
1643216435
// the global module.
16433-
if (ModuleScopes.empty() ||
16434-
ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)
16436+
if (ModuleScopes.empty() || !ModuleScopes.back().ModuleInterface)
1643516437
Diag(ExportLoc, diag::err_export_not_in_module_interface);
1643616438

1643716439
// An export-declaration [...] shall not contain more than one

test/CXX/modules-ts/basic/basic.link/module-declaration.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm
1010
//
1111
// Module implementation for unknown and known module. (The former is ill-formed.)
12-
// FIXME: TEST=1 should fail because we don't have an interface for module z.
1312
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
1413
// RUN: -DTEST=1 -DEXPORT= -DPARTITION= -DMODULE_NAME=z
1514
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
@@ -32,11 +31,11 @@
3231
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
3332
// RUN: -DTEST=7 -DEXPORT= -DPARTITION=elderberry -DMODULE_NAME=z
3433
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
35-
// RUN: -DTEST=8 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[]]'
34+
// RUN: -DTEST=8 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[]]'
3635
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
37-
// RUN: -DTEST=9 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[fancy]]'
36+
// RUN: -DTEST=9 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[fancy]]'
3837
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
39-
// RUN: -DTEST=10 -DEXPORT= -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]'
38+
// RUN: -DTEST=10 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]'
4039

4140
EXPORT module PARTITION MODULE_NAME;
4241
#if TEST == 4
@@ -45,11 +44,13 @@ EXPORT module PARTITION MODULE_NAME;
4544
#elif TEST == 6
4645
// expected-error@-5 {{module partition must be declared 'export'}}
4746
#elif TEST == 7
48-
// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}}
47+
// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}} expected-error@-7 {{definition of module 'elderberry' is not available}}
4948
#elif TEST == 9
5049
// expected-warning@-9 {{unknown attribute 'fancy' ignored}}
5150
#elif TEST == 10
5251
// expected-error-re@-11 {{'maybe_unused' attribute cannot be applied to a module{{$}}}}
52+
#elif TEST == 1
53+
// expected-error@-13 {{definition of module 'z' is not available}}
5354
#else
5455
// expected-no-diagnostics
5556
#endif

test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.import/p1.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/a.b.cppm -o %t/a.b.pcm
1010
//
1111
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \
12-
// RUN: -DMODULE_NAME=z
12+
// RUN: -DMODULE_NAME=z -DINTERFACE
1313
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \
1414
// RUN: -DMODULE_NAME=a.b
1515
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -fmodule-file=%t/a.b.pcm -verify %s \
1616
// RUN: -DMODULE_X -DMODULE_NAME=x
1717

18+
#ifdef INTERFACE
19+
export
20+
#endif
1821
module MODULE_NAME;
1922

2023
int use_1 = a;
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
// RUN: %clang_cc1 -fmodules-ts %s -verify -o /dev/null
2-
// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -o /dev/null
3-
// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -o /dev/null
2+
// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -emit-module-interface -o %t
3+
// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -fmodule-file=%t -o /dev/null
44
//
55
// RUN: %clang_cc1 -fmodules-ts %s -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
66
// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
77
// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
88

99
#if INTERFACE
10+
// expected-no-diagnostics
1011
export module A;
1112
#elif IMPLEMENTATION
1213
module A;
1314
#ifdef BUILT_AS_INTERFACE
1415
// expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}}
16+
#define INTERFACE
1517
#endif
1618
#else
1719
#ifdef BUILT_AS_INTERFACE
1820
// FIXME: Diagnose missing module declaration (at end of TU)
1921
#endif
2022
#endif
2123

22-
export int a;
2324
#ifndef INTERFACE
24-
// expected-error@-2 {{export declaration can only be used within a module interface unit}}
25+
export int b; // expected-error {{export declaration can only be used within a module interface unit}}
2526
#else
26-
// expected-no-diagnostics
27+
export int a;
2728
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_cc1 -fmodules-ts -verify %s
2+
3+
// A named module shall contain exactly one module interface unit.
4+
module M; // expected-error {{definition of module 'M' is not available; use -fmodule-file= to specify path to precompiled module interface}}
5+
6+
// FIXME: How do we ensure there is not more than one?

0 commit comments

Comments
 (0)