ChuanqiXu updated this revision to Diff 379907.
ChuanqiXu added a comment.
Herald added a subscriber: dexonsmith.

Address the comments from @rsmith. It looks much better now.


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

https://reviews.llvm.org/D110215

Files:
  clang/include/clang/Basic/Module.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/CXX/module/module.linkage_specification/Inputs/h1.h
  clang/test/CXX/module/module.linkage_specification/Inputs/h2.h
  clang/test/CXX/module/module.linkage_specification/Inputs/h4.h
  clang/test/CXX/module/module.linkage_specification/Inputs/h5.h
  clang/test/CXX/module/module.linkage_specification/p1.cpp
  clang/test/CXX/module/module.linkage_specification/p2.cpp
  clang/test/CXX/module/module.linkage_specification/p3.cpp
  clang/test/CXX/module/module.linkage_specification/p4.cpp
  clang/test/CXX/module/module.linkage_specification/p5.cpp
  clang/test/CodeGenCXX/Inputs/module-extern-C.h
  clang/test/CodeGenCXX/module-extern-C.cpp

Index: clang/test/CodeGenCXX/module-extern-C.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/module-extern-C.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
+
+module;
+
+#include "Inputs/module-extern-C.h"
+
+export module x;
+
+// CHECK: define dso_local void @foo()
+extern "C" void foo() {
+  return;
+}
+
+extern "C" {
+// CHECK: define dso_local void @bar()
+void bar() {
+  return;
+}
+// CHECK: define dso_local i32 @baz()
+int baz() {
+  return 3;
+}
+// CHECK: define dso_local double @double_func()
+double double_func() {
+  return 5.0;
+}
+}
Index: clang/test/CodeGenCXX/Inputs/module-extern-C.h
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/Inputs/module-extern-C.h
@@ -0,0 +1,7 @@
+extern "C" void foo();
+extern "C" {
+void bar();
+int baz();
+double double_func();
+}
+extern "C++" class CPP;
Index: clang/test/CXX/module/module.linkage_specification/p5.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/p5.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// expected-no-diagnostics
+module;
+
+#include "Inputs/h4.h"
+
+export module x;
+
+extern "C++" int a = 5;
Index: clang/test/CXX/module/module.linkage_specification/p4.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/p4.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// expected-no-diagnostics
+module;
+
+#include "Inputs/h4.h"
+
+export module x;
+
+extern "C" struct C {
+  int a;
+  int b;
+  double d;
+};
Index: clang/test/CXX/module/module.linkage_specification/p3.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/p3.cpp
@@ -0,0 +1,7 @@
+// This tests whether the global module would be created when the program don't declare it explicitly.
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// expected-no-diagnostics
+export module x;
+
+extern "C" void foo();
+extern "C++" class CPP {};
Index: clang/test/CXX/module/module.linkage_specification/p2.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/p2.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// expected-no-diagnostics
+module;
+
+#include "Inputs/h2.h"
+
+export module x;
+
+extern "C++" class CPP {};
Index: clang/test/CXX/module/module.linkage_specification/p1.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/p1.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+// expected-no-diagnostics
+module;
+
+#include "Inputs/h1.h"
+
+export module x;
+
+extern "C" void foo() {
+  return;
+}
+
+extern "C" {
+void bar() {
+  return;
+}
+int baz() {
+  return 3;
+}
+double double_func() {
+  return 5.0;
+}
+}
+
+extern "C++" {
+void bar_cpp() {
+  return;
+}
+int baz_cpp() {
+  return 3;
+}
+double double_func_cpp() {
+  return 5.0;
+}
+}
Index: clang/test/CXX/module/module.linkage_specification/Inputs/h5.h
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/Inputs/h5.h
@@ -0,0 +1 @@
+extern "C++" int a;
Index: clang/test/CXX/module/module.linkage_specification/Inputs/h4.h
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/Inputs/h4.h
@@ -0,0 +1 @@
+extern "C" struct C;
Index: clang/test/CXX/module/module.linkage_specification/Inputs/h2.h
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/Inputs/h2.h
@@ -0,0 +1 @@
+extern "C++" class CPP;
Index: clang/test/CXX/module/module.linkage_specification/Inputs/h1.h
===================================================================
--- /dev/null
+++ clang/test/CXX/module/module.linkage_specification/Inputs/h1.h
@@ -0,0 +1,12 @@
+extern "C" void foo();
+extern "C" {
+void bar();
+int baz();
+double double_func();
+}
+
+extern "C++" {
+void bar_cpp();
+int baz_cpp();
+double double_func_cpp();
+}
Index: clang/lib/Sema/SemaModule.cpp
===================================================================
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -68,15 +68,8 @@
 
   // We start in the global module; all those declarations are implicitly
   // module-private (though they do not have module linkage).
