aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CodeGenModule.cpp26
-rw-r--r--lib/CodeGen/CodeGenModule.h7
-rw-r--r--test/CodeGen/attr-used.c14
4 files changed, 43 insertions, 8 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index abcd547be9..ddc68d68c5 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -138,6 +138,9 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
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 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
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 ecfd8c98c3..e60edce213 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -238,11 +238,11 @@ void CodeGenModule::EmitAnnotations() {
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 @@ static void SetGlobalValueAttributes(const Decl *D,
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 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
}
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 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
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 967889a92d..4c2aeb75ac 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -284,6 +284,13 @@ public:
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 0000000000..c7f67600c0
--- /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;
+}