Added support for looking up the complete type for
Objective-C classes.  This allows LLDB to find
ivars declared in class extensions in modules other
than where the debugger is currently stopped (we
already supported this when the debugger was
stopped in the same module as the definition).

This involved the following main changes:

- The ObjCLanguageRuntime now knows how to hunt
  for the authoritative version of an Objective-C
  type.  It looks for the symbol indicating a
  definition, and then gets the type from the
  module containing that symbol.

- ValueObjects now report their type with a
  potential override, and the override is set if
  the type of the ValueObject is an Objective-C
  class or pointer type that is defined somewhere
  other than the original reported type.  This
  means that "frame variable" will always use the
  complete type if one is available.

- The ClangASTSource now looks for the complete
  type when looking for ivars.  This means that
  "expr" will always use the complete type if one
  is available.

- I added a testcase that verifies that both
  "frame variable" and "expr" work.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@151214 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 7cdc3f6..3376bd1 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -847,6 +847,63 @@
     return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
 }
 
+static bool
+FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, 
+                                        NameSearchContext &context,
+                                        clang::ASTContext &ast_context,
+                                        ClangASTImporter *ast_importer,
+                                        DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl)
+{
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+    if (origin_iface_decl.IsInvalid())
+        return false;
+    
+    std::string name_str = context.m_decl_name.getAsString();
+    StringRef name(name_str.c_str());
+    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
+    
+    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
+    
+    bool found = false;
+    
+    if (origin_property_decl.IsValid())
+    {
+        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context));
+        if (parser_property_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_property_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_property_decl.decl);
+            found = true;
+        }
+    }
+    
+    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
+    
+    if (origin_ivar_decl.IsValid())
+    {
+        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context));
+        if (parser_ivar_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_ivar_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_ivar_decl.decl);
+            found = true;
+        }
+    }
+    
+    return found;
+}
+
 void
 ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
 {
@@ -857,54 +914,77 @@
     
     DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
     DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
-    
-    if (origin_iface_decl.IsInvalid())
-        return;
-    
-    std::string name_str = context.m_decl_name.getAsString();
-    StringRef name(name_str.c_str());
-    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
+
+    ConstString class_name(parser_iface_decl->getNameAsString().c_str());
     
     if (log)
         log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
                     current_id, 
                     m_ast_context,
                     parser_iface_decl->getNameAsString().c_str(), 
-                    name_str.c_str());
+                    context.m_decl_name.getAsString().c_str());
     
-    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
+    if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, 
+                                               context, 
+                                               *m_ast_context, 
+                                               m_ast_importer, 
+                                               origin_iface_decl))
+        return;
     
-    if (origin_property_decl.IsValid())
-    {
-        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(m_ast_importer, *m_ast_context));
-        if (parser_property_decl.IsValid())
-        {
-            if (log)
-            {
-                ASTDumper dumper((Decl*)parser_property_decl.decl);
-                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
-            }
-            
-            context.AddNamedDecl(parser_property_decl.decl);
-        }
-    }
+    if (log)
+        log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...",
+                    current_id,
+                    origin_iface_decl.decl, 
+                    &origin_iface_decl->getASTContext());
     
-    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
+    SymbolContext null_sc;
+    TypeList type_list;
     
-    if (origin_ivar_decl.IsValid())
-    {
-        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(m_ast_importer, *m_ast_context));
-        if (parser_ivar_decl.IsValid())
-        {
-            if (log)
-            {
-                ASTDumper dumper((Decl*)parser_ivar_decl.decl);
-                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
-            }
-            
-            context.AddNamedDecl(parser_ivar_decl.decl);
-        }
-    }
+    lldb::ProcessSP process(m_target->GetProcessSP());
+    
+    if (!process)
+        return;
+    
+    ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+    
+    if (!language_runtime)
+        return;
+    
+    lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
+    
+    if (!complete_type_sp)
+        return;
+    
+    TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST());
+    lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
+    
+    if (!complete_opaque_type)
+        return;
+    
+    const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
+    const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
+    
+    if (!complete_interface_type)
+        return;
+    
+    DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl());
+    
+    if (complete_iface_decl.decl == origin_iface_decl.decl)
+        return; // already checked this one
+    
+    if (log)
+        log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+                    current_id,
+                    complete_iface_decl.decl, 
+                    &complete_iface_decl->getASTContext());
+    
+    
+    if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, 
+                                               context, 
+                                               *m_ast_context, 
+                                               m_ast_importer, 
+                                               complete_iface_decl))
+        return;
 }
 
 typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap;