dblaikie updated this revision to Diff 91193.
dblaikie added a comment.

sync/resolve


https://reviews.llvm.org/D29901

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/ExternalASTSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Serialization/ASTReader.h
  lib/AST/ASTContext.cpp
  lib/AST/ExternalASTSource.cpp
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriterDecl.cpp
  test/Modules/Inputs/codegen/foo.h
  test/Modules/Inputs/codegen/use.cpp
  test/Modules/codegen.test

Index: test/Modules/codegen.test
===================================================================
--- test/Modules/codegen.test
+++ test/Modules/codegen.test
@@ -3,8 +3,23 @@
 
 RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
 
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
 
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user.
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+FOO: define weak_odr void @_Z4instIfEvv() #0 comdat {
+FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat {
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
Index: test/Modules/Inputs/codegen/use.cpp
===================================================================
--- /dev/null
+++ test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst<int>();
+}
Index: test/Modules/Inputs/codegen/foo.h
===================================================================
--- test/Modules/Inputs/codegen/foo.h
+++ test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct non_trivial_dtor {
+  ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+  non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+  non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+  implicit_dtor d;
+}
+
+template<typename T>
+void inst() {
+}
+
+inline void inst_decl() {
+  // cause inst<int>'s declaration to be instantiated, without a definition.
+  (void)sizeof(&inst<int>);
+  inst<float>();
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -2157,7 +2157,7 @@
 /// relatively painless since they would presumably only do it for top-level
 /// decls.
 static bool isRequiredDecl(const Decl *D, ASTContext &Context,
-                           bool WritingModule, bool ModularCode) {
+                           bool WritingModule) {
   // An ObjCMethodDecl is never considered as "required" because its
   // implementation container always is.
 
@@ -2173,7 +2173,7 @@
     return false;
   }
 
-  return Context.DeclMustBeEmitted(D, ModularCode);
+  return Context.DeclMustBeEmitted(D);
 }
 
 void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
@@ -2217,18 +2217,20 @@
 
   // Note declarations that should be deserialized eagerly so that we can add
   // them to a record in the AST file later.
-  if (isRequiredDecl(D, Context, WritingModule, false))
+  if (isRequiredDecl(D, Context, WritingModule))
     EagerlyDeserializedDecls.push_back(ID);
-  else if (Context.getLangOpts().ModularCodegen && WritingModule &&
-           isRequiredDecl(D, Context, true, true))
-    ModularCodegenDecls.push_back(ID);
 }
 
 void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
   // Switch case IDs are per function body.
   Writer->ClearSwitchCaseIDs();
 
   assert(FD->doesThisDeclarationHaveABody());
+  bool ModularCodegen =
+      Writer->Context->getLangOpts().ModularCodegen && Writer->WritingModule;
+  Record->push_back(ModularCodegen);
+  if (ModularCodegen)
+    Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(FD));
   if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
     Record->push_back(CD->getNumCtorInitializers());
     if (CD->getNumCtorInitializers())
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -424,6 +424,11 @@
 }
 
 void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
+  if (Record.readInt()) {
+    Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile
+                                ? ExternalASTSource::EK_Never
+                                : ExternalASTSource::EK_Always;
+  }
   if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
     CD->NumCtorInitializers = Record.readInt();
     if (CD->NumCtorInitializers)
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7936,16 +7936,11 @@
   return None;
 }
 
-ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(unsigned ID) {
-  const Module *M = getSubmodule(ID);
-  if (!M || !M->WithCodegen)
+ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const FunctionDecl *FD) {
+  auto I = BodySource.find(FD);
+  if (I == BodySource.end())
     return EK_ReplyHazy;
-
-  ModuleFile *MF = ModuleMgr.lookup(M->getASTFile());
-  assert(MF); // ?
-  if (MF->Kind == ModuleKind::MK_MainFile)
-    return EK_Never;
-  return EK_Always;
+  return I->second;
 }
 
 Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
@@ -8779,9 +8774,9 @@
       // FIXME: Check for =delete/=default?
       // FIXME: Complain about ODR violations here?
       const FunctionDecl *Defn = nullptr;
-      if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn))
+      if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) {
         FD->setLazyBody(PB->second);
-      else
+      } else
         mergeDefinitionVisibility(const_cast<FunctionDecl*>(Defn), FD);
       continue;
     }
