[Lldb-commits] [lldb] r254476 - Added support for -gmodule debugging when debug info is left in the .o files on Darwin.

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Tue Dec 1 16:43:33 PST 2015


Author: gclayton
Date: Tue Dec  1 18:43:32 2015
New Revision: 254476

URL: http://llvm.org/viewvc/llvm-project?rev=254476&view=rev
Log:
Added support for -gmodule debugging when debug info is left in the .o files on Darwin.

This is done by finding the types that are forward declarations that come from a module, and loading that module's debug info in a separate lldb_private::Module, and copying the type over into the current module using a ClangASTImporter object. ClangASTImporter objects are already used to copy types from on clang::ASTContext to another for expressions so the type copying code has been around for a while.

A new FindTypes variant was added to SymbolVendor and SymbolFile:

size_t
SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);

size_t
SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);

The CompilerContext is a way to represent the exact context of a type and pass it through an agnostic API boundary so that we can find that exact context elsewhere in another file. This was required here because we can have a module that has submodules, both of which have a "foo" type.

I am not able to add tests for this yet as we currently don't build our C/C++/ObjC binaries with the clang binary that we build. There are some driver issues where it can't find the header files for the C and C++ standard library which makes compiling these tests hard. We can't also guarantee that if we are building with clang that it supporst the exact format of -gmodule debugging that we are trying to test. We have had other versions of clang that had a different implementation of -gmodule debugging that we are no longer supporting, so we can't enable tests if we are building with clang without compiling something and looking at the structure of the DWARF that was generated to ensure that it is the format we can actually use.


Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/include/lldb/Symbol/ClangASTImporter.h
    lldb/trunk/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
    lldb/trunk/include/lldb/Symbol/SymbolFile.h
    lldb/trunk/include/lldb/Symbol/SymbolVendor.h
    lldb/trunk/include/lldb/Symbol/Type.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/include/lldb/lldb-private-enumerations.h
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Symbol/ClangASTImporter.cpp
    lldb/trunk/source/Symbol/ClangExternalASTSourceCallbacks.cpp
    lldb/trunk/source/Symbol/SymbolFile.cpp
    lldb/trunk/source/Symbol/SymbolVendor.cpp
    lldb/trunk/source/Symbol/Type.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Tue Dec  1 18:43:32 2015
@@ -1006,10 +1006,18 @@ public:
                                lldb::AccessType access,
                                bool is_artificial);
     
-    bool
+    static bool
     SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern);
     
-    
+
+    static bool
+    CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer);
+
+    static bool
+    Import (const CompilerType &type, lldb_private::ClangASTImporter &importer);
+
+    static bool
+    GetHasExternalStorage (const CompilerType &type);
     //------------------------------------------------------------------
     // Tag Declarations
     //------------------------------------------------------------------
@@ -1092,13 +1100,19 @@ public:
     
     void
     DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override;
-    
+
+    static void
+    DumpTypeName (const CompilerType &type);
+
     static clang::EnumDecl *
     GetAsEnumDecl (const CompilerType& type);
     
     static clang::RecordDecl *
     GetAsRecordDecl (const CompilerType& type);
-    
+
+    static clang::TagDecl *
+    GetAsTagDecl (const CompilerType& type);
+
     clang::CXXRecordDecl *
     GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type);
     
@@ -1109,9 +1123,12 @@ public:
     GetQualType (const CompilerType& type)
     {
         // Make sure we have a clang type before making a clang::QualType
-        ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
-        if (ast)
-            return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
+        if (type.GetOpaqueQualType())
+        {
+            ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
+            if (ast)
+                return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
+        }
         return clang::QualType();
     }
 

Modified: lldb/trunk/include/lldb/Symbol/ClangASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTImporter.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTImporter.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTImporter.h Tue Dec  1 18:43:32 2015
@@ -107,7 +107,11 @@ public:
     CopyType (clang::ASTContext *dst_ctx,
               clang::ASTContext *src_ctx,
               lldb::opaque_compiler_type_t type);
-    
+
+    CompilerType
+    CopyType (ClangASTContext &dst,
+              const CompilerType &src_type);
+
     clang::Decl *
     CopyDecl (clang::ASTContext *dst_ctx,
               clang::ASTContext *src_ctx,
@@ -134,7 +138,10 @@ public:
     
     bool
     CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
-    
+
+    bool
+    CompleteAndFetchChildren (clang::QualType type);
+
     bool
     RequireCompleteType (clang::QualType type);
     

Modified: lldb/trunk/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h Tue Dec  1 18:43:32 2015
@@ -97,6 +97,11 @@ public:
     {
     }
 
+    void
+    FindExternalLexicalDecls(const clang::DeclContext *DC,
+                             llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+                             llvm::SmallVectorImpl<clang::Decl *> &Result) override;
+
     bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override;
 
     void CompleteType(clang::TagDecl *tag_decl) override;

Modified: lldb/trunk/include/lldb/Symbol/SymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolFile.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolFile.h Tue Dec  1 18:43:32 2015
@@ -15,7 +15,6 @@
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
-
 #include "lldb/Symbol/Type.h"
 
 namespace lldb_private {
@@ -142,6 +141,8 @@ public:
     virtual uint32_t        FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list);
     virtual uint32_t        FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list);
     virtual uint32_t        FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, TypeMap& types);
+    virtual size_t          FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
+
 //  virtual uint32_t        FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
     virtual TypeList *      GetTypeList ();
     virtual size_t          GetTypes (lldb_private::SymbolContextScope *sc_scope,

Modified: lldb/trunk/include/lldb/Symbol/SymbolVendor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolVendor.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolVendor.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolVendor.h Tue Dec  1 18:43:32 2015
@@ -128,6 +128,9 @@ public:
                size_t max_matches,
                TypeMap& types);
 
