paulherman updated this revision to Diff 34609. paulherman added a comment.
[WIP] Search variables based on clang::DeclContext and clang::Decl tree This revision fixes some of the comments. There are some things I'm not sure about. The problem is that at some point there will be the need to link decls with the object they represent (Function, Variable, CompileUnit, etc). Is the approach of getting the VariableSP from the TypeSystem the right one? Also, should ParseVariableDIE be moved to DWARFASTParser in order to create the decl there or should there only be a method CreateVariableDecl(VariableSP var)? http://reviews.llvm.org/D12658 Files: include/lldb/Symbol/Block.h include/lldb/Symbol/ClangASTContext.h include/lldb/Symbol/CompilerDecl.h include/lldb/Symbol/CompilerDeclContext.h include/lldb/Symbol/TypeSystem.h include/lldb/Symbol/Variable.h include/lldb/lldb-forward.h source/Expression/ClangASTSource.cpp source/Expression/ClangExpressionDeclMap.cpp source/Plugins/SymbolFile/DWARF/DWARFASTParser.h source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h source/Symbol/CMakeLists.txt source/Symbol/ClangASTContext.cpp source/Symbol/CompilerDecl.cpp source/Symbol/CompilerDeclContext.cpp source/Symbol/Variable.cpp test/lang/cpp/nsimport/TestCppNsImport.py test/lang/cpp/nsimport/main.cpp
Index: test/lang/cpp/nsimport/main.cpp =================================================================== --- test/lang/cpp/nsimport/main.cpp +++ test/lang/cpp/nsimport/main.cpp @@ -16,13 +16,49 @@ } } -using namespace N; -using namespace Nested; +namespace Global +{ + int global; +} + +namespace Fun +{ + int fun_var; + int fun() + { + fun_var = 5; + return 0; // break 1 + } +} + +namespace Single +{ + int single = 3; +} + +namespace NotImportedBefore +{ + int not_imported = 45; +} + +using namespace Global; + +int not_imported = 35; +int fun_var = 9; + +namespace NotImportedAfter +{ + int not_imported = 55; +} int main() { + using namespace N; + using namespace Nested; + using Single::single; n = 1; anon = 2; nested = 3; - return 0; // break 0 + global = 4; + return Fun::fun(); // break 0 } Index: test/lang/cpp/nsimport/TestCppNsImport.py =================================================================== --- test/lang/cpp/nsimport/TestCppNsImport.py +++ test/lang/cpp/nsimport/TestCppNsImport.py @@ -45,6 +45,8 @@ # Break on main function break_0 = target.BreakpointCreateBySourceRegex("// break 0", src_file_spec) self.assertTrue(break_0.IsValid() and break_0.GetNumLocations() >= 1, VALID_BREAKPOINT) + break_1 = target.BreakpointCreateBySourceRegex("// break 1", src_file_spec) + self.assertTrue(break_1.IsValid() and break_1.GetNumLocations() >= 1, VALID_BREAKPOINT) # Launch the process args = None @@ -72,6 +74,32 @@ test_result = frame.EvaluateExpression("anon") self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 2, "anon = 2") + test_result = frame.EvaluateExpression("global") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 4, "global = 4") + + test_result = frame.EvaluateExpression("fun_var") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 9, "fun_var = 9") + + test_result = frame.EvaluateExpression("not_imported") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 35, "not_imported = 35") + + test_result = frame.EvaluateExpression("single") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 3, "single = 3") + + # Continue to second breakpoint + process.Continue() + + # Get the thread of the process + self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + + # Get current fream of the thread at the breakpoint + frame = thread.GetSelectedFrame() + + # Test function inside namespace + test_result = frame.EvaluateExpression("fun_var") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 5, "fun_var = 5") + if __name__ == '__main__': import atexit Index: source/Symbol/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -18,6 +18,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" @@ -89,6 +90,13 @@ return m_name; } +ConstString +Variable::GetUnqualifiedName() const +{ + return m_name; +} + + bool Variable::NameMatches (const ConstString &name) const { @@ -230,6 +238,12 @@ return sizeof(Variable); } +CompilerDeclContext +Variable::GetParentDeclContext () +{ + Type *type = GetType(); + return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); +} void Variable::CalculateSymbolContext (SymbolContext *sc) Index: source/Symbol/CompilerDeclContext.cpp =================================================================== --- source/Symbol/CompilerDeclContext.cpp +++ source/Symbol/CompilerDeclContext.cpp @@ -8,10 +8,25 @@ //===----------------------------------------------------------------------===// #include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/TypeSystem.h" +#include <vector> using namespace lldb_private; +std::vector<CompilerDecl> +CompilerDeclContext::FindDeclByName (ConstString name) +{ + std::vector<CompilerDecl> found_decls; + if (IsValid()) + { + std::vector<void *> found_opaque_decls = m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name); + for (void *opaque_decl : found_opaque_decls) + found_decls.push_back(CompilerDecl(m_type_system, opaque_decl)); + } + return found_decls; +} + bool CompilerDeclContext::IsClang () const { Index: source/Symbol/CompilerDecl.cpp =================================================================== --- /dev/null +++ source/Symbol/CompilerDecl.cpp @@ -0,0 +1,46 @@ +//===-- CompilerDecl.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/TypeSystem.h" + +using namespace lldb_private; + +bool +CompilerDecl::IsClang () const +{ + return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang; +} + +ConstString +CompilerDecl::GetName() const +{ + return m_type_system->DeclGetName(m_opaque_decl); +} + +lldb::VariableSP +CompilerDecl::GetAsVariable () +{ + return m_type_system->DeclGetVariable(m_opaque_decl); +} + +bool +lldb_private::operator == (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs) +{ + return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDecl() == rhs.GetOpaqueDecl(); +} + + +bool +lldb_private::operator != (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs) +{ + return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl(); +} + Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -1750,6 +1750,82 @@ } +clang::BlockDecl * +ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx) +{ + if (ctx != nullptr) + { + clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation()); + ctx->addDecl(decl); + return decl; + } + return nullptr; +} + +clang::UsingDirectiveDecl * +ClangASTContext::CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) +{ + if (decl_ctx != nullptr && ns_decl != nullptr) + { + // TODO: run LCA between decl_tx and ns_decl + clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(), + decl_ctx, + clang::SourceLocation(), + clang::SourceLocation(), + clang::NestedNameSpecifierLoc(), + clang::SourceLocation(), + ns_decl, + GetTranslationUnitDecl(getASTContext())); + decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; +} + +clang::UsingDecl * +ClangASTContext::CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target) +{ + if (current_decl_ctx != nullptr && target != nullptr) + { + clang::UsingDecl *using_decl = clang::UsingDecl::Create(*getASTContext(), + current_decl_ctx, + clang::SourceLocation(), + clang::NestedNameSpecifierLoc(), + clang::DeclarationNameInfo(), + false); + clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(*getASTContext(), + current_decl_ctx, + clang::SourceLocation(), + using_decl, + target); + using_decl->addShadowDecl(shadow_decl); + current_decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; +} + +clang::VarDecl * +ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type) +{ + if (decl_context != nullptr) + { + clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(), + decl_context, + clang::SourceLocation(), + clang::SourceLocation(), + name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, + type, + nullptr, + clang::SC_None); + var_decl->setAccess(clang::AS_public); + decl_context->addDecl(var_decl); + decl_context->makeDeclVisibleInContext(var_decl); + return var_decl; + } + return nullptr; +} + #pragma mark Function Types FunctionDecl * @@ -8812,9 +8888,94 @@ } //---------------------------------------------------------------------- +// CompilerDecl override functions +//---------------------------------------------------------------------- +lldb::VariableSP +ClangASTContext::DeclGetVariable (void *opaque_decl) +{ + if (llvm::dyn_cast<clang::VarDecl>((clang::Decl *)opaque_decl)) + { + auto decl_search_it = m_decl_objects.find(opaque_decl); + if (decl_search_it != m_decl_objects.end()) + return std::static_pointer_cast<Variable>(decl_search_it->second); + } + return VariableSP(); +} + +void +ClangASTContext::DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) +{ + assert(m_decl_objects.find(opaque_decl) == m_decl_objects.end()); + m_decl_objects.insert(std::make_pair(opaque_decl, object)); +} + +ConstString +ClangASTContext::DeclGetName (void *opaque_decl) +{ + if (opaque_decl) + { + clang::NamedDecl *nd = llvm::dyn_cast<NamedDecl>((clang::Decl*)opaque_decl); + if (nd != nullptr) + return ConstString(nd->getName()); + } + return ConstString(); +} + +//---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- +std::vector<void *> +ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name) +{ + std::vector<void *> found_decls; + if (opaque_decl_ctx) + { + DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx; + std::set<DeclContext *> searched; + std::multimap<DeclContext *, DeclContext *> search_queue; + + for (clang::DeclContext *decl_context = root_decl_ctx; decl_context != nullptr && found_decls.empty(); decl_context = decl_context->getParent()) + { + search_queue.insert(std::make_pair(decl_context, decl_context)); + + for (auto it = search_queue.find(decl_context); it != search_queue.end(); it++) + { + searched.insert(it->second); + for (clang::Decl *child : it->second->decls()) + { + if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(child)) + { + IdentifierInfo *ii = nd->getIdentifier(); + if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) + found_decls.push_back(nd); + } + else if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) + { + clang::DeclContext *from = ud->getCommonAncestor(); + if (searched.find(ud->getNominatedNamespace()) == searched.end()) + search_queue.insert(std::make_pair(from, ud->getNominatedNamespace())); + } + else if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child)) + { + for (clang::UsingShadowDecl *usd : ud->shadows()) + { + clang::Decl *target = usd->getTargetDecl(); + if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target)) + { + IdentifierInfo *ii = nd->getIdentifier(); + if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) + found_decls.push_back(nd); + } + } + } + } + } + } + } + return found_decls; +} + bool ClangASTContext::DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) { Index: source/Symbol/CMakeLists.txt =================================================================== --- source/Symbol/CMakeLists.txt +++ source/Symbol/CMakeLists.txt @@ -4,6 +4,7 @@ ClangASTImporter.cpp ClangExternalASTSourceCallbacks.cpp ClangExternalASTSourceCommon.cpp + CompilerDecl.cpp CompilerDeclContext.cpp CompilerType.cpp CompileUnit.cpp Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -400,6 +400,12 @@ bool parse_children, lldb_private::VariableList* cc_variable_list = NULL); + void + ParseImportedNamespace ( + const lldb_private::SymbolContext &sc, + const DWARFDIE die, + const lldb::addr_t func_low_pc); + bool ClassOrStructIsVirtual (const DWARFDIE &die); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -48,6 +48,8 @@ #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" @@ -3048,6 +3050,8 @@ case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: + case DW_TAG_lexical_block: + case DW_TAG_subprogram: return die; default: @@ -3697,13 +3701,80 @@ } } + if (DWARFDIE cu_die = dwarf_cu->GetDIE(dwarf_cu->GetFirstDIEOffset())) + for (auto d = cu_die.GetFirstChild(); d; d = d.GetSibling()) + ParseImportedNamespace(sc, d, LLDB_INVALID_ADDRESS); } return vars_added; } } return 0; } +void +SymbolFileDWARF::ParseImportedNamespace +( + const SymbolContext &sc, + const DWARFDIE die, + const lldb::addr_t func_low_pc +) +{ + return; + if (!die || (die.Tag() != DW_TAG_imported_module && die.Tag() != DW_TAG_imported_declaration)) + return; + + dw_offset_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + if (UserIDMatches(imported_uid)) + { + DWARFDebugInfo *debug_info = DebugInfo(); + if (debug_info) + { + const DWARFDIE imported_die = debug_info->GetDIE(DIERef(imported_uid)); + TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast != nullptr) + { + sc.comp_unit->GetVariableList(true); + clang::DeclContext *context = nullptr; + if (sc.block != nullptr) + context = ClangASTContext::DeclContextGetAsDeclContext(sc.block->GetDeclContext()); + else + context = GetClangASTContext().GetTranslationUnitDecl(GetClangASTContext().getASTContext()); + + if (context != nullptr) + { + if (die.Tag() == DW_TAG_imported_module) + { + CompilerDeclContext ns_decl_context = dwarf_ast->GetDeclContextForUIDFromDWARF(imported_die); + if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(ns_decl_context)) + GetClangASTContext().CreateUsingDirectiveDeclaration(context, ns_decl); + } + else if (die.Tag() == DW_TAG_imported_declaration) + { + // TODO: handle imported declarations (using Namespace::Symbol) for other tags + if (imported_die.Tag() == DW_TAG_variable) + { + VariableSP var = ParseVariableDIE(sc, imported_die, func_low_pc); + if (var) + { + CompilerDecl clang_var_decl = var->GetVarDecl(); + if (clang_var_decl) + { + clang::VarDecl *var_decl = (clang::VarDecl *)clang_var_decl.GetOpaqueDecl(); + GetClangASTContext().CreateUsingDeclaration(context, var_decl); + } + } + } + } + } + } + } + } + } +} + VariableSP SymbolFileDWARF::ParseVariableDIE ( @@ -3732,6 +3803,7 @@ { DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); + DWARFDIE spec_die; if (num_attributes > 0) { const char *name = NULL; @@ -3853,7 +3925,17 @@ } } break; - + case DW_AT_specification: + { + dw_offset_t spec_uid = form_value.Reference(); + if (UserIDMatches(spec_uid)) + { + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + spec_die = debug_info->GetDIE(DIERef(spec_uid)); + } + break; + } case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: @@ -3865,15 +3947,14 @@ default: case DW_AT_abstract_origin: case DW_AT_sibling: - case DW_AT_specification: break; } } } const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); const dw_tag_t parent_tag = die.GetParent().Tag(); - bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type); + bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type ); ValueType scope = eValueTypeInvalid; @@ -4069,6 +4150,26 @@ // (missing location due to optimization, etc)) so we don't re-parse // this DIE over and over later... GetDIEToVariable()[die.GetDIE()] = var_sp; + if (spec_die) + GetDIEToVariable()[spec_die.GetDIE()] = var_sp; + + if (var_sp && var_sp->GetType()) + { + CompilerDeclContext decl_context = var_sp->GetParentDeclContext(); + if (decl_context) + { + clang::DeclContext *dc = ClangASTContext::DeclContextGetAsDeclContext(decl_context); + if (dc) + { + clang::VarDecl *clang_var_decl = GetClangASTContext().CreateVariableDeclaration( + dc, + var_sp->GetUnqualifiedName().AsCString(nullptr), + GetClangASTContext().GetQualType(var_sp->GetType()->GetForwardCompilerType())); + if (clang_var_decl) + GetClangASTContext().DeclLinkToObject((void *)clang_var_decl, var_sp); + } + } + } } return var_sp; } @@ -4232,6 +4333,8 @@ } } } + else if (tag == DW_TAG_imported_module || tag == DW_TAG_imported_declaration) + ParseImportedNamespace(sc, die, func_low_pc); } bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -83,6 +83,9 @@ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; }; + clang::BlockDecl * + ResolveBlockDIE (const DWARFDIE &die); + clang::NamespaceDecl * ResolveNamespaceDIE (const DWARFDIE &die); @@ -156,6 +159,9 @@ LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die); + void + LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); + typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap; Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -111,7 +111,6 @@ } }; - TypeSP DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, const DWARFDIE &die, @@ -2202,7 +2201,6 @@ }; #endif - Function * DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, const DWARFDIE &die) @@ -3197,6 +3195,11 @@ try_parsing_type = false; break; + case DW_TAG_lexical_block: + decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die); + try_parsing_type = false; + break; + default: break; } @@ -3217,6 +3220,28 @@ return nullptr; } +clang::BlockDecl * +DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die) +{ + if (die && die.Tag() == DW_TAG_lexical_block) + { + clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]); + + if (!decl) + { + DWARFDIE decl_context_die; + clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die); + decl = m_ast.CreateBlockDeclaration(decl_context); + + if (decl) + LinkDeclContextToDIE((clang::DeclContext *)decl, die); + } + + return decl; + } + return nullptr; +} + clang::NamespaceDecl * DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die) { @@ -3285,10 +3310,6 @@ return m_ast.GetTranslationUnitDecl(); } - - - - clang::DeclContext * DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die) { Index: source/Plugins/SymbolFile/DWARF/DWARFASTParser.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -27,7 +27,6 @@ lldb_private::Log *log, bool *type_is_new_ptr) = 0; - virtual lldb_private::Function * ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc, const DWARFDIE &die) = 0; @@ -42,7 +41,6 @@ virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0; - }; #endif // SymbolFileDWARF_DWARFASTParser_h_ Index: source/Expression/ClangExpressionDeclMap.cpp =================================================================== --- source/Expression/ClangExpressionDeclMap.cpp +++ source/Expression/ClangExpressionDeclMap.cpp @@ -28,6 +28,7 @@ #include "lldb/Expression/Materializer.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -1035,6 +1036,9 @@ // doesn't start with our phony prefix of '$' Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext sym_ctx; + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); if (name_unique_cstr[0] == '$' && !namespace_decl) { static ConstString g_lldb_class_name ("$__lldb_class"); @@ -1046,7 +1050,6 @@ if (frame == NULL) return; - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); // Find the block that defines the function represented by "sym_ctx" Block *function_block = sym_ctx.GetFunctionBlock(); @@ -1352,24 +1355,28 @@ if (frame && !namespace_decl) { - valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr, - eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsNoFragileObjcIvar | - StackFrame::eExpressionPathOptionsNoSyntheticChildren | - StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, - var, - err); - - // If we found a variable in scope, no need to pull up function names - if (err.Success() && var) + CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + + if (compiler_decl_context) { - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - return; + // Make sure that the variables are parsed so that we have the declarations + frame->GetInScopeVariableList(true); + + // Search for declarations matching the name + std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name); + for (CompilerDecl decl : found_decls) + { + var = decl.GetAsVariable(); + if (var) + { + valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; + } + } } } - if (target) { var = FindGlobalVariable (*target, Index: source/Expression/ClangASTSource.cpp =================================================================== --- source/Expression/ClangASTSource.cpp +++ source/Expression/ClangASTSource.cpp @@ -515,7 +515,7 @@ else log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); } - + Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl); if (!copied_decl) Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -64,6 +64,7 @@ class CommandReturnObject; class Communication; class CompactUnwindInfo; +class CompilerDecl; class CompilerDeclContext; class CompilerType; class CompileUnit; Index: include/lldb/Symbol/Variable.h =================================================================== --- include/lldb/Symbol/Variable.h +++ include/lldb/Symbol/Variable.h @@ -18,6 +18,8 @@ #include "lldb/Core/UserID.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/Declaration.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" namespace lldb_private { @@ -59,6 +61,9 @@ ConstString GetName() const; + ConstString + GetUnqualifiedName() const; + SymbolContextScope * GetSymbolContextScope() const { @@ -167,6 +172,21 @@ StringList &matches, bool &word_complete); + CompilerDeclContext + GetParentDeclContext (); + + CompilerDecl + GetVarDecl () + { + return m_var_decl; + } + + void + SetVarDecl (CompilerDecl var_decl) + { + m_var_decl = var_decl; + } + protected: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of the variable @@ -179,6 +199,7 @@ m_artificial:1, // Non-zero if the variable is not explicitly declared in source m_loc_is_const_data:1, // The m_location expression contains the constant variable value data, not a DWARF location m_static_member:1; // Non-zero if variable is static member of a class or struct. + CompilerDecl m_var_decl; private: Variable(const Variable& rhs); Variable& operator=(const Variable& rhs); Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- include/lldb/Symbol/TypeSystem.h +++ include/lldb/Symbol/TypeSystem.h @@ -97,8 +97,23 @@ } //---------------------------------------------------------------------- + // CompilerDecl functions + //---------------------------------------------------------------------- + virtual ConstString + DeclGetName (void *opaque_decl) = 0; + + virtual lldb::VariableSP + DeclGetVariable (void *opaque_decl) = 0; + + virtual void + DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) = 0; + + //---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- + + virtual std::vector<void *> + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) = 0; virtual bool DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) = 0; Index: include/lldb/Symbol/CompilerDeclContext.h =================================================================== --- include/lldb/Symbol/CompilerDeclContext.h +++ include/lldb/Symbol/CompilerDeclContext.h @@ -9,7 +9,6 @@ #ifndef liblldb_CompilerDeclContext_h_ #define liblldb_CompilerDeclContext_h_ - #include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" @@ -50,7 +49,7 @@ operator < (const CompilerDeclContext &rhs) const { if (m_type_system == rhs.m_type_system) - return m_type_system < rhs.m_type_system; + return m_opaque_decl_ctx < rhs.m_opaque_decl_ctx; return m_type_system < rhs.m_type_system; } @@ -63,6 +62,9 @@ bool IsClang () const; + std::vector<CompilerDecl> + FindDeclByName (ConstString name); + //---------------------------------------------------------------------- /// Checks if this decl context represents a method of a class. /// Index: include/lldb/Symbol/CompilerDecl.h =================================================================== --- /dev/null +++ include/lldb/Symbol/CompilerDecl.h @@ -0,0 +1,116 @@ +//===-- CompilerDecl.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CompilerDecl_h_ +#define liblldb_CompilerDecl_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +class CompilerDecl +{ +public: + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + CompilerDecl () : + m_type_system (nullptr), + m_opaque_decl (nullptr) + { + } + + CompilerDecl (TypeSystem *type_system, void *decl) : + m_type_system (type_system), + m_opaque_decl (decl) + { + } + + ~CompilerDecl () + { + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + explicit operator bool () const + { + return IsValid (); + } + + bool + operator < (const CompilerDecl &rhs) const + { + if (m_type_system == rhs.m_type_system) + return m_opaque_decl < rhs.m_opaque_decl; + return m_type_system < rhs.m_type_system; + } + + bool + IsValid () const + { + return m_type_system != nullptr && m_opaque_decl != nullptr; + } + + bool + IsClang () const; + + //---------------------------------------------------------------------- + // Object linked to the decl + //---------------------------------------------------------------------- + lldb::VariableSP + GetAsVariable (); + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + TypeSystem * + GetTypeSystem() const + { + return m_type_system; + } + + void * + GetOpaqueDecl() const + { + return m_opaque_decl; + } + + void + SetDecl (TypeSystem* type_system, void* decl) + { + m_type_system = type_system; + m_opaque_decl = decl; + } + + void + Clear() + { + m_type_system = nullptr; + m_opaque_decl = nullptr; + } + + ConstString + GetName () const; + +private: + TypeSystem *m_type_system; + void *m_opaque_decl; +}; + +bool operator == (const CompilerDecl &lhs, const CompilerDecl &rhs); +bool operator != (const CompilerDecl &lhs, const CompilerDecl &rhs); + + +} // namespace lldb_private + +#endif // #ifndef liblldb_CompilerDecl_h_ Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -23,13 +23,17 @@ #include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTContext.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" // Project includes #include "lldb/lldb-enumerations.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" +#include "lldb/Symbol/Block.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/Variable.h" namespace lldb_private { @@ -508,8 +512,23 @@ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); //---------------------------------------------------------------------- + // CompilerDecl override functions + //---------------------------------------------------------------------- + lldb::VariableSP + DeclGetVariable (void *opaque_decl) override; + + void + DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) override; + + ConstString + DeclGetName (void *opaque_decl) override; + + //---------------------------------------------------------------------- // CompilerDeclContext override functions //---------------------------------------------------------------------- + + std::vector<void *> + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name); bool DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) override; @@ -1071,6 +1090,17 @@ int tag_decl_kind, const ClangASTContext::TemplateParameterInfos &template_param_infos); + clang::BlockDecl * + CreateBlockDeclaration (clang::DeclContext *ctx); + + clang::UsingDirectiveDecl * + CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl); + + clang::UsingDecl * + CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target); + + clang::VarDecl * + CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type); protected: static clang::QualType GetQualType (void *type) @@ -1110,6 +1140,7 @@ void * m_callback_baton; uint32_t m_pointer_byte_size; bool m_ast_owned; + std::map<void *, std::shared_ptr<void>> m_decl_objects; private: //------------------------------------------------------------------ Index: include/lldb/Symbol/Block.h =================================================================== --- include/lldb/Symbol/Block.h +++ include/lldb/Symbol/Block.h @@ -18,6 +18,7 @@ #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/CompilerDeclContext.h" namespace lldb_private {
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits