diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
| commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
| tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /lldb/source/Plugins/ExpressionParser | |
| parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) | |
Notes
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser')
28 files changed, 1108 insertions, 1639 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp deleted file mode 100644 index f33a713cc0b22..0000000000000 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "ASTDumper.h" - -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangUtil.h" -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Log.h" - -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; - -ASTDumper::ASTDumper(clang::Decl *decl) { - clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl); - - bool has_external_lexical_storage; - bool has_external_visible_storage; - - if (decl_ctx) { - has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - decl_ctx->setHasExternalLexicalStorage(false); - decl_ctx->setHasExternalVisibleStorage(false); - } - - llvm::raw_string_ostream os(m_dump); - decl->print(os); - os.flush(); - - if (decl_ctx) { - decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); - decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); - } -} - -ASTDumper::ASTDumper(clang::DeclContext *decl_ctx) { - bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - - decl_ctx->setHasExternalLexicalStorage(false); - decl_ctx->setHasExternalVisibleStorage(false); - - if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) { - llvm::raw_string_ostream os(m_dump); - decl->print(os); - os.flush(); - } else { - m_dump.assign("<DeclContext is not a Decl>"); - } - - decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); - decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); -} - -ASTDumper::ASTDumper(const clang::Type *type) { - m_dump = clang::QualType(type, 0).getAsString(); -} - -ASTDumper::ASTDumper(clang::QualType type) { m_dump = type.getAsString(); } - -ASTDumper::ASTDumper(lldb::opaque_compiler_type_t type) { - m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); -} - -ASTDumper::ASTDumper(const CompilerType &compiler_type) { - m_dump = ClangUtil::GetQualType(compiler_type).getAsString(); -} - -const char *ASTDumper::GetCString() { return m_dump.c_str(); } - -void ASTDumper::ToLog(Log *log, const char *prefix) { - size_t len = m_dump.length() + 1; - - char *alloc = (char *)malloc(len); - char *str = alloc; - - memcpy(str, m_dump.c_str(), len); - - char *end = nullptr; - - end = strchr(str, '\n'); - - while (end) { - *end = '\0'; - - LLDB_LOGF(log, "%s%s", prefix, str); - - *end = '\n'; - - str = end + 1; - end = strchr(str, '\n'); - } - - LLDB_LOGF(log, "%s%s", prefix, str); - - free(alloc); -} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h deleted file mode 100644 index ddf055d9c0c3d..0000000000000 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ASTDumper_h_ -#define liblldb_ASTDumper_h_ - -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/TypeVisitor.h" - -#include "lldb/Utility/Stream.h" -#include "llvm/ADT/DenseSet.h" - -namespace lldb_private { - -class ASTDumper { -public: - ASTDumper(clang::Decl *decl); - ASTDumper(clang::DeclContext *decl_ctx); - ASTDumper(const clang::Type *type); - ASTDumper(clang::QualType type); - ASTDumper(lldb::opaque_compiler_type_t type); - ASTDumper(const CompilerType &compiler_type); - - const char *GetCString(); - void ToSTDERR(); - void ToLog(Log *log, const char *prefix); - void ToStream(lldb::StreamSP &stream); - -private: - std::string m_dump; -}; - -} // namespace lldb_private - -#endif diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 68eaad33f51ce..77bb9544ea406 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -388,8 +388,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, // replace the old statement with the new one // - *last_stmt_ptr = - reinterpret_cast<Stmt *>(result_initialization_stmt_result.get()); + *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get()); return true; } @@ -448,13 +447,20 @@ void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) { } void ASTResultSynthesizer::CommitPersistentDecls() { + auto *state = + m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC); + if (!state) + return; + + auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state); + ClangASTContext *scratch_ctx = ClangASTContext::GetScratch(m_target); + for (clang::NamedDecl *decl : m_decls) { StringRef name = decl->getName(); ConstString name_cs(name.str().c_str()); Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl( - m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context, - decl); + &scratch_ctx->getASTContext(), decl); if (!D_scratch) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -472,10 +478,8 @@ void ASTResultSynthesizer::CommitPersistentDecls() { } if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch)) - llvm::cast<ClangPersistentVariables>( - m_target.GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC)) - ->RegisterPersistentDecl(name_cs, NamedDecl_scratch); + persistent_vars->RegisterPersistentDecl(name_cs, NamedDecl_scratch, + scratch_ctx); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h index 670ba6dce72e1..0b0f3b97705d9 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -135,18 +135,11 @@ private: void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); /// Given a TypeDecl, if it declares a type whose name starts with a dollar - /// sign, register it as a pointer type in the target's scratch - /// AST context. - /// - /// \param[in] Body - /// The body of the function. + /// sign, register it as a pointer type in the target's scratch AST context. void MaybeRecordPersistentType(clang::TypeDecl *D); /// Given a NamedDecl, register it as a pointer type in the target's scratch /// AST context. - /// - /// \param[in] Body - /// The body of the function. void RecordPersistentDecl(clang::NamedDecl *D); clang::ASTContext diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp index 190eacaa2b62b..a164d48ae3e05 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -30,8 +30,8 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, const char *struct_name, ClangFunctionCaller &function) : m_ast_context(nullptr), m_passthrough(passthrough), - m_passthrough_sema(nullptr), m_sema(nullptr), m_action(nullptr), - m_function(function), m_struct_name(struct_name) { + m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function), + m_struct_name(struct_name) { if (!m_passthrough) return; @@ -170,7 +170,6 @@ void ASTStructExtractor::PrintStats() { void ASTStructExtractor::InitializeSema(Sema &S) { m_sema = &S; - m_action = reinterpret_cast<Action *>(m_sema); if (m_passthrough_sema) m_passthrough_sema->InitializeSema(S); @@ -178,7 +177,6 @@ void ASTStructExtractor::InitializeSema(Sema &S) { void ASTStructExtractor::ForgetSema() { m_sema = nullptr; - m_action = nullptr; if (m_passthrough_sema) m_passthrough_sema->ForgetSema(); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h index 7aef2e254e1f6..078cf095975f9 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -121,8 +121,6 @@ private: ///for passthrough. NULL if it's an ///ASTConsumer. clang::Sema *m_sema; ///< The Sema to use. - clang::Action - *m_action; ///< The Sema to use, cast to an Action so it's usable. ClangFunctionCaller &m_function; ///< The function to populate with ///information about the argument structure. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 372c2439ebf0a..42927ab6cc8a1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -8,7 +8,6 @@ #include "ClangASTSource.h" -#include "ASTDumper.h" #include "ClangDeclVendor.h" #include "ClangModulesDeclVendor.h" @@ -50,114 +49,42 @@ private: }; } -ClangASTSource::ClangASTSource(const lldb::TargetSP &target) +ClangASTSource::ClangASTSource(const lldb::TargetSP &target, + const lldb::ClangASTImporterSP &importer) : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), m_ast_context(nullptr), m_active_lexical_decls(), m_active_lookups() { - if (!target->GetUseModernTypeLookup()) { - m_ast_importer_sp = m_target->GetClangASTImporter(); - } + m_ast_importer_sp = importer; } -void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, - clang::FileManager &file_manager, - bool is_shared_context) { - m_ast_context = &ast_context; - m_file_manager = &file_manager; - if (m_target->GetUseModernTypeLookup()) { - // Configure the ExternalASTMerger. The merger needs to be able to import - // types from any source that we would do lookups in, which includes the - // persistent AST context as well as the modules and Objective-C runtime - // AST contexts. - - lldbassert(!m_merger_up); - clang::ExternalASTMerger::ImporterTarget target = {ast_context, - file_manager}; - std::vector<clang::ExternalASTMerger::ImporterSource> sources; - for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) { - auto type_system_or_err = - module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC); - if (auto err = type_system_or_err.takeError()) { - LLDB_LOG_ERROR( - lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS), - std::move(err), "Failed to get ClangASTContext"); - } else if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( - &type_system_or_err.get())) { - lldbassert(module_ast_ctx->getASTContext()); - lldbassert(module_ast_ctx->getFileManager()); - sources.emplace_back(*module_ast_ctx->getASTContext(), - *module_ast_ctx->getFileManager(), - module_ast_ctx->GetOriginMap()); - } - } - - do { - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - break; - - ObjCLanguageRuntime *language_runtime(ObjCLanguageRuntime::Get(*process)); - - if (!language_runtime) - break; - - if (auto *runtime_decl_vendor = llvm::dyn_cast_or_null<ClangDeclVendor>( - language_runtime->GetDeclVendor())) { - sources.push_back(runtime_decl_vendor->GetImporterSource()); - } - } while (false); - - do { - auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); - - if (!modules_decl_vendor) - break; - - sources.push_back(modules_decl_vendor->GetImporterSource()); - } while (false); - - if (!is_shared_context) { - // Update the scratch AST context's merger to reflect any new sources we - // might have come across since the last time an expression was parsed. - - auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( - m_target->GetScratchClangASTContext()); - - scratch_ast_context->GetMergerUnchecked().AddSources(sources); - - sources.push_back({*scratch_ast_context->getASTContext(), - *scratch_ast_context->getFileManager(), - scratch_ast_context->GetOriginMap()}); - } - - m_merger_up = - std::make_unique<clang::ExternalASTMerger>(target, sources); - } else { - m_ast_importer_sp->InstallMapCompleter(&ast_context, *this); - } +void ClangASTSource::InstallASTContext(ClangASTContext &clang_ast_context) { + m_ast_context = &clang_ast_context.getASTContext(); + m_clang_ast_context = &clang_ast_context; + m_file_manager = &m_ast_context->getSourceManager().getFileManager(); + m_ast_importer_sp->InstallMapCompleter(m_ast_context, *this); } ClangASTSource::~ClangASTSource() { - if (m_ast_importer_sp) - m_ast_importer_sp->ForgetDestination(m_ast_context); + if (!m_ast_importer_sp) + return; + + m_ast_importer_sp->ForgetDestination(m_ast_context); + if (!m_target) + return; // We are in the process of destruction, don't create clang ast context on // demand by passing false to // Target::GetScratchClangASTContext(create_on_demand). ClangASTContext *scratch_clang_ast_context = - m_target->GetScratchClangASTContext(false); + ClangASTContext::GetScratch(*m_target, false); if (!scratch_clang_ast_context) return; - clang::ASTContext *scratch_ast_context = + clang::ASTContext &scratch_ast_context = scratch_clang_ast_context->getASTContext(); - if (!scratch_ast_context) - return; - - if (m_ast_context != scratch_ast_context && m_ast_importer_sp) - m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); + if (m_ast_context != &scratch_ast_context && m_ast_importer_sp) + m_ast_importer_sp->ForgetSource(&scratch_ast_context, m_ast_context); } void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) { @@ -279,9 +206,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { current_id, static_cast<void *>(m_ast_context), static_cast<void *>(tag_decl), tag_decl->getName().str().c_str()); - LLDB_LOGF(log, " CTD[%u] Before:", current_id); - ASTDumper dumper((Decl *)tag_decl); - dumper.ToLog(log, " [CTD] "); + LLDB_LOG(log, " CTD[%u] Before:\n{0}", current_id, + ClangUtil::DumpDecl(tag_decl)); } auto iter = m_active_lexical_decls.find(tag_decl); @@ -291,9 +217,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); if (!m_ast_importer_sp) { - if (HasMerger()) { - GetMergerUnchecked().CompleteType(tag_decl); - } return; } @@ -365,7 +288,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { TypeList types; ConstString name(tag_decl->getName().str().c_str()); - CompilerDeclContext namespace_decl; const ModuleList &module_list = m_target->GetImages(); @@ -407,50 +329,30 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { } } - if (log) { - LLDB_LOGF(log, " [CTD] After:"); - ASTDumper dumper((Decl *)tag_decl); - dumper.ToLog(log, " [CTD] "); - } + LLDB_LOG(log, " [CTD] After:\n{0}", ClangUtil::DumpDecl(tag_decl)); } void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) { - LLDB_LOGF(log, - " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " - "an ObjCInterfaceDecl named %s", - static_cast<void *>(m_ast_context), - interface_decl->getName().str().c_str()); - LLDB_LOGF(log, " [COID] Before:"); - ASTDumper dumper((Decl *)interface_decl); - dumper.ToLog(log, " [COID] "); - } + LLDB_LOGF(log, + " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " + "an ObjCInterfaceDecl named %s", + static_cast<void *>(m_ast_context), + interface_decl->getName().str().c_str()); + LLDB_LOG(log, " [COID] Before:\n{0}", + ClangUtil::DumpDecl(interface_decl)); if (!m_ast_importer_sp) { - if (HasMerger()) { - ObjCInterfaceDecl *complete_iface_decl = - GetCompleteObjCInterface(interface_decl); - - if (complete_iface_decl && (complete_iface_decl != interface_decl)) { - m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); - } - - GetMergerUnchecked().CompleteType(interface_decl); - } else { - lldbassert(0 && "No mechanism for completing a type!"); - } + lldbassert(0 && "No mechanism for completing a type!"); return; } - Decl *original_decl = nullptr; - ASTContext *original_ctx = nullptr; + ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl); - if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, - &original_ctx)) { + if (original.Valid()) { if (ObjCInterfaceDecl *original_iface_decl = - dyn_cast<ObjCInterfaceDecl>(original_decl)) { + dyn_cast<ObjCInterfaceDecl>(original.decl)) { ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); @@ -468,8 +370,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { if (log) { LLDB_LOGF(log, " [COID] After:"); - ASTDumper dumper((Decl *)interface_decl); - dumper.ToLog(log, " [COID] "); + LLDB_LOG(log, " [COID] {0}", ClangUtil::DumpDecl(interface_decl)); } } @@ -519,23 +420,9 @@ void ClangASTSource::FindExternalLexicalDecls( llvm::function_ref<bool(Decl::Kind)> predicate, llvm::SmallVectorImpl<Decl *> &decls) { - if (HasMerger()) { - if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_context)) { - ObjCInterfaceDecl *complete_iface_decl = - GetCompleteObjCInterface(interface_decl); - - if (complete_iface_decl && (complete_iface_decl != interface_decl)) { - m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); - } - } - return GetMergerUnchecked().FindExternalLexicalDecls(decl_context, - predicate, - decls); - } else if (!m_ast_importer_sp) + if (!m_ast_importer_sp) return; - ClangASTMetrics::RegisterLexicalQuery(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const Decl *context_decl = dyn_cast<Decl>(decl_context); @@ -574,42 +461,38 @@ void ClangASTSource::FindExternalLexicalDecls( current_id, static_cast<const void *>(m_ast_context)); } - Decl *original_decl = nullptr; - ASTContext *original_ctx = nullptr; + ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(context_decl); - if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, - &original_ctx)) + if (!original.Valid()) return; - if (log) { - LLDB_LOGF( - log, " FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id, - static_cast<void *>(original_ctx), static_cast<void *>(original_decl)); - ASTDumper(original_decl).ToLog(log, " "); - } + LLDB_LOG( + log, " FELD[{0}] Original decl (ASTContext*){1:x} (Decl*){2:x}:\n{3}", + current_id, static_cast<void *>(original.ctx), + static_cast<void *>(original.decl), ClangUtil::DumpDecl(original.decl)); if (ObjCInterfaceDecl *original_iface_decl = - dyn_cast<ObjCInterfaceDecl>(original_decl)) { + dyn_cast<ObjCInterfaceDecl>(original.decl)) { ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) { - original_decl = complete_iface_decl; - original_ctx = &complete_iface_decl->getASTContext(); + original.decl = complete_iface_decl; + original.ctx = &complete_iface_decl->getASTContext(); m_ast_importer_sp->SetDeclOrigin(context_decl, complete_iface_decl); } } - if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { - ExternalASTSource *external_source = original_ctx->getExternalSource(); + if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original.decl)) { + ExternalASTSource *external_source = original.ctx->getExternalSource(); if (external_source) external_source->CompleteType(original_tag_decl); } const DeclContext *original_decl_context = - dyn_cast<DeclContext>(original_decl); + dyn_cast<DeclContext>(original.decl); if (!original_decl_context) return; @@ -625,16 +508,16 @@ void ClangASTSource::FindExternalLexicalDecls( // See clang::ExternalASTSource::FindExternalLexicalDecls() if (predicate(decl->getKind())) { if (log) { - ASTDumper ast_dumper(decl); + std::string ast_dump = ClangUtil::DumpDecl(decl); if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) LLDB_LOGF(log, " FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), - decl->getDeclKindName(), ast_dumper.GetCString()); + decl->getDeclKindName(), ast_dump.c_str()); else LLDB_LOGF(log, " FELD[%d] Adding lexical %sDecl %s", current_id, - decl->getDeclKindName(), ast_dumper.GetCString()); + decl->getDeclKindName(), ast_dump.c_str()); } Decl *copied_decl = CopyDecl(decl); @@ -647,20 +530,6 @@ void ClangASTSource::FindExternalLexicalDecls( m_ast_importer_sp->RequireCompleteType(copied_field_type); } - auto decl_context_non_const = const_cast<DeclContext *>(decl_context); - - // The decl ended up in the wrong DeclContext. Let's fix that so - // the decl we copied will actually be found. - // FIXME: This is a horrible hack that shouldn't be necessary. However - // it seems our current setup sometimes fails to copy decls to the right - // place. See rdar://55129537. - if (copied_decl->getDeclContext() != decl_context) { - assert(copied_decl->getDeclContext()->containsDecl(copied_decl)); - copied_decl->getDeclContext()->removeDecl(copied_decl); - copied_decl->setDeclContext(decl_context_non_const); - assert(!decl_context_non_const->containsDecl(copied_decl)); - decl_context_non_const->addDeclInternal(copied_decl); - } } else { SkippedDecls = true; } @@ -683,8 +552,6 @@ void ClangASTSource::FindExternalLexicalDecls( void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { assert(m_ast_context); - ClangASTMetrics::RegisterVisibleQuery(); - const ConstString name(context.m_decl_name.getAsString().c_str()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -715,25 +582,6 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { name.GetCString(), context.m_decl_context->getDeclKindName()); } - if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context) - /* possibly handle NamespaceDecls here? */) { - if (auto *interface_decl = - dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { - ObjCInterfaceDecl *complete_iface_decl = - GetCompleteObjCInterface(interface_decl); - - if (complete_iface_decl && (complete_iface_decl != interface_decl)) { - GetMergerUnchecked().ForceRecordOrigin( - interface_decl, - {complete_iface_decl, &complete_iface_decl->getASTContext()}); - } - } - - GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, - context.m_decl_name); - return; // otherwise we may need to fall back - } - context.m_namespace_map = std::make_shared<ClangASTImporter::NamespaceMap>(); if (const NamespaceDecl *namespace_context = @@ -758,7 +606,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { FindExternalVisibleDecls(context, i->first, i->second, current_id); } - } else if (isa<ObjCInterfaceDecl>(context.m_decl_context) && !HasMerger()) { + } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) { FindObjCPropertyAndIvarDecls(context); } else if (!isa<TranslationUnitDecl>(context.m_decl_context)) { // we shouldn't be getting FindExternalVisibleDecls calls for these @@ -788,7 +636,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { } clang::Sema *ClangASTSource::getSema() { - return ClangASTContext::GetASTContext(m_ast_context)->getSema(); + return m_clang_ast_context->getSema(); } bool ClangASTSource::IgnoreName(const ConstString name, @@ -821,6 +669,9 @@ void ClangASTSource::FindExternalVisibleDecls( if (IgnoreName(name, true)) return; + if (!m_target) + return; + if (module_sp && namespace_decl) { CompilerDeclContext found_namespace_decl; @@ -837,7 +688,7 @@ void ClangASTSource::FindExternalVisibleDecls( module_sp->GetFileSpec().GetFilename().GetCString()); } } - } else if (!HasMerger()) { + } else { const ModuleList &target_images = m_target->GetImages(); std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); @@ -1049,11 +900,10 @@ public: template <class D> DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) { - DeclFromUser<> origin_decl; - source.ResolveDeclOrigin(this->decl, &origin_decl.decl, nullptr); - if (origin_decl.IsInvalid()) + ClangASTImporter::DeclOrigin origin = source.GetDeclOrigin(this->decl); + if (!origin.Valid()) return DeclFromUser<D>(); - return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); + return DeclFromUser<D>(dyn_cast<D>(origin.decl)); } template <class D> @@ -1137,11 +987,8 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin( Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) { - ASTDumper dumper((Decl *)copied_method_decl); - LLDB_LOGF(log, " CAS::FOMD[%d] found (%s) %s", current_id, log_info, - dumper.GetCString()); - } + LLDB_LOG(log, " CAS::FOMD[{0}] found ({1}) {2}", current_id, log_info, + ClangUtil::DumpDecl(copied_method_decl)); context.AddNamedDecl(copied_method_decl); } @@ -1152,21 +999,6 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin( void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (HasMerger()) { - if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { - ObjCInterfaceDecl *complete_iface_decl = - GetCompleteObjCInterface(interface_decl); - - if (complete_iface_decl && (complete_iface_decl != context.m_decl_context)) { - m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); - } - } - - GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, - context.m_decl_name); - return; - } - static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; @@ -1180,17 +1012,13 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { return; do { - Decl *original_decl = nullptr; - ASTContext *original_ctx = nullptr; - - m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, - &original_ctx); + ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl); - if (!original_decl) + if (!original.Valid()) break; ObjCInterfaceDecl *original_interface_decl = - dyn_cast<ObjCInterfaceDecl>(original_decl); + dyn_cast<ObjCInterfaceDecl>(original.decl); if (FindObjCMethodDeclsWithOrigin(current_id, context, original_interface_decl, "at origin")) @@ -1343,11 +1171,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (!copied_method_decl) continue; - if (log) { - ASTDumper dumper((Decl *)copied_method_decl); - LLDB_LOGF(log, " CAS::FOMD[%d] found (in symbols) %s", current_id, - dumper.GetCString()); - } + LLDB_LOG(log, " CAS::FOMD[{0}] found (in symbols)\n{1}", current_id, + ClangUtil::DumpDecl(copied_method_decl)); context.AddNamedDecl(copied_method_decl); } @@ -1476,11 +1301,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( DeclFromParser<ObjCPropertyDecl> parser_property_decl( origin_property_decl.Import(source)); if (parser_property_decl.IsValid()) { - if (log) { - ASTDumper dumper((Decl *)parser_property_decl.decl); - LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); - } + LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id, + ClangUtil::DumpDecl(parser_property_decl.decl)); context.AddNamedDecl(parser_property_decl.decl); found = true; @@ -1495,9 +1317,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( origin_ivar_decl.Import(source)); if (parser_ivar_decl.IsValid()) { if (log) { - ASTDumper dumper((Decl *)parser_ivar_decl.decl); - LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); + LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id, + ClangUtil::DumpDecl(parser_ivar_decl.decl)); } context.AddNamedDecl(parser_ivar_decl.decl); @@ -1736,8 +1557,6 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, BaseOffsetMap &virtual_base_offsets) { - ClangASTMetrics::RegisterRecordLayout(); - static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; @@ -1984,90 +1803,37 @@ NamespaceDecl *ClangASTSource::AddNamespace( return dyn_cast<NamespaceDecl>(copied_decl); } -clang::QualType ClangASTSource::CopyTypeWithMerger( - clang::ASTContext &from_context, - clang::ExternalASTMerger &merger, - clang::QualType type) { - if (!merger.HasImporterForOrigin(from_context)) { - lldbassert(0 && "Couldn't find the importer for a source context!"); - return QualType(); - } - - if (llvm::Expected<QualType> type_or_error = - merger.ImporterForOrigin(from_context).Import(type)) { - return *type_or_error; - } else { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - LLDB_LOG_ERROR(log, type_or_error.takeError(), "Couldn't import type: {0}"); - return QualType(); - } -} - clang::Decl *ClangASTSource::CopyDecl(Decl *src_decl) { - clang::ASTContext &from_context = src_decl->getASTContext(); if (m_ast_importer_sp) { - return m_ast_importer_sp->CopyDecl(m_ast_context, &from_context, src_decl); - } else if (m_merger_up) { - if (!m_merger_up->HasImporterForOrigin(from_context)) { - lldbassert(0 && "Couldn't find the importer for a source context!"); - return nullptr; - } - - if (llvm::Expected<Decl *> decl_or_error = - m_merger_up->ImporterForOrigin(from_context).Import(src_decl)) { - return *decl_or_error; - } else { - Log *log = - lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - LLDB_LOG_ERROR(log, decl_or_error.takeError(), - "Couldn't import decl: {0}"); - return nullptr; - } + return m_ast_importer_sp->CopyDecl(m_ast_context, src_decl); } else { lldbassert(0 && "No mechanism for copying a decl!"); return nullptr; } } -bool ClangASTSource::ResolveDeclOrigin(const clang::Decl *decl, - clang::Decl **original_decl, - clang::ASTContext **original_ctx) { +ClangASTImporter::DeclOrigin ClangASTSource::GetDeclOrigin(const clang::Decl *decl) { if (m_ast_importer_sp) { - return m_ast_importer_sp->ResolveDeclOrigin(decl, original_decl, - original_ctx); - } else if (m_merger_up) { - return false; // Implement this correctly in ExternalASTMerger + return m_ast_importer_sp->GetDeclOrigin(decl); } else { // this can happen early enough that no ExternalASTSource is installed. - return false; + return ClangASTImporter::DeclOrigin(); } } -clang::ExternalASTMerger &ClangASTSource::GetMergerUnchecked() { - lldbassert(m_merger_up != nullptr); - return *m_merger_up; -} - CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); if (src_ast == nullptr) return CompilerType(); - ClangASTMetrics::RegisterLLDBImport(); - SetImportInProgress(true); QualType copied_qual_type; if (m_ast_importer_sp) { - copied_qual_type = - m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), - ClangUtil::GetQualType(src_type)); - } else if (m_merger_up) { - copied_qual_type = - CopyTypeWithMerger(*src_ast->getASTContext(), *m_merger_up, - ClangUtil::GetQualType(src_type)); + copied_qual_type = ClangUtil::GetQualType( + m_ast_importer_sp->CopyType(*m_clang_ast_context, src_type)); } else { lldbassert(0 && "No mechanism for copying a type!"); return CompilerType(); @@ -2081,8 +1847,7 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { // seems to be generating bad types on occasion. return CompilerType(); - return CompilerType(ClangASTContext::GetASTContext(m_ast_context), - copied_qual_type.getAsOpaquePtr()); + return m_clang_ast_context->GetType(copied_qual_type); } clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { @@ -2098,10 +1863,10 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); - clang::ASTContext *ast = lldb_ast->getASTContext(); + clang::ASTContext &ast = lldb_ast->getASTContext(); clang::NamedDecl *Decl = VarDecl::Create( - *ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(), + ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(), SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static); m_decls.push_back(Decl); @@ -2127,7 +1892,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, QualType qual_type(ClangUtil::GetQualType(type)); - clang::ASTContext *ast = lldb_ast->getASTContext(); + clang::ASTContext &ast = lldb_ast->getASTContext(); const bool isInlineSpecified = false; const bool hasWrittenPrototype = true; @@ -2137,7 +1902,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, if (extern_c) { context = LinkageSpecDecl::Create( - *ast, context, SourceLocation(), SourceLocation(), + ast, context, SourceLocation(), SourceLocation(), clang::LinkageSpecDecl::LanguageIDs::lang_c, false); } @@ -2149,7 +1914,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, : m_decl_name; clang::FunctionDecl *func_decl = FunctionDecl::Create( - *ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, + ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified ? CSK_constexpr : CSK_unspecified); @@ -2170,7 +1935,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, QualType arg_qual_type(func_proto_type->getParamType(ArgIndex)); parm_var_decls.push_back( - ParmVarDecl::Create(*ast, const_cast<DeclContext *>(context), + ParmVarDecl::Create(ast, const_cast<DeclContext *>(context), SourceLocation(), SourceLocation(), nullptr, arg_qual_type, nullptr, SC_Static, nullptr)); } @@ -2210,9 +1975,7 @@ clang::NamedDecl *NameSearchContext::AddGenericFunDecl() { proto_info)); return AddFunDecl( - CompilerType(ClangASTContext::GetASTContext(m_ast_source.m_ast_context), - generic_function_type.getAsOpaquePtr()), - true); + m_ast_source.m_clang_ast_context->GetType(generic_function_type), true); } clang::NamedDecl * diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 7a8bacf48a8fd..3149b4266b2fd 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -12,10 +12,9 @@ #include <set> #include "lldb/Symbol/ClangASTImporter.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" -#include "clang/AST/ExternalASTMerger.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/SmallSet.h" @@ -30,7 +29,7 @@ namespace lldb_private { /// knows the name it is looking for, but nothing else. The ExternalSemaSource /// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these /// names, consulting the ClangExpressionDeclMap to do the actual lookups. -class ClangASTSource : public ClangExternalASTSourceCommon, +class ClangASTSource : public clang::ExternalASTSource, public ClangASTImporter::MapCompleter { public: /// Constructor @@ -39,7 +38,11 @@ public: /// /// \param[in] target /// A reference to the target containing debug information to use. - ClangASTSource(const lldb::TargetSP &target); + /// + /// \param[in] importer + /// The ClangASTImporter to use. + ClangASTSource(const lldb::TargetSP &target, + const lldb::ClangASTImporterSP &importer); /// Destructor ~ClangASTSource() override; @@ -57,9 +60,7 @@ public: } void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } - void InstallASTContext(clang::ASTContext &ast_context, - clang::FileManager &file_manager, - bool is_shared_context = false); + void InstallASTContext(ClangASTContext &ast_context); // // APIs for ExternalASTSource @@ -89,7 +90,7 @@ public: /// \param[in] DC /// The DeclContext being searched. /// - /// \param[in] isKindWeWant + /// \param[in] IsKindWeWant /// A callback function that returns true given the /// DeclKinds of desired Decls, and false otherwise. /// @@ -155,7 +156,7 @@ public: /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that /// this object has something to say about undefined names. /// - /// \param[in] ASTConsumer + /// \param[in] Consumer /// Unused. void StartTranslationUnit(clang::ASTConsumer *Consumer) override; @@ -210,7 +211,7 @@ public: /// /// Clang AST contexts like to own their AST sources, so this is a state- /// free proxy object. - class ClangASTSourceProxy : public ClangExternalASTSourceCommon { + class ClangASTSourceProxy : public clang::ExternalASTSource { public: ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {} @@ -249,18 +250,6 @@ public: return m_original.StartTranslationUnit(Consumer); } - ClangASTMetadata *GetMetadata(const void *object) { - return m_original.GetMetadata(object); - } - - void SetMetadata(const void *object, ClangASTMetadata &metadata) { - return m_original.SetMetadata(object, metadata); - } - - bool HasMetadata(const void *object) { - return m_original.HasMetadata(object); - } - private: ClangASTSource &m_original; }; @@ -321,13 +310,6 @@ protected: /// A wrapper for ClangASTContext::CopyType that sets a flag that /// indicates that we should not respond to queries during import. /// - /// \param[in] dest_context - /// The target AST context, typically the parser's AST context. - /// - /// \param[in] source_context - /// The source AST context, typically the AST context of whatever - /// symbol file the type was found in. - /// /// \param[in] src_type /// The source type. /// @@ -341,7 +323,7 @@ public: /// \param[in] name /// The name to be considered. /// - /// \param[in] ignore_all_dollar_nmmes + /// \param[in] ignore_all_dollar_names /// True if $-names of all sorts should be ignored. /// /// \return @@ -358,24 +340,6 @@ public: /// \return /// A copy of the Decl in m_ast_context, or NULL if the copy failed. clang::Decl *CopyDecl(clang::Decl *src_decl); - - /// Copies a single Type to the target of the given ExternalASTMerger. - /// - /// \param[in] src_context - /// The ASTContext containing the type. - /// - /// \param[in] merger - /// The merger to use. This isn't just *m_merger_up because it might be - /// the persistent AST context's merger. - /// - /// \param[in] type - /// The type to copy. - /// - /// \return - /// A copy of the Type in the merger's target context. - clang::QualType CopyTypeWithMerger(clang::ASTContext &src_context, - clang::ExternalASTMerger &merger, - clang::QualType type); /// Determined the origin of a single Decl, if it can be found. /// @@ -390,16 +354,7 @@ public: /// /// \return /// True if lookup succeeded; false otherwise. - bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl, - clang::ASTContext **original_ctx); - - /// Returns m_merger_up. Only call this if the target is configured to use - /// modern lookup, - clang::ExternalASTMerger &GetMergerUnchecked(); - - /// Returns true if there is a merger. This only occurs if the target is - /// using modern lookup. - bool HasMerger() { return (bool)m_merger_up; } + ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl); protected: bool FindObjCMethodDeclsWithOrigin( @@ -411,15 +366,16 @@ protected: bool m_import_in_progress; bool m_lookups_enabled; - const lldb::TargetSP - m_target; ///< The target to use in finding variables and types. - clang::ASTContext - *m_ast_context; ///< The AST context requests are coming in for. - clang::FileManager - *m_file_manager; ///< The file manager paired with the AST context. - lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. - std::unique_ptr<clang::ExternalASTMerger> m_merger_up; - ///< The ExternalASTMerger for this parse. + /// The target to use in finding variables and types. + const lldb::TargetSP m_target; + /// The AST context requests are coming in for. + clang::ASTContext *m_ast_context; + /// The ClangASTContext for m_ast_context. + ClangASTContext *m_clang_ast_context; + /// The file manager paired with the AST context. + clang::FileManager *m_file_manager; + /// The target's AST importer. + lldb::ClangASTImporterSP m_ast_importer_sp; std::set<const clang::Decl *> m_active_lexical_decls; std::set<const char *> m_active_lookups; }; @@ -432,20 +388,20 @@ protected: /// what name is being searched for and provides helper functions to construct /// Decls given appropriate type information. struct NameSearchContext { - ClangASTSource &m_ast_source; ///< The AST source making the request - llvm::SmallVectorImpl<clang::NamedDecl *> - &m_decls; ///< The list of declarations already constructed - ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all - ///namespaces found for this - ///request back to their - ///modules - const clang::DeclarationName &m_decl_name; ///< The name being looked for - const clang::DeclContext - *m_decl_context; ///< The DeclContext to put declarations into - llvm::SmallSet<CompilerType, 5> m_function_types; ///< All the types of - ///functions that have been - ///reported, so we don't - ///report conflicts + /// The AST source making the request. + ClangASTSource &m_ast_source; + /// The list of declarations already constructed. + llvm::SmallVectorImpl<clang::NamedDecl *> &m_decls; + /// The mapping of all namespaces found for this request back to their + /// modules. + ClangASTImporter::NamespaceMapSP m_namespace_map; + /// The name being looked for. + const clang::DeclarationName &m_decl_name; + /// The DeclContext to put declarations into. + const clang::DeclContext *m_decl_context; + /// All the types of functions that have been reported, so we don't + /// report conflicts. + llvm::SmallSet<CompilerType, 5> m_function_types; struct { bool variable : 1; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp index c59722b7b4f89..c87507a25855b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp @@ -15,16 +15,16 @@ using namespace lldb_private; uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append, uint32_t max_matches, - std::vector<CompilerDecl> &decls) { + std::vector<clang::NamedDecl *> &decls) { if (!append) decls.clear(); - std::vector<clang::NamedDecl *> named_decls; - uint32_t ret = FindDecls(name, /*append*/ false, max_matches, named_decls); - for (auto *named_decl : named_decls) { - decls.push_back(CompilerDecl( - ClangASTContext::GetASTContext(&named_decl->getASTContext()), - named_decl)); + std::vector<CompilerDecl> compiler_decls; + uint32_t ret = FindDecls(name, /*append*/ false, max_matches, compiler_decls); + for (CompilerDecl compiler_decl : compiler_decls) { + clang::Decl *d = static_cast<clang::Decl *>(compiler_decl.GetOpaqueDecl()); + clang::NamedDecl *nd = llvm::cast<clang::NamedDecl>(d); + decls.push_back(nd); } return ret; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h index 90b715f37cba2..0c888de08841d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h @@ -12,8 +12,6 @@ #include "lldb/Core/ClangForward.h" #include "lldb/Symbol/DeclVendor.h" -#include "clang/AST/ExternalASTMerger.h" - namespace lldb_private { // A clang specialized extension to DeclVendor. @@ -23,19 +21,10 @@ public: virtual ~ClangDeclVendor() {} - /// Interface for ExternalASTMerger. Returns an ImporterSource allowing type - /// completion. - /// - /// \return - /// An ImporterSource for this ClangDeclVendor. - virtual clang::ExternalASTMerger::ImporterSource GetImporterSource() = 0; + using DeclVendor::FindDecls; uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, - std::vector<CompilerDecl> &decls) override; - - virtual uint32_t FindDecls(ConstString name, bool append, - uint32_t max_matches, - std::vector<clang::NamedDecl *> &decls) = 0; + std::vector<clang::NamedDecl *> &decls); static bool classof(const DeclVendor *vendor) { return vendor->GetKind() >= eClangDeclVendor && diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index f4457fc1b7404..bf3023be5f60d 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()) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 2711e90726e74..722f5e15a2aa2 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -63,12 +63,15 @@ public: /// the result persistent variable, and instead marks the variable /// as persisting. /// - /// \param[in] delegate + /// \param[in] result_delegate /// If non-NULL, use this delegate to report result values. This /// allows the client ClangUserExpression to report a result. /// - /// \param[in] exe_ctx - /// The execution context to use when parsing. + /// \param[in] target + /// The target to use when parsing. + /// + /// \param[in] importer + /// The ClangASTImporter to use when parsing. /// /// \param[in] ctx_obj /// If not empty, then expression is evaluated in context of this object. @@ -76,7 +79,7 @@ public: ClangExpressionDeclMap( bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, - ExecutionContext &exe_ctx, + const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer, ValueObject *ctx_obj); /// Destructor @@ -98,13 +101,6 @@ public: void InstallCodeGenerator(clang::ASTConsumer *code_gen); - /// [Used by ClangExpressionParser] For each variable that had an unknown - /// type at the beginning of parsing, determine its final type now. - /// - /// \return - /// True on success; false otherwise. - bool ResolveUnknownTypes(); - /// Disable the state needed for parsing and IR transformation. void DidParse(); @@ -248,17 +244,6 @@ public: lldb::addr_t GetSymbolAddress(ConstString name, lldb::SymbolType symbol_type); - /// [Used by IRInterpreter] Get basic target information. - /// - /// \param[out] byte_order - /// The byte order of the target. - /// - /// \param[out] address_byte_size - /// The size of a pointer in bytes. - /// - /// \return - /// True if the information could be determined; false - /// otherwise. struct TargetInfo { lldb::ByteOrder byte_order; size_t address_byte_size; @@ -276,9 +261,6 @@ public: /// /// \param[in] context /// The NameSearchContext that can construct Decls for this name. - /// - /// \return - /// True on success; false otherwise. void FindExternalVisibleDecls(NameSearchContext &context) override; /// Find all entities matching a given name in a given module/namespace, @@ -296,14 +278,19 @@ public: /// \param[in] current_id /// The ID for the current FindExternalVisibleDecls invocation, /// for logging purposes. - /// - /// \return - /// True on success; false otherwise. void FindExternalVisibleDecls(NameSearchContext &context, lldb::ModuleSP module, CompilerDeclContext &namespace_decl, unsigned int current_id); +protected: + /// Retrieves the declaration with the given name from the storage of + /// persistent declarations. + /// + /// \return + /// A persistent decl with the given name or a nullptr. + virtual clang::NamedDecl *GetPersistentDecl(ConstString name); + private: ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. @@ -329,7 +316,7 @@ private: if (m_exe_ctx.GetTargetPtr()) return m_exe_ctx.GetTargetPtr(); else if (m_sym_ctx.target_sp) - m_sym_ctx.target_sp.get(); + return m_sym_ctx.target_sp.get(); return nullptr; } @@ -396,6 +383,130 @@ private: /// from persistent variables. uint64_t GetParserID() { return (uint64_t) this; } + /// Should be called on all copied functions. + void MaybeRegisterFunctionBody(clang::FunctionDecl *copied_function_decl); + + /// Searches the persistent decls of the target for entities with the + /// given name. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] name + /// The name of the entities that need to be found. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void SearchPersistenDecls(NameSearchContext &context, const ConstString name, + unsigned int current_id); + + /// Handles looking up $__lldb_class which requires special treatment. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void LookUpLldbClass(NameSearchContext &context, unsigned int current_id); + + /// Handles looking up $__lldb_objc_class which requires special treatment. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void LookUpLldbObjCClass(NameSearchContext &context, unsigned int current_id); + + /// Handles looking up the synthetic namespace that contains our local + /// variables for the current frame. + /// + /// \param[in] sym_ctx + /// The current SymbolContext of this frame. + /// + /// \param[in] name_context + /// The NameSearchContext that can construct Decls for this name. + void LookupLocalVarNamespace(SymbolContext &sym_ctx, + NameSearchContext &name_context); + + /// Lookup entities in the ClangModulesDeclVendor. + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] name + /// The name of the entities that need to be found. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void LookupInModulesDeclVendor(NameSearchContext &context, ConstString name, + unsigned current_id); + + /// Looks up a local variable. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] name + /// The name of the entities that need to be found. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// \param[in] sym_ctx + /// The current SymbolContext of this frame. + /// + /// \param[in] namespace_decl + /// The parent namespace if there is one. + /// + /// \return + /// True iff a local variable was found. + bool LookupLocalVariable(NameSearchContext &context, ConstString name, + unsigned current_id, SymbolContext &sym_ctx, + CompilerDeclContext &namespace_decl); + + /// Searches for functions in the given SymbolContextList. + /// + /// \param[in] sc_list + /// The SymbolContextList to search. + /// + /// \param[in] frame_decl_context + /// The current DeclContext of the current frame. + /// + /// \return + /// A SymbolContextList with any found functions in the front and + /// any unknown SymbolContexts which are not functions in the back. + /// The SymbolContexts for the functions are ordered by how close they are + /// to the DeclContext for the given frame DeclContext. + SymbolContextList SearchFunctionsInSymbolContexts( + const SymbolContextList &sc_list, + const CompilerDeclContext &frame_decl_context); + + /// Looks up a function. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] module_sp + /// If non-NULL, the module to query. + /// + /// \param[in] name + /// The name of the function that should be find. + /// + /// \param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void LookupFunction(NameSearchContext &context, lldb::ModuleSP module_sp, + ConstString name, CompilerDeclContext &namespace_decl, + unsigned current_id); + /// Given a target, find a variable that matches the given name and type. /// /// \param[in] target @@ -410,17 +521,11 @@ private: /// \param[in] namespace_decl /// If non-NULL and module is non-NULL, the parent namespace. /// - /// \param[in] type - /// The required type for the variable. This function may be called - /// during parsing, in which case we don't know its type; hence the - /// default. - /// /// \return /// The LLDB Variable found, or NULL if none was found. lldb::VariableSP FindGlobalVariable(Target &target, lldb::ModuleSP &module, ConstString name, - CompilerDeclContext *namespace_decl, - TypeFromUser *type = nullptr); + CompilerDeclContext *namespace_decl); /// Get the value of a variable in a given execution context and return the /// associated Types if needed. @@ -441,9 +546,6 @@ private: /// AST context. This is only useful when the variable is being /// inspected on behalf of the parser, hence the default. /// - /// \param[in] decl - /// The Decl to be looked up. - /// /// \return /// Return true if the value was successfully filled in. bool GetVariableValue(lldb::VariableSP &var, @@ -471,7 +573,7 @@ private: /// \param[in] context /// The NameSearchContext to use when constructing the Decl. /// - /// \param[in] pvar + /// \param[in] pvar_sp /// The persistent variable that needs a Decl. /// /// \param[in] current_id @@ -483,12 +585,6 @@ private: /// Use the NameSearchContext to generate a Decl for the given LLDB symbol /// (treated as a variable), and put it in the list of found entities. - /// - /// \param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// \param[in] var - /// The LLDB Variable that needs a Decl. void AddOneGenericVariable(NameSearchContext &context, const Symbol &symbol, unsigned int current_id); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 1422911d6546f..8abd149428852 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -10,6 +10,7 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" @@ -582,15 +583,16 @@ ClangExpressionParser::ClangExpressionParser( if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) { - ClangPersistentVariables *clang_persistent_vars = - llvm::cast<ClangPersistentVariables>( + if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>( target_sp->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC)); - std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks( - *decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager())); - m_pp_callbacks = - static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get()); - m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + lldb::eLanguageTypeC))) { + std::unique_ptr<PPCallbacks> pp_callbacks( + new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars, + m_compiler->getSourceManager())); + m_pp_callbacks = + static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get()); + m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + } } // 8. Most of this we get from the CompilerInstance, but we also want to give @@ -696,10 +698,7 @@ class CodeComplete : public CodeCompleteConsumer { public: /// Constructs a CodeComplete consumer that can be attached to a Sema. - /// \param[out] matches - /// The list of matches that the lldb completion API expects as a result. - /// This may already contain matches, so it's only allowed to append - /// to this variable. + /// /// \param[out] expr /// The whole expression string that we are currently parsing. This /// string needs to be equal to the input the user typed, and NOT the @@ -976,7 +975,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, m_compiler->setASTConsumer(std::move(Consumer)); if (ast_context.getLangOpts().Modules) { - m_compiler->createModuleManager(); + m_compiler->createASTReader(); m_ast_context->setSema(&m_compiler->getSema()); } @@ -999,7 +998,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, } else { ast_context.setExternalSource(ast_source); } - decl_map->InstallASTContext(ast_context, m_compiler->getFileManager()); + decl_map->InstallASTContext(*m_ast_context); } // Check that the ASTReader is properly attached to ASTContext and Sema. @@ -1036,15 +1035,6 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, } if (!num_errors) { - if (type_system_helper->DeclMap() && - !type_system_helper->DeclMap()->ResolveUnknownTypes()) { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "Couldn't infer the type of a variable"); - num_errors++; - } - } - - if (!num_errors) { type_system_helper->CommitPersistentDecls(); } @@ -1268,8 +1258,9 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( interpret_error, interpret_function_calls); if (!can_interpret && execution_policy == eExecutionPolicyNever) { - err.SetErrorStringWithFormat("Can't run the expression locally: %s", - interpret_error.AsCString()); + err.SetErrorStringWithFormat( + "Can't evaluate the expression without a running target due to: %s", + interpret_error.AsCString()); return err; } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 79ad5728bf741..4a410cecb94ad 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -42,7 +42,7 @@ public: /// /// Initializes class variables. /// - /// \param[in] exe_scope, + /// \param[in] exe_scope /// If non-NULL, an execution context scope that can help to /// correctly create an expression with a valid process for /// optional tuning Objective-C runtime support. Can be NULL. @@ -77,7 +77,7 @@ public: /// \return /// The number of errors encountered during parsing. 0 means /// success. - unsigned Parse(DiagnosticManager &diagnostic_manager) override; + unsigned Parse(DiagnosticManager &diagnostic_manager); bool RewriteExpression(DiagnosticManager &diagnostic_manager) override; @@ -99,15 +99,6 @@ public: /// \param[in] exe_ctx /// The execution context to write the function into. /// - /// \param[out] evaluated_statically - /// Set to true if the expression could be interpreted statically; - /// untouched otherwise. - /// - /// \param[out] const_result - /// If the result of the expression is constant, and the - /// expression has no side effects, this is set to the result of the - /// expression. - /// /// \param[in] execution_policy /// Determines whether the expression must be JIT-compiled, must be /// evaluated statically, or whether this decision may be made diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 21cb33402e7f7..7ebb5fee1ec69 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -315,12 +315,10 @@ bool ClangExpressionSourceCode::GetText( } } - if (ClangModulesDeclVendor *decl_vendor = - target->GetClangModulesDeclVendor()) { - ClangPersistentVariables *persistent_vars = - llvm::cast<ClangPersistentVariables>( - target->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC)); + ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor(); + auto *persistent_vars = llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + if (decl_vendor && persistent_vars) { const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index eb7f74f20a20d..0e6de28ee4dfa 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -74,9 +74,6 @@ public: /// Finds a variable by NamedDecl in the list. /// - /// \param[in] name - /// The name of the requested variable. - /// /// \return /// The variable requested, or NULL if that variable is not in the list. static ClangExpressionVariable * diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index 8fbfa6e47578b..7f7c0a97f5384 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -42,6 +42,8 @@ using namespace lldb_private; +char ClangFunctionCaller::ID; + // ClangFunctionCaller constructor ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope, const CompilerType &return_type, @@ -186,10 +188,10 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (jit_process_sp) { const bool generate_debug_info = true; - m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, - generate_debug_info)); - - num_errors = m_parser->Parse(diagnostic_manager); + auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this, + generate_debug_info); + num_errors = clang_parser->Parse(diagnostic_manager); + m_parser.reset(clang_parser); } else { diagnostic_manager.PutString(eDiagnosticSeverityError, "no process - unable to inject function"); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 24f6f2eb91b3b..150a913152d01 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -59,11 +59,6 @@ class ClangExpressionParser; class ClangFunctionCaller : public FunctionCaller { friend class ASTStructExtractor; - /// LLVM-style RTTI support. - static bool classof(const Expression *E) { - return E->getKind() == eKindClangFunctionCaller; - } - class ClangFunctionCallerHelper : public ClangExpressionHelper { public: ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {} @@ -91,18 +86,23 @@ class ClangFunctionCaller : public FunctionCaller { ///layout. }; + // LLVM RTTI support + static char ID; + public: + bool isA(const void *ClassID) const override { + return ClassID == &ID || FunctionCaller::isA(ClassID); + } + static bool classof(const Expression *obj) { return obj->isA(&ID); } + /// Constructor /// /// \param[in] exe_scope /// An execution context scope that gets us at least a target and /// process. /// - /// \param[in] ast_context - /// The AST context to evaluate argument types in. - /// - /// \param[in] return_qualtype - /// An opaque Clang QualType for the function result. Should be + /// \param[in] return_type + /// A compiler type for the function result. Should be /// defined in ast_context. /// /// \param[in] function_address diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index f3df589d73112..0696c669f2e20 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -80,12 +80,10 @@ public: Stream &error_stream) override; uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, - std::vector<clang::NamedDecl *> &decls) override; + std::vector<CompilerDecl> &decls) override; void ForEachMacro(const ModuleVector &modules, std::function<bool(const std::string &)> handler) override; - - clang::ExternalASTMerger::ImporterSource GetImporterSource() override; private: void ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -110,7 +108,6 @@ private: typedef std::set<ModuleID> ImportedModuleSet; ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; - const clang::ExternalASTMerger::OriginMap m_origin_map; // We assume that every ASTContext has an ClangASTContext, so we also store // a custom ClangASTContext for our internal ASTContext. std::unique_ptr<ClangASTContext> m_ast_context; @@ -160,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( : m_diagnostics_engine(std::move(diagnostics_engine)), m_compiler_invocation(std::move(compiler_invocation)), m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)), m_origin_map() { + m_parser(std::move(parser)) { // Initialize our ClangASTContext. m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext())); @@ -359,7 +356,7 @@ bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit( uint32_t ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append, uint32_t max_matches, - std::vector<clang::NamedDecl *> &decls) { + std::vector<CompilerDecl> &decls) { if (!m_enabled) { return 0; } @@ -385,7 +382,7 @@ ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append, if (num_matches >= max_matches) return num_matches; - decls.push_back(named_decl); + decls.push_back(CompilerDecl(m_ast_context.get(), named_decl)); ++num_matches; } @@ -569,13 +566,6 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, is_inclusion_directive); } -clang::ExternalASTMerger::ImporterSource -ClangModulesDeclVendorImpl::GetImporterSource() { - return clang::ExternalASTMerger::ImporterSource( - m_compiler_instance->getASTContext(), - m_compiler_instance->getFileManager(), m_origin_map); -} - static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; lldb_private::ClangModulesDeclVendor * @@ -704,7 +694,7 @@ ClangModulesDeclVendor::Create(Target &target) { instance->getPreprocessor().enableIncrementalProcessing(); - instance->createModuleManager(); + instance->createASTReader(); instance->createSema(action->getTranslationUnitKind(), nullptr); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 24dd705e37b17..41d62a462ab4e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -67,39 +67,35 @@ void ClangPersistentVariables::RemovePersistentVariable( llvm::Optional<CompilerType> ClangPersistentVariables::GetCompilerTypeFromPersistentDecl( ConstString type_name) { - CompilerType compiler_type; - if (clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>( - GetPersistentDecl(type_name))) { - compiler_type.SetCompilerType( - ClangASTContext::GetASTContext(&tdecl->getASTContext()), - reinterpret_cast<lldb::opaque_compiler_type_t>( - const_cast<clang::Type *>(tdecl->getTypeForDecl()))); - return compiler_type; + PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString()); + + if (p.m_decl == nullptr) + return llvm::None; + + if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) { + opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>( + const_cast<clang::Type *>(tdecl->getTypeForDecl())); + return CompilerType(p.m_context, t); } return llvm::None; } void ClangPersistentVariables::RegisterPersistentDecl(ConstString name, - clang::NamedDecl *decl) { - m_persistent_decls.insert( - std::pair<const char *, clang::NamedDecl *>(name.GetCString(), decl)); + clang::NamedDecl *decl, + ClangASTContext *ctx) { + PersistentDecl p = {decl, ctx}; + m_persistent_decls.insert(std::make_pair(name.GetCString(), p)); if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) { for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) { - m_persistent_decls.insert(std::pair<const char *, clang::NamedDecl *>( - ConstString(enumerator_decl->getNameAsString()).GetCString(), - enumerator_decl)); + p = {enumerator_decl, ctx}; + m_persistent_decls.insert(std::make_pair( + ConstString(enumerator_decl->getNameAsString()).GetCString(), p)); } } } clang::NamedDecl * ClangPersistentVariables::GetPersistentDecl(ConstString name) { - PersistentDeclMap::const_iterator i = - m_persistent_decls.find(name.GetCString()); - - if (i == m_persistent_decls.end()) - return nullptr; - else - return i->second; + return m_persistent_decls.lookup(name.GetCString()).m_decl; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index 95e6c3ac963de..434196b35fd52 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -62,7 +62,8 @@ public: llvm::Optional<CompilerType> GetCompilerTypeFromPersistentDecl(ConstString type_name) override; - void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl); + void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl, + ClangASTContext *ctx); clang::NamedDecl *GetPersistentDecl(ConstString name); @@ -80,7 +81,14 @@ private: // The counter used by GetNextPersistentVariableName uint32_t m_next_persistent_variable_id = 0; - typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap; + struct PersistentDecl { + /// The persistent decl. + clang::NamedDecl *m_decl = nullptr; + /// The ClangASTContext for the ASTContext of m_decl. + ClangASTContext *m_context = nullptr; + }; + + typedef llvm::DenseMap<const char *, PersistentDecl> PersistentDeclMap; PersistentDeclMap m_persistent_decls; ///< Persistent entities declared by the user. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index da1ca785635c9..6698797617a31 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -38,10 +38,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTMetadata.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/VariableList.h" @@ -62,13 +63,15 @@ using namespace lldb_private; +char ClangUserExpression::ID; + ClangUserExpression::ClangUserExpression( ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj) : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type, - options, eKindClangUserExpression), + options), m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel), m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) { @@ -347,11 +350,12 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) { if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) { + auto *persistent_state = llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + if (!persistent_state) + return; const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = - llvm::cast<ClangPersistentVariables>( - target->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC)) - ->GetHandLoadedClangModules(); + persistent_state->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { @@ -476,15 +480,18 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, files.AppendIfUnique(f); // We also need to look at external modules in the case of -gmodules as they // contain the support files for libc++ and the C library. - sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) { - for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) { - const FileSpecList &support_files = - module->GetCompileUnitAtIndex(i)->GetSupportFiles(); - for (const FileSpec &f : support_files) { - files.AppendIfUnique(f); - } - } - }); + llvm::DenseSet<SymbolFile *> visited_symbol_files; + sc.comp_unit->ForEachExternalModule( + visited_symbol_files, [&files](Module &module) { + for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) { + const FileSpecList &support_files = + module.GetCompileUnitAtIndex(i)->GetSupportFiles(); + for (const FileSpec &f : support_files) { + files.AppendIfUnique(f); + } + } + return false; + }); LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze", files.GetSize()); @@ -576,7 +583,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); }); - if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) { + if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); @@ -676,10 +683,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, register_execution_unit = true; } - if (register_execution_unit) - exe_ctx.GetTargetPtr() - ->GetPersistentExpressionStateForLanguage(m_language) - ->RegisterExecutionUnit(m_execution_unit_sp); + if (register_execution_unit) { + if (auto *persistent_state = + exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( + m_language)) + persistent_state->RegisterExecutionUnit(m_execution_unit_sp); + } } if (generate_debug_info) { @@ -764,7 +773,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); }); - if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) { + if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); @@ -887,9 +896,9 @@ void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap( Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory, ValueObject *ctx_obj) { - m_expr_decl_map_up.reset( - new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx, - ctx_obj)); + m_expr_decl_map_up.reset(new ClangExpressionDeclMap( + keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), + exe_ctx.GetTargetRef().GetClangASTImporter(), ctx_obj)); } clang::ASTConsumer * diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index d94f9cc5e0660..00cbffa7fd6fe 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -38,11 +38,14 @@ namespace lldb_private { /// the objects needed to parse and interpret or JIT an expression. It uses /// the Clang parser to produce LLVM IR from the expression. class ClangUserExpression : public LLVMUserExpression { + // LLVM RTTI support + static char ID; + public: - /// LLVM-style RTTI support. - static bool classof(const Expression *E) { - return E->getKind() == eKindClangUserExpression; + bool isA(const void *ClassID) const override { + return ClassID == &ID || LLVMUserExpression::isA(ClassID); } + static bool classof(const Expression *obj) { return obj->isA(&ID); } enum { kDefaultTimeout = 500000u }; @@ -93,7 +96,7 @@ public: /// \param[in] expr /// The expression to parse. /// - /// \param[in] expr_prefix + /// \param[in] prefix /// If non-NULL, a C string containing translation-unit level /// definitions to be included when the expression is parsed. /// diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 564c62c6a2c69..199e4898e1184 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -31,6 +31,8 @@ using namespace lldb_private; +char ClangUtilityFunction::ID; + /// Constructor /// /// \param[in] text @@ -40,7 +42,7 @@ using namespace lldb_private; /// The name of the function, as used in the text. ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope, const char *text, const char *name) - : UtilityFunction(exe_scope, text, name, eKindClangUtilityFunction) { + : UtilityFunction(exe_scope, text, name) { m_function_text.assign(ClangExpressionSourceCode::g_expression_prefix); if (text && text[0]) m_function_text.append(text); @@ -157,7 +159,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap( ExecutionContext &exe_ctx, bool keep_result_in_memory) { - m_expr_decl_map_up.reset( - new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx, - nullptr)); + m_expr_decl_map_up.reset(new ClangExpressionDeclMap( + keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(), + exe_ctx.GetTargetRef().GetClangASTImporter(), nullptr)); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index 70ebb2f3ad8aa..9efaa0254c3e5 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -33,11 +33,14 @@ namespace lldb_private { /// simply provide a way to push a function into the target for the debugger /// to call later on. class ClangUtilityFunction : public UtilityFunction { + // LLVM RTTI support + static char ID; + public: - /// LLVM-style RTTI support. - static bool classof(const Expression *E) { - return E->getKind() == eKindClangUtilityFunction; + bool isA(const void *ClassID) const override { + return ClassID == &ID || UtilityFunction::isA(ClassID); } + static bool classof(const Expression *obj) { return obj->isA(&ID); } class ClangUtilityFunctionHelper : public ClangExpressionHelper { public: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h index 60c0691b21c18..5b9c8007ab763 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h @@ -76,10 +76,6 @@ public: /// /// \param[in] func_name /// The name of the function to prepare for execution in the target. - /// - /// \param[in] decl_map - /// The mapping used to look up entities in the target process. In - /// this case, used to find objc_msgSend IRDynamicChecks(ClangDynamicCheckerFunctions &checker_functions, const char *func_name = "$__lldb_expr"); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 4e871f7d6a44c..103a7ee46f356 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -355,7 +355,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), - reinterpret_cast<uint64_t>(result_decl), false); + reinterpret_cast<uintptr_t>(result_decl), false); llvm::Metadata *values[2]; values[0] = ConstantAsMetadata::get(new_result_global); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h index 893620f7f8e0a..262e8ee0c06c6 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -71,15 +71,6 @@ public: /// variables) should be resolved. If not, only external functions /// are resolved. /// - /// \param[in] execution_policy - /// Determines whether an IR interpreter can be used to statically - /// evaluate the expression. - /// - /// \param[in] const_result - /// This variable is populated with the statically-computed result - /// of the function, if it has no side-effects and the result can - /// be computed statically. - /// /// \param[in] execution_unit /// The holder for raw data associated with the expression. /// @@ -105,10 +96,6 @@ public: /// $__lldb_expr, and that function is passed to the passes one by /// one. /// - /// \param[in] interpreter_error - /// An error. If the expression fails to be interpreted, this error - /// is set to a reason why. - /// /// \return /// True on success; false otherwise bool runOnModule(llvm::Module &llvm_module) override; @@ -142,9 +129,6 @@ private: /// The top-level pass implementation /// - /// \param[in] llvm_module - /// The module currently being processed. - /// /// \param[in] llvm_function /// The function currently being processed. /// @@ -184,12 +168,12 @@ private: /// Find the NamedDecl corresponding to a Value. This interface is exposed /// for the IR interpreter. /// + /// \param[in] global_val + /// The global entity to search for + /// /// \param[in] module /// The module containing metadata to search /// - /// \param[in] global - /// The global entity to search for - /// /// \return /// The corresponding variable declaration public: @@ -287,7 +271,7 @@ private: /// Replace a single old-style class reference /// - /// \param[in] selector_load + /// \param[in] class_load /// The load of the statically-allocated selector. /// /// \return @@ -362,7 +346,7 @@ private: /// Handle all the arguments to a function call /// - /// \param[in] C + /// \param[in] call_inst /// The call instruction. /// /// \return @@ -381,8 +365,8 @@ private: /// Remove calls to __cxa_atexit, which should never be generated by /// expressions. /// - /// \param[in] call_inst - /// The call instruction. + /// \param[in] basic_block + /// The basic block currently being processed. /// /// \return /// True if the scan was successful; false if some operation @@ -391,7 +375,7 @@ private: /// The top-level pass implementation /// - /// \param[in] basic_block + /// \param[in] llvm_function /// The function currently being processed. /// /// \return @@ -474,28 +458,9 @@ private: ///pointer (see comments in /// ASTResultSynthesizer::SynthesizeBodyResult) - llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be - ///replaced by a pointer to the - ///final - /// location of the static allocation. - - /// UnfoldConstant operates on a constant [Old] which has just been replaced - /// with a value [New]. We assume that new_value has been properly placed - /// early in the function, in front of the first instruction in the entry - /// basic block [FirstEntryInstruction]. - /// - /// UnfoldConstant reads through the uses of Old and replaces Old in those - /// uses with New. Where those uses are constants, the function generates - /// new instructions to compute the result of the new, non-constant - /// expression and places them before FirstEntryInstruction. These - /// instructions replace the constant uses, so UnfoldConstant calls itself - /// recursively for those. - /// - /// \param[in] llvm_function - /// The function currently being processed. - /// - /// \return - /// True on success; false otherwise + /// A placeholder that will be replaced by a pointer to the final location of + /// the static allocation. + llvm::GlobalVariable *m_reloc_placeholder; class FunctionValueCache { public: @@ -513,6 +478,20 @@ private: FunctionValueCache m_entry_instruction_finder; + /// UnfoldConstant operates on a constant [Old] which has just been replaced + /// with a value [New]. We assume that new_value has been properly placed + /// early in the function, in front of the first instruction in the entry + /// basic block [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old in those + /// uses with New. Where those uses are constants, the function generates + /// new instructions to compute the result of the new, non-constant + /// expression and places them before FirstEntryInstruction. These + /// instructions replace the constant uses, so UnfoldConstant calls itself + /// recursively for those. + /// + /// \return + /// True on success; false otherwise static bool UnfoldConstant(llvm::Constant *old_constant, llvm::Function *llvm_function, FunctionValueCache &value_maker, @@ -522,9 +501,6 @@ private: /// Commit the allocation in m_data_allocator and use its final location to /// replace m_reloc_placeholder. /// - /// \param[in] module - /// The module that m_data_allocator resides in - /// /// \return /// True on success; false otherwise bool CompleteDataAllocation(); |