+    virtual size_t
+    FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
+
     virtual CompilerDeclContext
     FindNamespace (const SymbolContext& sc, 
                    const ConstString &name,

Modified: lldb/trunk/include/lldb/Symbol/Type.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Type.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Type.h (original)
+++ lldb/trunk/include/lldb/Symbol/Type.h Tue Dec  1 18:43:32 2015
@@ -24,6 +24,31 @@
 
 namespace lldb_private {
 
+//----------------------------------------------------------------------
+// CompilerContext allows an array of these items to be passed to
+// perform detailed lookups in SymbolVendor and SymbolFile functions.
+//----------------------------------------------------------------------
+struct CompilerContext
+{
+    CompilerContext (CompilerContextKind t, const ConstString &n) :
+        type(t),
+        name(n)
+    {
+    }
+
+    bool
+    operator == (const CompilerContext &rhs) const
+    {
+        return type == rhs.type && name == rhs.name;
+    }
+
+    void
+    Dump () const;
+
+    CompilerContextKind type;
+    ConstString name;
+};
+
 class SymbolFileType :
     public std::enable_shared_from_this<SymbolFileType>,
     public UserID
@@ -35,6 +60,9 @@ class SymbolFileType :
         {
         }
 
+        SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp);
+
+
         ~SymbolFileType ()
         {
         }

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Tue Dec  1 18:43:32 2015
@@ -62,6 +62,7 @@ class   CommandObject;
 class   CommandReturnObject;
 class   Communication;
 class   CompactUnwindInfo;
+struct  CompilerContext;
 class   CompilerDecl;
 class   CompilerDeclContext;
 class   CompilerType;

Modified: lldb/trunk/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-enumerations.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-private-enumerations.h Tue Dec  1 18:43:32 2015
@@ -241,6 +241,25 @@ enum class TypeValidatorResult : bool {
     Success = true,
     Failure = false
 };
+
+//----------------------------------------------------------------------
+// Enumerations that can be used to specify scopes types when looking up
+// types.
+//----------------------------------------------------------------------
+enum class CompilerContextKind
+{
+    Invalid = 0,
+    TranslationUnit,
+    Module,
+    Namespace,
+    Class,
+    Structure,
+    Union,
+    Function,
+    Variable,
+    Enumeration,
+    Typedef
+};
     
 } // namespace lldb_private
 

Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py Tue Dec  1 18:43:32 2015
@@ -14,11 +14,11 @@ class TestCppIncompleteTypes(TestBase):
 
         value_f = frame.EvaluateExpression("f")
         self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object")
-        self.assertFalse(value_f.GetError().Success(), "'expr f' results in an error, but LLDB does not crash")
+        self.assertTrue(value_f.GetError().Success(), "'expr f' is successful")
 
         value_a = frame.EvaluateExpression("a")
         self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object")
-        self.assertFalse(value_a.GetError().Success(), "'expr a' results in an error, but LLDB does not crash")
+        self.assertTrue(value_a.GetError().Success(), "'expr a' is successful")
 
     @skipIfGcc
     @skipIfWindows # Clang on Windows asserts in external record layout in this case.

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h Tue Dec  1 18:43:32 2015
@@ -33,6 +33,18 @@ public:
                             const DWARFDIE &die) = 0;
 
     virtual bool
+    CanCompleteType (const lldb_private::CompilerType &compiler_type)
+    {
+        return false;
+    }
+
+    virtual bool
+    CompleteType (const lldb_private::CompilerType &compiler_type)
+    {
+        return false;
+    }
+
+    virtual bool
     CompleteTypeFromDWARF (const DWARFDIE &die,
                            lldb_private::Type *type,
                            lldb_private::CompilerType &compiler_type) = 0;

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Tue Dec  1 18:43:32 2015
@@ -24,11 +24,14 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Symbol/ClangASTImporter.h"
 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
 #include "lldb/Target/Language.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 
@@ -114,6 +117,78 @@ struct BitfieldInfo
     }
 };
 
+
+ClangASTImporter &
+DWARFASTParserClang::GetClangASTImporter()
+{
+    if (!m_clang_ast_importer_ap)
+    {
+        m_clang_ast_importer_ap.reset (new ClangASTImporter);
+    }
+    return *m_clang_ast_importer_ap;
+}
+
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log)
+{
+    ModuleSP dwo_module_sp = die.GetContainingDWOModule();
+    if (dwo_module_sp)
+    {
+        // This type comes from an external DWO module
+        std::vector<CompilerContext> dwo_context;
+        die.GetDWOContext(dwo_context);
+        TypeMap dwo_types;
+        if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types))
+        {
+            const size_t num_dwo_types = dwo_types.GetSize();
+            if (num_dwo_types == 1)
+            {
+                // We found a real definition for this type elsewhere
+                // so lets use it and cache the fact that we found
+                // a complete type for this die
+                TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+                if (dwo_type_sp)
+                {
+                    lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+                    lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type);
+
+                    //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString());
+                    if (type)
+                    {
+                        SymbolFileDWARF *dwarf = die.GetDWARF();
+                        TypeSP type_sp (new Type (die.GetID(),
+                                                  dwarf,
+                                                  dwo_type_sp->GetName(),
+                                                  dwo_type_sp->GetByteSize(),
+                                                  NULL,
+                                                  LLDB_INVALID_UID,
+                                                  Type::eEncodingInvalid,
+                                                  &dwo_type_sp->GetDeclaration(),
+                                                  type,
+                                                  Type::eResolveStateForward));
+
+                        dwarf->GetTypeList()->Insert(type_sp);
+                        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+                        clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+                        if (tag_decl)
+                            LinkDeclContextToDIE(tag_decl, die);
+                        else
+                        {
+                            clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+                            if (defn_decl_ctx)
+                                LinkDeclContextToDIE(defn_decl_ctx, die);
+                        }
+                        return type_sp;
+                    }
+                }
+            }
+        }
+    }
+    return TypeSP();
+}
+
 TypeSP
 DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
                                          const DWARFDIE &die,
@@ -487,15 +562,15 @@ DWARFASTParserClang::ParseTypeFromDWARF
                             if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
                                                                        byte_size_valid ? byte_size : -1,
                                                                        *unique_ast_entry_ap))
-                        {
-                            type_sp = unique_ast_entry_ap->m_type_sp;
-                            if (type_sp)
                             {
-                            dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
-                            return type_sp;
+                                type_sp = unique_ast_entry_ap->m_type_sp;
+                                if (type_sp)
+                                {
+                                    dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+                                    return type_sp;
+                                }
                             }
                         }
-                        }
                     }
 
                     DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
@@ -600,6 +675,11 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                                                              type_name_cstr);
                         }
 
+                        // See if the type comes from a DWO module and if so, track down that type.
+                        type_sp = ParseTypeFromDWO(die, log);
+                        if (type_sp)
+                            return type_sp;
+
                         DWARFDeclContext die_decl_ctx;
                         die.GetDWARFDeclContext(die_decl_ctx);
 
@@ -833,7 +913,7 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                     case DW_AT_type:            encoding_form = form_value; break;
                                     case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break;
                                     case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
