//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//


#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Expression/ASTDumper.h"
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"

using namespace clang;
using namespace lldb_private;

ClangASTSource::~ClangASTSource()
{
    m_ast_importer->ForgetDestination(m_ast_context);

    // We are in the process of destruction, don't create clang ast context on demand
    // by passing false to Target::GetScratchClangASTContext(create_on_demand).
    ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false);

    if (!scratch_clang_ast_context)
        return;

    clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();

    if (!scratch_ast_context)
        return;

    if (m_ast_context != scratch_ast_context)
        m_ast_importer->ForgetSource(scratch_ast_context, m_ast_context);
}

void
ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
{
    if (!m_ast_context)
        return;

    m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage();
    m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage();
}

// The core lookup interface.
bool
ClangASTSource::FindExternalVisibleDeclsByName
(
    const DeclContext *decl_ctx,
    DeclarationName clang_decl_name
)
{
    if (!m_ast_context)
    {
        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
        return false;
    }

    if (GetImportInProgress())
    {
        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
        return false;
    }

    std::string decl_name (clang_decl_name.getAsString());

//    if (m_decl_map.DoingASTImport ())
//      return DeclContext::lookup_result();
//
    switch (clang_decl_name.getNameKind()) {
    // Normal identifiers.
    case DeclarationName::Identifier:
        {
            clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo();

            if (!identifier_info ||
                identifier_info->getBuiltinID() != 0)
            {
                SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
                return false;
            }
        }
        break;

    // Operator names.  Not important for now.
    case DeclarationName::CXXOperatorName:
    case DeclarationName::CXXLiteralOperatorName:
      SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
      return false;

    // Using directives found in this context.
    // Tell Sema we didn't find any or we'll end up getting asked a *lot*.
    case DeclarationName::CXXUsingDirective:
      SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
      return false;

    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
    {
      llvm::SmallVector<NamedDecl*, 1> method_decls;

      NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx);

      FindObjCMethodDecls(method_search_context);

      SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls);
      return (method_decls.size() > 0);
    }
    // These aren't possible in the global context.
    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
      SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
      return false;
    }


    if (!GetLookupsEnabled())
    {
        // Wait until we see a '$' at the start of a name before we start doing
        // any lookups so we can avoid lookup up all of the builtin types.
        if (!decl_name.empty() && decl_name[0] == '$')
        {
            SetLookupsEnabled (true);
        }
        else
        {
            SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
            return false;
        }
    }

    ConstString const_decl_name(decl_name.c_str());

    const char *uniqued_const_decl_name = const_decl_name.GetCString();
    if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end())
    {
        // We are currently looking up this name...
        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
        return false;
    }
    m_active_lookups.insert(uniqued_const_decl_name);
//  static uint32_t g_depth = 0;
//  ++g_depth;
//  printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name);
    llvm::SmallVector<NamedDecl*, 4> name_decls;
    NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx);
    FindExternalVisibleDecls(name_search_context);
    SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls);
//  --g_depth;
    m_active_lookups.erase (uniqued_const_decl_name);
    return (name_decls.size() != 0);
}

void
ClangASTSource::CompleteType (TagDecl *tag_decl)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    if (log)
    {
        log->Printf("    CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
                    current_id, static_cast<void*>(m_ast_context),
                    static_cast<void*>(tag_decl),
                    tag_decl->getName().str().c_str());

        log->Printf("      CTD[%u] Before:", current_id);
        ASTDumper dumper((Decl*)tag_decl);
        dumper.ToLog(log, "      [CTD] ");
    }

    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, static_cast<void*>(namespace_map.get()),
                            static_cast<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->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types);

                for (uint32_t ti = 0, te = types.GetSize();
                     ti != te && !found;
                     ++ti)
                {
                    lldb::TypeSP type = types.GetTypeAtIndex(ti);

                    if (!type)
                        continue;

                    ClangASTType clang_type (type->GetClangFullType());

                    if (!clang_type)
                        continue;

                    const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();

                    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;

            const ModuleList &module_list = m_target->GetImages();

            bool exact_match = false;
            module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types);

            for (uint32_t ti = 0, te = types.GetSize();
                 ti != te && !found;
                 ++ti)
            {
                lldb::TypeSP type = types.GetTypeAtIndex(ti);

                if (!type)
                    continue;

                ClangASTType clang_type (type->GetClangFullType());

                if (!clang_type)
                    continue;

                const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();

                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)
    {
        log->Printf("      [CTD] After:");
        ASTDumper dumper((Decl*)tag_decl);
        dumper.ToLog(log, "      [CTD] ");
    }
}

