]> granicus.if.org Git - clang/commitdiff
Implement __declspec(selectany) under -fms-extensions
authorReid Kleckner <reid@kleckner.net>
Mon, 20 May 2013 14:02:37 +0000 (14:02 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 20 May 2013 14:02:37 +0000 (14:02 +0000)
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/trunk@182266 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/ms-declspecs.c
test/SemaCXX/attr-selectany.cpp [new file with mode: 0644]

index 7c59c16f148286b1ed59f027532daa03911a7525..04903148521cd88138081a37a47e981ab0d76788 100644 (file)
@@ -962,6 +962,10 @@ def ForceInline : InheritableAttr {
   let Spellings = [Keyword<"__forceinline">];
 }
 
+def SelectAny : InheritableAttr {
+  let Spellings = [Declspec<"selectany">];
+}
+
 def Win64 : InheritableAttr {
   let Spellings = [Keyword<"__w64">];
 }
index a5b57e05ea0877c4cffa4727980fa81646ffa547..55fae9ffedf6aad7597d5d7f7544ad4d3a28dcb7 100644 (file)
@@ -1950,6 +1950,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>;
index 07368790372f792c42d7da2cd016447c749449ba..3a967c6fdc347c66b1939f2ff9879ae52cca96e0 100644 (file)
@@ -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
index 885e8759422c1ff1faf565c7f99d5c55f6c3cfc5..50951a03f0ce2349763515f64956689f11f52186 100644 (file)
@@ -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,
index c365bfc508ca7bfc1cb225643ff33038d8be001f..627bc3d364953a585635beac2f682b2387998b45 100644 (file)
@@ -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:
index 26bdc58ebb7f755b1eff1c49bc456cef625563c3..5dc7787b8fb99ca1c908688fe28e9cbf620943ab 100644 (file)
@@ -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 (file)
index 0000000..0f9776d
--- /dev/null
@@ -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);