forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1214 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1214 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- ClangASTImporter.cpp ------------------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "lldb/Symbol/ClangASTImporter.h"
 | |
| #include "lldb/Core/Log.h"
 | |
| #include "lldb/Core/Module.h"
 | |
| #include "lldb/Symbol/ClangASTContext.h"
 | |
| #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
 | |
| #include "lldb/Symbol/ClangUtil.h"
 | |
| #include "lldb/Utility/LLDBAssert.h"
 | |
| #include "clang/AST/Decl.h"
 | |
| #include "clang/AST/DeclCXX.h"
 | |
| #include "clang/AST/DeclObjC.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| 
 | |
| using namespace lldb_private;
 | |
| using namespace clang;
 | |
| 
 | |
| ClangASTMetrics::Counters ClangASTMetrics::global_counters = { 0, 0, 0, 0, 0, 0 };
 | |
| ClangASTMetrics::Counters ClangASTMetrics::local_counters = { 0, 0, 0, 0, 0, 0 };
 | |
| 
 | |
| void ClangASTMetrics::DumpCounters (Log *log, ClangASTMetrics::Counters &counters)
 | |
| {
 | |
|     log->Printf("  Number of visible Decl queries by name     : %" PRIu64, counters.m_visible_query_count);
 | |
|     log->Printf("  Number of lexical Decl queries             : %" PRIu64, counters.m_lexical_query_count);
 | |
|     log->Printf("  Number of imports initiated by LLDB        : %" PRIu64, counters.m_lldb_import_count);
 | |
|     log->Printf("  Number of imports conducted by Clang       : %" PRIu64, counters.m_clang_import_count);
 | |
|     log->Printf("  Number of Decls completed                  : %" PRIu64, counters.m_decls_completed_count);
 | |
|     log->Printf("  Number of records laid out                 : %" PRIu64, counters.m_record_layout_count);
 | |
| }
 | |
| 
 | |
| void ClangASTMetrics::DumpCounters (Log *log)
 | |
| {
 | |
|     if (!log)
 | |
|         return;
 | |
|     
 | |
|     log->Printf("== ClangASTMetrics output ==");
 | |
|     log->Printf("-- Global metrics --");
 | |
|     DumpCounters (log, global_counters);
 | |
|     log->Printf("-- Local metrics --");
 | |
|     DumpCounters (log, local_counters);
 | |
| }
 | |
| 
 | |
| clang::QualType
 | |
| ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
 | |
|                             clang::ASTContext *src_ast,
 | |
|                             clang::QualType type)
 | |
| {
 | |
|     MinionSP minion_sp (GetMinion(dst_ast, src_ast));
 | |
|     
 | |
|     if (minion_sp)
 | |
|         return minion_sp->Import(type);
 | |
|     
 | |
|     return QualType();
 | |
| }
 | |
| 
 | |
| lldb::opaque_compiler_type_t
 | |
| ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
 | |
|                             clang::ASTContext *src_ast,
 | |
|                             lldb::opaque_compiler_type_t type)
 | |
| {
 | |
|     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,
 | |
|                             clang::Decl *decl)
 | |