void
ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
    {
        log->Printf("    [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s",
                    static_cast<void*>(m_ast_context),
                    interface_decl->getName().str().c_str());
        log->Printf("      [COID] Before:");
        ASTDumper dumper((Decl*)interface_decl);
        dumper.ToLog(log, "      [COID] ");
    }

    Decl *original_decl = NULL;
    ASTContext *original_ctx = NULL;

    if (m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
    {
        if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
        {
            ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);

            if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
            {
                m_ast_importer->SetDeclOrigin(interface_decl, original_iface_decl);
            }
        }
    }

    m_ast_importer->CompleteObjCInterfaceDecl (interface_decl);

    if (interface_decl->getSuperClass() &&
        interface_decl->getSuperClass() != interface_decl)
        CompleteType(interface_decl->getSuperClass());

    if (log)
    {
        log->Printf("      [COID] After:");
        ASTDumper dumper((Decl*)interface_decl);
        dumper.ToLog(log, "      [COID] ");
    }
}

clang::ObjCInterfaceDecl *
ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl)
{
    lldb::ProcessSP process(m_target->GetProcessSP());

    if (!process)
        return NULL;

    ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());

    if (!language_runtime)
        return NULL;

    ConstString class_name(interface_decl->getNameAsString().c_str());

    lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));

    if (!complete_type_sp)
        return NULL;

    TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType());
    lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();

    if (!complete_opaque_type)
        return NULL;

    const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
    const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);

    if (!complete_interface_type)
        return NULL;

    ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl());

    return complete_iface_decl;
}

clang::ExternalLoadResult
ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
                                          bool (*predicate)(Decl::Kind),
                                          llvm::SmallVectorImpl<Decl*> &decls)
{
    ClangASTMetrics::RegisterLexicalQuery();

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    const Decl *context_decl = dyn_cast<Decl>(decl_context);

    if (!context_decl)
        return ELR_Failure;

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    if (log)
    {
        if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate",
                        current_id, static_cast<void*>(m_ast_context),
                        context_named_decl->getNameAsString().c_str(),
                        context_decl->getDeclKindName(),
                        static_cast<const void*>(context_decl),
                        (predicate ? "non-null" : "null"));
        else if(context_decl)
            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate",
                        current_id, static_cast<void*>(m_ast_context),
                        context_decl->getDeclKindName(),
                        static_cast<const void*>(context_decl),
                        (predicate ? "non-null" : "null"));
        else
            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate",
                        current_id, static_cast<const void*>(m_ast_context),
                        (predicate ? "non-null" : "null"));
    }

    Decl *original_decl = NULL;
    ASTContext *original_ctx = NULL;

    if (!m_ast_importer->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
        return ELR_Failure;

    if (log)
    {
        log->Printf("  FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:",
                    current_id, static_cast<void*>(original_ctx),
                    static_cast<void*>(original_decl));
        ASTDumper(original_decl).ToLog(log, "    ");
    }

    if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
    {
        ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);

        if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
        {
            original_decl = complete_iface_decl;
            original_ctx = &complete_iface_decl->getASTContext();

            m_ast_importer->SetDeclOrigin(context_decl, original_iface_decl);
        }
    }

    if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
    {
        ExternalASTSource *external_source = original_ctx->getExternalSource();

        if (external_source)
            external_source->CompleteType (original_tag_decl);
    }

    const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);

    if (!original_decl_context)
        return ELR_Failure;

    for (TagDecl::decl_iterator iter = original_decl_context->decls_begin();
         iter != original_decl_context->decls_end();
         ++iter)
    {
        Decl *decl = *iter;

        if (!predicate || predicate(decl->getKind()))
        {
            if (log)
            {
                ASTDumper ast_dumper(decl);
                if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
                    log->Printf("  FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString());
                else
                    log->Printf("  FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
            }

            Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);

            if (!copied_decl)
                continue;

            if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl))
            {
                QualType copied_field_type = copied_field->getType();

                m_ast_importer->RequireCompleteType(copied_field_type);
            }

            decls.push_back(copied_decl);

            DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context);

            if (copied_decl->getDeclContext() != decl_context)
            {
                if (copied_decl->getDeclContext()->containsDecl(copied_decl))
                    copied_decl->getDeclContext()->removeDecl(copied_decl);
                copied_decl->setDeclContext(decl_context_non_const);
            }

            if (!decl_context_non_const->containsDecl(copied_decl))
                decl_context_non_const->addDeclInternal(copied_decl);
        }
    }

    return ELR_AlreadyLoaded;
}

