[PATCH] D112903: [C++20] [Module] Fix front end crashes when trying to export a qualified entity which is already declared

Chuanqi Xu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 4 22:05:23 PDT 2021


ChuanqiXu updated this revision to Diff 384968.
ChuanqiXu added a comment.

Updated diagnostic messages. It looks good to me to reject for exporting non-namespace-scope names in `diagnoseQualifiedDeclaration()`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112903/new/

https://reviews.llvm.org/D112903

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CXX/module/module.interface/p6.cpp


Index: clang/test/CXX/module/module.interface/p6.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.interface/p6.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c++20 %s -verify
+
+export module X;
+
+export template <typename T>
+struct X {
+  struct iterator {
+    T node;
+  };
+  void foo() {}
+  template <typename U>
+  U bar();
+};
+
+export template <typename T> X<T>::iterator;                      // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}}
+export template <typename T> void X<T>::foo();                    // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}}
+export template <typename T> template <typename U> U X<T>::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}}
+
+export struct Y {
+  struct iterator {
+    int node;
+  };
+  void foo() {}
+  template <typename U>
+  U bar();
+};
+
+export struct Y::iterator;               // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}}
+export void Y::foo();                    // expected-error {{cannot export 'foo' here since only the entities in namespace scope could be exported.}}
+export template <typename U> U Y::bar(); // expected-error {{cannot export 'bar' here since only the entities in namespace scope could be exported.}}
+
+export {
+  template <typename T> X<T>::iterator; // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}}
+  struct Y::iterator;                   // expected-error {{cannot export 'iterator' here since only the entities in namespace scope could be exported.}}
+}
+
+namespace A {
+export struct X;
+struct Y;
+export void foo();
+void bar();
+} // namespace A
+
+// [module.interface]/p6
+// A redeclaration of an entity X is implicitly exported if X was introduced by an exported declaration
+void A::foo();
+export struct A::X;   // expected-error {{cannot export redeclaration 'X' here.}}
+export struct A::Y;   // expected-error {{cannot export redeclaration 'Y' here.}}
+export void A::foo(); // expected-error {{cannot export redeclaration 'foo' here.}}
+// The compiler couldn't export A::bar() here since A::bar() is declared above without exported.
+// See [module.interface]/p6 for details.
+export void A::bar(); // expected-error {{cannot export redeclaration 'bar' here.}}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -5745,7 +5745,12 @@
     else if (isa<BlockDecl>(Cur))
       Diag(Loc, diag::err_invalid_declarator_in_block)
         << Name << SS.getRange();
-    else
+    else if (isa<ExportDecl>(Cur)) {
+      if (!isa<NamespaceDecl>(DC))
+        Diag(Loc, diag::err_export_non_namespace_scope_name) << Name;
+      else
+        Diag(Loc, diag::err_export_qualified_redeclaration) << Name;
+    } else
       Diag(Loc, diag::err_invalid_declarator_scope)
       << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange();
 
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7781,6 +7781,10 @@
   "%select{ or namespace|, namespace, or enumeration}1">;
 def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here "
   "because namespace %1 does not enclose namespace %2">;
+def err_export_non_namespace_scope_name : Error<"cannot export %0 here since "
+  "only the entities in namespace scope could be exported.">;
+def err_export_qualified_redeclaration : Error<"cannot export redeclaration "
+  "%0 here.">;
 def err_invalid_declarator_global_scope : Error<
   "definition or redeclaration of %0 cannot name the global scope">;
 def err_invalid_declarator_in_function : Error<


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D112903.384968.patch
Type: text/x-patch
Size: 4127 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211105/70add26f/attachment.bin>


More information about the cfe-commits mailing list