If the expression parser is unable to complete a TagDecl
in the context in which it was originally found, the
expression parser now goes hunting for it in all modules
(in the appropriate namespace, if applicable).  This means
that forward-declared types that exist in another shared
library will now be resolved correctly.

Added a test case to cover this.  The test case also tests
"frame variable," which does not have this functionality
yet.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@146204 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 552c545..9831070 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -149,15 +149,127 @@
 {    
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
     
+    static unsigned int invocation_id = 0;
+    unsigned int current_id = invocation_id++;
+    
     if (log)
     {
-        log->Printf("    [CompleteTagDecl] on (ASTContext*)%p Completing a TagDecl named %s", m_ast_context, tag_decl->getName().str().c_str());
-        log->Printf("      [CTD] Before:");
+        log->Printf("    CompleteTagDecl[%u] on (ASTContext*)%p Completing a TagDecl named %s", 
+                    invocation_id, 
+                    m_ast_context, 
+                    tag_decl->getName().str().c_str());
+        
+        log->Printf("      CTD[%u] Before:", current_id);
         ASTDumper dumper((Decl*)tag_decl);
         dumper.ToLog(log, "      [CTD] ");
     }
     
-    m_ast_importer->CompleteTagDecl (tag_decl);
+    if (!m_ast_importer->CompleteTagDecl (tag_decl))
+    {
+        // We couldn't complete the type.  Maybe there's a definition
+        // somewhere else that can be completed.
+        
+        if (log)
+            log->Printf("      CTD[%u] Type could not be completed in the module in which it was first found.", current_id);
+        
+        bool found = false;
+
+        DeclContext *decl_ctx = tag_decl->getDeclContext();
+                
+        if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx))
+        {
+            ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
+            
+            if (log && log->GetVerbose())
+                log->Printf("      CTD[%u] Inspecting namespace map %p (%d entries)", 
+                            current_id, 
+                            namespace_map.get(), 
+                            (int)namespace_map->size());
+            
+            if (!namespace_map)
+                return;
+            
+            for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
+                 i != e && !found;
+                 ++i)
+            {
+                if (log)
+                    log->Printf("      CTD[%u] Searching namespace %s in module %s",
+                                current_id,
+                                i->second.GetNamespaceDecl()->getNameAsString().c_str(),
+                                i->first->GetFileSpec().GetFilename().GetCString());
+                
+                TypeList types;
+                
+                SymbolContext null_sc;
+                ConstString name(tag_decl->getName().str().c_str());
+                
+                i->first->FindTypes(null_sc, name, &i->second, true, UINT32_MAX, types);
+                
+                for (uint32_t ti = 0, te = types.GetSize();
+                     ti != te && !found;
+                     ++ti)
+                {
+                    lldb::TypeSP type = types.GetTypeAtIndex(ti);
+                    
+                    if (!type)
+                        continue;
+                    
+                    lldb::clang_type_t opaque_type = type->GetClangFullType();
+                    
+                    if (!opaque_type)
+                        continue;
+                    
+                    const TagType *tag_type = dyn_cast<TagType>(QualType::getFromOpaquePtr(opaque_type).getTypePtr());
+                    
+                    if (!tag_type)
+                        continue;
+                    
+                    TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
+                    
+                    if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+                        found = true;
+                }
+            }
+        }
+        else 
+        {
+            TypeList types;
+            
+            SymbolContext null_sc;
+            ConstString name(tag_decl->getName().str().c_str());
+            ClangNamespaceDecl namespace_decl;
+            
+            ModuleList &module_list = m_target->GetImages();
+
+            module_list.FindTypes(null_sc, name, true, UINT32_MAX, types);
+            
+            for (uint32_t ti = 0, te = types.GetSize();
+                 ti != te && !found;
+                 ++ti)
+            {
+                lldb::TypeSP type = types.GetTypeAtIndex(ti);
+                
+                if (!type)
+                    continue;
+                
+                lldb::clang_type_t opaque_type = type->GetClangFullType();
+                
+                if (!opaque_type)
+                    continue;
+                
+                const TagType *tag_type = dyn_cast<TagType>(QualType::getFromOpaquePtr(opaque_type).getTypePtr());
+                
+                if (!tag_type)
+                    continue;
+                
+                TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
+                
+                if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+                    found = true;
+            }
+        }
+    }
     
     if (log)
     {
@@ -249,7 +361,7 @@
             external_source->CompleteType (original_tag_decl);
     }
     