void
ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
{
    assert (m_ast_context);

    ClangASTMetrics::RegisterVisibleQuery();

    const ConstString name(context.m_decl_name.getAsString().c_str());

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    if (log)
    {
        if (!context.m_decl_context)
            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext",
                        current_id, static_cast<void*>(m_ast_context),
                        name.GetCString());
        else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'",
                        current_id, static_cast<void*>(m_ast_context),
                        name.GetCString(),
                        context_named_decl->getNameAsString().c_str());
        else
            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'",
                        current_id, static_cast<void*>(m_ast_context),
                        name.GetCString(),
                        context.m_decl_context->getDeclKindName());
    }

    context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap);

    if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
    {
        ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);

        if (log && log->GetVerbose())
            log->Printf("  CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
                        current_id, static_cast<void*>(namespace_map.get()),
                        static_cast<int>(namespace_map->size()));

        if (!namespace_map)
            return;

        for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
             i != e;
             ++i)
        {
            if (log)
                log->Printf("  CAS::FEVD[%u] Searching namespace %s in module %s",
                            current_id,
                            i->second.GetNamespaceDecl()->getNameAsString().c_str(),
                            i->first->GetFileSpec().GetFilename().GetCString());

            FindExternalVisibleDecls(context,
                                     i->first,
                                     i->second,
                                     current_id);
        }
    }
    else if (isa<ObjCInterfaceDecl>(context.m_decl_context))
    {
        FindObjCPropertyAndIvarDecls(context);
    }
    else if (!isa<TranslationUnitDecl>(context.m_decl_context))
    {
        // we shouldn't be getting FindExternalVisibleDecls calls for these
        return;
    }
    else
    {
        ClangNamespaceDecl namespace_decl;

        if (log)
            log->Printf("  CAS::FEVD[%u] Searching the root namespace", current_id);

        FindExternalVisibleDecls(context,
                                 lldb::ModuleSP(),
                                 namespace_decl,
                                 current_id);
    }

    if (!context.m_namespace_map->empty())
    {
        if (log && log->GetVerbose())
            log->Printf("  CAS::FEVD[%u] Registering namespace map %p (%d entries)",
                        current_id,
                        static_cast<void*>(context.m_namespace_map.get()),
                        static_cast<int>(context.m_namespace_map->size()));

        NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map);

        if (clang_namespace_decl)
            clang_namespace_decl->setHasExternalVisibleStorage();
    }
}

void
ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
                                          lldb::ModuleSP module_sp,
                                          ClangNamespaceDecl &namespace_decl,
                                          unsigned int current_id)
{
    assert (m_ast_context);

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    SymbolContextList sc_list;

    const ConstString name(context.m_decl_name.getAsString().c_str());

    const char *name_unique_cstr = name.GetCString();

    static ConstString id_name("id");
    static ConstString Class_name("Class");

    if (name == id_name || name == Class_name)
        return;

    if (name_unique_cstr == NULL)
        return;

    // The ClangASTSource is not responsible for finding $-names.
    if (name_unique_cstr[0] == '$')
        return;

    if (module_sp && namespace_decl)
    {
        ClangNamespaceDecl found_namespace_decl;

        SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();

        if (symbol_vendor)
        {
            SymbolContext null_sc;

            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);

            if (found_namespace_decl)
            {
                context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));

                if (log)
                    log->Printf("  CAS::FEVD[%u] Found namespace %s in module %s",
                                current_id,
                                name.GetCString(),
                                module_sp->GetFileSpec().GetFilename().GetCString());
            }
        }
    }
    else
    {
        const ModuleList &target_images = m_target->GetImages();
        Mutex::Locker modules_locker (target_images.GetMutex());

        for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
        {
            lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);

            if (!image)
                continue;

            ClangNamespaceDecl found_namespace_decl;

            SymbolVendor *symbol_vendor = image->GetSymbolVendor();

            if (!symbol_vendor)
                continue;

            SymbolContext null_sc;

            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);

            if (found_namespace_decl)
            {
                context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));

                if (log)
                    log->Printf("  CAS::FEVD[%u] Found namespace %s in module %s",
                                current_id,
                                name.GetCString(),
                                image->GetFileSpec().GetFilename().GetCString());
            }
        }
    }

    do
    {
        TypeList types;
        SymbolContext null_sc;
        const bool exact_match = false;

        if (module_sp && namespace_decl)
            module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
        else
            m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types);

        if (types.GetSize())
        {
            lldb::TypeSP type_sp = types.GetTypeAtIndex(0);

            if (log)
            {
                const char *name_string = type_sp->GetName().GetCString();

                log->Printf("  CAS::FEVD[%u] Matching type found for \"%s\": %s",
                            current_id,
                            name.GetCString(),
                            (name_string ? name_string : "<anonymous>"));
            }

            ClangASTType full_type = type_sp->GetClangFullType();

            ClangASTType copied_clang_type (GuardedCopyType(full_type));

            if (!copied_clang_type)
            {
                if (log)
                    log->Printf("  CAS::FEVD[%u] - Couldn't export a type",
                                current_id);

                break;
            }

            context.AddTypeDecl(copied_clang_type);
        }
        else
        {
            do
            {
                // Couldn't find any types elsewhere.  Try the Objective-C runtime if one exists.

                lldb::ProcessSP process(m_target->GetProcessSP());

                if (!process)
                    break;

                ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());

                if (!language_runtime)
                    break;

                TypeVendor *type_vendor = language_runtime->GetTypeVendor();

                if (!type_vendor)
                    break;

                bool append = false;
                uint32_t max_matches = 1;
                std::vector <ClangASTType> types;

                if (!type_vendor->FindTypes(name,
                                            append,
                                            max_matches,
                                            types))
                    break;

                if (log)
                {
                    log->Printf("  CAS::FEVD[%u] Matching type found for \"%s\" in the runtime",
                                current_id,
                                name.GetCString());
                }

                ClangASTType copied_clang_type (GuardedCopyType(types[0]));

                if (!copied_clang_type)
                {
                    if (log)
                        log->Printf("  CAS::FEVD[%u] - Couldn't export a type from the runtime",
                                    current_id);

                    break;
                }

                context.AddTypeDecl(copied_clang_type);
            }
            while(0);
        }

    } while(0);
}

