Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -16308,6 +16308,15 @@ TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); TU->setLocalOwningModule(Mod); + // Modules TS + p0731r0 [dcl.module.interface]p1: + // Every name of an entity with linkage other than internal linkage made + // visible in the purview of the module interface unit of a module M is + // visible in the purview of all module implementation units of M. + if (MDK == ModuleDeclKind::Implementation) { + for (Module *ImportedModule : Mod->Imports) + VisibleModules.setVisible(ImportedModule, ModuleLoc); + } + // FIXME: Create a ModuleDecl. return nullptr; } @@ -16355,10 +16364,19 @@ Context.addModuleInitializer(ModuleScopes.back().Module, Import); CurContext->addDecl(Import); - // Re-export the module if needed. - if (Import->isExported() && - !ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) - getCurrentModule()->Exports.emplace_back(Mod, false); + if (getLangOpts().ModulesTS && + !ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) { + Module *CurrentModule = getCurrentModule(); + + // Store imports that occur in the purview of a module interface unit. + // This is so that we know what to make visible in the purview of the + // corresponding implementation units. + CurrentModule->Imports.insert(Mod); + + // Re-export the module if needed. + if (Import->isExported()) + CurrentModule->Exports.emplace_back(Mod, false); + } return Import; } Index: test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp =================================================================== --- test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp +++ test/CXX/modules-ts/basic/basic.def.odr/p6/module-vs-module.cpp @@ -10,9 +10,7 @@ // // RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N.pcm -DMODULE_INTERFACE -DNO_ERRORS // RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -verify -// FIXME: Once we start importing "import" declarations properly, this should -// be rejected (-verify should be added to the following line). -// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -DNO_IMPORT +// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -DNO_IMPORT -verify // // RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N-no-M.pcm -DMODULE_INTERFACE -DNO_ERRORS -DNO_IMPORT // RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N-no-M.pcm -verify Index: test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp =================================================================== --- test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp +++ test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp @@ -1,28 +0,0 @@ -// RUN: %clang_cc1 -fmodules-ts %s -verify -o /dev/null -// RUN: %clang_cc1 -fmodules-ts %s -DINTERFACE -verify -emit-module-interface -o %t -// RUN: %clang_cc1 -fmodules-ts %s -DIMPLEMENTATION -verify -fmodule-file=%t -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 -// expected-no-diagnostics -export module A; -#elif IMPLEMENTATION -module A; - #ifdef BUILT_AS_INTERFACE - // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}} - #define INTERFACE - #endif -#else - #ifdef BUILT_AS_INTERFACE - // expected-error@1 {{missing 'export module' declaration in module interface unit}} - #endif -#endif - -#ifndef INTERFACE -export int b; // expected-error {{export declaration can only be used within a module interface unit}} -#else -export int a; -#endif Index: test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1/interface-imports.cpp =================================================================== --- test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1/interface-imports.cpp +++ test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1/interface-imports.cpp @@ -0,0 +1,29 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: echo 'export module a; export class A { };' > %t/a.cppm +// RUN: echo 'export module b; export class B { };' > %t/b.cppm +// +// RUN: %clang_cc1 -fmodules-ts -emit-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -fmodules-ts -emit-module-interface %t/b.cppm -o %t/b.pcm +// +// RUN: %clang_cc1 -fmodules-ts -fprebuilt-module-path=%t -emit-module-interface %s -o %t/test.pcm -DINTERFACE +// RUN: %clang_cc1 -fmodules-ts -I%t -fmodule-file=%t/test.pcm %s -verify + +#ifdef INTERFACE + +import a; +export module test; +import b; + +#else // IMPLEMENTATION + +module test; + +A a; // expected-error {{must be imported from module 'a'}} + // expected-note@a.cppm:1 {{here}} + +// Module b is imported within the purview of this module's interface unit. +// So its exported definitions should be visible here. +B b; + +#endif