-    DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);
+    const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);
     
     if (!original_decl_context)
         return ELR_Failure;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 196bec8..e0abf9a 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4548,22 +4548,25 @@
                     GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, 
                                                        unique_ast_entry);
                     
-                    if (die->HasChildren() == false && is_forward_declaration == false)
-                    {
-                        // No children for this struct/union/class, lets finish it
-                        ast.StartTagDeclarationDefinition (clang_type);
-                        ast.CompleteTagDeclarationDefinition (clang_type);
-                    }
-                    else if (clang_type_was_created)
-                    {
-                        // Leave this as a forward declaration until we need
-                        // to know the details of the type. lldb_private::Type
-                        // will automatically call the SymbolFile virtual function
-                        // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
-                        // When the definition needs to be defined.
-                        m_forward_decl_die_to_clang_type[die] = clang_type;
-                        m_forward_decl_clang_type_to_die[ClangASTType::RemoveFastQualifiers (clang_type)] = die;
-                        ClangASTContext::SetHasExternalStorage (clang_type, true);
+                    if (!is_forward_declaration)
+                    {                    
+                        if (die->HasChildren() == false)
+                        {
+                            // No children for this struct/union/class, lets finish it
+                            ast.StartTagDeclarationDefinition (clang_type);
+                            ast.CompleteTagDeclarationDefinition (clang_type);
+                        }
+                        else if (clang_type_was_created)
+                        {
+                            // Leave this as a forward declaration until we need
+                            // to know the details of the type. lldb_private::Type
+                            // will automatically call the SymbolFile virtual function
+                            // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
+                            // When the definition needs to be defined.
+                            m_forward_decl_die_to_clang_type[die] = clang_type;
+                            m_forward_decl_clang_type_to_die[ClangASTType::RemoveFastQualifiers (clang_type)] = die;
+                            ClangASTContext::SetHasExternalStorage (clang_type, true);
+                        }
                     }
                     
                 }
diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index eb65c9d..3bbd9c6 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/source/Symbol/ClangASTImporter.cpp
@@ -95,28 +95,48 @@
     return result;
 }
 
-void
+bool
 ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl)
-{
-    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-    
+{   
     DeclOrigin decl_origin = GetDeclOrigin(decl);
     
     if (!decl_origin.Valid())
-        return;
+        return false;
     
     if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
-        return;
+        return false;
     
     MinionSP minion_sp (GetMinion(&decl->getASTContext(), decl_origin.ctx));
     
     if (minion_sp)
         minion_sp->ImportDefinition(decl_origin.decl);
     
-    return;
+    return true;
 }
 
-void
+bool
+ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin_decl)
+{
+    clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
+        
+    if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
+        return false;
+    
+    MinionSP minion_sp (GetMinion(&decl->getASTContext(), origin_ast_ctx));
+    
+    if (minion_sp)
+        minion_sp->ImportDefinition(origin_decl);
+    
+    ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+    OriginMap &origins = context_md->m_origins;
+
+    origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
+    
+    return true;
+}
+
+bool
 ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl)
 {
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -124,17 +144,17 @@
     DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
     
     if (!decl_origin.Valid())
-        return;
+        return false;
     
     if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
-        return;
+        return false;
     
     MinionSP minion_sp (GetMinion(&interface_decl->getASTContext(), decl_origin.ctx));
     
     if (minion_sp)
         minion_sp->ImportDefinition(decl_origin.decl);
     
-    return;
+    return true;
 }
 
 ClangASTImporter::DeclOrigin