-                                    case DW_AT_declaration:     break; //is_forward_declaration = form_value.Boolean(); break;
+                                    case DW_AT_declaration:     is_forward_declaration = form_value.Boolean(); break;
                                     case DW_AT_allocated:
                                     case DW_AT_associated:
                                     case DW_AT_bit_stride:
@@ -850,6 +930,54 @@ DWARFASTParserClang::ParseTypeFromDWARF
                             }
                         }
 
+                        if (is_forward_declaration)
+                        {
+                            type_sp = ParseTypeFromDWO(die, log);
+                            if (type_sp)
+                                return type_sp;
+
+                            DWARFDeclContext die_decl_ctx;
+                            die.GetDWARFDeclContext(die_decl_ctx);
+
+                            type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+
+                            if (!type_sp)
+                            {
+                                SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+                                if (debug_map_symfile)
+                                {
+                                    // We weren't able to find a full declaration in
+                                    // this DWARF, see if we have a declaration anywhere
+                                    // else...
+                                    type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+                                }
+                            }
+
+                            if (type_sp)
+                            {
+                                if (log)
+                                {
+                                    dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+                                                                                     "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
+                                                                                     static_cast<void*>(this),
+                                                                                     die.GetOffset(),
+                                                                                     DW_TAG_value_to_name(tag),
+                                                                                     type_name_cstr,
+                                                                                     type_sp->GetID());
+                                }
+
+                                // We found a real definition for this type elsewhere
+                                // so lets use it and cache the fact that we found
+                                // a complete type for this die
+                                dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+                                clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(
+                                                                                                    dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+                                if (defn_decl_ctx)
+                                    LinkDeclContextToDIE(defn_decl_ctx, die);
+                                return type_sp;
+                            }
+
+                        }
                         DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
 
                         CompilerType enumerator_clang_type;
@@ -1130,7 +1258,7 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                 if (class_type)
                                 {
                                     bool alternate_defn = false;
-                                    if (class_type->GetID() != decl_ctx_die.GetID())
+                                    if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE())
                                     {
                                         alternate_defn = true;
 
@@ -1798,6 +1926,33 @@ DWARFASTParserClang::ParseTemplateParame
 }
 
 bool
+DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type)
+{
+    if (m_clang_ast_importer_ap)
+        return ClangASTContext::CanImport(compiler_type, GetClangASTImporter());
+    else
+        return false;
+}
+
+bool
+DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type)
+{
+    if (CanCompleteType(compiler_type))
+    {
+        if (ClangASTContext::Import(compiler_type, GetClangASTImporter()))
+        {
+            ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+            return true;
+        }
+        else
+        {
+            ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false);
+        }
+    }
+    return false;
+}
+
+bool
 DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
                                             lldb_private::Type *type,
                                             CompilerType &clang_type)
@@ -1868,25 +2023,17 @@ DWARFASTParserClang::CompleteTypeFromDWA
                     DWARFDIECollection member_function_dies;
 
                     DelayedPropertyList delayed_properties;
-                    if (!ParseChildMembers (sc,
-                                            die,
-                                            clang_type,
-                                            class_language,
-                                            base_classes,
-                                            member_accessibilities,
-                                            member_function_dies,
-                                            delayed_properties,
-                                            default_accessibility,
-                                            is_a_class,
-                                            layout_info))
-                    {
-                        auto module = dwarf->GetObjectFile()->GetModule();
-                        module->ReportError (":: Class %s has members with incomplete type.", die.GetName());
-                        if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
-                            module->ReportError(":: Try compiling the source file with -fno-limit-debug-info.");
-
-                        return false;
-                    }
+                    ParseChildMembers (sc,
+                                       die,
+                                       clang_type,
+                                       class_language,
+                                       base_classes,
+                                       member_accessibilities,
+                                       member_function_dies,
+                                       delayed_properties,
+                                       default_accessibility,
+                                       is_a_class,
+                                       layout_info);
 
                     // Now parse any methods if there were any...
                     size_t num_functions = member_function_dies.Size();
@@ -1977,7 +2124,14 @@ DWARFASTParserClang::CompleteTypeFromDWA
                                     if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
                                          module->ReportError (":: Try compiling the source file with -fno-limit-debug-info.");
 
-                                    return false;
+                                    // We have no choice other than to pretend that the base class
+                                    // is complete. If we don't do this, clang will crash when we
+                                    // call setBases() inside of "clang_type.SetBaseClassesForClassType()"
+                                    // below. Since we provide layout assistance, all ivars in this
+                                    // class and other classes will be fine, this is the best we can do
+                                    // short of crashing.
+                                    ClangASTContext::StartTagDeclarationDefinition (base_class_type);
+                                    ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
                                 }
                             }
                         }
@@ -2420,7 +2574,6 @@ DWARFASTParserClang::ParseChildMembers (
     if (!parent_die)
         return 0;
 
-    uint32_t incomplete_member_info_count = 0;
     uint32_t member_idx = 0;
     BitfieldInfo last_field_info;
 
@@ -2754,8 +2907,8 @@ DWARFASTParserClang::ParseChildMembers (
                                 }
 
                                 CompilerType member_clang_type = member_type->GetLayoutCompilerType ();
-                                if (!member_clang_type.IsCompleteType() && !member_clang_type.GetCompleteType())
-                                    incomplete_member_info_count += 1;
+                                if (!member_clang_type.IsCompleteType())
+                                    member_clang_type.GetCompleteType();
 
                                 {
                                     // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
@@ -2789,6 +2942,30 @@ DWARFASTParserClang::ParseChildMembers (
                                     }
                                 }
 
+                                if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false)
+                                {
+                                    if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
+                                        module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info",
+                                                                parent_die.GetOffset(),
+                                                                parent_die.GetName(),
+                                                                die.GetOffset(),
+                                                                name);
+                                    else
+                                        module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s",
+                                                                parent_die.GetOffset(),
+                                                                parent_die.GetName(),
+                                                                die.GetOffset(),
+                                                                name,
+                                                                sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
+                                    // We have no choice other than to pretend that the member class
+                                    // is complete. If we don't do this, clang will crash when trying
+                                    // to layout the class. Since we provide layout assistance, all
+                                    // ivars in this class and other classes will be fine, this is
+                                    // the best we can do short of crashing.
+                                    ClangASTContext::StartTagDeclarationDefinition(member_clang_type);
+                                    ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+                                }
+
                                 field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
                                                                                     name,
                                                                                     member_clang_type,
@@ -2978,7 +3155,7 @@ DWARFASTParserClang::ParseChildMembers (
         }
     }
 
