summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--clang/include/clang/Basic/Module.h12
-rw-r--r--clang/lib/Lex/ModuleMap.cpp1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp6
-rw-r--r--clang/lib/Serialization/ASTReader.cpp3
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp7
-rw-r--r--clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp27
-rw-r--r--clang/test/Parser/cxx-modules-interface.cppm3
-rw-r--r--clang/test/SemaCXX/modules-ts.cppm13
9 files changed, 66 insertions, 13 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 914e304de48..b5fed1f218b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8804,7 +8804,7 @@ let CategoryName = "Modules Issue" in {
def err_module_decl_in_module_map_module : Error<
"'module' declaration found while building module from module map">;
def err_module_interface_implementation_mismatch : Error<
- "missing 'export' specifier in 'module' declaration while "
+ "missing 'export' specifier in module declaration while "
"building module interface">;
def err_current_module_name_mismatch : Error<
"module name '%0' specified on command line does not match name of module">;
@@ -8848,8 +8848,13 @@ def err_module_self_import : Error<
"import of module '%0' appears within same top-level module '%1'">;
def err_module_import_in_implementation : Error<
"@import of module '%0' in implementation of '%1'; use #import">;
+
+// C++ Modules TS
def err_export_within_export : Error<
"export declaration appears within another export declaration">;
+def err_export_not_in_module_interface : Error<
+ "export declaration can only be used within a module interface unit after "
+ "the module declaration">;
def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn<
"ambiguous use of internal linkage declaration %0 defined in multiple modules">,
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 8fcb0e8b056..28aa7db5299 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -62,6 +62,18 @@ public:
/// \brief The location of the module definition.
SourceLocation DefinitionLoc;
+ enum ModuleKind {
+ /// \brief This is a module that was defined by a module map and built out
+ /// of header files.
+ ModuleMapModule,
+
+ /// \brief This is a C++ Modules TS module interface unit.
+ ModuleInterfaceUnit
+ };
+
+ /// \brief The kind of this module.
+ ModuleKind Kind = ModuleMapModule;
+
/// \brief The parent of this module. This will be NULL for the top-level
/// module.
Module *Parent;
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 5b60ed3f812..512d7dc5de6 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -581,6 +581,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
auto *Result =
new Module(Name, Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
+ Result->Kind = Module::ModuleInterfaceUnit;
Modules[Name] = SourceModule = Result;
// Mark the main source file as being within the newly-created module so that
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6138cbb114e..e7ea68e8e69 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15922,6 +15922,12 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc);
// C++ Modules TS draft:
+ // An export-declaration shall appear in the purview of a module other than
+ // the global module.
+ if (ModuleScopes.empty() || !ModuleScopes.back().Module ||
+ ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)
+ Diag(ExportLoc, diag::err_export_not_in_module_interface);
+
// An export-declaration [...] shall not contain more than one
// export keyword.
//
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 406c4b50d92..7b1edc062d1 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4779,6 +4779,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
bool First = true;
Module *CurrentModule = nullptr;
+ Module::ModuleKind ModuleKind = Module::ModuleMapModule;
RecordData Record;
while (true) {
llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
@@ -4871,6 +4872,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->setASTFile(F.File);
}
+ CurrentModule->Kind = ModuleKind;
CurrentModule->Signature = F.Signature;
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
@@ -4969,6 +4971,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
}
+ ModuleKind = (Module::ModuleKind)Record[2];
break;
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index bb869077f4c..5758ac953b2 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2694,9 +2694,10 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
// Write the submodule metadata block.
- RecordData::value_type Record[] = {getNumberOfModules(WritingModule),
- FirstSubmoduleID -
- NUM_PREDEF_SUBMODULE_IDS};
+ RecordData::value_type Record[] = {
+ getNumberOfModules(WritingModule),
+ FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS,
+ WritingModule->Kind};
Stream.EmitRecord(SUBMODULE_METADATA, Record);
// Write all of the submodules.
diff --git a/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp b/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp
new file mode 100644
index 00000000000..afe3a7a4858
--- /dev/null
+++ b/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fmodules-ts %s -verify -o /dev/null
+// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -o /dev/null
+// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -o /dev/null
+//
+// RUN: %clang_cc1 -fmodules-ts %s -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
+// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
+// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -DBUILT_AS_INTERFACE -emit-module-interface -verify -o /dev/null
+
+#if INTERFACE
+export module A;
+#elif IMPLEMENTATION
+module A;
+ #ifdef BUILT_AS_INTERFACE
+ // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}}
+ #endif
+#else
+ #ifdef BUILT_AS_INTERFACE
+ // FIXME: Diagnose missing module declaration (at end of TU)
+ #endif
+#endif
+
+export int a;
+#ifndef INTERFACE
+// expected-error@-2 {{export declaration can only be used within a module interface unit}}
+#else
+// expected-no-diagnostics
+#endif
diff --git a/clang/test/Parser/cxx-modules-interface.cppm b/clang/test/Parser/cxx-modules-interface.cppm
index 628b854fd23..0e7c7468335 100644
--- a/clang/test/Parser/cxx-modules-interface.cppm
+++ b/clang/test/Parser/cxx-modules-interface.cppm
@@ -1,11 +1,10 @@
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify
-// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DERRORS
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DERRORS
export module foo;
#ifndef ERRORS
// expected-no-diagnostics
#else
-// FIXME: diagnose 'export' declaration in non-module
// FIXME: diagnose missing module-declaration when building module interface
// FIXME: proclaimed-ownership-declarations?
diff --git a/clang/test/SemaCXX/modules-ts.cppm b/clang/test/SemaCXX/modules-ts.cppm
index 109a1f48496..16695f6463a 100644
--- a/clang/test/SemaCXX/modules-ts.cppm
+++ b/clang/test/SemaCXX/modules-ts.cppm
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0
-// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DTEST=1
-// RUN: not %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -DTEST=2 2>&1 | FileCheck %s --check-prefix=CHECK-2
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=1
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -DTEST=2
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3
#if TEST == 0
@@ -8,15 +8,14 @@
#endif
export module foo;
-#if TEST == 1
-// FIXME: diagnose export outside of module interface unit
-#elif TEST == 2
-// CHECK-2: error: redefinition of module 'foo'
+#if TEST == 2
+// expected-error@-2 {{redefinition of module 'foo'}}
+// expected-note@modules-ts.cppm:* {{loaded from}}
#endif
static int m; // ok, internal linkage, so no redefinition error
int n;
-#if TEST == 3
+#if TEST >= 2
// expected-error@-2 {{redefinition of '}}
// expected-note@-3 {{previous}}
#endif
OpenPOWER on IntegriCloud