summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-05-20 14:02:37 +0000
committerReid Kleckner <reid@kleckner.net>2013-05-20 14:02:37 +0000
commitb144d366934f3160ff4b1341db47dd15cd2a8c18 (patch)
treeec4ef604035da6ce9174caa61e33a732c8a23d7e /clang/lib
parent95935c5de142edf90273dc76ebafb7d09561821e (diff)
downloadbcm5719-llvm-b144d366934f3160ff4b1341db47dd15cd2a8c18.tar.gz
bcm5719-llvm-b144d366934f3160ff4b1341db47dd15cd2a8c18.zip
Implement __declspec(selectany) under -fms-extensions
selectany only applies to externally visible global variables. It has the effect of making the data weak_odr. The MSDN docs suggest that unused definitions can only be dropped at linktime, so Clang uses weak instead of linkonce. MSVC optimizes away references to constant selectany data, so it must assume that there is only one definition, hence weak_odr. Reviewers: espindola Differential Revision: http://llvm-reviews.chandlerc.com/D814 llvm-svn: 182266
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--clang/lib/Sema/SemaDecl.cpp9
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp13
3 files changed, 29 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 07368790372..3a967c6fdc3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1937,7 +1937,13 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
return llvm::Function::DLLImportLinkage;
else if (D->hasAttr<DLLExportAttr>())
return llvm::Function::DLLExportLinkage;
- else if (D->hasAttr<WeakAttr>()) {
+ else if (D->hasAttr<SelectAnyAttr>()) {
+ // selectany symbols are externally visible, so use weak instead of
+ // linkonce. MSVC optimizes away references to const selectany globals, so
+ // all definitions should be the same and ODR linkage should be used.
+ // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
+ return llvm::GlobalVariable::WeakODRLinkage;
+ } else if (D->hasAttr<WeakAttr>()) {
if (GV->isConstant())
return llvm::GlobalVariable::WeakODRLinkage;
else
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 885e8759422..50951a03f0c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4636,6 +4636,15 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
ND.dropAttr<WeakRefAttr>();
}
}
+
+ // 'selectany' only applies to externally visible varable declarations.
+ // It does not apply to functions.
+ if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) {
+ if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data);
+ ND.dropAttr<SelectAnyAttr>();
+ }
+ }
}
/// Given that we are within the definition of the given function,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c365bfc508c..627bc3d3649 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4718,6 +4718,16 @@ static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkMicrosoftExt(S, Attr))
+ return;
+ // Check linkage after possibly merging declaratinos. See
+ // checkAttributesAfterMerging().
+ D->addAttr(::new (S.Context)
+ SelectAnyAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
@@ -4944,6 +4954,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ForceInline:
handleForceInlineAttr(S, D, Attr);
break;
+ case AttributeList::AT_SelectAny:
+ handleSelectAnyAttr(S, D, Attr);
+ break;
// Thread safety attributes:
case AttributeList::AT_AssertExclusiveLock:
OpenPOWER on IntegriCloud