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

Format.


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

https://reviews.llvm.org/D110215

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.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/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/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/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,22 @@
+// 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;
+}
+}
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,6 @@
+extern "C" void foo();
+extern "C" {
+void bar();
+int baz();
+double double_func();
+}
Index: clang/lib/Sema/SemaModule.cpp
===================================================================
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -66,10 +66,12 @@
     return nullptr;
   }
 
+  assert(!GlobalModule &&
+         "Global module already created but was not covered above.");
   // 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);
+  GlobalModule = Map.createGlobalModuleFragmentForModuleUnit(ModuleLoc);
   assert(GlobalModule && "module creation should not fail");
 
   // Enter the scope of the global module.
@@ -708,3 +710,19 @@
 
   return D;
 }
+
+Module *Sema::getOrCreateGlobalModule(SourceLocation BeginLoc) {
+  if (!GlobalModule) {
+    auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+    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 = true;
+    VisibleModules.setVisible(GlobalModule, BeginLoc);
+  }
+  return GlobalModule;
+}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -9339,6 +9339,8 @@
       }
     }
 
+    HandleLinkSpecDeclInModule(NewFD);
+
     if (isFriend) {
       if (FunctionTemplate) {
         FunctionTemplate->setObjectOfFriendDecl();
@@ -15567,6 +15569,31 @@
   return false;
 }
 
+/// Try to attach a Decl to the global module if following conditions
+/// are met.
+///
+/// C++ [module.unit]p7.2.3
+/// - Otherwise, if the declaration
+///   - ...
+///   - ...
+///   - appears within a linkage-specification,
+///   it is attached to the global module.
+void Sema::HandleLinkSpecDeclInModule(Decl *D) {
+  Module *M = D->getOwningModule();
+
+  if (!M || M->Kind != Module::ModuleInterfaceUnit)
+    return;
+
+  auto *DC = D->getDeclContext();
+
+  if (DC->isExternCContext() || DC->isExternCXXContext()) {
+    Module *Global = getOrCreateGlobalModule(D->getBeginLoc());
+    D->setLocalOwningModule(Global);
+    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Unowned);
+    return;
+  }
+}
+
 /// This is invoked when we see 'struct foo' or 'struct {'.  In the
 /// former case, Name will be non-null.  In the later case, Name will be null.
 /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
@@ -16407,6 +16434,8 @@
       New->setModulePrivate();
   }
 
+  HandleLinkSpecDeclInModule(New);
+
   // If this is a specialization of a member class (of a class template),
   // check the specialization.
   if (isMemberSpecialization && CheckMemberSpecialization(New, Previous))
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2195,6 +2195,7 @@
   };
   /// The modules we're currently parsing.
   llvm::SmallVector<ModuleScope, 16> ModuleScopes;
+  Module *GlobalModule = nullptr;
 
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet<const NamespaceDecl*, 8> DeferredExportedNamespaces;
@@ -2204,6 +2205,11 @@
     return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
   }
 
+  Module *getOrCreateGlobalModule(SourceLocation BeginLoc);
+
+  /// Try to attach Declaration to global module. See C++ [module.unit]p7.2.3
+  void HandleLinkSpecDeclInModule(Decl *D);
+
   VisibleModuleSet VisibleModules;
 
 public:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to