summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Parse/Parser.h2
-rw-r--r--clang/lib/Parse/ParseObjc.cpp6
-rw-r--r--clang/lib/Parse/Parser.cpp14
-rw-r--r--clang/lib/Sema/SemaDecl.cpp13
-rw-r--r--clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp40
-rw-r--r--clang/test/SemaCXX/modules-ts.cppm4
6 files changed, 62 insertions, 17 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index ce60cbb4317..396b5a9aa39 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2788,7 +2788,7 @@ private:
//===--------------------------------------------------------------------===//
// Modules
DeclGroupPtrTy ParseModuleDecl();
- DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
+ Decl *ParseModuleImport(SourceLocation AtLoc);
bool parseMisplacedModuleImport();
bool tryParseMisplacedModuleImport() {
tok::TokenKind Kind = Tok.getKind();
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index edf1da171b0..fb8624a324b 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -81,8 +81,10 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
SingleDecl = ParseObjCPropertyDynamic(AtLoc);
break;
case tok::objc_import:
- if (getLangOpts().Modules || getLangOpts().DebuggerSupport)
- return ParseModuleImport(AtLoc);
+ if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {
+ SingleDecl = ParseModuleImport(AtLoc);
+ break;
+ }
Diag(AtLoc, diag::err_atimport);
SkipUntil(tok::semi);
return Actions.ConvertDeclToDeclGroup(nullptr);
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 0b07ba1888b..72d653797c6 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -556,10 +556,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
HandlePragmaUnused();
return false;
- case tok::kw_import:
- Result = ParseModuleImport(SourceLocation());
- return false;
-
case tok::kw_export:
if (NextToken().isNot(tok::kw_module))
break;
@@ -637,6 +633,9 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
+///
+/// [Modules-TS] module-import-declaration
+///
Parser::DeclGroupPtrTy
Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS) {
@@ -764,6 +763,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
CurParsedObjCImpl ? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace);
cutOffParsing();
return nullptr;
+ case tok::kw_import:
+ SingleDecl = ParseModuleImport(SourceLocation());
+ break;
case tok::kw_export:
if (getLangOpts().ModulesTS) {
SingleDecl = ParseExportDeclaration();
@@ -2092,7 +2094,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
/// '@' 'import' module-name ';'
/// [ModTS] module-import-declaration:
/// 'import' module-name attribute-specifier-seq[opt] ';'
-Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
+Decl *Parser::ParseModuleImport(SourceLocation AtLoc) {
assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
: Tok.isObjCAtKeyword(tok::objc_import)) &&
"Improper start to module import");
@@ -2119,7 +2121,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
if (Import.isInvalid())
return nullptr;
- return Actions.ConvertDeclToDeclGroup(Import.get());
+ return Import.get();
}
/// Parse a C++ Modules TS / Objective-C module name (both forms use the same
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14dcce48d29..41f6f730b2f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16171,7 +16171,7 @@ static void checkModuleImportContext(Sema &S, Module *M,
DC = LSD->getParent();
}
- while (isa<LinkageSpecDecl>(DC))
+ while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC))
DC = DC->getParent();
if (!isa<TranslationUnitDecl>(DC)) {
@@ -16349,12 +16349,17 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
IdentifierLocs.push_back(Path[I].second);
}
- TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
- ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
+ ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc,
Mod, IdentifierLocs);
if (!ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
- TU->addDecl(Import);
+ CurContext->addDecl(Import);
+
+ // Re-export the module if needed.
+ if (Import->isExported() &&
+ !ModuleScopes.empty() && ModuleScopes.back().ModuleInterface)
+ getCurrentModule()->Exports.emplace_back(Mod, false);
+
return Import;
}
diff --git a/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp b/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp
new file mode 100644
index 00000000000..ab8c690441c
--- /dev/null
+++ b/clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp
@@ -0,0 +1,40 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+//
+// RUN: echo 'export module a; export class A{};' | %clang_cc1 -x c++ -fmodules-ts -emit-module-interface - -o %t/a.pcm
+// RUN: echo 'export module b; export class B{};' | %clang_cc1 -x c++ -fmodules-ts -emit-module-interface - -o %t/b.pcm
+// RUN: echo 'export module c; export class C{};' | %clang_cc1 -x c++ -fmodules-ts -emit-module-interface - -o %t/c.pcm
+//
+// RUN: %clang_cc1 -fmodules-ts -fprebuilt-module-path=%t -emit-module-interface %s -o %t/aggregate.internal.pcm -DAGGREGATE_INTERNAL
+// RUN: %clang_cc1 -fmodules-ts -fprebuilt-module-path=%t -emit-module-interface %s -o %t/aggregate.pcm -DAGGREGATE
+//
+// RUN: %clang_cc1 -fmodules-ts -fprebuilt-module-path=%t %s -verify -DTEST
+// expected-no-diagnostics
+
+
+#ifdef AGGREGATE_INTERNAL
+export module aggregate.internal;
+export import a;
+export {
+ import b;
+ import c;
+}
+#endif
+
+
+// Export the above aggregate module.
+// This is done to ensure that re-exports are transitive.
+#ifdef AGGREGATE
+export module aggregate;
+export import aggregate.internal;
+#endif
+
+
+// For the actual test, just try using the classes from the exported modules
+// and hope that they're accessible.
+#ifdef TEST
+import aggregate;
+A a;
+B b;
+C c;
+#endif
diff --git a/clang/test/SemaCXX/modules-ts.cppm b/clang/test/SemaCXX/modules-ts.cppm
index f64a4c0ab41..c07ee82e313 100644
--- a/clang/test/SemaCXX/modules-ts.cppm
+++ b/clang/test/SemaCXX/modules-ts.cppm
@@ -52,10 +52,6 @@ export {} // expected-error {{export declaration cannot be empty}}
export { ; }
export { static_assert(true); }
-// FIXME: These diagnostics are not very good.
-export import foo; // expected-error {{expected unqualified-id}}
-export { import foo; } // expected-error {{expected unqualified-id}}
-
int use_b = b;
int use_n = n; // FIXME: this should not be visible, because it is not exported
OpenPOWER on IntegriCloud