Index: lib/Sema/MultiplexExternalSemaSource.cpp
===================================================================
--- lib/Sema/MultiplexExternalSemaSource.cpp
+++ lib/Sema/MultiplexExternalSemaSource.cpp
@@ -95,9 +95,9 @@
 }
 
 ExternalASTSource::ExtKind
-MultiplexExternalSemaSource::hasExternalDefinitions(unsigned int ID) {
+MultiplexExternalSemaSource::hasExternalDefinitions(const FunctionDecl *FD) {
   for (const auto &S : Sources)
-    if (auto EK = S->hasExternalDefinitions(ID))
+    if (auto EK = S->hasExternalDefinitions(FD))
       if (EK != EK_ReplyHazy)
         return EK;
   return EK_ReplyHazy;
Index: lib/AST/ExternalASTSource.cpp
===================================================================
--- lib/AST/ExternalASTSource.cpp
+++ lib/AST/ExternalASTSource.cpp
@@ -29,7 +29,7 @@
 }
 
 ExternalASTSource::ExtKind
-ExternalASTSource::hasExternalDefinitions(unsigned ID) {
+ExternalASTSource::hasExternalDefinitions(const FunctionDecl *FD) {
   return EK_ReplyHazy;
 }
 
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -8889,7 +8889,7 @@
       *this, basicGVALinkageForFunction(*this, FD), FD);
   auto EK = ExternalASTSource::EK_ReplyHazy;
   if (auto *Ext = getExternalSource())
-    EK = Ext->hasExternalDefinitions(FD->getOwningModuleID());
+    EK = Ext->hasExternalDefinitions(FD);
   switch (EK) {
   case ExternalASTSource::EK_Never:
     if (L == GVA_DiscardableODR)
@@ -8985,7 +8985,7 @@
       *this, basicGVALinkageForVariable(*this, VD), VD);
 }
 
-bool ASTContext::DeclMustBeEmitted(const Decl *D, bool ForModularCodegen) {
+bool ASTContext::DeclMustBeEmitted(const Decl *D) {
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     if (!VD->isFileVarDecl())
       return false;
@@ -9051,9 +9051,6 @@
 
     GVALinkage Linkage = GetGVALinkageForFunction(FD);
 
-    if (Linkage == GVA_DiscardableODR && ForModularCodegen)
-      return true;
-
     // static, static inline, always_inline, and extern inline functions can
     // always be deferred.  Normal inline functions can be deferred in C99/C++.
     // Implicit template instantiations can also be deferred in C++.
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -1101,6 +1101,8 @@
   /// predefines buffer may contain additional definitions.
   std::string SuggestedPredefines;
 
+  std::map<const FunctionDecl*, ExternalASTSource::ExtKind> BodySource;
+
   /// \brief Reads a statement from the specified cursor.
   Stmt *ReadStmtFromStream(ModuleFile &F);
 
@@ -1968,7 +1970,7 @@
   /// \brief Return a descriptor for the corresponding module.
   llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
 
-  ExtKind hasExternalDefinitions(unsigned ID) override;
+  ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
 
   /// \brief Retrieve a selector from the given module with its local ID
   /// number.
Index: include/clang/Sema/MultiplexExternalSemaSource.h
===================================================================
--- include/clang/Sema/MultiplexExternalSemaSource.h
+++ include/clang/Sema/MultiplexExternalSemaSource.h
@@ -90,7 +90,7 @@
   /// initializers themselves.
   CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
 
-  ExtKind hasExternalDefinitions(unsigned ID) override;
+  ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
 
   /// \brief Find all declarations with the given name in the
   /// given context.
Index: include/clang/AST/ExternalASTSource.h
===================================================================
--- include/clang/AST/ExternalASTSource.h
+++ include/clang/AST/ExternalASTSource.h
@@ -172,7 +172,7 @@
 
   enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
 
-  virtual ExtKind hasExternalDefinitions(unsigned ID);
+  virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD);
 
   /// \brief Finds all declarations lexically contained within the given
   /// DeclContext, after applying an optional filter predicate.
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -2507,7 +2507,7 @@
   ///
   /// \returns true if the function/var must be CodeGen'ed/deserialized even if
   /// it is not used.
-  bool DeclMustBeEmitted(const Decl *D, bool ForModularCodegen = false);
+  bool DeclMustBeEmitted(const Decl *D);
 
   const CXXConstructorDecl *
   getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to