forked from OSchip/llvm-project
[C++20][Modules][5/8] Diagnose wrong import/export for partition CMIs.
We cannot export partition implementation CMIs, but we can export the content of partition interface CMIs. Differential Revision: https://reviews.llvm.org/D118588
This commit is contained in:
parent
4d006520b8
commit
1a76d25639
|
@ -10991,6 +10991,8 @@ def ext_module_import_not_at_top_level_noop : ExtWarn<
|
|||
def note_module_import_not_at_top_level : Note<"%0 begins here">;
|
||||
def err_module_self_import : Error<
|
||||
"import of module '%0' appears within same top-level module '%1'">;
|
||||
def err_module_self_import_cxx20 : Error<
|
||||
"import of module '%0' appears within its own %select{interface|implementation}1">;
|
||||
def err_module_import_in_implementation : Error<
|
||||
"@import of module '%0' in implementation of '%1'; use #import">;
|
||||
|
||||
|
@ -11024,6 +11026,8 @@ def err_export_using_internal : Error<
|
|||
def err_export_not_in_module_interface : Error<
|
||||
"export declaration can only be used within a module interface unit"
|
||||
"%select{ after the module declaration|}0">;
|
||||
def err_export_partition_impl : Error<
|
||||
"module partition implementations cannot be exported">;
|
||||
def err_export_in_private_module_fragment : Error<
|
||||
"export declaration cannot be used in a private module fragment">;
|
||||
def note_private_module_fragment : Note<
|
||||
|
|
|
@ -403,10 +403,16 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
|
|||
}
|
||||
|
||||
// Diagnose self-import before attempting a load.
|
||||
// [module.import]/9
|
||||
// A module implementation unit of a module M that is not a module partition
|
||||
// shall not contain a module-import-declaration nominating M.
|
||||
// (for an implementation, the module interface is imported implicitly,
|
||||
// but that's handled in the module decl code).
|
||||
|
||||
if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&
|
||||
getCurrentModule()->Name == ModuleName) {
|
||||
Diag(ImportLoc, diag::err_module_self_import)
|
||||
<< ModuleName << getLangOpts().CurrentModule;
|
||||
Diag(ImportLoc, diag::err_module_self_import_cxx20)
|
||||
<< ModuleName << !ModuleScopes.back().ModuleInterface;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -440,8 +446,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
|
|||
// of the same top-level module. Until we do, make it an error rather than
|
||||
// silently ignoring the import.
|
||||
// FIXME: Should we warn on a redundant import of the current module?
|
||||
if (!getLangOpts().CPlusPlusModules &&
|
||||
Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
|
||||
if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
|
||||
(getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS)) {
|
||||
Diag(ImportLoc, getLangOpts().isCompilingModule()
|
||||
? diag::err_module_self_import
|
||||
|
@ -482,7 +487,12 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
|
|||
if (!ModuleScopes.empty())
|
||||
Context.addModuleInitializer(ModuleScopes.back().Module, Import);
|
||||
|
||||
if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) {
|
||||
// A module (partition) implementation unit shall not be exported.
|
||||
if (getLangOpts().CPlusPlusModules && Mod && ExportLoc.isValid() &&
|
||||
Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
|
||||
Diag(ExportLoc, diag::err_export_partition_impl)
|
||||
<< SourceRange(ExportLoc, Path.back().second);
|
||||
} else if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) {
|
||||
// Re-export the module if the imported module is exported.
|
||||
// Note that we don't need to add re-exported module to Imports field
|
||||
// since `Exports` implies the module is imported already.
|
||||
|
@ -494,7 +504,9 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
|
|||
// [module.interface]p1:
|
||||
// An export-declaration shall inhabit a namespace scope and appear in the
|
||||
// purview of a module interface unit.
|
||||
Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;
|
||||
Diag(ExportLoc, diag::err_export_not_in_module_interface)
|
||||
<< (!ModuleScopes.empty() &&
|
||||
!ModuleScopes.back().ImplicitGlobalModuleFragment);
|
||||
} else if (getLangOpts().isCompilingModule()) {
|
||||
Module *ThisModule = PP.getHeaderSearchInfo().lookupModule(
|
||||
getLangOpts().CurrentModule, ExportLoc, false, false);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: split-file %s %t
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu1.cpp \
|
||||
// RUN: -o %t/M_PartImpl.pcm
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu2.cpp \
|
||||
// RUN: -fmodule-file=%t/M_PartImpl.pcm -o %t/M.pcm -verify
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu3.cpp \
|
||||
// RUN: -o %t/M_Part.pcm
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu4.cpp \
|
||||
// RUN: -fmodule-file=%t/M_Part.pcm -o %t/M.pcm
|
||||
|
||||
//--- std10-3-ex1-tu1.cpp
|
||||
module M:PartImpl;
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
//--- std10-3-ex1-tu2.cpp
|
||||
export module M;
|
||||
// error: exported partition :Part is an implementation unit
|
||||
export import :PartImpl; // expected-error {{module partition implementations cannot be exported}}
|
||||
|
||||
//--- std10-3-ex1-tu3.cpp
|
||||
export module M:Part;
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
//--- std10-3-ex1-tu4.cpp
|
||||
export module M;
|
||||
export import :Part;
|
||||
|
||||
// expected-no-diagnostics
|
|
@ -0,0 +1,25 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: split-file %s %t
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex2-tu1.cpp \
|
||||
// RUN: -o %t/M.pcm
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -S %t/std10-3-ex2-tu2.cpp \
|
||||
// RUN: -fmodule-file=%t/M.pcm -o %t/tu_8.s -verify
|
||||
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex2-tu3.cpp \
|
||||
// RUN: -o %t/M.pcm -verify
|
||||
|
||||
//--- std10-3-ex2-tu1.cpp
|
||||
export module M;
|
||||
|
||||
//--- std10-3-ex2-tu2.cpp
|
||||
module M;
|
||||
// error: cannot import M in its own unit
|
||||
import M; // expected-error {{import of module 'M' appears within its own implementation}}
|
||||
|
||||
//--- std10-3-ex2-tu3.cpp
|
||||
export module M;
|
||||
// error: cannot import M in its own unit
|
||||
import M; // expected-error {{import of module 'M' appears within its own interface}}
|
|
@ -118,13 +118,13 @@ import B; // expected-error {{module imports cannot be in the private module fra
|
|||
|
||||
module B;
|
||||
|
||||
import B; // expected-error {{import of module 'B' appears within same top-level module 'B'}}
|
||||
import B; // expected-error {{import of module 'B' appears within its own implementation}}
|
||||
|
||||
//--- import-diags-tu10.cpp
|
||||
|
||||
export module B;
|
||||
|
||||
import B; // expected-error {{import of module 'B' appears within same top-level module 'B'}}
|
||||
import B; // expected-error {{import of module 'B' appears within its own interface}}
|
||||
|
||||
//--- import-diags-tu11.cpp
|
||||
|
||||
|
|
Loading…
Reference in New Issue