IRgen support for attribute used.
 - PR3566


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64492 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index abcd547..ddc68d6 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -138,6 +138,9 @@
   if (const SectionAttr *SA = D.getAttr<SectionAttr>())
     GV->setSection(SA->getName());
   
+  if (D.getAttr<UsedAttr>())
+    CGM.AddUsedGlobal(GV);
+
   const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
   const llvm::Type *LPtrTy =
     llvm::PointerType::get(LTy, D.getType().getAddressSpace());
@@ -149,7 +152,6 @@
     DI->setLocation(D.getLocation());
     DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D);
   }
-
 }
   
 /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index ecfd8c9..e60edce 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -238,11 +238,11 @@
   gv->setSection("llvm.metadata");
 }
 
-static void SetGlobalValueAttributes(const Decl *D, 
-                                     bool IsInternal,
-                                     bool IsInline,
-                                     llvm::GlobalValue *GV,
-                                     bool ForDefinition) {
+void CodeGenModule::SetGlobalValueAttributes(const Decl *D, 
+                                             bool IsInternal,
+                                             bool IsInline,
+                                             llvm::GlobalValue *GV,
+                                             bool ForDefinition) {
   // FIXME: Set up linkage and many other things.  Note, this is a simple 
   // approximation of what we really want.
   if (!ForDefinition) {
@@ -290,6 +290,14 @@
 
   if (const SectionAttr *SA = D->getAttr<SectionAttr>())
     GV->setSection(SA->getName());
+
+  // Only add to llvm.used when we see a definition, otherwise we
+  // might add multiple times or risk the value being replaced by a
+  // subsequent RAUW.
+  if (ForDefinition) {
+    if (D->getAttr<UsedAttr>())
+      AddUsedGlobal(GV);
+  }
 }
 
 void CodeGenModule::SetFunctionAttributes(const Decl *D,
@@ -492,8 +500,9 @@
 }
 
 bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
-  // Never defer when EmitAllDecls is specified.
-  if (Features.EmitAllDecls)
+  // Never defer when EmitAllDecls is specified or the decl has
+  // attribute used.
+  if (Features.EmitAllDecls || Global->getAttr<UsedAttr>())
     return false;
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
@@ -728,6 +737,9 @@
   if (const SectionAttr *SA = D->getAttr<SectionAttr>())
     GV->setSection(SA->getName());
 
+  if (D->getAttr<UsedAttr>())
+    AddUsedGlobal(GV);
+
   // Emit global variable debug information.
   CGDebugInfo *DI = getDebugInfo();
   if(DI) {
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 967889a..4c2aeb7 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -284,6 +284,13 @@
 
 
 private:
+  /// SetGlobalValueAttributes - Set attributes for a global decl.
+  void SetGlobalValueAttributes(const Decl *D, 
+                                bool IsInternal,
+                                bool IsInline,
+                                llvm::GlobalValue *GV,
+                                bool ForDefinition);
+    
   /// SetFunctionAttributesForDefinition - Set function attributes specific to a
   /// function definition.
   /// \param D - The ObjCMethodDecl or FunctionDecl defining \arg F.
diff --git a/test/CodeGen/attr-used.c b/test/CodeGen/attr-used.c
new file mode 100644
index 0000000..c7f6760
--- /dev/null
+++ b/test/CodeGen/attr-used.c
@@ -0,0 +1,14 @@
+// RUN: clang -emit-llvm -o %t %s &&
+// RUN: grep '@llvm.used = .*@g0' %t &&
+// RUN: grep '@llvm.used = .*@f0' %t &&
+// RUN: grep '@llvm.used = .*@f1.l0' %t
+
+
+int g0 __attribute__((used));
+
+static void __attribute__((used)) f0(void) {
+}
+
+void f1() { 
+  static int l0 __attribute__((used)) = 5225; 
+}