-  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
-  auto *GlobalModule = Map.createGlobalModuleFragmentForModuleUnit(ModuleLoc);
-  assert(GlobalModule && "module creation should not fail");
-
-  // Enter the scope of the global module.
-  ModuleScopes.push_back({});
-  ModuleScopes.back().BeginLoc = ModuleLoc;
-  ModuleScopes.back().Module = GlobalModule;
-  VisibleModules.setVisible(GlobalModule, ModuleLoc);
+  auto *GlobalModule =
+      PushGlobalModuleFragment(ModuleLoc, /*IsImplicit=*/false);
 
   // All declarations created from now on are owned by the global module.
   auto *TU = Context.getTranslationUnitDecl();
@@ -708,3 +701,25 @@
 
   return D;
 }
+
+Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc,
+                                       bool IsImplicit) {
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+  auto *GlobalModule = Map.createGlobalModuleFragmentForModuleUnit(BeginLoc);
+  assert(GlobalModule && "module creation should not fail");
+
+  // Enter the scope of the global module.
+  ModuleScopes.push_back({});
+  ModuleScopes.back().BeginLoc = BeginLoc;
+  ModuleScopes.back().Module = GlobalModule;
+  ModuleScopes.back().ImplicitGlobalModuleFragment = IsImplicit;
+  VisibleModules.setVisible(GlobalModule, BeginLoc);
+
+  return GlobalModule;
+}
+
+void Sema::PopGlobalModuleFragment() {
+  assert(!ModuleScopes.empty() && getCurrentModule().isGlobalModule() &&
+         "left the wrong module scope, which is not global module fragment");
+  ModuleScopes.pop_back();
+}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -16144,6 +16144,20 @@
   LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc,
                                                LangStr->getExprLoc(), Language,
                                                LBraceLoc.isValid());
+
+  /// C++ [module.unit]p7.2.3
+  /// - Otherwise, if the declaration
+  ///   - ...
+  ///   - ...
+  ///   - appears within a linkage-specification,
+  ///   it is attached to the global module.
+  if (getLangOpts().CPlusPlusModules) {
+    auto *GlobalModule =
+        PushGlobalModuleFragment(ExternLoc, /*IsImplicit=*/true);
+    D->setLocalOwningModule(GlobalModule);
+    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Unowned);
+  }
+
   CurContext->addDecl(D);
   PushDeclContext(S, D);
   return D;
@@ -16160,6 +16174,10 @@
     LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
     LSDecl->setRBraceLoc(RBraceLoc);
   }
+
+  if (getLangOpts().CPlusPlusModules)
+    PopGlobalModuleFragment();
+
   PopDeclContext();
   return LinkageSpec;
 }
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2204,6 +2204,11 @@
     return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
   }
 
+  /// Enter the scope of the global module.
+  Module *PushGlobalModuleFragment(SourceLocation BeginLoc, bool IsImplicit);
+  /// Leave the scope of the global module.
+  void PopGlobalModuleFragment();
+
   VisibleModuleSet VisibleModules;
 
 public:
Index: clang/include/clang/Basic/Module.h
===================================================================
--- clang/include/clang/Basic/Module.h
+++ clang/include/clang/Basic/Module.h
@@ -153,6 +153,10 @@
     return Kind == ModuleInterfaceUnit || Kind == PrivateModuleFragment;
   }
 
+  /// Does this Module scope describe a fragment of the global module within
+  /// some C++ module.
+  bool isGlobalModule() const { return Kind == GlobalModuleFragment; }
+
 private:
   /// The submodules of this module, indexed by name.
   std::vector<Module *> SubModules;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to