Pull MayDeferGeneration out of EmitGlobal.
 - 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
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 69af3d2..ecfd8c9 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -429,7 +429,7 @@
       // 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,10 +491,31 @@
   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.
     if (FD->getAttr<AliasAttr>()) {
@@ -504,25 +525,22 @@
       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;
   }
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 1d10f9d..967889a 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -324,6 +324,11 @@
   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