-    return incomplete_member_info_count == 0;
+    return true;
 }
 
 

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h Tue Dec  1 18:43:32 2015
@@ -47,6 +47,12 @@ public:
                             const DWARFDIE &die) override;
 
     bool
+    CanCompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+    bool
+    CompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+    bool
     CompleteTypeFromDWARF (const DWARFDIE &die,
                            lldb_private::Type *type,
                            lldb_private::CompilerType &compiler_type) override;
@@ -175,6 +181,19 @@ protected:
     void
     LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
 
+    lldb_private::ClangASTImporter &
+    GetClangASTImporter();
+
+    lldb::TypeSP
+    ParseTypeFromDWO (const DWARFDIE &die, lldb_private::Log *log);
+
+    //----------------------------------------------------------------------
+    // Return true if this type is a declaration to a type in an external
+    // module.
+    //----------------------------------------------------------------------
+    lldb::ModuleSP
+    GetModuleForType (const DWARFDIE &die);
+
     typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
     //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
@@ -188,6 +207,7 @@ protected:
     DIEToDeclContextMap m_die_to_decl_ctx;
     DeclContextToDIEMap m_decl_ctx_to_die;
     RecordDeclToLayoutMap m_record_decl_to_layout_map;
+    std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
 };
 
 #endif // SymbolFileDWARF_DWARFASTParserClang_h_

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp Tue Dec  1 18:43:32 2015
@@ -22,8 +22,11 @@
 
 #include "lldb/Core/Module.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/TypeSystem.h"
 
+using namespace lldb_private;
+
 DIERef
 DWARFDIE::GetDIERef() const
 {
@@ -307,6 +310,51 @@ DWARFDIE::GetDWARFDeclContext (DWARFDecl
     }
 }
 
+void
+DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const
+{
+    const dw_tag_t tag = Tag();
+    if (tag == DW_TAG_compile_unit)
+        return;
+    DWARFDIE parent = GetParent();
+    if (parent)
+        parent.GetDWOContext(context);
+    switch (tag)
+    {
+        case DW_TAG_module:
+            context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
+            break;
+        case DW_TAG_namespace:
+            context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName())));
+            break;
+        case DW_TAG_structure_type:
+            context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName())));
+            break;
+        case DW_TAG_union_type:
+            context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
+            break;
+        case DW_TAG_class_type:
+            context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
+            break;
+        case DW_TAG_enumeration_type:
+            context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName())));
+            break;
+        case DW_TAG_subprogram:
+            context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname())));
+            break;
+        case DW_TAG_variable:
+            context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname())));
+            break;
+        case DW_TAG_typedef:
+            context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
+            break;
+        default:
+            assert(!"remove this prior to checkin");
+            break;
+    }
+}
+
+
 
 DWARFDIE
 DWARFDIE::GetParentDeclContextDIE () const
@@ -371,6 +419,45 @@ DWARFDIE::IsStructOrClass () const
     return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
 }
 
+
+DWARFDIE
+DWARFDIE::GetContainingDWOModuleDIE () const
+{
+    if (IsValid())
+    {
+        DWARFDIE top_module_die;
+        // Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so
+        for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent())
+        {
+            const dw_tag_t tag = parent.Tag();
+            if (tag == DW_TAG_module)
+                top_module_die = parent;
+            else if (tag == DW_TAG_compile_unit)
+                break;
+        }
+
+        return top_module_die;
+    }
+    return DWARFDIE();
+}
+
+lldb::ModuleSP
+DWARFDIE::GetContainingDWOModule () const
+{
+    if (IsValid())
+    {
+        DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
+
+        if (dwo_module_die)
+        {
+            const char *module_name = dwo_module_die.GetName();
+            if (module_name)
+                return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name));
+        }
+    }
+    return lldb::ModuleSP();
+}
+
 bool
 DWARFDIE::HasChildren () const
 {

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h Tue Dec  1 18:43:32 2015
@@ -126,6 +126,12 @@ public:
         m_die = nullptr;
     }
 
+    lldb::ModuleSP
+    GetContainingDWOModule () const;
+
+    DWARFDIE
+    GetContainingDWOModuleDIE () const;
+
     //----------------------------------------------------------------------
     // Accessing information about a DIE
     //----------------------------------------------------------------------
@@ -217,6 +223,9 @@ public:
     void
     GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
 
+    void
+    GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const;
+
     //----------------------------------------------------------------------
     // Getting attribute values from the DIE.
     //

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Dec  1 18:43:32 2015
@@ -1077,9 +1077,9 @@ SymbolFileDWARF::ParseImportedModules (c
         if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
         {
             UpdateExternalModuleListIfNeeded();
-            for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules)
+            for (const auto &pair : m_external_type_modules)
             {
-                imported_modules.push_back(external_type_module.second.m_name);
+                imported_modules.push_back(pair.first);
             }
         }
     }
@@ -1515,13 +1515,32 @@ bool
 SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)
 {
     CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
-    return GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType());
+    if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()))
+    {
+        return true;
+    }
+    TypeSystem *type_system = compiler_type.GetTypeSystem();
+    if (type_system)
+    {
+        DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+        if (dwarf_ast)
+            return dwarf_ast->CanCompleteType(compiler_type);
+    }
+    return false;
 }
 
 
 bool
 SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
 {
+    TypeSystem *type_system = compiler_type.GetTypeSystem();
+    if (type_system)
+    {
+        DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+        if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type))
+            return dwarf_ast->CompleteType(compiler_type);
+    }
+
     // We have a struct/union/class/enum that needs to be fully resolved.
     CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
     auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
@@ -1641,6 +1660,17 @@ SymbolFileDWARF::GetFunction (const DWAR
     return false;
 }
 
+lldb::ModuleSP
+SymbolFileDWARF::GetDWOModule (ConstString name)
+{
+    UpdateExternalModuleListIfNeeded();
+    const auto &pos = m_external_type_modules.find(name);
+    if (pos != m_external_type_modules.end())
+        return pos->second;
+    else
+        return lldb::ModuleSP();
+}
+
 void
 SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
 {
@@ -1658,37 +1688,24 @@ SymbolFileDWARF::UpdateExternalModuleLis
         const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
         if (die && die.HasChildren() == false)
         {
-            const uint64_t name_strp = die.GetAttributeValueAsUnsigned (DW_AT_name, UINT64_MAX);
-            const uint64_t dwo_path_strp = die.GetAttributeValueAsUnsigned (DW_AT_GNU_dwo_name, UINT64_MAX);
-            
-            if (name_strp != UINT64_MAX)
+            const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+
+            if (name)
             {
-                if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end())
+                ConstString const_name(name);
+                if (m_external_type_modules.find(const_name) == m_external_type_modules.end())
                 {
-                    const char *name = get_debug_str_data().PeekCStr(name_strp);
-                    const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
-                    if (name || dwo_path)
+                    ModuleSP module_sp;
+                    const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
+                    if (dwo_path)
                     {
-                        ModuleSP module_sp;
-                        if (dwo_path)
-                        {
-                            ModuleSpec dwo_module_spec;
-                            dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
-                            dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
-                            //printf ("Loading dwo = '%s'\n", dwo_path);
-                            Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
-                        }
-                        
-                        if (dwo_path_strp != LLDB_INVALID_UID)
-                        {
-                            m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp };
-                        }
-                        else
-                        {
-                            // This hack should be removed promptly once clang emits both.
-                            m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp };
-                        }
+                        ModuleSpec dwo_module_spec;
+                        dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+                        dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
+                        //printf ("Loading dwo = '%s'\n", dwo_path);
+                        Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
                     }
+                    m_external_type_modules[const_name] = module_sp;
                 }
             }
         }
@@ -2970,6 +2987,104 @@ SymbolFileDWARF::FindTypes (const Symbol
         }
         return num_matches;
     }
+    else
+    {
+        UpdateExternalModuleListIfNeeded();
+
+        for (const auto &pair : m_external_type_modules)
+        {
+            ModuleSP external_module_sp = pair.second;
+            if (external_module_sp)
+            {
+                SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor();
+                if (sym_vendor)
+                {
+                    const uint32_t num_external_matches = sym_vendor->FindTypes (sc,
+                                                                                 name,
+                                                                                 parent_decl_ctx,
+                                                                                 append,
+                                                                                 max_matches,
+                                                                                 types);
+                    if (num_external_matches)
+                        return num_external_matches;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+size_t
+SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context,
+                            bool append,
+                            TypeMap& types)
+{
+    if (!append)
+        types.Clear();
+
+    if (context.empty())
+        return 0;
+
+    DIEArray die_offsets;
+
+    ConstString name = context.back().name;
+
+    if (m_using_apple_tables)
+    {
+        if (m_apple_types_ap.get())
+        {
+            const char *name_cstr = name.GetCString();
+            m_apple_types_ap->FindByName (name_cstr, die_offsets);
+        }
+    }
+    else
+    {
+        if (!m_indexed)
+            Index ();
+
+        m_type_index.Find (name, die_offsets);
+    }
+
+    const size_t num_die_matches = die_offsets.size();
+
+    if (num_die_matches)
+    {
+        size_t num_matches = 0;
+        DWARFDebugInfo* debug_info = DebugInfo();
+        for (size_t i=0; i<num_die_matches; ++i)
+        {
+            const DIERef& die_ref = die_offsets[i];
+            DWARFDIE die = debug_info->GetDIE (die_ref);
+
+            if (die)
+            {
+                std::vector<CompilerContext> die_context;
+                die.GetDWOContext(die_context);
+                if (die_context != context)
+                    continue;
+
+                Type *matching_type = ResolveType (die, true, true);
+                if (matching_type)
+                {
+                    // We found a type pointer, now find the shared pointer form our type list
+                    types.InsertUnique (matching_type->shared_from_this());
+                    ++num_matches;
+                }
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                               die_ref.die_offset, name.GetCString());
+                }
+            }
+
+        }
+        return num_matches;
+    }
     return 0;
 }
 

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Tue Dec  1 18:43:32 2015
@@ -211,6 +211,11 @@ public:
                uint32_t max_matches,
                lldb_private::TypeMap& types) override;
 
+    size_t
+    FindTypes (const std::vector<lldb_private::CompilerContext> &context,
+               bool append,
+               lldb_private::TypeMap& types) override;
+
     lldb_private::TypeList *
     GetTypeList () override;
 
@@ -306,6 +311,9 @@ public:
     virtual lldb_private::DWARFExpression::LocationListFormat
     GetLocationListFormat() const;
 
+    lldb::ModuleSP
+    GetDWOModule (lldb_private::ConstString name);
+
 protected:
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
@@ -483,12 +491,7 @@ protected:
 
     typedef std::set<lldb_private::Type *> TypeSet;
     
-    typedef struct {
-        lldb_private::ConstString   m_name;
-        lldb::ModuleSP              m_module_sp;
-    } ClangModuleInfo;
-    
-    typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
+    typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;
 
     void
     GetTypes (const DWARFDIE &die,

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Tue Dec  1 18:43:32 2015
@@ -2297,9 +2297,6 @@ ClangASTContext::GetCompleteDecl (clang:
         if (tag_decl->isCompleteDefinition())
             return true;
         
-        if (!tag_decl->hasExternalLexicalStorage())
-            return false;
-        
         ast_source->CompleteType(tag_decl);
         
         return !tag_decl->getTypeForDecl()->isIncompleteType();
@@ -2451,81 +2448,110 @@ GetCompleteQualType (clang::ASTContext *
         case clang::Type::ConstantArray:
         case clang::Type::IncompleteArray:
         case clang::Type::VariableArray:
-        {
-            const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
-            
-            if (array_type)
-                return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
-        }
+            {
+                const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
+                
+                if (array_type)
+                    return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
+            }
             break;
             
         case clang::Type::Record:
-        case clang::Type::Enum:
-        {
-            const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
-            if (tag_type)
             {
-                clang::TagDecl *tag_decl = tag_type->getDecl();
-                if (tag_decl)
+                clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+                if (cxx_record_decl)
                 {
-                    if (tag_decl->isCompleteDefinition())
+                    bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage();
+                    if (cxx_record_decl->isCompleteDefinition() && fields_loaded)
                         return true;
-                    
+
                     if (!allow_completion)
                         return false;
-                    
-                    if (tag_decl->hasExternalLexicalStorage())
+
+                    // Call the field_begin() accessor to for it to use the external source
+                    // to load the fields...
+                    clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+                    if (external_ast_source)
+                    {
+                        external_ast_source->CompleteType(cxx_record_decl);
+                        if (cxx_record_decl->isCompleteDefinition())
+                        {
+                            cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true);
+                            cxx_record_decl->field_begin();
+                            return cxx_record_decl->hasLoadedFieldsFromExternalStorage();
+                        }
+                    }
+                }
+                return false;
+            }
+                break;
+
+        case clang::Type::Enum:
+            {
+                const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+                if (tag_type)
+                {
+                    clang::TagDecl *tag_decl = tag_type->getDecl();
+                    if (tag_decl)
                     {
-                        if (ast)
+                        if (tag_decl->getDefinition())
+                            return true;
+                        
+                        if (!allow_completion)
+                            return false;
+                        
+                        if (tag_decl->hasExternalLexicalStorage())
                         {
-                            clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
-                            if (external_ast_source)
+                            if (ast)
                             {
-                                external_ast_source->CompleteType(tag_decl);
-                                return !tag_type->isIncompleteType();
+                                clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+                                if (external_ast_source)
+                                {
+                                    external_ast_source->CompleteType(tag_decl);
+                                    return !tag_type->isIncompleteType();
+                                }
                             }
                         }
+                        return false;
                     }
-                    return false;
                 }
+                
             }
-            
-        }
             break;
             
         case clang::Type::ObjCObject:
         case clang::Type::ObjCInterface:
-        {
-            const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-            if (objc_class_type)
             {
-                clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-                // We currently can't complete objective C types through the newly added ASTContext
-                // because it only supports TagDecl objects right now...
-                if (class_interface_decl)
+                const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+                if (objc_class_type)
                 {
-                    if (class_interface_decl->getDefinition())
-                        return true;
-                    
-                    if (!allow_completion)
-                        return false;
-                    
-                    if (class_interface_decl->hasExternalLexicalStorage())
+                    clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    // We currently can't complete objective C types through the newly added ASTContext
+                    // because it only supports TagDecl objects right now...
+                    if (class_interface_decl)
                     {
-                        if (ast)
+                        if (class_interface_decl->getDefinition())
+                            return true;
+                        
+                        if (!allow_completion)
+                            return false;
+                        
+                        if (class_interface_decl->hasExternalLexicalStorage())
                         {
-                            clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
-                            if (external_ast_source)
+                            if (ast)
                             {
-                                external_ast_source->CompleteType (class_interface_decl);
-                                return !objc_class_type->isIncompleteType();
+                                clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+                                if (external_ast_source)
+                                {
+                                    external_ast_source->CompleteType (class_interface_decl);
+                                    return !objc_class_type->isIncompleteType();
+                                }
                             }
                         }
+                        return false;
                     }
-                    return false;
                 }
             }
-        }
             break;
             
         case clang::Type::Typedef:
@@ -2536,7 +2562,10 @@ GetCompleteQualType (clang::ASTContext *
             
         case clang::Type::Paren:
             return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
-            
+
+        case clang::Type::Attributed:
+            return GetCompleteQualType (ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), allow_completion);
+
         default:
             break;
     }
@@ -7160,6 +7189,16 @@ ClangASTContext::GetAsRecordDecl (const
     return nullptr;
 }
 
+clang::TagDecl *
+ClangASTContext::GetAsTagDecl (const CompilerType& type)
+{
+    clang::QualType qual_type = GetCanonicalQualType(type);
+    if (qual_type.isNull())
+        return nullptr;
+    else
+        return qual_type->getAsTagDecl();
+}
+
 clang::CXXRecordDecl *
 ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type)
 {
@@ -8037,6 +8076,64 @@ ClangASTContext::AddMethodToObjCObjectTy
 }
 
 bool
+ClangASTContext::GetHasExternalStorage (const CompilerType &type)
+{
+    if (IsClangType(type))
+        return false;
+
+    clang::QualType qual_type (GetCanonicalQualType(type));
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class)
+    {
+        case clang::Type::Record:
+        {
+            clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+            if (cxx_record_decl)
+                return cxx_record_decl->hasExternalLexicalStorage () || cxx_record_decl->hasExternalVisibleStorage();
+        }
+            break;
+
+        case clang::Type::Enum:
+        {
+            clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+            if (enum_decl)
+                return enum_decl->hasExternalLexicalStorage () || enum_decl->hasExternalVisibleStorage();
+        }
+            break;
+
+        case clang::Type::ObjCObject:
+        case clang::Type::ObjCInterface:
+        {
+            const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+            assert (objc_class_type);
+            if (objc_class_type)
+            {
+                clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+                if (class_interface_decl)
+                    return class_interface_decl->hasExternalLexicalStorage () || class_interface_decl->hasExternalVisibleStorage ();
+            }
+        }
+            break;
+
+        case clang::Type::Typedef:
+            return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()));
+
+        case clang::Type::Elaborated:
+            return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
+
+        case clang::Type::Paren:
+            return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+        default:
+            break;
+    }
+    return false;
+}
+
+
+bool
 ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern)
 {
     if (!type)
@@ -8106,67 +8203,198 @@ ClangASTContext::SetHasExternalStorage (
 }
 
 
-#pragma mark TagDecl
+bool
+ClangASTContext::CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer)
+{
+    if (IsClangType(type))
+    {
+        // TODO: remove external completion BOOL
+        // CompleteAndFetchChildren should get the Decl out and check for the
+
+        clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+        const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+        switch (type_class)
+        {
+            case clang::Type::Record:
+            {
+                const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+                if (cxx_record_decl)
+                {
+                    if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
+                        return true;
+                }
+            }
+                break;
+
+            case clang::Type::Enum:
+            {
+                clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+                if (enum_decl)
+                {
+                    if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
+                        return true;
+                }
+            }
+                break;
+
+            case clang::Type::ObjCObject:
+            case clang::Type::ObjCInterface:
+            {
+                const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+                if (objc_class_type)
+                {
+                    clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    // We currently can't complete objective C types through the newly added ASTContext
+                    // because it only supports TagDecl objects right now...
+                    if (class_interface_decl)
+                    {
+                        if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
+                            return true;
+                    }
+                }
+            }
+                break;
+
+
+            case clang::Type::Typedef:
+                return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
+
+            case clang::Type::Elaborated:
+                return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
 
+            case clang::Type::Paren:
+                return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
+
+            default:
+                break;
+        }
+    }
+    return false;
+}
 bool
-ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
+ClangASTContext::Import (const CompilerType &type, lldb_private::ClangASTImporter &importer)
 {
-    if (type)
+    if (IsClangType(type))
     {
-        
-        clang::QualType qual_type (GetQualType(type));
-        const clang::Type *t = qual_type.getTypePtr();
-        if (t)
+        // TODO: remove external completion BOOL
+        // CompleteAndFetchChildren should get the Decl out and check for the
+
+        clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+        const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+        switch (type_class)
         {
-            const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(t);
-            if (tag_type)
+            case clang::Type::Record:
             {
-                clang::TagDecl *tag_decl = tag_type->getDecl();
-                if (tag_decl)
+                const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+                if (cxx_record_decl)
                 {
-                    tag_decl->startDefinition();
-                    return true;
+                    if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
+                        return importer.CompleteAndFetchChildren(qual_type);
                 }
             }
-            
-            const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(t);
-            if (object_type)
+                break;
+
+            case clang::Type::Enum:
             {
-                clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
-                if (interface_decl)
+                clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+                if (enum_decl)
                 {
-                    interface_decl->startDefinition();
-                    return true;
+                    if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
+                        return importer.CompleteAndFetchChildren(qual_type);
+                }
+            }
+                break;
+
+            case clang::Type::ObjCObject:
+            case clang::Type::ObjCInterface:
+            {
+                const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+                if (objc_class_type)
+                {
+                    clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    // We currently can't complete objective C types through the newly added ASTContext
+                    // because it only supports TagDecl objects right now...
+                    if (class_interface_decl)
+                    {
+                        if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
+                            return importer.CompleteAndFetchChildren(qual_type);
+                    }
                 }
             }
+                break;
+
+
+            case clang::Type::Typedef:
+                return Import (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
+
+            case clang::Type::Elaborated:
+                return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
+
+            case clang::Type::Paren:
+                return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
+                
+            default:
+                break;
         }
     }
     return false;
 }
 
+
+#pragma mark TagDecl
+
 bool
-ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
+ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
 {
-    if (type)
+    clang::QualType qual_type (ClangASTContext::GetQualType(type));
+    if (!qual_type.isNull())
     {
-        clang::QualType qual_type (GetQualType(type));
-        if (qual_type.isNull())
-            return false;
-        ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
-        if (lldb_ast == nullptr)
-            return false;
-        clang::ASTContext *ast = lldb_ast->getASTContext();
+        const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+        if (tag_type)
+        {
+            clang::TagDecl *tag_decl = tag_type->getDecl();
+            if (tag_decl)
+            {
+                tag_decl->startDefinition();
+                return true;
+            }
+        }
+        
+        const clang::ObjCObjectType *object_type = qual_type->getAs<clang::ObjCObjectType>();
+        if (object_type)
+        {
+            clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
+            if (interface_decl)
+            {
+                interface_decl->startDefinition();
+                return true;
+            }
+        }
+    }
+    return false;
+}
 
+bool
+ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
+{
+    clang::QualType qual_type (ClangASTContext::GetQualType(type));
+    if (!qual_type.isNull())
+    {
         clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
         
         if (cxx_record_decl)
         {
-            cxx_record_decl->completeDefinition();
-            
+            if (!cxx_record_decl->isCompleteDefinition())
+                cxx_record_decl->completeDefinition();
+            cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+            cxx_record_decl->setHasExternalLexicalStorage (false);
+            cxx_record_decl->setHasExternalVisibleStorage (false);
             return true;
         }
         
-        const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(qual_type.getTypePtr());
+        const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
         
         if (enutype)
         {
@@ -8174,25 +8402,33 @@ ClangASTContext::CompleteTagDeclarationD
             
             if (enum_decl)
             {
-                /// TODO This really needs to be fixed.
-                
-                unsigned NumPositiveBits = 1;
-                unsigned NumNegativeBits = 0;
-                
-                clang::QualType promotion_qual_type;
-                // If the enum integer type is less than an integer in bit width,
-                // then we must promote it to an integer size.
-                if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy))
+                if (!enum_decl->isCompleteDefinition())
                 {
-                    if (enum_decl->getIntegerType()->isSignedIntegerType())
-                        promotion_qual_type = ast->IntTy;
+                    ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+                    if (lldb_ast == nullptr)
+                        return false;
+                    clang::ASTContext *ast = lldb_ast->getASTContext();
+
+                    /// TODO This really needs to be fixed.
+                    
+                    unsigned NumPositiveBits = 1;
+                    unsigned NumNegativeBits = 0;
+                    
+                    clang::QualType promotion_qual_type;
+                    // If the enum integer type is less than an integer in bit width,
+                    // then we must promote it to an integer size.
+                    if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy))
+                    {
+                        if (enum_decl->getIntegerType()->isSignedIntegerType())
+                            promotion_qual_type = ast->IntTy;
+                        else
+                            promotion_qual_type = ast->UnsignedIntTy;
+                    }
                     else
-                        promotion_qual_type = ast->UnsignedIntTy;
+                        promotion_qual_type = enum_decl->getIntegerType();
+                    
+                    enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
                 }
-                else
-                    promotion_qual_type = enum_decl->getIntegerType();
-                
-                enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
                 return true;
             }
         }
@@ -8976,6 +9212,72 @@ ClangASTContext::DumpTypeDescription (ll
     }
 }
 
+void
+ClangASTContext::DumpTypeName (const CompilerType &type)
+{
+    if (IsClangType(type))
+    {
+        clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+        const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+        switch (type_class)
+        {
+            case clang::Type::Record:
+            {
+                const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+                if (cxx_record_decl)
+                    printf("class %s", cxx_record_decl->getName().str().c_str());
+            }
+                break;
+
+            case clang::Type::Enum:
+            {
+                clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+                if (enum_decl)
+                {
+                    printf("enum %s", enum_decl->getName().str().c_str());
+                }
+            }
+                break;
+
+            case clang::Type::ObjCObject:
+            case clang::Type::ObjCInterface:
+            {
+                const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+                if (objc_class_type)
+                {
+                    clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                    // We currently can't complete objective C types through the newly added ASTContext
+                    // because it only supports TagDecl objects right now...
+                    if (class_interface_decl)
+                        printf("@class %s", class_interface_decl->getName().str().c_str());
+                }
+            }
+                break;
+
+
+            case clang::Type::Typedef:
+                printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getName().str().c_str());
+                break;
+
+            case clang::Type::Elaborated:
+                printf("elaborated ");
+                return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
+
+            case clang::Type::Paren:
+                printf("paren ");
+                return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+            default:
+                printf("ClangASTContext::DumpTypeName() type_class = %u", type_class);
+                break;
+        }
+    }
+
+}
+
+
+
 clang::ClassTemplateDecl *
 ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
                                          lldb::AccessType access_type,

Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Tue Dec  1 18:43:32 2015
@@ -67,6 +67,31 @@ ClangASTImporter::CopyType (clang::ASTCo
     return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr();
 }
 
