Don't skip lambdas when mangling local vars.

This commit rearranges the logic in CXXNameMangler::mangleLocalName and
GetLocalClassDecl so that it doesn't accidentally skip over lambdas.  It
also reduces code duplication a bit.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185402 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 394e707..7948ef7 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -64,15 +64,13 @@
   return getEffectiveDeclContext(cast<Decl>(DC));
 }
   
-static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
-  const DeclContext *DC = dyn_cast<DeclContext>(ND);
-  if (!DC)
-    DC = getEffectiveDeclContext(ND);
+static const CXXRecordDecl *GetLocalClassDecl(const Decl *D) {
+  const DeclContext *DC = getEffectiveDeclContext(D);
   while (!DC->isNamespace() && !DC->isTranslationUnit()) {
-    const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC));
-    if (isa<FunctionDecl>(Parent))
-      return dyn_cast<CXXRecordDecl>(DC);
-    DC = Parent;
+    if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC))
+      return dyn_cast<CXXRecordDecl>(D);
+    D = cast<Decl>(DC);
+    DC = getEffectiveDeclContext(D);
   }
   return 0;
 }
@@ -1272,16 +1270,21 @@
   // <local-name> := Z <function encoding> E d [ <parameter number> ] 
   //                 _ <entity name>
   // <discriminator> := _ <non-negative number>
-  const DeclContext *DC = getEffectiveDeclContext(ND);
+  const CXXRecordDecl *RD = GetLocalClassDecl(ND);
+  const DeclContext *DC = getEffectiveDeclContext(RD ? RD : ND);
 
   Out << 'Z';
 
-  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
-   mangleObjCMethodName(MD);
-  } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
-    mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD)));
-    Out << 'E';
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
+    mangleObjCMethodName(MD);
+  else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
+    manglePrefix(BD); // FIXME: This isn't right.
+  else
+    mangleFunctionEncoding(cast<FunctionDecl>(DC));
 
+  Out << 'E';
+
+  if (RD) {
     // The parameter number is omitted for the last parameter, 0 for the 
     // second-to-last parameter, 1 for the third-to-last parameter, etc. The 
     // <entity name> will of course contain a <closure-type-name>: Its 
@@ -1307,7 +1310,7 @@
     if (ND == RD) // equality ok because RD derived from ND above
       mangleUnqualifiedName(ND);
     else
-      mangleNestedName(ND, DC, true /*NoFunction*/);
+      mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/);
 
     if (!SkipDiscriminator) {
       unsigned disc;
@@ -1321,10 +1324,7 @@
     
     return;
   }
-  else
-    mangleFunctionEncoding(cast<FunctionDecl>(DC));
 
-  Out << 'E';
   mangleUnqualifiedName(ND);
 }
 
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
index 39f59a3..a86770d 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
@@ -14,7 +14,7 @@
   }
 
   // CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
-  // CHECK: call zeroext i1 @"_ZNK7PR127462f1Ub_3$_0clEv"
+  // CHECK: call zeroext i1 @"_ZZ7PR127462f1Ub_ENK3$_0clEv"
 
   bool f2(int *x) {
     auto outer = [&]() -> bool {
diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp
index a9c3ace..76839e1 100644
--- a/test/CodeGenCXX/mangle-lambdas.cpp
+++ b/test/CodeGenCXX/mangle-lambdas.cpp
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s
 
 // CHECK: @_ZZNK7PR12917IJiiEE1nMUlvE_clEvE1n = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd_N1nE = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd0_N1nE = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd1_N1nE = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd_NKUlvE_clEvE1n = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd0_NKUlvE_clEvE1n = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd1_NKUlvE_clEvE1n = linkonce_odr global i32 0
 
 // CHECK: define linkonce_odr void @_Z11inline_funci
 inline void inline_func(int n) {