template <class D> class TaggedASTDecl {
public:
    TaggedASTDecl() : decl(NULL) { }
    TaggedASTDecl(D *_decl) : decl(_decl) { }
    bool IsValid() const { return (decl != NULL); }
    bool IsInvalid() const { return !IsValid(); }
    D *operator->() const { return decl; }
    D *decl;
};

template <class D2, template <class D> class TD, class D1>
TD<D2>
DynCast(TD<D1> source)
{
    return TD<D2> (dyn_cast<D2>(source.decl));
}

template <class D = Decl> class DeclFromParser;
template <class D = Decl> class DeclFromUser;

template <class D> class DeclFromParser : public TaggedASTDecl<D> {
public:
    DeclFromParser() : TaggedASTDecl<D>() { }
    DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }

    DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
};

template <class D> class DeclFromUser : public TaggedASTDecl<D> {
public:
    DeclFromUser() : TaggedASTDecl<D>() { }
    DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }

    DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
};

template <class D>
DeclFromUser<D>
DeclFromParser<D>::GetOrigin(ClangASTImporter *importer)
{
    DeclFromUser <> origin_decl;
    importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL);
    if (origin_decl.IsInvalid())
        return DeclFromUser<D>();
    return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
}

template <class D>
DeclFromParser<D>
DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx)
{
    DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl));
    if (parser_generic_decl.IsInvalid())
        return DeclFromParser<D>();
    return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
}

static bool
FindObjCMethodDeclsWithOrigin (unsigned int current_id,
                               NameSearchContext &context,
                               ObjCInterfaceDecl *original_interface_decl,
                               clang::ASTContext *ast_context,
                               ClangASTImporter *ast_importer,
                               const char *log_info)
{
    const DeclarationName &decl_name(context.m_decl_name);
    clang::ASTContext *original_ctx = &original_interface_decl->getASTContext();

    Selector original_selector;

    if (decl_name.isObjCZeroArgSelector())
    {
        IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
        original_selector = original_ctx->Selectors.getSelector(0, &ident);
    }
    else if (decl_name.isObjCOneArgSelector())
    {
        const std::string &decl_name_string = decl_name.getAsString();
        std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1);
        IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str());
        original_selector = original_ctx->Selectors.getSelector(1, &ident);
    }
    else
    {
        SmallVector<IdentifierInfo *, 4> idents;

        clang::Selector sel = decl_name.getObjCSelector();

        unsigned num_args = sel.getNumArgs();

        for (unsigned i = 0;
             i != num_args;
             ++i)
        {
            idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
        }

        original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
    }

    DeclarationName original_decl_name(original_selector);

    ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name);

    if (result.empty())
        return false;

    if (!result[0])
        return false;

    for (NamedDecl *named_decl : result)
    {
        ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl);

        if (!result_method)
            return false;

        Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);

        if (!copied_decl)
            return false;

        ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);

        if (!copied_method_decl)
            return false;

        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        if (log)
        {
            ASTDumper dumper((Decl*)copied_method_decl);
            log->Printf("  CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
        }

        context.AddNamedDecl(copied_method_decl);
    }

    return true;
}

