]> granicus.if.org Git - clang/commitdiff
defer emission of always_inline, extern_inline, and inline functions (when
authorChris Lattner <sabre@nondot.org>
Tue, 14 Apr 2009 06:44:48 +0000 (06:44 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 14 Apr 2009 06:44:48 +0000 (06:44 +0000)
not in c89 mode).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69032 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/function-attributes.c
test/CodeGen/inline.c

index 5ef57ffdcc205ddd596ec9cd42d6af783676fa45..c771461704d906b31bc326a3c4c7a00e4a3c50ae 100644 (file)
@@ -482,18 +482,23 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
     if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
       return false;
 
-    // FIXME: What about inline, and/or extern inline?
-    if (FD->getStorageClass() != FunctionDecl::Static)
-      return false;
-  } else {
-    const VarDecl *VD = cast<VarDecl>(Global);
-    assert(VD->isFileVarDecl() && "Invalid decl");
-
-    if (VD->getStorageClass() != VarDecl::Static)
-      return false;
+    GVALinkage Linkage = GetLinkageForFunctionOrMethodDecl(FD);
+    
+    // static, static inline, always_inline, and extern inline functions can
+    // always be deferred.
+    if (Linkage == GVA_Internal || Linkage == GVA_ExternInline)
+      return true;
+
+    // inline functions can be deferred unless we're in C89 mode.
+    if (Linkage == GVA_Inline && (Features.C99 || Features.CPlusPlus))
+      return true;
+    
+    return false;
   }
-
-  return true;
+  
+  const VarDecl *VD = cast<VarDecl>(Global);
+  assert(VD->isFileVarDecl() && "Invalid decl");
+  return VD->getStorageClass() == VarDecl::Static;
 }
 
 void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
index a12111ec94acc6f69cedda3ad2c234414e8e657b..3269f98a56de3ea6460348a9fbe0b5a20da2ef0a 100644 (file)
@@ -7,7 +7,6 @@
 // RUN: grep 'define zeroext i16 @f5(i32 %x) nounwind' %t &&
 // RUN: grep 'define void @f6(i16 signext %x) nounwind' %t &&
 // RUN: grep 'define void @f7(i16 zeroext %x) nounwind' %t &&
-// RUN: grep 'define void @f8() nounwind alwaysinline' %t &&
 
 signed char f0(int x) { return x; }
 
@@ -25,6 +24,8 @@ void f6(signed short x) { }
 
 void f7(unsigned short x) { }
 
+// F8 is dead so it should not be emitted.
+// RUN: not grep '@f8' %t &&
 void __attribute__((always_inline)) f8(void) { }
 
 // RUN: grep 'call void @f9_t() noreturn' %t &&
index 8360896f367e88ce1eacafc34ef92e74820bf6cb..fa2794780b66c1b6b1347c45f8b32a92b58983b0 100644 (file)
@@ -2,19 +2,20 @@
 // RUN: grep "define available_externally i32 @ei()" %t &&
 // RUN: grep "define i32 @foo()" %t &&
 // RUN: grep "define i32 @bar()" %t &&
-// RUN: grep "define void @unreferenced()" %t &&
+// RUN: grep "define void @unreferenced1()" %t &&
+// RUN: not grep unreferenced2 %t &&
 
 // RUN: clang %s -emit-llvm -S -o %t -std=c99 &&
 // RUN: grep "define available_externally i32 @ei()" %t &&
 // RUN: grep "define available_externally i32 @foo()" %t &&
 // RUN: grep "define i32 @bar()" %t &&
-// RUN: grep "define available_externally void @unreferenced()" %t &&
+// RUN: not grep unreferenced %t &&
 
 // RUN: clang %s -emit-llvm -S -o %t -std=c++98 &&
 // RUN: grep "define available_externally i32 @_Z2eiv()" %t &&
 // RUN: grep "define linkonce_odr i32 @_Z3foov()" %t &&
 // RUN: grep "define i32 @_Z3barv()" %t &&
-// RUN: grep "define linkonce_odr void @_Z12unreferencedv()" %t
+// RUN: not grep unreferenced %t
 
 extern inline int ei() { return 123; }
 
@@ -25,5 +26,6 @@ inline int foo() {
 int bar() { return foo(); }
 
 
-inline void unreferenced() {}
+inline void unreferenced1() {}
+extern inline void unreferenced2() {}