summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2013-05-21 00:06:11 +0000
committerBill Wendling <isanbard@gmail.com>2013-05-21 00:06:11 +0000
commit1cac0481166dd383a5d685fd53154661fbac5896 (patch)
tree053bffe7753ef4be0649a497b87ea5cb863f1371
parent424aa2e72ee59d51914201ce184b585410e1a5fa (diff)
downloadclang-1cac0481166dd383a5d685fd53154661fbac5896.tar.gz
clang-1cac0481166dd383a5d685fd53154661fbac5896.tar.bz2
clang-1cac0481166dd383a5d685fd53154661fbac5896.tar.xz
Merging r182266:
------------------------------------------------------------------------ r182266 | rnk | 2013-05-20 07:02:37 -0700 (Mon, 20 May 2013) | 13 lines 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 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_33@182337 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/Attr.td4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--lib/Sema/SemaDecl.cpp9
-rw-r--r--lib/Sema/SemaDeclAttr.cpp13
-rw-r--r--test/CodeGen/ms-declspecs.c5
-rw-r--r--test/SemaCXX/attr-selectany.cpp33
7 files changed, 73 insertions, 1 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 441a79a23b..25c9fcb5af 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -948,6 +948,10 @@ def ForceInline : InheritableAttr {
let Spellings = [Keyword<"__forceinline">];
}
+def SelectAny : InheritableAttr {
+ let Spellings = [Declspec<"selectany">];
+}
+
def Win64 : InheritableAttr {
let Spellings = [Keyword<"__w64">];
}
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index f5345eb8c3..b770c07339 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1948,6 +1948,8 @@ def warn_weak_identifier_undeclared : Warning<
"weak identifier %0 never declared">;
def err_attribute_weak_static : Error<
"weak declaration cannot have internal linkage">;
+def err_attribute_selectany_non_extern_data : Error<
+ "'selectany' can only be applied to data items with external linkage">;
def warn_attribute_weak_import_invalid_on_definition : Warning<
"'weak_import' attribute cannot be specified on a definition">,
InGroup<IgnoredAttributes>;
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 0b03a3c4b6..b3b05199a5 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1900,7 +1900,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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e0e8bd646b..03e9afc002 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4638,6 +4638,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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 7b3345a332..ddcbafc30a 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -4683,6 +4683,16 @@ static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
+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
//===----------------------------------------------------------------------===//
@@ -4909,6 +4919,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_GuardedVar:
diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c
index 26bdc58ebb..5dc7787b8f 100644
--- a/test/CodeGen/ms-declspecs.c
+++ b/test/CodeGen/ms-declspecs.c
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -o - | FileCheck %s
+__declspec(selectany) int x1 = 1;
+const __declspec(selectany) int x2 = 2;
+// CHECK: @x1 = weak_odr global i32 1, align 4
+// CHECK: @x2 = weak_odr constant i32 2, align 4
+
struct __declspec(align(16)) S {
char x;
};
diff --git a/test/SemaCXX/attr-selectany.cpp b/test/SemaCXX/attr-selectany.cpp
new file mode 100644
index 0000000000..0f9776dbf5
--- /dev/null
+++ b/test/SemaCXX/attr-selectany.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
+// MSVC produces similar diagnostics.
+
+__declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
+
+__declspec(selectany) int x1 = 1;
+
+const __declspec(selectany) int x2 = 2; // expected-error{{'selectany' can only be applied to data items with external linkage}}
+
+extern const __declspec(selectany) int x3 = 3;
+
+extern const int x4;
+const __declspec(selectany) int x4 = 4;
+
+// MSDN says this is incorrect, but MSVC doesn't diagnose it.
+extern __declspec(selectany) int x5;
+
+static __declspec(selectany) int x6 = 2; // expected-error{{'selectany' can only be applied to data items with external linkage}}
+
+// FIXME: MSVC accepts this and makes x7 externally visible and comdat, but keep
+// it as internal and not weak/linkonce.
+static int x7; // expected-note{{previous definition}}
+extern __declspec(selectany) int x7; // expected-warning{{attribute declaration must precede definition}}
+
+int asdf() { return x7; }
+
+class X {
+ public:
+ X(int i) { i++; };
+ int i;
+};
+
+__declspec(selectany) X x(1);