diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1cdc24e65fc0..628c9b053ea4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1915,7 +1915,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { if (hasInit()) return Definition; - if (hasAttr()) + if (hasAttr() || hasAttr()) return Definition; // A variable template specialization (other than a static data member @@ -1925,14 +1925,14 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { getTemplateSpecializationKind() != TSK_ExplicitSpecialization) return DeclarationOnly; - if (!hasAttr() && hasExternalStorage()) + if (hasExternalStorage()) return DeclarationOnly; // [dcl.link] p7: // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - if (!hasAttr() && isSingleLineLanguageLinkage(*this)) + if (isSingleLineLanguageLinkage(*this)) return DeclarationOnly; // C99 6.9.2p2: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f60a68ab0115..17b7ddc7683d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2134,7 +2134,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { } static bool isVarDeclStrongDefinition(const ASTContext &Context, - const VarDecl *D, bool NoCommon) { + CodeGenModule &CGM, const VarDecl *D, + bool NoCommon) { // Don't give variables common linkage if -fno-common was specified unless it // was overridden by a NoCommon attribute. if ((NoCommon || D->hasAttr()) && !D->hasAttr()) @@ -2159,6 +2160,10 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, if (D->hasAttr()) return true; + // A variable cannot be both common and exist in a comdat. + if (shouldBeInCOMDAT(CGM, *D)) + return true; + // Declarations with a required alignment do not have common linakge in MSVC // mode. if (Context.getLangOpts().MSVCCompat) { @@ -2227,7 +2232,7 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( // C++ doesn't have tentative definitions and thus cannot have common // linkage. if (!getLangOpts().CPlusPlus && isa(D) && - !isVarDeclStrongDefinition(Context, cast(D), + !isVarDeclStrongDefinition(Context, *this, cast(D), CodeGenOpts.NoCommon)) return llvm::GlobalVariable::CommonLinkage; diff --git a/clang/test/CodeGen/ms-declspecs.c b/clang/test/CodeGen/ms-declspecs.c index 985c227faa36..c32733e65ff6 100644 --- a/clang/test/CodeGen/ms-declspecs.c +++ b/clang/test/CodeGen/ms-declspecs.c @@ -6,8 +6,10 @@ const __declspec(selectany) int x2 = 2; // CHECK: @x2 = weak_odr constant i32 2, comdat, align 4 // selectany turns extern variable declarations into definitions. -extern __declspec(selectany) int x3; +__declspec(selectany) int x3; +extern __declspec(selectany) int x4; // CHECK: @x3 = weak_odr global i32 0, comdat, align 4 +// CHECK: @x4 = weak_odr global i32 0, comdat, align 4 struct __declspec(align(16)) S { char x; diff --git a/clang/test/CodeGen/ms-declspecs.cpp b/clang/test/CodeGen/ms-declspecs.cpp index f77c7cb89169..decf5d6fcb22 100644 --- a/clang/test/CodeGen/ms-declspecs.cpp +++ b/clang/test/CodeGen/ms-declspecs.cpp @@ -7,7 +7,9 @@ extern "C++" __declspec(selectany) int x3; extern "C" { __declspec(selectany) int x4; } +__declspec(selectany) int x5; // CHECK: @"\01?x1@@3HA" = weak_odr global i32 0, comdat, align 4 // CHECK: @x2 = weak_odr global i32 0, comdat, align 4 // CHECK: @"\01?x3@@3HA" = weak_odr global i32 0, comdat, align 4 // CHECK: @x4 = weak_odr global i32 0, comdat, align 4 +// CHECK: @"\01?x5@@3HA" = weak_odr global i32 0, comdat, align 4