Make blocks that capture their containing method's object pointer look like methods of 
the containing class so that direct ivar access will work in the expression parser.

<rdar://problem/9797999>


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@167061 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index f8304b9..f54d53e 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -2470,34 +2470,83 @@
             
             clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context);
             
-            if (!method_decl)
-                return;
-            
-            clang::CXXRecordDecl *class_decl = method_decl->getParent();
-            
-            QualType class_qual_type(class_decl->getTypeForDecl(), 0);
-            
-            TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
-                                          &class_decl->getASTContext());
-            
-            if (log)
+            if (method_decl)
             {
-                ASTDumper ast_dumper(class_qual_type);
-                log->Printf("  CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
+            
+                clang::CXXRecordDecl *class_decl = method_decl->getParent();
+                
+                QualType class_qual_type(class_decl->getTypeForDecl(), 0);
+                
+                TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
+                                              &class_decl->getASTContext());
+                
+                if (log)
+                {
+                    ASTDumper ast_dumper(class_qual_type);
+                    log->Printf("  CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
+                }
+                
+                AddOneType(context, class_user_type, current_id, true);
+                
+                if (method_decl->isInstance())
+                {
+                    // self is a pointer to the object
+                    
+                    QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
+                    
+                    TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+                                                &method_decl->getASTContext());
+                    
+                    m_struct_vars->m_object_pointer_type = self_user_type;
+                }
             }
-            
-            AddOneType(context, class_user_type, current_id, true);
-            
-            if (method_decl->isInstance())
+            else
             {
-                // self is a pointer to the object
+                // This branch will get hit if we are executing code in the context of a function that
+                // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a
+                // method of the class.  In that case, just look up the "this" variable in the the current
+                // scope and use its type.
+                // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer
+                // for C++ so it hasn't actually been tested.
                 
-                QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
+                VariableList *vars = frame->GetVariableList(false);
                 
-                TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
-                                            &method_decl->getASTContext());
+                lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
                 
-                m_struct_vars->m_object_pointer_type = self_user_type;
+                if (this_var &&
+                    this_var->IsInScope(frame) &&
+                    this_var->LocationIsValidForFrame (frame))
+                {
+                    Type *this_type = this_var->GetType();
+                    
+                    if (!this_type)
+                        return;
+                    
+                    QualType this_qual_type = QualType::getFromOpaquePtr(this_type->GetClangFullType());
+                    const PointerType *class_pointer_type = this_qual_type->getAs<PointerType>();
+                    
+                    if (class_pointer_type)
+                    {
+                        QualType class_type = class_pointer_type->getPointeeType();
+                        
+                        if (log)
+                        {
+                            ASTDumper ast_dumper(this_type->GetClangFullType());
+                            log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+                        }
+                        
+                        TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
+                                                        this_type->GetClangAST());
+                        AddOneType(context, class_user_type, current_id, false);
+                                    
+                                    
+                        TypeFromUser this_user_type(this_type->GetClangFullType(),
+                                                    this_type->GetClangAST());
+                        
+                        m_struct_vars->m_object_pointer_type = this_user_type;
+                        return;
+                    }
+                }
             }
             
             return;
@@ -2529,65 +2578,96 @@
             
             clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context);
             
-            if (!method_decl)
-                return;
-
-            ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
-            
-            if (!self_interface)
-                return;
-            
-            const clang::Type *interface_type = self_interface->getTypeForDecl();
-                    
-            TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
-                                         &method_decl->getASTContext());
-            
-            if (log)
+            if (method_decl)
             {
-                ASTDumper ast_dumper(interface_type);
-                log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
-            }
+
+                ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
                 
-            AddOneType(context, class_user_type, current_id, false);
-            
-#if 0
-            VariableList *vars = frame->GetVariableList(false);
-            
-            lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
-            
-            if (self_var &&
-                self_var->IsInScope(frame) && 
-                self_var->LocationIsValidForFrame (frame)) {
-                Type *self_type = self_var->GetType();
-                
-                if (!self_type)
+                if (!self_interface)
                     return;
                 
-                TypeFromUser self_user_type(self_type->GetClangFullType(),
-                                            self_type->GetClangAST());
-            }
-#endif
-            
-            if (method_decl->isInstanceMethod())
-            {
-                // self is a pointer to the object
+                const clang::Type *interface_type = self_interface->getTypeForDecl();
+                        
+                TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
+                                             &method_decl->getASTContext());
                 
-                QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
-            
-                TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
-                                            &method_decl->getASTContext());
-            
-                m_struct_vars->m_object_pointer_type = self_user_type;
+                if (log)
+                {
+                    ASTDumper ast_dumper(interface_type);
+                    log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+                }
+                    
+                AddOneType(context, class_user_type, current_id, false);
+                                
+                if (method_decl->isInstanceMethod())
+                {
+                    // self is a pointer to the object
+                    
+                    QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
+                
+                    TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+                                                &method_decl->getASTContext());
+                
+                    m_struct_vars->m_object_pointer_type = self_user_type;
+                }
+                else
+                {
+                    // self is a Class pointer
+                    QualType class_type = method_decl->getASTContext().getObjCClassType();
+                    
+                    TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
+                                                &method_decl->getASTContext());
+                    
+                    m_struct_vars->m_object_pointer_type = self_user_type;
+                }
+
+                return;
             }
             else
             {
-                // self is a Class pointer
-                QualType class_type = method_decl->getASTContext().getObjCClassType();
+                // This branch will get hit if we are executing code in the context of a function that
+                // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a
+                // method of the class.  In that case, just look up the "self" variable in the the current
+                // scope and use its type.
                 
-                TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
-                                            &method_decl->getASTContext());
+                VariableList *vars = frame->GetVariableList(false);
                 
-                m_struct_vars->m_object_pointer_type = self_user_type;
+                lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
+                
+                if (self_var &&
+                    self_var->IsInScope(frame) && 
+                    self_var->LocationIsValidForFrame (frame))
+                {
+                    Type *self_type = self_var->GetType();
+                    
+                    if (!self_type)
+                        return;
+                    
+                    QualType self_qual_type = QualType::getFromOpaquePtr(self_type->GetClangFullType());
+                    const ObjCObjectPointerType *class_pointer_type = self_qual_type->getAs<ObjCObjectPointerType>();
+                    
+                    if (class_pointer_type)
+                    {
+                        QualType class_type = class_pointer_type->getPointeeType();
+                        
+                        if (log)
+                        {
+                            ASTDumper ast_dumper(self_type->GetClangFullType());
+                            log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+                        }
+                        
+                        TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
+                                                        self_type->GetClangAST());
+                        AddOneType(context, class_user_type, current_id, false);
+                                    
+                                    
+                        TypeFromUser self_user_type(self_type->GetClangFullType(),
+                                                    self_type->GetClangAST());
+                        
+                        m_struct_vars->m_object_pointer_type = self_user_type;
+                        return;
+                    }
+                }
             }
 
             return;