void
ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    const DeclarationName &decl_name(context.m_decl_name);
    const DeclContext *decl_ctx(context.m_decl_context);

    const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx);

    if (!interface_decl)
        return;

    do
    {
        Decl *original_decl = NULL;
        ASTContext *original_ctx = NULL;

        m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);

        if (!original_decl)
            break;

        ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl);

        if (FindObjCMethodDeclsWithOrigin(current_id,
                                          context,
                                          original_interface_decl,
                                          m_ast_context,
                                          m_ast_importer,
                                          "at origin"))
            return; // found it, no need to look any further
    } while (0);

    StreamString ss;

    if (decl_name.isObjCZeroArgSelector())
    {
        ss.Printf("%s", decl_name.getAsString().c_str());
    }
    else if (decl_name.isObjCOneArgSelector())
    {
        ss.Printf("%s", decl_name.getAsString().c_str());
    }
    else
    {
        clang::Selector sel = decl_name.getObjCSelector();

        for (unsigned i = 0, e = sel.getNumArgs();
             i != e;
             ++i)
        {
            llvm::StringRef r = sel.getNameForSlot(i);
            ss.Printf("%s:", r.str().c_str());
        }
    }
    ss.Flush();

    if (strstr(ss.GetData(), "$__lldb"))
        return; // we don't need any results

    ConstString selector_name(ss.GetData());

    if (log)
        log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]",
                    current_id, static_cast<void*>(m_ast_context),
                    interface_decl->getNameAsString().c_str(),
                    selector_name.AsCString());
    SymbolContextList sc_list;

    const bool include_symbols = false;
    const bool include_inlines = false;
    const bool append = false;

    std::string interface_name = interface_decl->getNameAsString();

    do
    {
        StreamString ms;
        ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString());
        ms.Flush();
        ConstString instance_method_name(ms.GetData());

        m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);

        if (sc_list.GetSize())
            break;

        ms.Clear();
        ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString());
        ms.Flush();
        ConstString class_method_name(ms.GetData());

        m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);

        if (sc_list.GetSize())
            break;

        // Fall back and check for methods in categories.  If we find methods this way, we need to check that they're actually in
        // categories on the desired class.

        SymbolContextList candidate_sc_list;

        m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list);

        for (uint32_t ci = 0, ce = candidate_sc_list.GetSize();
             ci != ce;
             ++ci)
        {
            SymbolContext candidate_sc;

            if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc))
                continue;

            if (!candidate_sc.function)
                continue;

            const char *candidate_name = candidate_sc.function->GetName().AsCString();

            const char *cursor = candidate_name;

            if (*cursor != '+' && *cursor != '-')
                continue;

            ++cursor;

            if (*cursor != '[')
                continue;

            ++cursor;

            size_t interface_len = interface_name.length();

            if (strncmp(cursor, interface_name.c_str(), interface_len))
                continue;

            cursor += interface_len;

            if (*cursor == ' ' || *cursor == '(')
                sc_list.Append(candidate_sc);
        }
    }
    while (0);

    if (sc_list.GetSize())
    {
        // We found a good function symbol.  Use that.

        for (uint32_t i = 0, e = sc_list.GetSize();
             i != e;
             ++i)
        {
            SymbolContext sc;

            if (!sc_list.GetContextAtIndex(i, sc))
                continue;

            if (!sc.function)
                continue;

            DeclContext *function_ctx = sc.function->GetClangDeclContext();

            if (!function_ctx)
                continue;

            ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);

            if (!method_decl)
                continue;

            ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();

            if (!found_interface_decl)
                continue;

            if (found_interface_decl->getName() == interface_decl->getName())
            {
                Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);

                if (!copied_decl)
                    continue;

                ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);

                if (!copied_method_decl)
                    continue;

                if (log)
                {
                    ASTDumper dumper((Decl*)copied_method_decl);
                    log->Printf("  CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString());
                }

                context.AddNamedDecl(copied_method_decl);
            }
        }

        return;
    }

    // Try the debug information.

    do
    {
        ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl));

        if (!complete_interface_decl)
            break;

        // We found the complete interface.  The runtime never needs to be queried in this scenario.

        DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);

        if (complete_interface_decl == interface_decl)
            break; // already checked this one

        if (log)
            log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
                        current_id, static_cast<void*>(complete_interface_decl),
                        static_cast<void*>(&complete_iface_decl->getASTContext()));

        FindObjCMethodDeclsWithOrigin(current_id,
                                      context,
                                      complete_interface_decl,
                                      m_ast_context,
                                      m_ast_importer,
                                      "in debug info");

        return;
    }
    while (0);

    do
    {
        // Check the runtime only if the debug information didn't have a complete interface.

        lldb::ProcessSP process(m_target->GetProcessSP());

        if (!process)
            break;

        ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());

        if (!language_runtime)
            break;

        TypeVendor *type_vendor = language_runtime->GetTypeVendor();

        if (!type_vendor)
            break;

        ConstString interface_name(interface_decl->getNameAsString().c_str());
        bool append = false;
        uint32_t max_matches = 1;
        std::vector <ClangASTType> types;

        if (!type_vendor->FindTypes(interface_name,
                                    append,
                                    max_matches,
                                    types))
            break;

        const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();

        const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);

        if (!runtime_interface_type)
            break;

        ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl();

        FindObjCMethodDeclsWithOrigin(current_id,
                                      context,
                                      runtime_interface_decl,
                                      m_ast_context,
                                      m_ast_importer,
                                      "in runtime");
    }
    while(0);
}

