]> granicus.if.org Git - clang/commitdiff
[modules ts] Emit global variables in a module interface unit as part of that unit...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Sep 2017 20:01:14 +0000 (20:01 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Sep 2017 20:01:14 +0000 (20:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312665 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTReader.h
lib/AST/ASTContext.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp

index 94ac9f2facebe2806cddd6acde5498ed2da96802..f9a026067e044ed13c83fe967c870b198ee64d75 100644 (file)
@@ -1133,7 +1133,7 @@ private:
   /// predefines buffer may contain additional definitions.
   std::string SuggestedPredefines;
 
-  llvm::DenseMap<const Decl *, bool> BodySource;
+  llvm::DenseMap<const Decl *, bool> DefinitionSource;
 
   /// \brief Reads a statement from the specified cursor.
   Stmt *ReadStmtFromStream(ModuleFile &F);
index 1fb146e839ba52fe3cee0b9de85c07a8081877ee..fbc8874e93e5fe6b522e5f3fca9132cc9a6e81b8 100644 (file)
@@ -8908,7 +8908,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
 }
 
 static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
-                                                GVALinkage L, const Decl *D) {
+                                                const Decl *D, GVALinkage L) {
   // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
   // dllexport/dllimport on inline functions.
   if (D->hasAttr<DLLImportAttr>()) {
@@ -8927,25 +8927,37 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
   return L;
 }
 
-GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
-  auto L = adjustGVALinkageForAttributes(
-      *this, basicGVALinkageForFunction(*this, FD), FD);
-  auto EK = ExternalASTSource::EK_ReplyHazy;
-  if (auto *Ext = getExternalSource())
-    EK = Ext->hasExternalDefinitions(FD);
-  switch (EK) {
+/// Adjust the GVALinkage for a declaration based on what an external AST source
+/// knows about whether there can be other definitions of this declaration.
+static GVALinkage
+adjustGVALinkageForExternalDefinitionKind(const ASTContext &Ctx, const Decl *D,
+                                          GVALinkage L) {
+  ExternalASTSource *Source = Ctx.getExternalSource();
+  if (!Source)
+    return L;
+
+  switch (Source->hasExternalDefinitions(D)) {
   case ExternalASTSource::EK_Never:
+    // Other translation units rely on us to provide the definition.
     if (L == GVA_DiscardableODR)
       return GVA_StrongODR;
     break;
+
   case ExternalASTSource::EK_Always:
     return GVA_AvailableExternally;
+
   case ExternalASTSource::EK_ReplyHazy:
     break;
   }
   return L;
 }
 
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+  return adjustGVALinkageForExternalDefinitionKind(*this, FD,
+           adjustGVALinkageForAttributes(*this, FD,
+             basicGVALinkageForFunction(*this, FD)));
+}
+
 static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
                                              const VarDecl *VD) {
   if (!VD->isExternallyVisible())
@@ -9024,8 +9036,9 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
 }
 
 GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
-  return adjustGVALinkageForAttributes(
-      *this, basicGVALinkageForVariable(*this, VD), VD);
+  return adjustGVALinkageForExternalDefinitionKind(*this, VD,
+           adjustGVALinkageForAttributes(*this, VD,
+             basicGVALinkageForVariable(*this, VD)));
 }
 
 bool ASTContext::DeclMustBeEmitted(const Decl *D) {
@@ -9108,9 +9121,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
     return false;
 
   // Variables that can be needed in other TUs are required.
-  if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD)))
+  auto Linkage = GetGVALinkageForVariable(VD);
+  if (!isDiscardableGVALinkage(Linkage))
     return true;
 
+  // We never need to emit a variable that is available in another TU.
+  if (Linkage == GVA_AvailableExternally)
+    return false;
+
   // Variables that have destruction with side-effects are required.
   if (VD->getType().isDestructedType())
     return true;
index 4ba54fb712788b6fd11fcb8dc2e422fdda89374a..3221d78d16711076c8bcb38bac40db908024d9fc 100644 (file)
@@ -8291,8 +8291,8 @@ ASTReader::getSourceDescriptor(unsigned ID) {
 }
 
 ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) {
-  auto I = BodySource.find(FD);
-  if (I == BodySource.end())
+  auto I = DefinitionSource.find(FD);
+  if (I == DefinitionSource.end())
     return EK_ReplyHazy;
   return I->second ? EK_Never : EK_Always;
 }
