diff options
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp')
| -rw-r--r-- | lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp | 1494 |
1 files changed, 674 insertions, 820 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index f4457fc1b740..bf3023be5f60 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -8,7 +8,6 @@ #include "ClangExpressionDeclMap.h" -#include "ASTDumper.h" #include "ClangASTSource.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" @@ -20,6 +19,7 @@ #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Expression/Materializer.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" @@ -65,9 +65,10 @@ const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; ClangExpressionDeclMap::ClangExpressionDeclMap( bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, - ExecutionContext &exe_ctx, ValueObject *ctx_obj) - : ClangASTSource(exe_ctx.GetTargetSP()), m_found_entities(), - m_struct_members(), m_keep_result_in_memory(keep_result_in_memory), + const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer, + ValueObject *ctx_obj) + : ClangASTSource(target, importer), m_found_entities(), m_struct_members(), + m_keep_result_in_memory(keep_result_in_memory), m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(), m_struct_vars() { EnableStructVars(); @@ -84,8 +85,6 @@ ClangExpressionDeclMap::~ClangExpressionDeclMap() { bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, Materializer *materializer) { - ClangASTMetrics::ClearLocalCounters(); - EnableParserVars(); m_parser_vars->m_exe_ctx = exe_ctx; @@ -110,7 +109,7 @@ bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>( target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); - if (!target->GetScratchClangASTContext()) + if (!ClangASTContext::GetScratch(*target)) return false; } @@ -127,12 +126,7 @@ void ClangExpressionDeclMap::InstallCodeGenerator( } void ClangExpressionDeclMap::DidParse() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - ClangASTMetrics::DumpCounters(log); - - if (m_parser_vars) { + if (m_parser_vars && m_parser_vars->m_persistent_vars) { for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); entity_index < num_entities; ++entity_index) { ExpressionVariableSP var_sp( @@ -180,55 +174,15 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { return ret; } -static clang::QualType ExportAllDeclaredTypes( - clang::ExternalASTMerger &parent_merger, clang::ExternalASTMerger &merger, - clang::ASTContext &source, clang::FileManager &source_file_manager, - const clang::ExternalASTMerger::OriginMap &source_origin_map, - clang::FileID file, clang::QualType root) { - // Mark the source as temporary to make sure all declarations from the - // AST are exported. Also add the parent_merger as the merger into the - // source AST so that the merger can track back any declarations from - // the persistent ASTs we used as sources. - clang::ExternalASTMerger::ImporterSource importer_source( - source, source_file_manager, source_origin_map, /*Temporary*/ true, - &parent_merger); - merger.AddSources(importer_source); - clang::ASTImporter &exporter = merger.ImporterForOrigin(source); - llvm::Expected<clang::QualType> ret_or_error = exporter.Import(root); - merger.RemoveSources(importer_source); - if (ret_or_error) { - return *ret_or_error; - } else { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - LLDB_LOG_ERROR(log, ret_or_error.takeError(), "Couldn't import type: {0}"); - return clang::QualType(); - } -} - TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, ClangASTContext &source, TypeFromParser parser_type) { - assert(&target == m_target->GetScratchClangASTContext()); + assert(&target == ClangASTContext::GetScratch(*m_target)); assert((TypeSystem *)&source == parser_type.GetTypeSystem()); - assert(source.getASTContext() == m_ast_context); + assert(&source.getASTContext() == m_ast_context); if (m_ast_importer_sp) { - return TypeFromUser(m_ast_importer_sp->DeportType( - target.getASTContext(), source.getASTContext(), - parser_type.GetOpaqueQualType()), - &target); - } else if (m_merger_up) { - clang::FileID source_file = - source.getASTContext()->getSourceManager().getFileID( - source.getASTContext()->getTranslationUnitDecl()->getLocation()); - auto scratch_ast_context = static_cast<ClangASTContextForExpressions *>( - m_target->GetScratchClangASTContext()); - clang::QualType exported_type = ExportAllDeclaredTypes( - *m_merger_up.get(), scratch_ast_context->GetMergerUnchecked(), - *source.getASTContext(), *source.getFileManager(), - m_merger_up->GetOrigins(), source_file, - clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType())); - return TypeFromUser(exported_type.getAsOpaquePtr(), &target); + return TypeFromUser(m_ast_importer_sp->DeportType(target, parser_type)); } else { lldbassert(0 && "No mechanism for deporting a type!"); return TypeFromUser(); @@ -255,8 +209,11 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - TypeFromUser user_type = - DeportType(*target->GetScratchClangASTContext(), *ast, parser_type); + auto *clang_ast_context = ClangASTContext::GetScratch(*target); + if (!clang_ast_context) + return false; + + TypeFromUser user_type = DeportType(*clang_ast_context, *ast, parser_type); uint32_t offset = m_parser_vars->m_materializer->AddResultVariable( user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err); @@ -291,7 +248,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - ClangASTContext *context(target->GetScratchClangASTContext()); + ClangASTContext *context = ClangASTContext::GetScratch(*target); + if (!context) + return false; TypeFromUser user_type = DeportType(*context, *ast, parser_type); @@ -303,6 +262,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (!m_parser_vars->m_target_info.IsValid()) return false; + if (!m_parser_vars->m_persistent_vars) + return false; + ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>( m_parser_vars->m_persistent_vars ->CreatePersistentVariable( @@ -368,7 +330,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList( m_found_entities, decl, GetParserID())); - if (!var) { + if (!var && m_parser_vars->m_persistent_vars) { var = ClangExpressionVariable::FindVariableInList( *m_parser_vars->m_persistent_vars, decl, GetParserID()); is_persistent_variable = true; @@ -638,7 +600,7 @@ addr_t ClangExpressionDeclMap::GetSymbolAddress(ConstString name, lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable( Target &target, ModuleSP &module, ConstString name, - CompilerDeclContext *namespace_decl, TypeFromUser *type) { + CompilerDeclContext *namespace_decl) { VariableList vars; if (module && namespace_decl) @@ -646,21 +608,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable( else target.GetImages().FindGlobalVariables(name, -1, vars); - if (vars.GetSize()) { - if (type) { - for (size_t i = 0; i < vars.GetSize(); ++i) { - VariableSP var_sp = vars.GetVariableAtIndex(i); - - if (ClangASTContext::AreTypesSame( - *type, var_sp->GetType()->GetFullCompilerType())) - return var_sp; - } - } else { - return vars.GetVariableAtIndex(0); - } - } - - return VariableSP(); + if (vars.GetSize() == 0) + return VariableSP(); + return vars.GetVariableAtIndex(0); } ClangASTContext *ClangExpressionDeclMap::GetClangASTContext() { @@ -687,8 +637,6 @@ void ClangExpressionDeclMap::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)); @@ -727,9 +675,9 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( dyn_cast<NamespaceDecl>(context.m_decl_context)) { if (namespace_context->getName().str() == std::string(g_lldb_local_vars_namespace_cstr)) { - CompilerDeclContext compiler_decl_ctx( - GetClangASTContext(), const_cast<void *>(static_cast<const void *>( - context.m_decl_context))); + CompilerDeclContext compiler_decl_ctx = + m_clang_ast_context->CreateDeclContext( + const_cast<clang::DeclContext *>(context.m_decl_context)); FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx, current_id); return; @@ -771,743 +719,760 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( ClangASTSource::FindExternalVisibleDecls(context); } -void ClangExpressionDeclMap::FindExternalVisibleDecls( - NameSearchContext &context, lldb::ModuleSP module_sp, - CompilerDeclContext &namespace_decl, unsigned int current_id) { - assert(m_ast_context); +void ClangExpressionDeclMap::MaybeRegisterFunctionBody( + FunctionDecl *copied_function_decl) { + if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) { + clang::DeclGroupRef decl_group_ref(copied_function_decl); + m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); + } +} - std::function<void(clang::FunctionDecl *)> MaybeRegisterFunctionBody = - [this](clang::FunctionDecl *copied_function_decl) { - if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) { - DeclGroupRef decl_group_ref(copied_function_decl); - m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); - } - }; +clang::NamedDecl *ClangExpressionDeclMap::GetPersistentDecl(ConstString name) { + if (!m_parser_vars) + return nullptr; + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + if (!target) + return nullptr; + + ClangASTContext::GetScratch(*target); + + if (!m_parser_vars->m_persistent_vars) + return nullptr; + return m_parser_vars->m_persistent_vars->GetPersistentDecl(name); +} +void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context, + const ConstString name, + unsigned int current_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - SymbolContextList sc_list; + NamedDecl *persistent_decl = GetPersistentDecl(name); - const ConstString name(context.m_decl_name.getAsString().c_str()); - if (IgnoreName(name, false)) + if (!persistent_decl) return; - // Only look for functions by name out in our symbols if the function doesn't - // start with our phony prefix of '$' - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + Decl *parser_persistent_decl = CopyDecl(persistent_decl); + + if (!parser_persistent_decl) + return; + + NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(parser_persistent_decl); + + if (!parser_named_decl) + return; + + if (clang::FunctionDecl *parser_function_decl = + llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) { + MaybeRegisterFunctionBody(parser_function_decl); + } + + LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id, + name.GetCString()); + + context.AddNamedDecl(parser_named_decl); +} + +void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context, + unsigned int current_id) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); SymbolContext sym_ctx; if (frame != nullptr) sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); - // Try the persistent decls, which take precedence over all else. - if (!namespace_decl) { - do { - if (!target) - break; + if (m_ctx_obj) { + Status status; + lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); + if (!ctx_obj_ptr || status.Fail()) + return; - ClangASTContext *scratch_clang_ast_context = - target->GetScratchClangASTContext(); + AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), + current_id); - if (!scratch_clang_ast_context) - break; + m_struct_vars->m_object_pointer_type = + TypeFromUser(ctx_obj_ptr->GetCompilerType()); - ASTContext *scratch_ast_context = - scratch_clang_ast_context->getASTContext(); + return; + } - if (!scratch_ast_context) - break; + // Clang is looking for the type of "this" - NamedDecl *persistent_decl = - m_parser_vars->m_persistent_vars->GetPersistentDecl(name); + if (frame == nullptr) + return; - if (!persistent_decl) - break; + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - Decl *parser_persistent_decl = CopyDecl(persistent_decl); + if (!function_block) + return; - if (!parser_persistent_decl) - break; + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); - NamedDecl *parser_named_decl = - dyn_cast<NamedDecl>(parser_persistent_decl); + if (!function_decl_ctx) + return; - if (!parser_named_decl) - break; + clang::CXXMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); - if (clang::FunctionDecl *parser_function_decl = - llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) { - MaybeRegisterFunctionBody(parser_function_decl); - } + if (method_decl) { + clang::CXXRecordDecl *class_decl = method_decl->getParent(); - LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id, - name.GetCString()); + QualType class_qual_type(class_decl->getTypeForDecl(), 0); - context.AddNamedDecl(parser_named_decl); - } while (false); - } + TypeFromUser class_user_type(class_qual_type.getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()); - if (name.GetCString()[0] == '$' && !namespace_decl) { - static ConstString g_lldb_class_name("$__lldb_class"); + LLDB_LOG(log, " CEDM::FEVD[{0}] Adding type for $__lldb_class: {1}", + current_id, class_qual_type.getAsString()); - if (name == g_lldb_class_name) { - if (m_ctx_obj) { - Status status; - lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); - if (!ctx_obj_ptr || status.Fail()) - return; + AddThisType(context, class_user_type, current_id); - AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), - current_id); + if (method_decl->isInstance()) { + // self is a pointer to the object - m_struct_vars->m_object_pointer_type = - TypeFromUser(ctx_obj_ptr->GetCompilerType()); + QualType class_pointer_type = + method_decl->getASTContext().getPointerType(class_qual_type); - return; - } + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()); - // Clang is looking for the type of "this" + m_struct_vars->m_object_pointer_type = self_user_type; + } + return; + } - if (frame == nullptr) - return; + // This branch will get hit if we are executing code in the context of + // a function that claims to have an object pointer (through + // DW_AT_object_pointer?) but is not formally a method of the class. + // In that case, just look up the "this" variable in the current scope + // and use its type. + // FIXME: This code is formally correct, but clang doesn't currently + // emit DW_AT_object_pointer + // for C++ so it hasn't actually been tested. - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + VariableList *vars = frame->GetVariableList(false); - if (!function_block) - return; + lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); - CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + if (this_var && this_var->IsInScope(frame) && + this_var->LocationIsValidForFrame(frame)) { + Type *this_type = this_var->GetType(); - if (!function_decl_ctx) - return; + if (!this_type) + return; - clang::CXXMethodDecl *method_decl = - ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); + TypeFromUser pointee_type = + this_type->GetForwardCompilerType().GetPointeeType(); - if (method_decl) { - clang::CXXRecordDecl *class_decl = method_decl->getParent(); + LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_class: {1}", current_id, + ClangUtil::GetQualType(pointee_type).getAsString()); - QualType class_qual_type(class_decl->getTypeForDecl(), 0); + AddThisType(context, pointee_type, current_id); + TypeFromUser this_user_type(this_type->GetFullCompilerType()); + m_struct_vars->m_object_pointer_type = this_user_type; + } +} - TypeFromUser class_user_type( - class_qual_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&class_decl->getASTContext())); +void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context, + unsigned int current_id) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) { - ASTDumper ast_dumper(class_qual_type); - LLDB_LOGF(log, " CEDM::FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); - } + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - AddThisType(context, class_user_type, current_id); + if (m_ctx_obj) { + Status status; + lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); + if (!ctx_obj_ptr || status.Fail()) + return; - if (method_decl->isInstance()) { - // self is a pointer to the object + AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), current_id); - QualType class_pointer_type = - method_decl->getASTContext().getPointerType(class_qual_type); + m_struct_vars->m_object_pointer_type = + TypeFromUser(ctx_obj_ptr->GetCompilerType()); - TypeFromUser self_user_type( - class_pointer_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + return; + } - m_struct_vars->m_object_pointer_type = self_user_type; - } - } else { - // This branch will get hit if we are executing code in the context of - // a function that claims to have an object pointer (through - // DW_AT_object_pointer?) but is not formally a method of the class. - // In that case, just look up the "this" variable in the current scope - // and use its type. - // FIXME: This code is formally correct, but clang doesn't currently - // emit DW_AT_object_pointer - // for C++ so it hasn't actually been tested. + // Clang is looking for the type of "*self" + + if (!frame) + return; - VariableList *vars = frame->GetVariableList(false); + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - if (this_var && this_var->IsInScope(frame) && - this_var->LocationIsValidForFrame(frame)) { - Type *this_type = this_var->GetType(); + if (!function_block) + return; - if (!this_type) - return; + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); - TypeFromUser pointee_type = - this_type->GetForwardCompilerType().GetPointeeType(); + if (!function_decl_ctx) + return; - if (pointee_type.IsValid()) { - if (log) { - ASTDumper ast_dumper(pointee_type); - LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); - } + clang::ObjCMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); - AddThisType(context, pointee_type, current_id); - TypeFromUser this_user_type(this_type->GetFullCompilerType()); - m_struct_vars->m_object_pointer_type = this_user_type; - return; - } - } - } + if (method_decl) { + ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); + if (!self_interface) return; - } - static ConstString g_lldb_objc_class_name("$__lldb_objc_class"); - if (name == g_lldb_objc_class_name) { - if (m_ctx_obj) { - Status status; - lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); - if (!ctx_obj_ptr || status.Fail()) - return; + const clang::Type *interface_type = self_interface->getTypeForDecl(); - AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), - current_id); + if (!interface_type) + return; // This is unlikely, but we have seen crashes where this + // occurred - m_struct_vars->m_object_pointer_type = - TypeFromUser(ctx_obj_ptr->GetCompilerType()); + TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()); - return; - } + LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}", + current_id, ClangUtil::ToString(interface_type)); - // Clang is looking for the type of "*self" + AddOneType(context, class_user_type, current_id); - if (!frame) - return; + if (method_decl->isInstanceMethod()) { + // self is a pointer to the object - SymbolContext sym_ctx = frame->GetSymbolContext( - lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + QualType class_pointer_type = + method_decl->getASTContext().getObjCObjectPointerType( + QualType(interface_type, 0)); - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()); - if (!function_block) - return; + m_struct_vars->m_object_pointer_type = self_user_type; + } else { + // self is a Class pointer + QualType class_type = method_decl->getASTContext().getObjCClassType(); - CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + TypeFromUser self_user_type(class_type.getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()); - if (!function_decl_ctx) - return; + m_struct_vars->m_object_pointer_type = self_user_type; + } - clang::ObjCMethodDecl *method_decl = - ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + return; + } + // This branch will get hit if we are executing code in the context of + // a function that claims to have an object pointer (through + // DW_AT_object_pointer?) but is not formally a method of the class. + // In that case, just look up the "self" variable in the current scope + // and use its type. - if (method_decl) { - ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); + VariableList *vars = frame->GetVariableList(false); - if (!self_interface) - return; + lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); - const clang::Type *interface_type = self_interface->getTypeForDecl(); + if (!self_var) + return; + if (!self_var->IsInScope(frame)) + return; + if (!self_var->LocationIsValidForFrame(frame)) + return; - if (!interface_type) - return; // This is unlikely, but we have seen crashes where this - // occurred + Type *self_type = self_var->GetType(); - TypeFromUser class_user_type( - QualType(interface_type, 0).getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + if (!self_type) + return; - if (log) { - ASTDumper ast_dumper(interface_type); - LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); - } + CompilerType self_clang_type = self_type->GetFullCompilerType(); - AddOneType(context, class_user_type, current_id); + if (ClangASTContext::IsObjCClassType(self_clang_type)) { + return; + } + if (!ClangASTContext::IsObjCObjectPointerType(self_clang_type)) + return; + self_clang_type = self_clang_type.GetPointeeType(); - if (method_decl->isInstanceMethod()) { - // self is a pointer to the object + if (!self_clang_type) + return; - QualType class_pointer_type = - method_decl->getASTContext().getObjCObjectPointerType( - QualType(interface_type, 0)); + LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}", + current_id, ClangUtil::ToString(self_type->GetFullCompilerType())); - TypeFromUser self_user_type( - class_pointer_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + TypeFromUser class_user_type(self_clang_type); - m_struct_vars->m_object_pointer_type = self_user_type; - } else { - // self is a Class pointer - QualType class_type = method_decl->getASTContext().getObjCClassType(); + AddOneType(context, class_user_type, current_id); - TypeFromUser self_user_type( - class_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + TypeFromUser self_user_type(self_type->GetFullCompilerType()); - m_struct_vars->m_object_pointer_type = self_user_type; - } + m_struct_vars->m_object_pointer_type = self_user_type; +} - return; - } else { - // This branch will get hit if we are executing code in the context of - // a function that claims to have an object pointer (through - // DW_AT_object_pointer?) but is not formally a method of the class. - // In that case, just look up the "self" variable in the current scope - // and use its type. +void ClangExpressionDeclMap::LookupLocalVarNamespace( + SymbolContext &sym_ctx, NameSearchContext &name_context) { + if (sym_ctx.block == nullptr) + return; - VariableList *vars = frame->GetVariableList(false); + CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); + if (!frame_decl_context) + return; - lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + ClangASTContext *frame_ast = llvm::dyn_cast_or_null<ClangASTContext>( + frame_decl_context.GetTypeSystem()); + if (!frame_ast) + return; - if (self_var && self_var->IsInScope(frame) && - self_var->LocationIsValidForFrame(frame)) { - Type *self_type = self_var->GetType(); + clang::NamespaceDecl *namespace_decl = + m_clang_ast_context->GetUniqueNamespaceDeclaration( + g_lldb_local_vars_namespace_cstr, nullptr); + if (!namespace_decl) + return; - if (!self_type) - return; + name_context.AddNamedDecl(namespace_decl); + clang::DeclContext *ctxt = clang::Decl::castToDeclContext(namespace_decl); + ctxt->setHasExternalVisibleStorage(true); + name_context.m_found.local_vars_nsp = true; +} - CompilerType self_clang_type = self_type->GetFullCompilerType(); +void ClangExpressionDeclMap::LookupInModulesDeclVendor( + NameSearchContext &context, ConstString name, unsigned current_id) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (ClangASTContext::IsObjCClassType(self_clang_type)) { - return; - } else if (ClangASTContext::IsObjCObjectPointerType( - self_clang_type)) { - self_clang_type = self_clang_type.GetPointeeType(); + if (!m_target) + return; - if (!self_clang_type) - return; + auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); + if (!modules_decl_vendor) + return; - if (log) { - ASTDumper ast_dumper(self_type->GetFullCompilerType()); - LLDB_LOGF(log, - " FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); - } + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - TypeFromUser class_user_type(self_clang_type); + if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) + return; - AddOneType(context, class_user_type, current_id); + assert(!decls.empty() && "FindDecls returned true but no decls?"); + clang::NamedDecl *const decl_from_modules = decls[0]; - TypeFromUser self_user_type(self_type->GetFullCompilerType()); + LLDB_LOG(log, + " CAS::FEVD[{0}] Matching decl found for " + "\"{1}\" in the modules", + current_id, name); - m_struct_vars->m_object_pointer_type = self_user_type; - return; - } - } - } + clang::Decl *copied_decl = CopyDecl(decl_from_modules); + if (!copied_decl) { + LLDB_LOG(log, + " CAS::FEVD[{0}] - Couldn't export a " + "declaration from the modules", + current_id); + return; + } - return; - } + if (auto copied_function = dyn_cast<clang::FunctionDecl>(copied_decl)) { + MaybeRegisterFunctionBody(copied_function); - if (name == ConstString(g_lldb_local_vars_namespace_cstr)) { - CompilerDeclContext frame_decl_context = - sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() - : CompilerDeclContext(); - - if (frame_decl_context) { - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>( - frame_decl_context.GetTypeSystem()); - - if (ast) { - clang::NamespaceDecl *namespace_decl = - ClangASTContext::GetUniqueNamespaceDeclaration( - m_ast_context, name.GetCString(), nullptr); - if (namespace_decl) { - context.AddNamedDecl(namespace_decl); - clang::DeclContext *clang_decl_ctx = - clang::Decl::castToDeclContext(namespace_decl); - clang_decl_ctx->setHasExternalVisibleStorage(true); - context.m_found.local_vars_nsp = true; - } - } - } + context.AddNamedDecl(copied_function); - return; - } + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) { + context.AddNamedDecl(copied_var); + context.m_found.variable = true; + } +} - // any other $__lldb names should be weeded out now - if (name.GetStringRef().startswith("$__lldb")) - return; +bool ClangExpressionDeclMap::LookupLocalVariable( + NameSearchContext &context, ConstString name, unsigned current_id, + SymbolContext &sym_ctx, CompilerDeclContext &namespace_decl) { + if (sym_ctx.block == nullptr) + return false; - ExpressionVariableSP pvar_sp( - m_parser_vars->m_persistent_vars->GetVariable(name)); + CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext(); + if (!decl_context) + return false; - if (pvar_sp) { - AddOneVariable(context, pvar_sp, current_id); - return; + // Make sure that the variables are parsed so that we have the + // declarations. + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + VariableListSP vars = frame->GetInScopeVariableList(true); + for (size_t i = 0; i < vars->GetSize(); i++) + vars->GetVariableAtIndex(i)->GetDecl(); + + // Search for declarations matching the name. Do not include imported + // decls in the search if we are looking for decls in the artificial + // namespace $__lldb_local_vars. + std::vector<CompilerDecl> found_decls = + decl_context.FindDeclByName(name, namespace_decl.IsValid()); + + VariableSP var; + bool variable_found = false; + for (CompilerDecl decl : found_decls) { + for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) { + VariableSP candidate_var = vars->GetVariableAtIndex(vi); + if (candidate_var->GetDecl() == decl) { + var = candidate_var; + break; + } } - const char *reg_name(&name.GetCString()[1]); + if (var && !variable_found) { + variable_found = true; + ValueObjectSP valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + } + } + return variable_found; +} - if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { - const RegisterInfo *reg_info( - m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName( - reg_name)); +/// Structure to hold the info needed when comparing function +/// declarations. +namespace { +struct FuncDeclInfo { + ConstString m_name; + CompilerType m_copied_type; + uint32_t m_decl_lvl; + SymbolContext m_sym_ctx; +}; +} // namespace + +SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts( + const SymbolContextList &sc_list, + const CompilerDeclContext &frame_decl_context) { + // First, symplify things by looping through the symbol contexts to + // remove unwanted functions and separate out the functions we want to + // compare and prune into a separate list. Cache the info needed about + // the function declarations in a vector for efficiency. + uint32_t num_indices = sc_list.GetSize(); + SymbolContextList sc_sym_list; + std::vector<FuncDeclInfo> decl_infos; + decl_infos.reserve(num_indices); + clang::DeclContext *frame_decl_ctx = + (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); + ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>( + frame_decl_context.GetTypeSystem()); - if (reg_info) { - LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id, - reg_info->name); + for (uint32_t index = 0; index < num_indices; ++index) { + FuncDeclInfo fdi; + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); - AddOneRegister(context, reg_info, current_id); - } + // We don't know enough about symbols to compare them, but we should + // keep them in the list. + Function *function = sym_ctx.function; + if (!function) { + sc_sym_list.Append(sym_ctx); + continue; + } + // Filter out functions without declaration contexts, as well as + // class/instance methods, since they'll be skipped in the code that + // follows anyway. + CompilerDeclContext func_decl_context = function->GetDeclContext(); + if (!func_decl_context || + func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + // We can only prune functions for which we can copy the type. + CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); + CompilerType copied_func_type = GuardedCopyType(func_clang_type); + if (!copied_func_type) { + sc_sym_list.Append(sym_ctx); + continue; } - } else { - ValueObjectSP valobj; - VariableSP var; - - bool local_var_lookup = - !namespace_decl || (namespace_decl.GetName() == - ConstString(g_lldb_local_vars_namespace_cstr)); - if (frame && local_var_lookup) { - CompilerDeclContext compiler_decl_context = - sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() - : CompilerDeclContext(); - - if (compiler_decl_context) { - // Make sure that the variables are parsed so that we have the - // declarations. - VariableListSP vars = frame->GetInScopeVariableList(true); - for (size_t i = 0; i < vars->GetSize(); i++) - vars->GetVariableAtIndex(i)->GetDecl(); - - // Search for declarations matching the name. Do not include imported - // decls in the search if we are looking for decls in the artificial - // namespace $__lldb_local_vars. - std::vector<CompilerDecl> found_decls = - compiler_decl_context.FindDeclByName(name, - namespace_decl.IsValid()); - - bool variable_found = false; - for (CompilerDecl decl : found_decls) { - for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) { - VariableSP candidate_var = vars->GetVariableAtIndex(vi); - if (candidate_var->GetDecl() == decl) { - var = candidate_var; - break; - } - } - if (var && !variable_found) { - variable_found = true; - valobj = ValueObjectVariable::Create(frame, var); - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - } - } - if (variable_found) - return; - } + fdi.m_sym_ctx = sym_ctx; + fdi.m_name = function->GetName(); + fdi.m_copied_type = copied_func_type; + fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; + if (fdi.m_copied_type && func_decl_context) { + // Call CountDeclLevels to get the number of parent scopes we have + // to look through before we find the function declaration. When + // comparing functions of the same type, the one with a lower count + // will be closer to us in the lookup scope and shadows the other. + clang::DeclContext *func_decl_ctx = + (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); + fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx, + &fdi.m_name, &fdi.m_copied_type); } - if (target) { - var = FindGlobalVariable(*target, module_sp, name, &namespace_decl, - nullptr); + decl_infos.emplace_back(fdi); + } - if (var) { - valobj = ValueObjectVariable::Create(target, var); - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - return; - } + // Loop through the functions in our cache looking for matching types, + // then compare their scope levels to see which is closer. + std::multimap<CompilerType, const FuncDeclInfo *> matches; + for (const FuncDeclInfo &fdi : decl_infos) { + const CompilerType t = fdi.m_copied_type; + auto q = matches.find(t); + if (q != matches.end()) { + if (q->second->m_decl_lvl > fdi.m_decl_lvl) + // This function is closer; remove the old set. + matches.erase(t); + else if (q->second->m_decl_lvl < fdi.m_decl_lvl) + // The functions in our set are closer - skip this one. + continue; } + matches.insert(std::make_pair(t, &fdi)); + } - std::vector<clang::NamedDecl *> decls_from_modules; + // Loop through our matches and add their symbol contexts to our list. + SymbolContextList sc_func_list; + for (const auto &q : matches) + sc_func_list.Append(q.second->m_sym_ctx); - if (target) { - if (ClangModulesDeclVendor *decl_vendor = - target->GetClangModulesDeclVendor()) { - decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); - } - } + // Rejoin the lists with the functions in front. + sc_func_list.Append(sc_sym_list); + return sc_func_list; +} - const bool include_inlines = false; - sc_list.Clear(); - if (namespace_decl && module_sp) { - const bool include_symbols = false; +void ClangExpressionDeclMap::LookupFunction(NameSearchContext &context, + lldb::ModuleSP module_sp, + ConstString name, + CompilerDeclContext &namespace_decl, + unsigned current_id) { + if (!m_parser_vars) + return; - module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase, - include_symbols, include_inlines, sc_list); - } else if (target && !namespace_decl) { - const bool include_symbols = true; + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - // TODO Fix FindFunctions so that it doesn't return - // instance methods for eFunctionNameTypeBase. + std::vector<clang::NamedDecl *> decls_from_modules; - target->GetImages().FindFunctions(name, eFunctionNameTypeFull, - include_symbols, include_inlines, - sc_list); + if (target) { + if (ClangModulesDeclVendor *decl_vendor = + target->GetClangModulesDeclVendor()) { + decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); } + } - // If we found more than one function, see if we can use the frame's decl - // context to remove functions that are shadowed by other functions which - // match in type but are nearer in scope. - // - // AddOneFunction will not add a function whose type has already been - // added, so if there's another function in the list with a matching type, - // check to see if their decl context is a parent of the current frame's or - // was imported via a and using statement, and pick the best match - // according to lookup rules. - if (sc_list.GetSize() > 1) { - // Collect some info about our frame's context. - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - SymbolContext frame_sym_ctx; - if (frame != nullptr) - frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | - lldb::eSymbolContextBlock); - CompilerDeclContext frame_decl_context = - frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() - : CompilerDeclContext(); - - // We can't do this without a compiler decl context for our frame. - if (frame_decl_context) { - clang::DeclContext *frame_decl_ctx = - (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>( - frame_decl_context.GetTypeSystem()); - - // Structure to hold the info needed when comparing function - // declarations. - struct FuncDeclInfo { - ConstString m_name; - CompilerType m_copied_type; - uint32_t m_decl_lvl; - SymbolContext m_sym_ctx; - }; - - // First, symplify things by looping through the symbol contexts to - // remove unwanted functions and separate out the functions we want to - // compare and prune into a separate list. Cache the info needed about - // the function declarations in a vector for efficiency. - SymbolContextList sc_sym_list; - uint32_t num_indices = sc_list.GetSize(); - std::vector<FuncDeclInfo> fdi_cache; - fdi_cache.reserve(num_indices); - for (uint32_t index = 0; index < num_indices; ++index) { - FuncDeclInfo fdi; - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(index, sym_ctx); - - // We don't know enough about symbols to compare them, but we should - // keep them in the list. - Function *function = sym_ctx.function; - if (!function) { - sc_sym_list.Append(sym_ctx); - continue; - } - // Filter out functions without declaration contexts, as well as - // class/instance methods, since they'll be skipped in the code that - // follows anyway. - CompilerDeclContext func_decl_context = function->GetDeclContext(); - if (!func_decl_context || - func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) - continue; - // We can only prune functions for which we can copy the type. - CompilerType func_clang_type = - function->GetType()->GetFullCompilerType(); - CompilerType copied_func_type = GuardedCopyType(func_clang_type); - if (!copied_func_type) { - sc_sym_list.Append(sym_ctx); - continue; - } + const bool include_inlines = false; + SymbolContextList sc_list; + if (namespace_decl && module_sp) { + const bool include_symbols = false; - fdi.m_sym_ctx = sym_ctx; - fdi.m_name = function->GetName(); - fdi.m_copied_type = copied_func_type; - fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; - if (fdi.m_copied_type && func_decl_context) { - // Call CountDeclLevels to get the number of parent scopes we have - // to look through before we find the function declaration. When - // comparing functions of the same type, the one with a lower count - // will be closer to us in the lookup scope and shadows the other. - clang::DeclContext *func_decl_ctx = - (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); - fdi.m_decl_lvl = ast->CountDeclLevels( - frame_decl_ctx, func_decl_ctx, &fdi.m_name, &fdi.m_copied_type); - } - fdi_cache.emplace_back(fdi); - } + module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase, + include_symbols, include_inlines, sc_list); + } else if (target && !namespace_decl) { + const bool include_symbols = true; - // Loop through the functions in our cache looking for matching types, - // then compare their scope levels to see which is closer. - std::multimap<CompilerType, const FuncDeclInfo *> matches; - for (const FuncDeclInfo &fdi : fdi_cache) { - const CompilerType t = fdi.m_copied_type; - auto q = matches.find(t); - if (q != matches.end()) { - if (q->second->m_decl_lvl > fdi.m_decl_lvl) - // This function is closer; remove the old set. - matches.erase(t); - else if (q->second->m_decl_lvl < fdi.m_decl_lvl) - // The functions in our set are closer - skip this one. - continue; - } - matches.insert(std::make_pair(t, &fdi)); - } + // TODO Fix FindFunctions so that it doesn't return + // instance methods for eFunctionNameTypeBase. - // Loop through our matches and add their symbol contexts to our list. - SymbolContextList sc_func_list; - for (const auto &q : matches) - sc_func_list.Append(q.second->m_sym_ctx); + target->GetImages().FindFunctions( + name, eFunctionNameTypeFull | eFunctionNameTypeBase, include_symbols, + include_inlines, sc_list); + } - // Rejoin the lists with the functions in front. - sc_list = sc_func_list; - sc_list.Append(sc_sym_list); - } + // If we found more than one function, see if we can use the frame's decl + // context to remove functions that are shadowed by other functions which + // match in type but are nearer in scope. + // + // AddOneFunction will not add a function whose type has already been + // added, so if there's another function in the list with a matching type, + // check to see if their decl context is a parent of the current frame's or + // was imported via a and using statement, and pick the best match + // according to lookup rules. + if (sc_list.GetSize() > 1) { + // Collect some info about our frame's context. + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext frame_sym_ctx; + if (frame != nullptr) + frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); + CompilerDeclContext frame_decl_context = + frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() + : CompilerDeclContext(); + + // We can't do this without a compiler decl context for our frame. + if (frame_decl_context) { + sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context); } + } - if (sc_list.GetSize()) { - Symbol *extern_symbol = nullptr; - Symbol *non_extern_symbol = nullptr; - - for (uint32_t index = 0, num_indices = sc_list.GetSize(); - index < num_indices; ++index) { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(index, sym_ctx); + if (sc_list.GetSize()) { + Symbol *extern_symbol = nullptr; + Symbol *non_extern_symbol = nullptr; - if (sym_ctx.function) { - CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); + for (uint32_t index = 0, num_indices = sc_list.GetSize(); + index < num_indices; ++index) { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); - if (!decl_ctx) - continue; + if (sym_ctx.function) { + CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); - // Filter out class/instance methods. - if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) - continue; + if (!decl_ctx) + continue; - AddOneFunction(context, sym_ctx.function, nullptr, current_id); - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } else if (sym_ctx.symbol) { - if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) { - sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); - if (sym_ctx.symbol == nullptr) - continue; - } + // Filter out class/instance methods. + if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) + continue; - if (sym_ctx.symbol->IsExternal()) - extern_symbol = sym_ctx.symbol; - else - non_extern_symbol = sym_ctx.symbol; + AddOneFunction(context, sym_ctx.function, nullptr, current_id); + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } else if (sym_ctx.symbol) { + if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) { + sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); + if (sym_ctx.symbol == nullptr) + continue; } + + if (sym_ctx.symbol->IsExternal()) + extern_symbol = sym_ctx.symbol; + else + non_extern_symbol = sym_ctx.symbol; } + } - if (!context.m_found.function_with_type_info) { - for (clang::NamedDecl *decl : decls_from_modules) { - if (llvm::isa<clang::FunctionDecl>(decl)) { - clang::NamedDecl *copied_decl = - llvm::cast_or_null<FunctionDecl>(CopyDecl(decl)); - if (copied_decl) { - context.AddNamedDecl(copied_decl); - context.m_found.function_with_type_info = true; - } + if (!context.m_found.function_with_type_info) { + for (clang::NamedDecl *decl : decls_from_modules) { + if (llvm::isa<clang::FunctionDecl>(decl)) { + clang::NamedDecl *copied_decl = + llvm::cast_or_null<FunctionDecl>(CopyDecl(decl)); + if (copied_decl) { + context.AddNamedDecl(copied_decl); + context.m_found.function_with_type_info = true; } } } + } - if (!context.m_found.function_with_type_info) { - if (extern_symbol) { - AddOneFunction(context, nullptr, extern_symbol, current_id); - context.m_found.function = true; - } else if (non_extern_symbol) { - AddOneFunction(context, nullptr, non_extern_symbol, current_id); - context.m_found.function = true; - } + if (!context.m_found.function_with_type_info) { + if (extern_symbol) { + AddOneFunction(context, nullptr, extern_symbol, current_id); + context.m_found.function = true; + } else if (non_extern_symbol) { + AddOneFunction(context, nullptr, non_extern_symbol, current_id); + context.m_found.function = true; } } + } +} - if (!context.m_found.function_with_type_info) { - // Try the modules next. +void ClangExpressionDeclMap::FindExternalVisibleDecls( + NameSearchContext &context, lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, unsigned int current_id) { + assert(m_ast_context); - do { - if (ClangModulesDeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor()) { - bool append = false; - uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) - break; + const ConstString name(context.m_decl_name.getAsString().c_str()); + if (IgnoreName(name, false)) + return; - clang::NamedDecl *const decl_from_modules = decls[0]; + // Only look for functions by name out in our symbols if the function doesn't + // start with our phony prefix of '$' - if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) { - if (log) { - LLDB_LOGF(log, - " CAS::FEVD[%u] Matching function found for " - "\"%s\" in the modules", - current_id, name.GetCString()); - } + Target *target = nullptr; + StackFrame *frame = nullptr; + SymbolContext sym_ctx; + if (m_parser_vars) { + target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + } + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - clang::Decl *copied_decl = CopyDecl(decl_from_modules); - clang::FunctionDecl *copied_function_decl = - copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) - : nullptr; + // Try the persistent decls, which take precedence over all else. + if (!namespace_decl) + SearchPersistenDecls(context, name, current_id); - if (!copied_function_decl) { - LLDB_LOGF(log, - " CAS::FEVD[%u] - Couldn't export a function " - "declaration from the modules", - current_id); + if (name.GetStringRef().startswith("$") && !namespace_decl) { + if (name == "$__lldb_class") { + LookUpLldbClass(context, current_id); + return; + } - break; - } + if (name == "$__lldb_objc_class") { + LookUpLldbObjCClass(context, current_id); + return; + } + if (name == g_lldb_local_vars_namespace_cstr) { + LookupLocalVarNamespace(sym_ctx, context); + return; + } + + // any other $__lldb names should be weeded out now + if (name.GetStringRef().startswith("$__lldb")) + return; - MaybeRegisterFunctionBody(copied_function_decl); + // No ParserVars means we can't do register or variable lookup. + if (!m_parser_vars || !m_parser_vars->m_persistent_vars) + return; - context.AddNamedDecl(copied_function_decl); + ExpressionVariableSP pvar_sp( + m_parser_vars->m_persistent_vars->GetVariable(name)); - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) { - if (log) { - LLDB_LOGF(log, - " CAS::FEVD[%u] Matching variable found for " - "\"%s\" in the modules", - current_id, name.GetCString()); - } + if (pvar_sp) { + AddOneVariable(context, pvar_sp, current_id); + return; + } - clang::Decl *copied_decl = CopyDecl(decl_from_modules); - clang::VarDecl *copied_var_decl = - copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) - : nullptr; + assert(name.GetStringRef().startswith("$")); + llvm::StringRef reg_name = name.GetStringRef().substr(1); - if (!copied_var_decl) { - LLDB_LOGF(log, - " CAS::FEVD[%u] - Couldn't export a variable " - "declaration from the modules", - current_id); + if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { + const RegisterInfo *reg_info( + m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName( + reg_name)); - break; - } + if (reg_info) { + LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id, + reg_info->name); - context.AddNamedDecl(copied_var_decl); + AddOneRegister(context, reg_info, current_id); + } + } + return; + } - context.m_found.variable = true; - } - } - } while (false); + bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() == + g_lldb_local_vars_namespace_cstr); + if (frame && local_var_lookup) + if (LookupLocalVariable(context, name, current_id, sym_ctx, namespace_decl)) + return; + + if (target) { + ValueObjectSP valobj; + VariableSP var; + var = FindGlobalVariable(*target, module_sp, name, &namespace_decl); + + if (var) { + valobj = ValueObjectVariable::Create(target, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; } + } - if (target && !context.m_found.variable && !namespace_decl) { - // We couldn't find a non-symbol variable for this. Now we'll hunt for a - // generic data symbol, and -- if it is found -- treat it as a variable. - Status error; + LookupFunction(context, module_sp, name, namespace_decl, current_id); - const Symbol *data_symbol = - m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); + // Try the modules next. + if (!context.m_found.function_with_type_info) + LookupInModulesDeclVendor(context, name, current_id); - if (!error.Success()) { - const unsigned diag_id = - m_ast_context->getDiagnostics().getCustomDiagID( - clang::DiagnosticsEngine::Level::Error, "%0"); - m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString(); - } + if (target && !context.m_found.variable && !namespace_decl) { + // We couldn't find a non-symbol variable for this. Now we'll hunt for a + // generic data symbol, and -- if it is found -- treat it as a variable. + Status error; - if (data_symbol) { - std::string warning("got name from symbols: "); - warning.append(name.AsCString()); - const unsigned diag_id = - m_ast_context->getDiagnostics().getCustomDiagID( - clang::DiagnosticsEngine::Level::Warning, "%0"); - m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); - AddOneGenericVariable(context, *data_symbol, current_id); - context.m_found.variable = true; - } + const Symbol *data_symbol = + m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); + + if (!error.Success()) { + const unsigned diag_id = + m_ast_context->getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Level::Error, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString(); + } + + if (data_symbol) { + std::string warning("got name from symbols: "); + warning.append(name.AsCString()); + const unsigned diag_id = + m_ast_context->getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Level::Warning, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); + AddOneGenericVariable(context, *data_symbol, current_id); + context.m_found.variable = true; } } } @@ -1543,15 +1508,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return false; } - ASTContext *ast = clang_ast->getASTContext(); - - if (!ast) { - if (log) - log->PutCString( - "There is no AST context for the current execution context"); - return false; - } - DWARFExpression &var_location_expr = var->LocationExpression(); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); @@ -1664,14 +1620,10 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (is_reference) entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; - if (log) { - ASTDumper orig_dumper(ut.GetOpaqueQualType()); - ASTDumper ast_dumper(var_decl); - LLDB_LOGF(log, - " CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", - current_id, decl_name.c_str(), ast_dumper.GetCString(), - orig_dumper.GetCString()); - } + LLDB_LOG(log, + " CEDM::FEVD[{0}] Found variable {1}, returned\n{2} (original {3})", + current_id, decl_name, ClangUtil::DumpDecl(var_decl), + ClangUtil::ToString(ut)); } void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, @@ -1703,11 +1655,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_value.Clear(); - if (log) { - ASTDumper ast_dumper(var_decl); - LLDB_LOGF(log, " CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, - pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); - } + LLDB_LOG(log, " CEDM::FEVD[{0}] Added pvar {1}, returned\n{2}", current_id, + pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl)); } void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, @@ -1722,17 +1671,16 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, if (target == nullptr) return; - ASTContext *scratch_ast_context = - target->GetScratchClangASTContext()->getASTContext(); + ClangASTContext *scratch_ast_context = ClangASTContext::GetScratch(*target); + if (!scratch_ast_context) + return; - TypeFromUser user_type( - ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid) - .GetPointerType() - .GetLValueReferenceType()); - TypeFromParser parser_type( - ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid) - .GetPointerType() - .GetLValueReferenceType()); + TypeFromUser user_type(scratch_ast_context->GetBasicType(eBasicTypeVoid) + .GetPointerType() + .GetLValueReferenceType()); + TypeFromParser parser_type(m_clang_ast_context->GetBasicType(eBasicTypeVoid) + .GetPointerType() + .GetLValueReferenceType()); NamedDecl *var_decl = context.AddVarDecl(parser_type); std::string decl_name(context.m_decl_name.getAsString()); @@ -1761,86 +1709,8 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_sym = &symbol; - if (log) { - ASTDumper ast_dumper(var_decl); - - LLDB_LOGF(log, " CEDM::FEVD[%u] Found variable %s, returned %s", - current_id, decl_name.c_str(), ast_dumper.GetCString()); - } -} - -bool ClangExpressionDeclMap::ResolveUnknownTypes() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - - ClangASTContextForExpressions *scratch_ast_context = - static_cast<ClangASTContextForExpressions *>( - target->GetScratchClangASTContext()); - - for (size_t index = 0, num_entities = m_found_entities.GetSize(); - index < num_entities; ++index) { - ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); - - ClangExpressionVariable::ParserVars *parser_vars = - llvm::cast<ClangExpressionVariable>(entity.get()) - ->GetParserVars(GetParserID()); - - if (entity->m_flags & ClangExpressionVariable::EVUnknownType) { - const NamedDecl *named_decl = parser_vars->m_named_decl; - const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); - - if (!var_decl) { - LLDB_LOGF(log, "Entity of unknown type does not have a VarDecl"); - return false; - } - - if (log) { - ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl)); - LLDB_LOGF(log, "Variable of unknown type now has Decl %s", - ast_dumper.GetCString()); - } - - QualType var_type = var_decl->getType(); - TypeFromParser parser_type( - var_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&var_decl->getASTContext())); - - lldb::opaque_compiler_type_t copied_type = nullptr; - if (m_ast_importer_sp) { - copied_type = m_ast_importer_sp->CopyType( - scratch_ast_context->getASTContext(), &var_decl->getASTContext(), - var_type.getAsOpaquePtr()); - } else if (HasMerger()) { - copied_type = CopyTypeWithMerger( - var_decl->getASTContext(), - scratch_ast_context->GetMergerUnchecked(), var_type) - .getAsOpaquePtr(); - } else { - lldbassert(0 && "No mechanism to copy a resolved unknown type!"); - return false; - } - - if (!copied_type) { - LLDB_LOGF(log, "ClangExpressionDeclMap::ResolveUnknownType - Couldn't " - "import the type for a variable"); - - return (bool)lldb::ExpressionVariableSP(); - } - - TypeFromUser user_type(copied_type, scratch_ast_context); - - // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, - // user_type.GetOpaqueQualType()); - parser_vars->m_lldb_value.SetCompilerType(user_type); - parser_vars->m_parser_type = parser_type; - - entity->SetCompilerType(user_type); - - entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); - } - } - - return true; + LLDB_LOG(log, " CEDM::FEVD[{0}] Found variable {1}, returned\n{2}", + current_id, decl_name, ClangUtil::DumpDecl(var_decl)); } void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, @@ -1849,8 +1719,8 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); CompilerType clang_type = - ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( - m_ast_context, reg_info->encoding, reg_info->byte_size * 8); + m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( + reg_info->encoding, reg_info->byte_size * 8); if (!clang_type) { LLDB_LOGF(log, " Tried to add a type for %s, but couldn't get one", @@ -1880,12 +1750,9 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, parser_vars->m_lldb_value.Clear(); entity->m_flags |= ClangExpressionVariable::EVBareRegister; - if (log) { - ASTDumper ast_dumper(var_decl); - LLDB_LOGF(log, " CEDM::FEVD[%d] Added register %s, returned %s", - current_id, context.m_decl_name.getAsString().c_str(), - ast_dumper.GetCString()); - } + LLDB_LOG(log, " CEDM::FEVD[{0}] Added register {1}, returned\n{2}", + current_id, context.m_decl_name.getAsString(), + ClangUtil::DumpDecl(var_decl)); } void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, @@ -1928,17 +1795,16 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, CopyDecl(function_template)); if (copied_function_template) { if (log) { - ASTDumper ast_dumper((clang::Decl *)copied_function_template); - StreamString ss; function->DumpSymbolContext(&ss); - log->Printf(" CEDM::FEVD[%u] Imported decl for function template" - " %s (description %s), returned %s", - current_id, - copied_function_template->getNameAsString().c_str(), - ss.GetData(), ast_dumper.GetCString()); + LLDB_LOG(log, + " CEDM::FEVD[{0}] Imported decl for function template" + " {1} (description {2}), returned\n{3}", + current_id, copied_function_template->getNameAsString(), + ss.GetData(), + ClangUtil::DumpDecl(copied_function_template)); } context.AddNamedDecl(copied_function_template); @@ -1948,18 +1814,15 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, llvm::dyn_cast_or_null<clang::FunctionDecl>( CopyDecl(src_function_decl))) { if (log) { - ASTDumper ast_dumper((clang::Decl *)copied_function_decl); - StreamString ss; function->DumpSymbolContext(&ss); - LLDB_LOGF(log, - " CEDM::FEVD[%u] Imported decl for function %s " - "(description %s), returned %s", - current_id, - copied_function_decl->getNameAsString().c_str(), - ss.GetData(), ast_dumper.GetCString()); + LLDB_LOG(log, + " CEDM::FEVD[{0}]] Imported decl for function {1} " + "(description {2}), returned\n{3}", + current_id, copied_function_decl->getNameAsString(), + ss.GetData(), ClangUtil::DumpDecl(copied_function_decl)); } context.AddNamedDecl(copied_function_decl); @@ -2061,20 +1924,17 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, parser_vars->m_llvm_value = nullptr; if (log) { - std::string function_str = - function_decl ? ASTDumper(function_decl).GetCString() : "nullptr"; - StreamString ss; fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); - LLDB_LOGF( - log, - " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", - current_id, (function ? "specific" : "generic"), decl_name.c_str(), - ss.GetData(), function_str.c_str()); + LLDB_LOG(log, + " CEDM::FEVD[{0}] Found {1} function {2} (description {3}), " + "returned\n{4}", + current_id, (function ? "specific" : "generic"), decl_name, + ss.GetData(), ClangUtil::DumpDecl(function_decl)); } } @@ -2097,11 +1957,11 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType()) { CompilerType void_clang_type = - ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); + m_clang_ast_context->GetBasicType(eBasicTypeVoid); CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); - CompilerType method_type = ClangASTContext::CreateFunctionType( - m_ast_context, void_clang_type, &void_ptr_clang_type, 1, false, 0); + CompilerType method_type = m_clang_ast_context->CreateFunctionType( + void_clang_type, &void_ptr_clang_type, 1, false, 0); const bool is_virtual = false; const bool is_static = false; @@ -2110,22 +1970,16 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, const bool is_attr_used = true; const bool is_artificial = false; - CXXMethodDecl *method_decl = - ClangASTContext::GetASTContext(m_ast_context) - ->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, - method_type, lldb::eAccessPublic, is_virtual, is_static, - is_inline, is_explicit, is_attr_used, is_artificial); - - if (log) { - ASTDumper method_ast_dumper((clang::Decl *)method_decl); - ASTDumper type_ast_dumper(copied_clang_type); + CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, + method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, + is_explicit, is_attr_used, is_artificial); - LLDB_LOGF(log, - " CEDM::AddThisType Added function $__lldb_expr " - "(description %s) for this type %s", - method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); - } + LLDB_LOG(log, + " CEDM::AddThisType Added function $__lldb_expr " + "(description {0}) for this type\n{1}", + ClangUtil::ToString(copied_clang_type), + ClangUtil::DumpDecl(method_decl)); } if (!copied_clang_type.IsValid()) |
