Fix mangling for block literals.

Blocks, like lambdas, can be written in contexts which are required to be
treated as the same under ODR.  Unlike lambdas, it isn't possible to actually
take the address of a block, so the mangling of the block itself doesn't
matter. However, objects like static variables inside a block do need to
be mangled in a consistent way.

There are basically three components here. One, block literals need a
consistent numbering.  Two, objects/types inside a block literal need
to be mangled using it.  Three, objects/types inside a block literal need
to have their linkage computed correctly.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185372 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 519f03a..62cd744 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -130,9 +130,27 @@
     if (D.isExternallyVisible()) {
       const Decl *D = CurCodeDecl;
       while (true) {
-        if (isa<BlockDecl>(D)) {
-          // FIXME: Handle this case properly!  (Should be similar to the
-          // way we handle lambdas in computeLVForDecl in Decl.cpp.)
+        if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+          if (!BD->getBlockManglingNumber())
+            break;
+
+          // This block has the linkage/visibility of its contained variables
+          // determined by its owner.
+          const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+          if (Decl *ContextDecl = BD->getBlockManglingContextDecl()) {
+            if (isa<ParmVarDecl>(ContextDecl)) {
+              DC = ContextDecl->getDeclContext()->getRedeclContext();
+            } else {
+              D = ContextDecl;
+              continue;
+            }
+          }
+
+          if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+            D = ND;
+            continue;
+          }
+
           break;
         } else if (isa<CapturedDecl>(D)) {
           D = cast<Decl>(cast<CapturedDecl>(D)->getParent());
@@ -140,13 +158,26 @@
           break;
         }
       }
-      // FIXME: Do we really only care about FunctionDecls here?
+      llvm::GlobalValue::LinkageTypes ParentLinkage;
       if (isa<FunctionDecl>(D)) {
-        llvm::GlobalValue::LinkageTypes ParentLinkage =
-            CGM.getFunctionLinkage(cast<FunctionDecl>(D));
-        if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
-          Linkage = ParentLinkage;
+        ParentLinkage = CGM.getFunctionLinkage(cast<FunctionDecl>(D));
+      } else if (isa<VarDecl>(D)) {
+        // FIXME: I'm pretty sure this is wrong...
+        ParentLinkage = CGM.GetLLVMLinkageVarDefinition(cast<VarDecl>(D),
+                                                        /*constant*/false);
+      } else {
+        assert(isa<FieldDecl>(D) && "Expect function, variable, or field");
+        // FIXME: Is this right?
+        ParentLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
       }
+
+      if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
+        Linkage = ParentLinkage;
+
+      // FIXME: We need to force the emission/use of a guard variable for
+      // some variables even if we can constant-evaluate them because
+      // we can't guarantee every translation unit will constant-evaluate them.
+      // Also, we might need to fix up the linkage.
     }
 
     return EmitStaticVarDecl(D, Linkage);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 3298d5a..cfb9e78 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1797,7 +1797,7 @@
 
   // Set the llvm linkage type as appropriate.
   llvm::GlobalValue::LinkageTypes Linkage = 
-    GetLLVMLinkageVarDefinition(D, GV);
+    GetLLVMLinkageVarDefinition(D, GV->isConstant());
   GV->setLinkage(Linkage);
   if (Linkage == llvm::GlobalVariable::CommonLinkage)
     // common vars aren't constant even if declared const.
@@ -1828,8 +1828,7 @@
 }
 
 llvm::GlobalValue::LinkageTypes
-CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
-                                           llvm::GlobalVariable *GV) {
+CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
   GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
@@ -1844,7 +1843,7 @@
     // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
     return llvm::GlobalVariable::WeakODRLinkage;
   } else if (D->hasAttr<WeakAttr>()) {
-    if (GV->isConstant())
+    if (isConstant)
       return llvm::GlobalVariable::WeakODRLinkage;
     else
       return llvm::GlobalVariable::WeakAnyLinkage;
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 6e5985d..a5fca36 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -942,8 +942,7 @@
   /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global 
   /// variable.
   llvm::GlobalValue::LinkageTypes 
-  GetLLVMLinkageVarDefinition(const VarDecl *D,
-                              llvm::GlobalVariable *GV);
+  GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
   
   /// Emit all the global annotations.
   void EmitGlobalAnnotations();