static bool
FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
                                        NameSearchContext &context,
                                        clang::ASTContext &ast_context,
                                        ClangASTImporter *ast_importer,
                                        DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (origin_iface_decl.IsInvalid())
        return false;

    std::string name_str = context.m_decl_name.getAsString();
    StringRef name(name_str.c_str());
    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));

    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));

    bool found = false;

    if (origin_property_decl.IsValid())
    {
        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context));
        if (parser_property_decl.IsValid())
        {
            if (log)
            {
                ASTDumper dumper((Decl*)parser_property_decl.decl);
                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
            }

            context.AddNamedDecl(parser_property_decl.decl);
            found = true;
        }
    }

    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));

    if (origin_ivar_decl.IsValid())
    {
        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context));
        if (parser_ivar_decl.IsValid())
        {
            if (log)
            {
                ASTDumper dumper((Decl*)parser_ivar_decl.decl);
                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
            }

            context.AddNamedDecl(parser_ivar_decl.decl);
            found = true;
        }
    }

    return found;
}

void
ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
    DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));

    ConstString class_name(parser_iface_decl->getNameAsString().c_str());

    if (log)
        log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
                    current_id, static_cast<void*>(m_ast_context),
                    parser_iface_decl->getNameAsString().c_str(),
                    context.m_decl_name.getAsString().c_str());

    if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
                                               context,
                                               *m_ast_context,
                                               m_ast_importer,
                                               origin_iface_decl))
        return;

    if (log)
        log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...",
                    current_id, static_cast<const void*>(origin_iface_decl.decl),
                    static_cast<void*>(&origin_iface_decl->getASTContext()));

    SymbolContext null_sc;
    TypeList type_list;

    do
    {
        ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl));

        if (!complete_interface_decl)
            break;

        // We found the complete interface.  The runtime never needs to be queried in this scenario.

        DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);

        if (complete_iface_decl.decl == origin_iface_decl.decl)
            break; // already checked this one

        if (log)
            log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
                        current_id,
                        static_cast<const void*>(complete_iface_decl.decl),
                        static_cast<void*>(&complete_iface_decl->getASTContext()));

        FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
                                               context,
                                               *m_ast_context,
                                               m_ast_importer,
                                               complete_iface_decl);

        return;
    }
    while(0);

    do
    {
        // Check the runtime only if the debug information didn't have a complete interface.

        lldb::ProcessSP process(m_target->GetProcessSP());

        if (!process)
            return;

        ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());

        if (!language_runtime)
            return;

        TypeVendor *type_vendor = language_runtime->GetTypeVendor();

        if (!type_vendor)
            break;

        bool append = false;
        uint32_t max_matches = 1;
        std::vector <ClangASTType> types;

        if (!type_vendor->FindTypes(class_name,
                                    append,
                                    max_matches,
                                    types))
            break;

        const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();

        const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);

        if (!runtime_interface_type)
            break;

        DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(runtime_interface_type->getDecl());

        if (log)
            log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
                        current_id,
                        static_cast<const void*>(runtime_iface_decl.decl),
                        static_cast<void*>(&runtime_iface_decl->getASTContext()));

        if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
                                                   context,
                                                   *m_ast_context,
                                                   m_ast_importer,
                                                   runtime_iface_decl))
            return;
    }
    while(0);
}

typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap;
typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap;

template <class D, class O>
static bool
ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map,
                 llvm::DenseMap <const D*, O> &source_map,
                 ClangASTImporter *importer,
                 ASTContext &dest_ctx)
{
    typedef llvm::DenseMap <const D*, O> MapType;

    for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end();
         fi != fe;
         ++fi)
    {
        DeclFromUser <D> user_decl(const_cast<D*>(fi->first));
        DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx));
        if (parser_decl.IsInvalid())
            return false;
        destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second));
    }

    return true;
}

template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record_layout,
                                                   DeclFromUser<const CXXRecordDecl> &record,
                                                   BaseOffsetMap &base_offsets)
{
    for (CXXRecordDecl::base_class_const_iterator
            bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
            be = (IsVirtual ? record->vbases_end() : record->bases_end());
         bi != be;
         ++bi)
    {
        if (!IsVirtual && bi->isVirtual())
            continue;

        const clang::Type *origin_base_type = bi->getType().getTypePtr();
        const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();

        if (!origin_base_record_type)
            return false;

        DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());

        if (origin_base_record.IsInvalid())
            return false;

        DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));

        if (origin_base_cxx_record.IsInvalid())
            return false;

        CharUnits base_offset;

        if (IsVirtual)
            base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
        else
            base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);

        base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
    }

    return true;
}

