/// 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);
}
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>()) {
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())
}
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) {
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;
}
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;
}
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)
}
}
+ if (VD->getStorageDuration() == SD_Static && Record.readInt())
+ Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile;
+
enum VarKind {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
};
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();
} 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
!D->isConstexpr() &&
!D->isInitCapture() &&
!D->isPreviousDeclInSameBlockScope() &&
+ D->getStorageDuration() != SD_Static &&
!D->getMemberSpecializationInfo())
AbbrevToUse = Writer.getDeclVarAbbrev();
// 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;
// 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;