]> granicus.if.org Git - clang/commitdiff
Make sure we don't inline functions marked with __attribute__((naked)). <rdar:/...
authorEli Friedman <eli.friedman@gmail.com>
Mon, 22 Aug 2011 23:55:33 +0000 (23:55 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 22 Aug 2011 23:55:33 +0000 (23:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138310 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/attr-naked.c

index 0584a3280652126f58414d0f3243b2b9d7879736..3e30c57f240f8b5a42305184564cc794b1dfa3f9 100644 (file)
@@ -472,15 +472,20 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   if (!Features.Exceptions && !Features.ObjCNonFragileABI)
     F->addFnAttr(llvm::Attribute::NoUnwind);
 
-  if (D->hasAttr<AlwaysInlineAttr>())
-    F->addFnAttr(llvm::Attribute::AlwaysInline);
-
-  if (D->hasAttr<NakedAttr>())
+  if (D->hasAttr<NakedAttr>()) {
+    // Naked implies noinline: we should not be inlining such functions.
     F->addFnAttr(llvm::Attribute::Naked);
+    F->addFnAttr(llvm::Attribute::NoInline);
+  }
 
   if (D->hasAttr<NoInlineAttr>())
     F->addFnAttr(llvm::Attribute::NoInline);
 
+  // (noinline wins over always_inline, and we can't specify both in IR)
+  if (D->hasAttr<AlwaysInlineAttr>() &&
+      !F->hasFnAttr(llvm::Attribute::NoInline))
+    F->addFnAttr(llvm::Attribute::AlwaysInline);
+
   if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
     F->setUnnamedAddr(true);
 
index bccacc9916f11089b0c853e5578e6d05912cac9b..2387d288eca8ce27b5fb45e32663164ad5eba684 100644 (file)
@@ -1,9 +1,16 @@
-// RUN: %clang_cc1 -g -emit-llvm -o %t %s
-// RUN: grep 'naked' %t
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s
 
 void t1() __attribute__((naked));
 
+// Basic functionality check
+// (Note that naked needs to imply noinline to work properly.)
+// CHECK: define void @t1() nounwind noinline naked {
 void t1()
 {
 }
 
+// Make sure this doesn't explode in the verifier.
+// (It doesn't really make sense, but it isn't invalid.)
+// CHECK: define void @t2() nounwind noinline naked {
+__attribute((naked, always_inline)) void t2()  {
+}