bool
ClangASTSource::layoutRecordType(const RecordDecl *record,
                                 uint64_t &size,
                                 uint64_t &alignment,
                                 FieldOffsetMap &field_offsets,
                                 BaseOffsetMap &base_offsets,
                                 BaseOffsetMap &virtual_base_offsets)
{
    ClangASTMetrics::RegisterRecordLayout();

    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
        log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']",
                    current_id, static_cast<void*>(m_ast_context),
                    static_cast<const void*>(record),
                    record->getNameAsString().c_str());

    DeclFromParser <const RecordDecl> parser_record(record);
    DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));

    if (origin_record.IsInvalid())
        return false;

    FieldOffsetMap origin_field_offsets;
    BaseOffsetMap origin_base_offsets;
    BaseOffsetMap origin_virtual_base_offsets;

    ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl));

    if (!origin_record.decl->getDefinition())
        return false;

    const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));

    int field_idx = 0, field_count = record_layout.getFieldCount();

    for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end();
         fi != fe;
         ++fi)
    {
        if (field_idx >= field_count)
            return false; // Layout didn't go well.  Bail out.

        uint64_t field_offset = record_layout.getFieldOffset(field_idx);

        origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));

        field_idx++;
    }

    ASTContext &parser_ast_context(record->getASTContext());

    DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));

    if (origin_cxx_record.IsValid())
    {
        if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) ||
            !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets))
            return false;
    }

    if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) ||
        !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
        !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
        return false;

    size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
    alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();

    if (log)
    {
        log->Printf("LRT[%u] returned:", current_id);
        log->Printf("LRT[%u]   Original = (RecordDecl*)%p", current_id,
                    static_cast<const void*>(origin_record.decl));
        log->Printf("LRT[%u]   Size = %" PRId64, current_id, size);
        log->Printf("LRT[%u]   Alignment = %" PRId64, current_id, alignment);
        log->Printf("LRT[%u]   Fields:", current_id);
        for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end();
             fi != fe;
             ++fi)
        {
            log->Printf("LRT[%u]     (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits",
                        current_id, static_cast<void*>(*fi),
                        fi->getNameAsString().c_str(), field_offsets[*fi]);
        }
        DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
        if (parser_cxx_record.IsValid())
        {
            log->Printf("LRT[%u]   Bases:", current_id);
            for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end();
                 bi != be;
                 ++bi)
            {
                bool is_virtual = bi->isVirtual();

                QualType base_type = bi->getType();
                const RecordType *base_record_type = base_type->getAs<RecordType>();
                DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
                DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);

                log->Printf("LRT[%u]     %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars",
                            current_id, (is_virtual ? "Virtual " : ""),
                            static_cast<void*>(base_cxx_record.decl),
                            base_cxx_record.decl->getNameAsString().c_str(),
                            (is_virtual
                                ? virtual_base_offsets[base_cxx_record.decl].getQuantity()
                                : base_offsets[base_cxx_record.decl].getQuantity()));
            }
        }
        else
        {
            log->Printf("LRD[%u]   Not a CXXRecord, so no bases", current_id);
        }
    }

    return true;
}

void
ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map,
                                      const ConstString &name,
                                      ClangASTImporter::NamespaceMapSP &parent_map) const
{
    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
    {
        if (parent_map && parent_map->size())
            log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
                        current_id, static_cast<void*>(m_ast_context),
                        name.GetCString(),
                        parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str());
        else
            log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
                        current_id, static_cast<void*>(m_ast_context),
                        name.GetCString());
    }

    if (parent_map)
    {
        for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end();
             i != e;
             ++i)
        {
            ClangNamespaceDecl found_namespace_decl;

            lldb::ModuleSP module_sp = i->first;
            ClangNamespaceDecl module_parent_namespace_decl = i->second;

            SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();

            if (!symbol_vendor)
                continue;

            SymbolContext null_sc;

            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl);

            if (!found_namespace_decl)
                continue;

            namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));

            if (log)
                log->Printf("  CMN[%u] Found namespace %s in module %s",
                            current_id,
                            name.GetCString(),
                            module_sp->GetFileSpec().GetFilename().GetCString());
        }
    }
    else
    {
        const ModuleList &target_images = m_target->GetImages();
        Mutex::Locker modules_locker(target_images.GetMutex());

        ClangNamespaceDecl null_namespace_decl;

        for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
        {
            lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);

            if (!image)
                continue;

            ClangNamespaceDecl found_namespace_decl;

            SymbolVendor *symbol_vendor = image->GetSymbolVendor();

            if (!symbol_vendor)
                continue;

            SymbolContext null_sc;

            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl);

            if (!found_namespace_decl)
                continue;

            namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));

            if (log)
                log->Printf("  CMN[%u] Found namespace %s in module %s",
                            current_id,
                            name.GetCString(),
                            image->GetFileSpec().GetFilename().GetCString());
        }
    }
}