| {
 | |
|     MinionSP minion_sp;
 | |
|     
 | |
|     minion_sp = GetMinion(dst_ast, src_ast);
 | |
|     
 | |
|     if (minion_sp)
 | |
|     {
 | |
|         clang::Decl *result = minion_sp->Import(decl);
 | |
|         
 | |
|         if (!result)
 | |
|         {
 | |
|             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|             if (log)
 | |
|             {
 | |
|                 lldb::user_id_t user_id = LLDB_INVALID_UID;
 | |
|                 ClangASTMetadata *metadata = GetDeclMetadata(decl);
 | |
|                 if (metadata)
 | |
|                     user_id = metadata->GetUserID();
 | |
|                 
 | |
|                 if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl))
 | |
|                     log->Printf("  [ClangASTImporter] WARNING: Failed to import a %s '%s', metadata 0x%" PRIx64,
 | |
|                                 decl->getDeclKindName(),
 | |
|                                 named_decl->getNameAsString().c_str(),
 | |
|                                 user_id);
 | |
|                 else
 | |
|                     log->Printf("  [ClangASTImporter] WARNING: Failed to import a %s, metadata 0x%" PRIx64,
 | |
|                                 decl->getDeclKindName(),
 | |
|                                 user_id);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return result;
 | |
|     }
 | |
|     
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| class DeclContextOverride
 | |
| {
 | |
| private:
 | |
|     struct Backup
 | |
|     {
 | |
|         clang::DeclContext *decl_context;
 | |
|         clang::DeclContext *lexical_decl_context;
 | |
|     };
 | |
|     
 | |
|     std::map<clang::Decl *, Backup> m_backups;
 | |
|     
 | |
|     void OverrideOne(clang::Decl *decl)
 | |
|     {
 | |
|         if (m_backups.find(decl) != m_backups.end())
 | |
|         {
 | |
|             return;
 | |
|         }
 | |
|             
 | |
|         m_backups[decl] = { decl->getDeclContext(), decl->getLexicalDeclContext() };
 | |
|         
 | |
|         decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
 | |
|         decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
 | |
|     }
 | |
|     
 | |
|     bool ChainPassesThrough(clang::Decl *decl,
 | |
|                             clang::DeclContext *base,
 | |
|                             clang::DeclContext *(clang::Decl::*contextFromDecl)(),
 | |
|                             clang::DeclContext *(clang::DeclContext::*contextFromContext)())
 | |
|     {
 | |
|         for (DeclContext *decl_ctx = (decl->*contextFromDecl)();
 | |
|              decl_ctx;
 | |
|              decl_ctx = (decl_ctx->*contextFromContext)())
 | |
|         {
 | |
|             if (decl_ctx == base)
 | |
|             {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return false;
 | |
|     }
 | |
|     
 | |
|     clang::Decl *GetEscapedChild(clang::Decl *decl, clang::DeclContext *base = nullptr)
 | |
|     {
 | |
|         if (base)
 | |
|         {
 | |
|             // decl's DeclContext chains must pass through base.
 | |
|             
 | |
|             if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext, &clang::DeclContext::getParent) ||
 | |
|                 !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext, &clang::DeclContext::getLexicalParent))
 | |
|             {
 | |
|                 return decl;
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             base = clang::dyn_cast<clang::DeclContext>(decl);
 | |
|             
 | |
|             if (!base)
 | |
|             {
 | |
|                 return nullptr;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         if (clang::DeclContext *context = clang::dyn_cast<clang::DeclContext>(decl))
 | |
|         {
 | |
|             for (clang::Decl *decl : context->decls())
 | |
|             {
 | |
|                 if (clang::Decl *escaped_child = GetEscapedChild(decl))
 | |
|                 {
 | |
|                     return escaped_child;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return nullptr;
 | |
|     }
 | |
|     
 | |
|     void Override(clang::Decl *decl)
 | |
|     {
 | |
|         if (clang::Decl *escaped_child = GetEscapedChild(decl))
 | |
|         {
 | |
|             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
|             
 | |
|             if (log)
 | |
|                 log->Printf("    [ClangASTImporter] DeclContextOverride couldn't override (%sDecl*)%p - its child (%sDecl*)%p escapes",
 | |
|                             decl->getDeclKindName(), static_cast<void*>(decl),
 | |
|                             escaped_child->getDeclKindName(), static_cast<void*>(escaped_child));
 | |
|             lldbassert(0 && "Couldn't override!");
 | |
|         }
 | |
|         
 | |
|         OverrideOne(decl);
 | |
|     }
 | |
|     
 | |
| public:
 | |
|     DeclContextOverride()
 | |
|     {
 | |
|     }
 | |
|     
 | |
|     void OverrideAllDeclsFromContainingFunction(clang::Decl *decl)
 | |
|     {
 | |
|         for (DeclContext *decl_context = decl->getLexicalDeclContext();
 | |
|              decl_context;
 | |
|              decl_context = decl_context->getLexicalParent())
 | |
|         {
 | |
|             DeclContext *redecl_context = decl_context->getRedeclContext();
 | |
|             
 | |
|             if (llvm::isa<FunctionDecl>(redecl_context) &&
 | |
|                 llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent()))
 | |
|             {
 | |
|                 for (clang::Decl *child_decl : decl_context->decls())
 | |
|                 {
 | |
|                     Override(child_decl);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     ~DeclContextOverride()
 | |
|     {
 | |
|         for (const std::pair<clang::Decl *, Backup> &backup : m_backups)
 | |
|         {
 | |
|             backup.first->setDeclContext(backup.second.decl_context);
 | |
|             backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
 | |
|         }
 | |
|     }
 | |
| };
 | |
| 
 | |
| lldb::opaque_compiler_type_t
 | |
| ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
 | |
|                               clang::ASTContext *src_ctx,
 | |
|                               lldb::opaque_compiler_type_t type)
 | |
| {
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
|   
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] DeportType called on (%sType*)0x%llx from (ASTContext*)%p to (ASTContext*)%p",
 | |
|                     QualType::getFromOpaquePtr(type)->getTypeClassName(), (unsigned long long)type,
 | |
|                     static_cast<void*>(src_ctx),
 | |
|                     static_cast<void*>(dst_ctx));
 | |
| 
 | |
|     MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
 | |
|     
 | |
|     if (!minion_sp)
 | |
|         return nullptr;
 | |
|     
 | |
|     std::set<NamedDecl *> decls_to_deport;
 | |
|     std::set<NamedDecl *> decls_already_deported;
 | |
|     
 | |
|     DeclContextOverride decl_context_override;
 | |
|     
 | |
|     if (const clang::TagType *tag_type = clang::QualType::getFromOpaquePtr(type)->getAs<TagType>())
 | |
|     {
 | |
|         decl_context_override.OverrideAllDeclsFromContainingFunction(tag_type->getDecl());
 | |
|     }
 | |
|     
 | |
|     minion_sp->InitDeportWorkQueues(&decls_to_deport,
 | |
|                                     &decls_already_deported);
 | |
|     
 | |
|     lldb::opaque_compiler_type_t result = CopyType(dst_ctx, src_ctx, type);
 | |
|     
 | |
|     minion_sp->ExecuteDeportWorkQueues();
 | |
|     
 | |
|     if (!result)
 | |
|         return nullptr;
 | |
|     
 | |
|     return result;
 | |
| 
 | |
| }
 | |
| 
 | |
| clang::Decl *
 | |
| ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
 | |
|                               clang::ASTContext *src_ctx,
 | |
|                               clang::Decl *decl)
 | |
| {
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContext*)%p",
 | |
|                     decl->getDeclKindName(), static_cast<void*>(decl),
 | |
|                     static_cast<void*>(src_ctx),
 | |
|                     static_cast<void*>(dst_ctx));
 | |
| 
 | |
|     MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
 | |
| 
 | |
|     if (!minion_sp)
 | |
|         return nullptr;
 | |
| 
 | |
|     std::set<NamedDecl *> decls_to_deport;
 | |
|     std::set<NamedDecl *> decls_already_deported;
 | |
|     
 | |
|     DeclContextOverride decl_context_override;
 | |
|     
 | |
|     decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
 | |
| 
 | |
|     minion_sp->InitDeportWorkQueues(&decls_to_deport,
 | |
|                                     &decls_already_deported);
 | |
| 
 | |
|     clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
 | |
| 
 | |
|     minion_sp->ExecuteDeportWorkQueues();
 | |
| 
 | |
|     if (!result)
 | |
|         return nullptr;
 | |
| 
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
 | |
|                     decl->getDeclKindName(), static_cast<void*>(decl),
 | |
|                     result->getDeclKindName(), static_cast<void*>(result));
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::CanImport(const CompilerType &type)
 | |
| {
 | |
|     if (!ClangUtil::IsClangType(type))
 | |
|         return false;
 | |
| 
 | |
|     // TODO: remove external completion BOOL
 | |
|     // CompleteAndFetchChildren should get the Decl out and check for the
 | |
| 
 | |
|     clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::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 (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 (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 (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()));
 | |
| 
 | |
|         case clang::Type::Auto:
 | |
|             return CanImport(CompilerType(type.GetTypeSystem(),
 | |
|                                           llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()));
 | |
| 
 | |
|         case clang::Type::Elaborated:
 | |
|             return CanImport(CompilerType(
 | |
|                 type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
 | |
| 
 | |
|         case clang::Type::Paren:
 | |
|             return CanImport(CompilerType(type.GetTypeSystem(),
 | |
|                                           llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
 | |
| 
 | |
|         default:
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::Import(const CompilerType &type)
 | |
| {
 | |
|     if (!ClangUtil::IsClangType(type))
 | |
|         return false;
 | |
|     // TODO: remove external completion BOOL
 | |
|     // CompleteAndFetchChildren should get the Decl out and check for the
 | |
| 
 | |
|     clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::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 (ResolveDeclOrigin(cxx_record_decl, NULL, NULL))
 | |
|                     return CompleteAndFetchChildren(qual_type);
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|         case clang::Type::Enum:
 | |
|         {
 | |
|             clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
 | |
|             if (enum_decl)
 | |
|             {
 | |
|                 if (ResolveDeclOrigin(enum_decl, NULL, NULL))
 | |
|                     return 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 (ResolveDeclOrigin(class_interface_decl, NULL, NULL))
 | |
|                         return CompleteAndFetchChildren(qual_type);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|         case clang::Type::Typedef:
 | |
|             return Import(CompilerType(
 | |
|                 type.GetTypeSystem(),
 | |
|                 llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()));
 | |
| 
 | |
|         case clang::Type::Auto:
 | |
|             return Import(CompilerType(type.GetTypeSystem(),
 | |
|                                        llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()));
 | |
| 
 | |
|         case clang::Type::Elaborated:
 | |
|             return Import(CompilerType(type.GetTypeSystem(),
 | |
|                                        llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
 | |
| 
 | |
|         case clang::Type::Paren:
 | |
|             return Import(CompilerType(type.GetTypeSystem(),
 | |
|                                        llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
 | |
| 
 | |
|         default:
 | |
|             break;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::CompleteType(const CompilerType &compiler_type)
 | |
| {
 | |
|     if (!CanImport(compiler_type))
 | |
|         return false;
 | |
| 
 | |
|     if (Import(compiler_type))
 | |
|     {
 | |
|         ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), false);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment,
 | |
|                                    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
 | |
|                                    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
 | |
|                                    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
 | |
| {
 | |
|     RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find(record_decl);
 | |
|     bool success = false;
 | |
|     base_offsets.clear();
 | |
|     vbase_offsets.clear();
 | |
|     if (pos != m_record_decl_to_layout_map.end())
 | |
|     {
 | |
|         bit_size = pos->second.bit_size;
 | |
|         alignment = pos->second.alignment;
 | |
|         field_offsets.swap(pos->second.field_offsets);
 | |
|         base_offsets.swap(pos->second.base_offsets);
 | |
|         vbase_offsets.swap(pos->second.vbase_offsets);
 | |
|         m_record_decl_to_layout_map.erase(pos);
 | |
|         success = true;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         bit_size = 0;
 | |
|         alignment = 0;
 | |
|         field_offsets.clear();
 | |
|     }
 | |
|     return success;
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout)
 | |
| {
 | |
|     m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::CompleteDecl (clang::Decl *decl)
 | |
| {
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] CompleteDecl called on (%sDecl*)%p",
 | |
|                     decl->getDeclKindName(), static_cast<void*>(decl));
 | |
| 
 | |
|     if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) 
 | |
|     {
 | |
|         if (!interface_decl->getDefinition())
 | |
|         {
 | |
|             interface_decl->startDefinition();
 | |
|             CompleteObjCInterfaceDecl(interface_decl);
 | |
|         }
 | |
|     }
 | |
|     else if (ObjCProtocolDecl *protocol_decl = dyn_cast<ObjCProtocolDecl>(decl)) 
 | |
|     {
 | |
|         if (!protocol_decl->getDefinition())
 | |
|             protocol_decl->startDefinition();
 | |
|     }
 | |
|     else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) 
 | |
|     {
 | |
|         if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined()) 
 | |
|         {
 | |
|             tag_decl->startDefinition();
 | |
|             CompleteTagDecl(tag_decl);
 | |
|             tag_decl->setCompleteDefinition(true);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         assert (0 && "CompleteDecl called on a Decl that can't be completed");
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl)
 | |
| {
 | |
|     ClangASTMetrics::RegisterDeclCompletion();
 | |
|     
 | |
|     DeclOrigin decl_origin = GetDeclOrigin(decl);
 | |
|     
 | |
|     if (!decl_origin.Valid())
 | |
|         return false;
 | |
|     
 | |
|     if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
 | |
|         return false;
 | |
|     
 | |
|     MinionSP minion_sp (GetMinion(&decl->getASTContext(), decl_origin.ctx));
 | |
|     
 | |
|     if (minion_sp)
 | |
|         minion_sp->ImportDefinitionTo(decl, decl_origin.decl);
 | |
|         
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin_decl)
 | |
| {
 | |
|     ClangASTMetrics::RegisterDeclCompletion();
 | |
| 
 | |
|     clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
 | |
|         
 | |
|     if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
 | |
|         return false;
 | |
|     
 | |
|     MinionSP minion_sp (GetMinion(&decl->getASTContext(), origin_ast_ctx));
 | |
|     
 | |
|     if (minion_sp)
 | |
|         minion_sp->ImportDefinitionTo(decl, origin_decl);
 | |
|         
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
| 
 | |
|     OriginMap &origins = context_md->m_origins;
 | |
| 
 | |
|     origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
 | |
|     
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl)
 | |
| {
 | |
|     ClangASTMetrics::RegisterDeclCompletion();
 | |
|     
 | |
|     DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
 | |
|     
 | |
|     if (!decl_origin.Valid())
 | |
|         return false;
 | |
|     
 | |
|     if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
 | |
|         return false;
 | |
|     
 | |
|     MinionSP minion_sp (GetMinion(&interface_decl->getASTContext(), decl_origin.ctx));
 | |
|     
 | |
|     if (minion_sp)
 | |
|         minion_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
 | |
| 
 | |
|     if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
 | |
|         RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| 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())
 | |
|         return false;
 | |
|     
 | |
|     if (const TagType *tag_type = type->getAs<TagType>())
 | |
|     {
 | |
|         TagDecl *tag_decl = tag_type->getDecl();
 | |
| 
 | |
|         if (tag_decl->getDefinition() || tag_decl->isBeingDefined())
 | |
|             return true;
 | |
| 
 | |
|         return CompleteTagDecl(tag_decl);
 | |
|     }
 | |
|     if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>())
 | |
|     {
 | |
|         if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface())
 | |
|             return CompleteObjCInterfaceDecl(objc_interface_decl);
 | |
|         else
 | |
|             return false;
 | |
|     }
 | |
|     if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
 | |
|     {
 | |
|         return RequireCompleteType(array_type->getElementType());
 | |
|     }
 | |
|     if (const AtomicType *atomic_type = type->getAs<AtomicType>())
 | |
|     {
 | |
|         return RequireCompleteType(atomic_type->getPointeeType());
 | |
|     }
 | |
|     
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| ClangASTMetadata *
 | |
| ClangASTImporter::GetDeclMetadata (const clang::Decl *decl)
 | |
| {
 | |
|     DeclOrigin decl_origin = GetDeclOrigin(decl);
 | |
|     
 | |
|     if (decl_origin.Valid())
 | |
|         return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl);
 | |
|     else
 | |
|         return ClangASTContext::GetMetadata(&decl->getASTContext(), decl);
 | |
| }
 | |
| 
 | |
| ClangASTImporter::DeclOrigin
 | |
| ClangASTImporter::GetDeclOrigin(const clang::Decl *decl)
 | |
| {
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
|     
 | |
|     OriginMap &origins = context_md->m_origins;
 | |
|     
 | |
|     OriginMap::iterator iter = origins.find(decl);
 | |
|     
 | |
|     if (iter != origins.end())
 | |
|         return iter->second;
 | |
|     else
 | |
|         return DeclOrigin();
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl)
 | |
| {
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
|     
 | |
|     OriginMap &origins = context_md->m_origins;
 | |
|     
 | |
|     OriginMap::iterator iter = origins.find(decl);
 | |
|     
 | |
|     if (iter != origins.end())
 | |
|     {
 | |
|         iter->second.decl = original_decl;
 | |
|         iter->second.ctx = &original_decl->getASTContext();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl, 
 | |
|                                        NamespaceMapSP &namespace_map)
 | |
| {
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
|     
 | |
|     context_md->m_namespace_maps[decl] = namespace_map;
 | |
| }
 | |
| 
 | |
| ClangASTImporter::NamespaceMapSP 
 | |
| ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl)
 | |
| {
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
| 
 | |
|     NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps;
 | |
|     
 | |
|     NamespaceMetaMap::iterator iter = namespace_maps.find(decl);
 | |
|     
 | |
|     if (iter != namespace_maps.end())
 | |
|         return iter->second;
 | |
|     else
 | |
|         return NamespaceMapSP();
 | |
| }
 | |
| 
 | |
| void 
 | |
| ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl)
 | |
| {
 | |
|     assert (decl);
 | |
|     ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
 | |
| 
 | |
|     const DeclContext *parent_context = decl->getDeclContext();
 | |
|     const NamespaceDecl *parent_namespace = dyn_cast<NamespaceDecl>(parent_context);
 | |
|     NamespaceMapSP parent_map;
 | |
|     
 | |
|     if (parent_namespace)
 | |
|         parent_map = GetNamespaceMap(parent_namespace);
 | |
|     
 | |
|     NamespaceMapSP new_map;
 | |
|     
 | |
|     new_map.reset(new NamespaceMap);
 | |
|  
 | |
|     if (context_md->m_map_completer)
 | |
|     {
 | |
|         std::string namespace_string = decl->getDeclName().getAsString();
 | |
|     
 | |
|         context_md->m_map_completer->CompleteNamespaceMap (new_map, ConstString(namespace_string.c_str()), parent_map);
 | |
|     }
 | |
|     
 | |
|     context_md->m_namespace_maps[decl] = new_map;
 | |
| }
 | |
| 
 | |
| void 
 | |
| ClangASTImporter::ForgetDestination (clang::ASTContext *dst_ast)
 | |
| {
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] Forgetting destination (ASTContext*)%p",
 | |
|                     static_cast<void*>(dst_ast));
 | |
| 
 | |
|     m_metadata_map.erase(dst_ast);
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::ForgetSource (clang::ASTContext *dst_ast, clang::ASTContext *src_ast)
 | |
| {
 | |
|     ASTContextMetadataSP md = MaybeGetContextMetadata (dst_ast);
 | |
| 
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|     if (log)
 | |
|         log->Printf("    [ClangASTImporter] Forgetting source->dest (ASTContext*)%p->(ASTContext*)%p",
 | |
|                     static_cast<void*>(src_ast), static_cast<void*>(dst_ast));
 | |
| 
 | |
|     if (!md)
 | |
|         return;
 | |
| 
 | |
|     md->m_minions.erase(src_ast);
 | |
| 
 | |
|     for (OriginMap::iterator iter = md->m_origins.begin();
 | |
|          iter != md->m_origins.end();
 | |
|          )
 | |
|     {
 | |
|         if (iter->second.ctx == src_ast)
 | |
|             md->m_origins.erase(iter++);
 | |
|         else
 | |
|             ++iter;
 | |
|     }
 | |
| }
 | |
| 
 | |
| ClangASTImporter::MapCompleter::~MapCompleter ()
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
 | |
|                                                 std::set<clang::NamedDecl *> *decls_already_deported)
 | |
| {
 | |
|     assert(!m_decls_to_deport);
 | |
|     assert(!m_decls_already_deported);
 | |
|     
 | |
|     m_decls_to_deport = decls_to_deport;
 | |
|     m_decls_already_deported = decls_already_deported;
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
 | |
| {
 | |
|     assert(m_decls_to_deport);
 | |
|     assert(m_decls_already_deported);
 | |
|     
 | |
|     ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&getToContext());
 | |
|         
 | |
|     while (!m_decls_to_deport->empty())
 | |
|     {
 | |
|         NamedDecl *decl = *m_decls_to_deport->begin();
 | |
|         
 | |
|         m_decls_already_deported->insert(decl);
 | |
|         m_decls_to_deport->erase(decl);
 | |
|         
 | |
|         DeclOrigin &origin = to_context_md->m_origins[decl];
 | |
|         UNUSED_IF_ASSERT_DISABLED(origin);
 | |
|         
 | |
|         assert (origin.ctx == m_source_ctx);    // otherwise we should never have added this
 | |
|                                                 // because it doesn't need to be deported
 | |
|         
 | |
|         Decl *original_decl = to_context_md->m_origins[decl].decl;
 | |
|         
 | |
|         ClangASTContext::GetCompleteDecl (m_source_ctx, original_decl);
 | |
|         
 | |
|         if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl))
 | |
|         {
 | |
|             if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
 | |
|             {
 | |
|                 if (original_tag_decl->isCompleteDefinition())
 | |
|                 {
 | |
|                     ImportDefinitionTo(tag_decl, original_tag_decl);
 | |
|                     tag_decl->setCompleteDefinition(true);
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             tag_decl->setHasExternalLexicalStorage(false);
 | |
|             tag_decl->setHasExternalVisibleStorage(false);
 | |
|         }
 | |
|         else if (ObjCContainerDecl *container_decl = dyn_cast<ObjCContainerDecl>(decl))
 | |
|         {
 | |
|             container_decl->setHasExternalLexicalStorage(false);
 | |
|             container_decl->setHasExternalVisibleStorage(false);
 | |
|         }
 | |
|         
 | |
|         to_context_md->m_origins.erase(decl);
 | |
|     }
 | |
|     
 | |
|     m_decls_to_deport = nullptr;
 | |
|     m_decls_already_deported = nullptr;
 | |
| }
 | |
| 
 | |
| void
 | |
| ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from)
 | |
| {
 | |
|     ASTImporter::Imported(from, to);
 | |
| 
 | |
|     /*
 | |
|     if (to_objc_interface)
 | |
|         to_objc_interface->startDefinition();
 | |
|  
 | |
|     CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
 | |
|     
 | |
|     if (to_cxx_record)
 | |
|         to_cxx_record->startDefinition();
 | |
|     */
 | |
| 
 | |
|     ImportDefinition(from);
 | |
|     
 | |
|     if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to))
 | |
|     {
 | |
|         if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from))
 | |
|         {
 | |
|             to_tag->setCompleteDefinition(from_tag->isCompleteDefinition());
 | |
|         }
 | |
|     }
 | |
|      
 | |
|     // If we're dealing with an Objective-C class, ensure that the inheritance has
 | |
|     // been set up correctly.  The ASTImporter may not do this correctly if the 
 | |
|     // class was originally sourced from symbols.
 | |
|     
 | |
|     if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to))
 | |
|     {
 | |
|         do
 | |
|         {
 | |
|             ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass();
 | |
| 
 | |
|             if (to_superclass)
 | |
|                 break; // we're not going to override it if it's set
 | |
|             
 | |
|             ObjCInterfaceDecl *from_objc_interface = dyn_cast<ObjCInterfaceDecl>(from);
 | |
|             
 | |
|             if (!from_objc_interface)
 | |
|                 break;
 | |
|             
 | |
|             ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass();
 | |
|             
 | |
|             if (!from_superclass)
 | |
|                 break;
 | |
|             
 | |
|             Decl *imported_from_superclass_decl = Import(from_superclass);
 | |
|                 
 | |
|             if (!imported_from_superclass_decl)
 | |
|                 break;
 | |
|                 
 | |
|             ObjCInterfaceDecl *imported_from_superclass = dyn_cast<ObjCInterfaceDecl>(imported_from_superclass_decl);
 | |
|             
 | |
|             if (!imported_from_superclass)
 | |
|                 break;
 | |
|             
 | |
|             if (!to_objc_interface->hasDefinition())
 | |
|                 to_objc_interface->startDefinition();
 | |
|             
 | |
|             to_objc_interface->setSuperClass(
 | |
|                     m_source_ctx->getTrivialTypeSourceInfo(m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
 | |
|         }
 | |
|         while (0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| clang::Decl *
 | |
| ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
 | |
| {
 | |
|     ClangASTMetrics::RegisterClangImport();
 | |
| 
 | |
|     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|     lldb::user_id_t user_id = LLDB_INVALID_UID;
 | |
|     ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
 | |
|     if (metadata)
 | |
|         user_id = metadata->GetUserID();
 | |
|     
 | |
|     if (log)
 | |
|     {
 | |
|         if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from))
 | |
|         {
 | |
|             std::string name_string;
 | |
|             llvm::raw_string_ostream name_stream(name_string);
 | |
|             from_named_decl->printName(name_stream);
 | |
|             name_stream.flush();
 | |
| 
 | |
|             log->Printf("    [ClangASTImporter] Imported (%sDecl*)%p, named %s (from (Decl*)%p), metadata 0x%" PRIx64,
 | |
|                         from->getDeclKindName(), static_cast<void*>(to),
 | |
|                         name_string.c_str(), static_cast<void*>(from),
 | |
|                         user_id);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             log->Printf("    [ClangASTImporter] Imported (%sDecl*)%p (from (Decl*)%p), metadata 0x%" PRIx64,
 | |
|                         from->getDeclKindName(), static_cast<void*>(to),
 | |
|                         static_cast<void*>(from), user_id);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&to->getASTContext());
 | |
|     ASTContextMetadataSP from_context_md = m_master.MaybeGetContextMetadata(m_source_ctx);
 | |
| 
 | |
|     if (from_context_md)
 | |
|     {
 | |
|         OriginMap &origins = from_context_md->m_origins;
 | |
| 
 | |
|         OriginMap::iterator origin_iter = origins.find(from);
 | |
| 
 | |
|         if (origin_iter != origins.end())
 | |
|         {
 | |
|             if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
 | |
|                 user_id != LLDB_INVALID_UID)
 | |
|             {
 | |
|                 if (origin_iter->second.ctx != &to->getASTContext())
 | |
|                     to_context_md->m_origins[to] = origin_iter->second;
 | |
|             }
 | |
|                 
 | |
|             MinionSP direct_completer = m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx);
 | |
| 
 | |
|             if (direct_completer.get() != this)
 | |
|                 direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
 | |
| 
 | |
|             if (log)
 | |
|                 log->Printf("    [ClangASTImporter] Propagated origin (Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to (ASTContext*)%p",
 | |
|                             static_cast<void*>(origin_iter->second.decl),
 | |
|                             static_cast<void*>(origin_iter->second.ctx),
 | |
|                             static_cast<void*>(&from->getASTContext()),
 | |
|                             static_cast<void*>(&to->getASTContext()));
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (m_decls_to_deport && m_decls_already_deported)
 | |
|             {
 | |
|                 if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
 | |
|                 {
 | |
|                     RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
 | |
|                     if (from_record_decl == nullptr || from_record_decl->isInjectedClassName() == false)
 | |
|                     {
 | |
|                         NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
 | |
| 
 | |
|                         if (!m_decls_already_deported->count(to_named_decl))
 | |
|                             m_decls_to_deport->insert(to_named_decl);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
 | |
|                 user_id != LLDB_INVALID_UID)
 | |
|             {
 | |
|                 to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
 | |
|             }
 | |
| 
 | |
|             if (log)
 | |
|                 log->Printf("    [ClangASTImporter] Decl has no origin information in (ASTContext*)%p",
 | |
|                             static_cast<void*>(&from->getASTContext()));
 | |
|         }
 | |
| 
 | |
|         if (clang::NamespaceDecl *to_namespace = dyn_cast<clang::NamespaceDecl>(to))
 | |
|         {
 | |
|             clang::NamespaceDecl *from_namespace = dyn_cast<clang::NamespaceDecl>(from);
 | |
| 
 | |
|             NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
 | |
| 
 | |
|             NamespaceMetaMap::iterator namespace_map_iter = namespace_maps.find(from_namespace);
 | |
| 
 | |
|             if (namespace_map_iter != namespace_maps.end())
 | |
|                 to_context_md->m_namespace_maps[to_namespace] = namespace_map_iter->second;
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         to_context_md->m_origins[to] = DeclOrigin (m_source_ctx, from);
 | |
| 
 | |
|         if (log)
 | |
|             log->Printf("    [ClangASTImporter] Sourced origin (Decl*)%p/(ASTContext*)%p into (ASTContext*)%p",
 | |
|                         static_cast<void*>(from),
 | |
|                         static_cast<void*>(m_source_ctx),
 | |
|                         static_cast<void*>(&to->getASTContext()));
 | |
|     }
 | |
| 
 | |
|     if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from))
 | |
|     {
 | |
|         TagDecl *to_tag_decl = dyn_cast<TagDecl>(to);
 | |
| 
 | |
|         to_tag_decl->setHasExternalLexicalStorage();
 | |
|         to_tag_decl->setMustBuildLookupTable();
 | |
| 
 | |
|         if (log)
 | |
|             log->Printf("    [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
 | |
|                         (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
 | |
|                         (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
 | |
|                         (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
 | |
|                         (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
 | |
|     }
 | |
| 
 | |
|     if (isa<NamespaceDecl>(from))
 | |
|     {
 | |
|         NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to);
 | |
| 
 | |
|         m_master.BuildNamespaceMap(to_namespace_decl);
 | |
| 
 | |
|         to_namespace_decl->setHasExternalVisibleStorage();
 | |
|     }
 | |
| 
 | |
|     if (isa<ObjCContainerDecl>(from))
 | |
|     {
 | |
|         ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to);
 | |
| 
 | |
|         to_container_decl->setHasExternalLexicalStorage();
 | |
|         to_container_decl->setHasExternalVisibleStorage();
 | |
| 
 | |
|         /*to_interface_decl->setExternallyCompleted();*/
 | |
| 
 | |
|         if (log)
 | |
|         {
 | |
|             if (ObjCInterfaceDecl *to_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl))
 | |
|             {
 | |
|                 log->Printf("    [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s",
 | |
|                             (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
 | |
|                             (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
 | |
|                             (to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 log->Printf("    [ClangASTImporter] To is an %sDecl - attributes %s%s",
 | |
|                             ((Decl*)to_container_decl)->getDeclKindName(),
 | |
|                             (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
 | |
|                             (to_container_decl->hasExternalVisibleStorage() ? " Visible" : ""));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return clang::ASTImporter::Imported(from, to);
 | |
| }
 | |
| 
 | |
| clang::Decl *ClangASTImporter::Minion::GetOriginalDecl (clang::Decl *To)
 | |
| {
 | |
|     ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&To->getASTContext());
 | |
|     
 | |
|     if (!to_context_md)
 | |
|         return nullptr;
 | |
|     
 | |
|     OriginMap::iterator iter = to_context_md->m_origins.find(To);
 | |
|     
 | |
|     if (iter == to_context_md->m_origins.end())
 | |
|         return nullptr;
 | |
|     
 | |
|     return const_cast<clang::Decl*>(iter->second.decl);
 | |
| }
 |