]> granicus.if.org Git - clang/commitdiff
Pull MayDeferGeneration out of EmitGlobal.
authorDaniel Dunbar <daniel@zuster.org>
Fri, 13 Feb 2009 21:18:01 +0000 (21:18 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 13 Feb 2009 21:18:01 +0000 (21:18 +0000)
 - Fix emission of static functions with constructor attribute while I
   was here.
<rdar://problem/6140899> [codegen] "static" and attribute-constructor interact poorly

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

lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGen/constructor-attribute.c

index 69af3d265c9c7512324ec686859cdcd33281da10..ecfd8c98c32c544340814648c3b812cc2f851f88 100644 (file)
@@ -429,7 +429,7 @@ void CodeGenModule::EmitDeferred() {
       // FIXME: The AST should have some sort of aggregate decls or
       // global symbol map.
       // FIXME: This is missing some important cases. For example, we
-      // need to check for uses in an alias and in a constructor.
+      // need to check for uses in an alias.
       if (!GlobalDeclMap.count(getMangledName(D))) {
         i++;
         continue;
@@ -491,9 +491,30 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
   return llvm::ConstantStruct::get(Fields, 4, false);
 }
 
-void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
-  bool isDef, isStatic;
+bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
+  // Never defer when EmitAllDecls is specified.
+  if (Features.EmitAllDecls)
+    return false;
 
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
+    // Constructors and destructors should never be deferred.
+    if (FD->getAttr<ConstructorAttr>() || FD->getAttr<DestructorAttr>())
+      return false;
+
+    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;
+  }
+
+  return true;
+}
+
+void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
     // Aliases are deferred until code for everything else has been
     // emitted.
@@ -504,25 +525,22 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
       return;
     }
 
-    isDef = FD->isThisDeclarationADefinition();
-    isStatic = FD->getStorageClass() == FunctionDecl::Static;
+    // Forward declarations are emitted lazily on first use.
+    if (!FD->isThisDeclarationADefinition())
+      return;
   } else {
     const VarDecl *VD = cast<VarDecl>(Global);
     assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
 
-    isDef = !((VD->getStorageClass() == VarDecl::Extern ||
-               VD->getStorageClass() == VarDecl::PrivateExtern) && 
-              VD->getInit() == 0);
-    isStatic = VD->getStorageClass() == VarDecl::Static;
+    // Forward declarations are emitted lazily on first use.
+    if ((VD->getStorageClass() == VarDecl::Extern ||
+         VD->getStorageClass() == VarDecl::PrivateExtern) && 
+        VD->getInit() == 0)
+      return;
   }
 
-  // Forward declarations are emitted lazily on first use.
-  if (!isDef)
-    return;
-
-  // If the global is a static, defer code generation until later so
-  // we can easily omit unused statics.
-  if (isStatic && !Features.EmitAllDecls) {
+  // Defer code generation when possible.
+  if (MayDeferGeneration(Global)) {
     DeferredDecls.push_back(Global);
     return;
   }
index 1d10f9d1e39ff1c49a8fa58963d142670830ca82..967889a92dfd742f79c662caf21b2c85f954e93d 100644 (file)
@@ -324,6 +324,11 @@ private:
   void EmitLLVMUsed(void);
 
   void BindRuntimeFunctions();
+
+  /// MayDeferGeneration - Determine if the given decl can be emitted
+  /// lazily; this is only relevant for definitions. The given decl
+  /// must be either a function or var decl.
+  bool MayDeferGeneration(const ValueDecl *D);
 };
 }  // end namespace CodeGen
 }  // end namespace clang
index 0ecc47babfe6fb2e7f65d40a160ecab65a3696f4..f75fa4f7fac742d3d1b37e091bcf11bc63e7673c 100644 (file)
@@ -1,6 +1,8 @@
 // RUN: clang -emit-llvm -o %t %s &&
 // RUN: grep -e "global_ctors.*@A" %t &&
-// RUN: grep -e "global_dtors.*@B" %t
+// RUN: grep -e "global_dtors.*@B" %t &&
+// RUN: grep -e "global_ctors.*@C" %t &&
+// RUN: grep -e "global_dtors.*@D" %t
 
 #include <stdio.h>
 
@@ -15,6 +17,22 @@ void B() {
   printf("B\n");
 }
 
+static void C() __attribute__((constructor));
+
+static void D() __attribute__((destructor));
+
+static int foo() {
+  return 10;
+}
+
+static void C() {
+  printf("A: %d\n", foo());
+}
+
+static void D() {
+  printf("B\n");
+}
+
 int main() {
   return 0;
 }