NamespaceDecl *
ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls)
{
    if (!namespace_decls)
        return NULL;

    const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second;

    Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());

    if (!copied_decl)
        return NULL;

    NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);

    if (!copied_namespace_decl)
        return NULL;

    context.m_decls.push_back(copied_namespace_decl);

    m_ast_importer->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);

    return dyn_cast<NamespaceDecl>(copied_decl);
}

ClangASTType
ClangASTSource::GuardedCopyType (const ClangASTType &src_type)
{
    ClangASTMetrics::RegisterLLDBImport();

    SetImportInProgress(true);

    QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType());

    SetImportInProgress(false);

    if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull())
        // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types
        // on occasion.
        return ClangASTType();

    return ClangASTType(m_ast_context, copied_qual_type);
}

clang::NamedDecl *
NameSearchContext::AddVarDecl(const ClangASTType &type)
{
    assert (type && "Type for variable must be valid!");

    if (!type.IsValid())
        return NULL;

    IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();

    clang::ASTContext *ast = type.GetASTContext();

    clang::NamedDecl *Decl = VarDecl::Create(*ast,
                                             const_cast<DeclContext*>(m_decl_context),
                                             SourceLocation(),
                                             SourceLocation(),
                                             ii,
                                             type.GetQualType(),
                                             0,
                                             SC_Static);
    m_decls.push_back(Decl);

    return Decl;
}

clang::NamedDecl *
NameSearchContext::AddFunDecl (const ClangASTType &type)
{
    assert (type && "Type for variable must be valid!");

    if (!type.IsValid())
        return NULL;

    if (m_function_types.count(type))
        return NULL;

    m_function_types.insert(type);

    QualType qual_type (type.GetQualType());

    clang::ASTContext *ast = type.GetASTContext();

    const bool isInlineSpecified = false;
    const bool hasWrittenPrototype = true;
    const bool isConstexprSpecified = false;

    clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast,
                                                           const_cast<DeclContext*>(m_decl_context),
                                                           SourceLocation(),
                                                           SourceLocation(),
                                                           m_decl_name.getAsIdentifierInfo(),
                                                           qual_type,
                                                           NULL,
                                                           SC_Static,
                                                           isInlineSpecified,
                                                           hasWrittenPrototype,
                                                           isConstexprSpecified);

    // We have to do more than just synthesize the FunctionDecl.  We have to
    // synthesize ParmVarDecls for all of the FunctionDecl's arguments.  To do
    // this, we raid the function's FunctionProtoType for types.

    const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>();

    if (func_proto_type)
    {
        unsigned NumArgs = func_proto_type->getNumParams();
        unsigned ArgIndex;

        SmallVector<ParmVarDecl *, 5> parm_var_decls;

        for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex)
        {
            QualType arg_qual_type (func_proto_type->getParamType(ArgIndex));

            parm_var_decls.push_back(ParmVarDecl::Create (*ast,
                                                          const_cast<DeclContext*>(m_decl_context),
                                                          SourceLocation(),
                                                          SourceLocation(),
                                                          NULL,
                                                          arg_qual_type,
                                                          NULL,
                                                          SC_Static,
                                                          NULL));
        }

        func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls));
    }
    else
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        if (log)
            log->Printf("Function type wasn't a FunctionProtoType");
    }

    m_decls.push_back(func_decl);

    return func_decl;
}

clang::NamedDecl *
NameSearchContext::AddGenericFunDecl()
{
    FunctionProtoType::ExtProtoInfo proto_info;

    proto_info.Variadic = true;

    QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy,    // result
                                                                                ArrayRef<QualType>(),                                        // argument types
                                                                                proto_info));

    return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type));
}

clang::NamedDecl *
NameSearchContext::AddTypeDecl(const ClangASTType &clang_type)
{
    if (clang_type)
    {
        QualType qual_type = clang_type.GetQualType();

        if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type))
        {
            TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();

            m_decls.push_back(typedef_name_decl);

            return (NamedDecl*)typedef_name_decl;
        }
        else if (const TagType *tag_type = qual_type->getAs<TagType>())
        {
            TagDecl *tag_decl = tag_type->getDecl();

            m_decls.push_back(tag_decl);

            return tag_decl;
        }
        else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>())
        {
            ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();

            m_decls.push_back((NamedDecl*)interface_decl);

            return (NamedDecl*)interface_decl;
        }
    }
    return NULL;
}

void
NameSearchContext::AddLookupResult (clang::DeclContextLookupConstResult result)
{
    for (clang::NamedDecl *decl : result)
        m_decls.push_back (decl);
}

void
NameSearchContext::AddNamedDecl (clang::NamedDecl *decl)
{
    m_decls.push_back (decl);
}
