summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp15
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp31
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp2
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp13
5 files changed, 31 insertions, 34 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 5c271f027fe..bccdae91d2e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4781,6 +4781,12 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
return sz;
}
+bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
+ return getLangOpts().MSVCCompat && VD->isStaticDataMember() &&
+ VD->getType()->isIntegralOrEnumerationType() &&
+ !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
+}
+
static inline
std::string charUnitsToString(const CharUnits &CU) {
return llvm::itostr(CU.getQuantity());
@@ -7849,6 +7855,12 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
: StaticLocalLinkage;
}
+ // MSVC treats in-class initialized static data members as definitions.
+ // By giving them non-strong linkage, out-of-line definitions won't
+ // cause link errors.
+ if (Context.isMSStaticDataMemberInlineDefinition(VD))
+ return GVA_DiscardableODR;
+
switch (VD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
@@ -7934,7 +7946,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
const VarDecl *VD = cast<VarDecl>(D);
assert(VD->isFileVarDecl() && "Expected file scoped var");
- if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
+ if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly &&
+ !isMSStaticDataMemberInlineDefinition(VD))
return false;
// Variables that can be needed in other TUs are required.
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index b49c68a4df1..91e49707bae 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -403,10 +403,6 @@ public:
/// Gets the deleted virtual member call name.
virtual StringRef GetDeletedVirtualCallName() = 0;
- /// \brief Returns true iff static data members that are initialized in the
- /// class definition should have linkonce linkage.
- virtual bool isInlineInitializedStaticDataMemberLinkOnce() { return false; }
-
/**************************** Array cookies ******************************/
/// Returns the extra size required in order to store the array
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 66ac524f2b9..6c33f922792 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1256,7 +1256,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
const auto *VD = cast<VarDecl>(Global);
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
- if (VD->isThisDeclarationADefinition() != VarDecl::Definition)
+ if (VD->isThisDeclarationADefinition() != VarDecl::Definition &&
+ !Context.isMSStaticDataMemberInlineDefinition(VD))
return;
}
@@ -1592,18 +1593,6 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
return true;
}
-static bool isVarDeclInlineInitializedStaticDataMember(const VarDecl *VD) {
- if (!VD->isStaticDataMember())
- return false;
- const VarDecl *InitDecl;
- const Expr *InitExpr = VD->getAnyInitializer(InitDecl);
- if (!InitExpr)
- return false;
- if (InitDecl->isThisDeclarationADefinition())
- return false;
- return true;
-}
-
/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
/// create and return an llvm GlobalVariable with the specified type. If there
/// is something in the module with the specified name, return it potentially
@@ -1666,9 +1655,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
// If required by the ABI, treat declarations of static data members with
// inline initializers as definitions.
- if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
- isVarDeclInlineInitializedStaticDataMember(D))
+ if (getContext().isMSStaticDataMemberInlineDefinition(D)) {
EmitGlobalVarDefinition(D);
+ }
// Handle XCore specific ABI requirements.
if (getTarget().getTriple().getArch() == llvm::Triple::xcore &&
@@ -2087,18 +2076,6 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(
return !Context.getLangOpts().AppleKext ? llvm::Function::WeakODRLinkage
: llvm::Function::ExternalLinkage;
- // If required by the ABI, give definitions of static data members with inline
- // initializers at least linkonce_odr linkage.
- auto const VD = dyn_cast<VarDecl>(D);
- if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
- VD && isVarDeclInlineInitializedStaticDataMember(VD)) {
- if (VD->hasAttr<DLLImportAttr>())
- return llvm::GlobalValue::AvailableExternallyLinkage;
- if (VD->hasAttr<DLLExportAttr>())
- return llvm::GlobalValue::WeakODRLinkage;
- return llvm::GlobalValue::LinkOnceODRLinkage;
- }
-
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) &&
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 41b7574e34c..a69d4dd3fe8 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -55,8 +55,6 @@ public:
// arbitrary.
StringRef GetDeletedVirtualCallName() override { return "_purecall"; }
- bool isInlineInitializedStaticDataMemberLinkOnce() override { return true; }
-
llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
llvm::Value *ptr,
QualType type) override;
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index c4a0e5c063d..c5d18d3286a 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -128,6 +128,19 @@ namespace {
return;
Builder->UpdateCompletedType(D);
+
+ // For MSVC compatibility, treat declarations of static data members with
+ // inline initializers as definitions.
+ if (Ctx->getLangOpts().MSVCCompat) {
+ for (Decl *Member : D->decls()) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(Member)) {
+ if (Ctx->isMSStaticDataMemberInlineDefinition(VD) &&
+ Ctx->DeclMustBeEmitted(VD)) {
+ Builder->EmitGlobal(VD);
+ }
+ }
+ }
+ }
}
void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
OpenPOWER on IntegriCloud