[clang] 1a76d25 - [C++20][Modules][5/8] Diagnose wrong import/export for partition CMIs.

Iain Sandoe via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 26 03:27:24 PST 2022


Author: Iain Sandoe
Date: 2022-02-26T11:27:08Z
New Revision: 1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30

URL: https://github.com/llvm/llvm-project/commit/1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30
DIFF: https://github.com/llvm/llvm-project/commit/1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30.diff

LOG: [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

Added: 
    clang/test/Modules/cxx20-10-3-ex1.cpp
    clang/test/Modules/cxx20-10-3-ex2.cpp

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaModule.cpp
    clang/test/Modules/cxx20-import-diagnostics-a.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 15487260eb732..2528777678571 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index b2515075a7f23..0606b3a4edae8 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -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);

diff  --git a/clang/test/Modules/cxx20-10-3-ex1.cpp b/clang/test/Modules/cxx20-10-3-ex1.cpp
new file mode 100644
index 0000000000000..69a48c4f7a4aa
--- /dev/null
+++ b/clang/test/Modules/cxx20-10-3-ex1.cpp
@@ -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

diff  --git a/clang/test/Modules/cxx20-10-3-ex2.cpp b/clang/test/Modules/cxx20-10-3-ex2.cpp
new file mode 100644
index 0000000000000..589d8cb7baa14
--- /dev/null
+++ b/clang/test/Modules/cxx20-10-3-ex2.cpp
@@ -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}}

diff  --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
index 8017e19e957d6..d940722f8ee8e 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
@@ -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
 


        


More information about the cfe-commits mailing list