index 533a3f9bdca92e35e2d33f70c9b3f21d55950417..6932261ad9b5658109b42b619187bd4466dd030d 100644 (file)
@@ -453,7 +453,7 @@ uint64_t ASTDeclReader::GetCurrentCursorOffset() {
 
 void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
   if (Record.readInt())
-    Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
+    Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
   if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
     CD->NumCtorInitializers = Record.readInt();
     if (CD->NumCtorInitializers)
@@ -1294,6 +1294,9 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
     }
   }
 
+  if (VD->getStorageDuration() == SD_Static && Record.readInt())
+    Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile;
+
   enum VarKind {
     VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
   };
@@ -1589,9 +1592,9 @@ void ASTDeclReader::ReadCXXDefinitionData(
   Data.HasODRHash = true;
 
   if (Record.readInt()) {
-    Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile
-                               ? ExternalASTSource::EK_Never
-                               : ExternalASTSource::EK_Always;
+    Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile
+                                     ? ExternalASTSource::EK_Never
+                                     : ExternalASTSource::EK_Always;
   }
 
   Data.NumBases = Record.readInt();
index 76021e270ba5afc1642c89f5412aab96868dcc35..bdf3fca49a7f1a4a6c914bac12dcfea6fd934bc2 100644 (file)
@@ -928,6 +928,24 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
   } else {
     Record.push_back(0);
   }
+
+  if (D->getStorageDuration() == SD_Static) {
+    bool ModulesCodegen = false;
+    if (Writer.WritingModule &&
+        !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() &&
+        !isa<VarTemplateSpecializationDecl>(D)) {
+      // When building a C++ Modules TS module interface unit, a strong
+      // definition in the module interface is provided by the compilation of
+      // that module interface unit, not by its users. (Inline variables are
+      // still emitted in module users.)
+      ModulesCodegen =
+          (Writer.WritingModule->Kind == Module::ModuleInterfaceUnit &&
+           Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal);
+    }
+    Record.push_back(ModulesCodegen);
+    if (ModulesCodegen)
+      Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
+  }
   
   enum {
     VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
@@ -963,6 +981,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
       !D->isConstexpr() &&
       !D->isInitCapture() &&
       !D->isPreviousDeclInSameBlockScope() &&
+      D->getStorageDuration() != SD_Static &&
       !D->getMemberSpecializationInfo())
     AbbrevToUse = Writer.getDeclVarAbbrev();
 
index 83cad5cc9b27af59efd228f2e280871ce0857d7b..bdb541e9c47470bb2c7995bfea5f61f9970c9a20 100644 (file)
@@ -2,17 +2,15 @@
 // RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module
 
 // CHECK-DAG: @extern_var_exported = external global
-// FIXME: Should this be 'external global'?
 // CHECK-DAG: @inline_var_exported = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE19static_var_exported = external global
-// CHECK-DAG: @const_var_exported = external constant
+// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally global i32 0,
+// CHECK-DAG: @const_var_exported = available_externally constant i32 3,
 //
 // FIXME: The module name should be mangled into all of these.
 // CHECK-DAG: @extern_var_module_linkage = external global
-// FIXME: Should this be 'external global'?
 // CHECK-DAG: @inline_var_module_linkage = linkonce_odr global
-// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = external global
-// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = external constant
+// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = available_externally global i32 0,
+// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = available_externally constant i32 3,
 
 module Module;
 
index ccbf222658cd244848327dbc9b3e99cc07043716..5e9f7ecf5babaeb0fb14bfbb9fb566c7a8ebb8af 100644 (file)
@@ -2,11 +2,9 @@
 // RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module
 
 // CHECK-DAG: @extern_var_exported = external global
-// FIXME: Should this be 'external global'?
 // CHECK-DAG: @inline_var_exported = linkonce_odr global
-// FIXME: These should be 'extern global' and 'extern constant'.
-// CHECK-DAG: @_ZW6ModuleE19static_var_exported = global
-// CHECK-DAG: @const_var_exported = constant
+// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally global i32 0
+// CHECK-DAG: @const_var_exported = available_externally constant i32 3
 
 import Module;