+CompilerType
+ClangASTImporter::CopyType (ClangASTContext &dst_ast,
+                            const CompilerType &src_type)
+{
+    clang::ASTContext *dst_clang_ast = dst_ast.getASTContext();
+    if (dst_clang_ast)
+    {
+        ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
+        if (src_ast)
+        {
+            clang::ASTContext *src_clang_ast = src_ast->getASTContext();
+            if (src_clang_ast)
+            {
+                lldb::opaque_compiler_type_t dst_clang_type = CopyType(dst_clang_ast,
+                                                                       src_clang_ast,
+                                                                       src_type.GetOpaqueQualType());
+
+                if (dst_clang_type)
+                    return CompilerType(&dst_ast, dst_clang_type);
+            }
+        }
+    }
+    return CompilerType();
+}
+
 clang::Decl *
 ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
                             clang::ASTContext *src_ast,
@@ -429,6 +454,68 @@ ClangASTImporter::CompleteObjCInterfaceD
 }
 
 bool
+ClangASTImporter::CompleteAndFetchChildren (clang::QualType type)
+{
+    if (!RequireCompleteType(type))
+        return false;
+
+    if (const TagType *tag_type = type->getAs<TagType>())
+    {
+        TagDecl *tag_decl = tag_type->getDecl();
+
+        DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
+
+        if (!decl_origin.Valid())
+            return false;
+
+        MinionSP minion_sp (GetMinion(&tag_decl->getASTContext(), decl_origin.ctx));
+
+        TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
+
+        for (Decl *origin_child_decl : origin_tag_decl->decls())
+        {
+            minion_sp->Import(origin_child_decl);
+        }
+
+        if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
+        {
+            record_decl->setHasLoadedFieldsFromExternalStorage(true);
+        }
+
+        return true;
+    }
+
+    if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>())
+    {
+        if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface())
+        {
+            DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
+
+            if (!decl_origin.Valid())
+                return false;
+
+            MinionSP minion_sp (GetMinion(&objc_interface_decl->getASTContext(), decl_origin.ctx));
+
+            ObjCInterfaceDecl *origin_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
+
+            for (Decl *origin_child_decl : origin_interface_decl->decls())
+            {
+                minion_sp->Import(origin_child_decl);
+            }
+
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+
+bool
 ClangASTImporter::RequireCompleteType (clang::QualType type)
 {
     if (type.isNull())

Modified: lldb/trunk/source/Symbol/ClangExternalASTSourceCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangExternalASTSourceCallbacks.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangExternalASTSourceCallbacks.cpp (original)
+++ lldb/trunk/source/Symbol/ClangExternalASTSourceCallbacks.cpp Tue Dec  1 18:43:32 2015
@@ -41,6 +41,7 @@
 #endif
 
 #include "lldb/Core/Log.h"
+#include "clang/AST/Decl.h"
 
 using namespace clang;
 using namespace lldb_private;
@@ -160,3 +161,16 @@ ClangExternalASTSourceCallbacks::layoutR
     return false;
 }
 
+void
+ClangExternalASTSourceCallbacks::FindExternalLexicalDecls (const clang::DeclContext *decl_ctx,
+                                                           llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+                                                           llvm::SmallVectorImpl<clang::Decl *> &decls)
+{
+    if (m_callback_tag_decl && decl_ctx)
+    {
+        clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(const_cast<clang::DeclContext *>(decl_ctx));
+        if (tag_decl)
+            CompleteType(tag_decl);
+    }
+}
+

Modified: lldb/trunk/source/Symbol/SymbolFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolFile.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolFile.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolFile.cpp Tue Dec  1 18:43:32 2015
@@ -142,3 +142,11 @@ SymbolFile::FindTypes (const SymbolConte
     return 0;
 }
 
+
+size_t
+SymbolFile::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
+{
+    if (!append)
+        types.Clear();
+    return 0;
+}

Modified: lldb/trunk/source/Symbol/SymbolVendor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolVendor.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolVendor.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolVendor.cpp Tue Dec  1 18:43:32 2015
@@ -361,6 +361,21 @@ SymbolVendor::FindTypes (const SymbolCon
 }
 
 size_t
+SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
+{
+    ModuleSP module_sp(GetModule());
+    if (module_sp)
+    {
+        lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+        if (m_sym_file_ap.get())
+            return m_sym_file_ap->FindTypes(context, append, types);
+    }
+    if (!append)
+        types.Clear();
+    return 0;
+}
+
+size_t
 SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
                         uint32_t type_mask,
                         lldb_private::TypeList &type_list)

Modified: lldb/trunk/source/Symbol/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Type.cpp?rev=254476&r1=254475&r2=254476&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Type.cpp (original)
+++ lldb/trunk/source/Symbol/Type.cpp Tue Dec  1 18:43:32 2015
@@ -7,8 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-// Other libraries and framework includes
+// C Includes
+#include <stdio.h>
 
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Module.h"
@@ -36,6 +40,27 @@
 using namespace lldb;
 using namespace lldb_private;
 
+void
+CompilerContext::Dump() const
+{
+    switch (type)
+    {
+        case CompilerContextKind::Invalid:          printf("Invalid"); break;
+        case CompilerContextKind::TranslationUnit:  printf("TranslationUnit"); break;
+        case CompilerContextKind::Module:           printf("Module"); break;
+        case CompilerContextKind::Namespace:        printf("Namespace"); break;
+        case CompilerContextKind::Class:            printf("Class"); break;
+        case CompilerContextKind::Structure:        printf("Structure"); break;
+        case CompilerContextKind::Union:            printf("Union"); break;
+        case CompilerContextKind::Function:         printf("Function"); break;
+        case CompilerContextKind::Variable:         printf("Variable"); break;
+        case CompilerContextKind::Enumeration:      printf("Enumeration"); break;
+        case CompilerContextKind::Typedef:          printf("Typedef"); break;
+        default: printf("???(%u)", type);
+    }
+    printf("(\"%s\")\n", name.GetCString());
+}
+
 class TypeAppendVisitor
 {
 public:
@@ -62,6 +87,13 @@ TypeListImpl::Append (const lldb_private
     type_list.ForEach(cb);
 }
 
+SymbolFileType::SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp) :
+    UserID (type_sp ? type_sp->GetID() : LLDB_INVALID_UID),
+    m_symbol_file (symbol_file),
+    m_type_sp (type_sp)
+{
+}
+
 
 Type *
 SymbolFileType::GetType ()




More information about the lldb-commits mailing list