Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -507,8 +507,23 @@ llvm::DenseMap &vbase_offsets); //---------------------------------------------------------------------- + // CompilerDecl override functions + //---------------------------------------------------------------------- + lldb::VariableSP + DeclGetVariable (void *opaque_decl) override; + + void + DeclLinkToObject (void *opaque_decl, std::shared_ptr object) override; + + ConstString + DeclGetName (void *opaque_decl) override; + + //---------------------------------------------------------------------- // CompilerDeclContext override functions //---------------------------------------------------------------------- + + std::vector + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name); bool DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) override; @@ -1070,6 +1085,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 +1136,7 @@ uint32_t m_pointer_byte_size; bool m_ast_owned; bool m_can_evaluate_expressions; + std::map> m_decl_objects; private: //------------------------------------------------------------------ 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/CompilerDeclContext.h =================================================================== --- include/lldb/Symbol/CompilerDeclContext.h +++ include/lldb/Symbol/CompilerDeclContext.h @@ -50,7 +50,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 +63,9 @@ bool IsClang () const; + std::vector + FindDeclByName (ConstString name); + //---------------------------------------------------------------------- /// Checks if this decl context represents a method of a class. /// Index: include/lldb/Symbol/GoASTContext.h =================================================================== --- include/lldb/Symbol/GoASTContext.h +++ include/lldb/Symbol/GoASTContext.h @@ -44,8 +44,34 @@ } //---------------------------------------------------------------------- + // CompilerDecl functions + //---------------------------------------------------------------------- + virtual ConstString + DeclGetName (void *opaque_decl) override + { + return ConstString(); + } + + virtual lldb::VariableSP + DeclGetVariable (void *opaque_decl) override + { + return lldb::VariableSP(); + } + + virtual void + DeclLinkToObject (void *opaque_decl, std::shared_ptr object) override + { + } + + //---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- + + virtual std::vector + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) override + { + return std::vector(); + } virtual bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override Index: include/lldb/Symbol/SymbolFile.h =================================================================== --- include/lldb/Symbol/SymbolFile.h +++ include/lldb/Symbol/SymbolFile.h @@ -13,6 +13,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Type.h" @@ -130,6 +131,7 @@ virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0; virtual Type* ResolveTypeUID (lldb::user_id_t type_uid) = 0; virtual bool CompleteType (CompilerType &clang_type) = 0; + virtual CompilerDecl GetDeclForUID (lldb::user_id_t uid) { return CompilerDecl(); } virtual CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) { return CompilerDeclContext(); } virtual CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) { return CompilerDeclContext(); } virtual uint32_t ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) = 0; Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- include/lldb/Symbol/TypeSystem.h +++ include/lldb/Symbol/TypeSystem.h @@ -98,8 +98,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 object) = 0; + + //---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- + + virtual std::vector + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) = 0; virtual bool DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) = 0; Index: include/lldb/Symbol/Variable.h =================================================================== --- include/lldb/Symbol/Variable.h +++ include/lldb/Symbol/Variable.h @@ -1,4 +1,5 @@ -//===-- Variable.h ----------------------------------------------*- C++ -*-===// +//===-- Variable.h ----------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,6 +11,7 @@ #ifndef liblldb_Variable_h_ #define liblldb_Variable_h_ +#include #include #include "lldb/lldb-private.h" @@ -21,7 +23,8 @@ namespace lldb_private { -class Variable : public UserID +class Variable : public UserID, + public std::enable_shared_from_this { public: //------------------------------------------------------------------ @@ -59,6 +62,9 @@ ConstString GetName() const; + ConstString + GetUnqualifiedName() const; + SymbolContextScope * GetSymbolContextScope() const { @@ -167,6 +173,11 @@ StringList &matches, bool &word_complete); + CompilerDeclContext + GetDeclContext (); + + CompilerDecl + GetDecl (); protected: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of the variable Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -61,6 +61,7 @@ class CommandReturnObject; class Communication; class CompactUnwindInfo; +class CompilerDecl; class CompilerDeclContext; class CompilerType; class CompileUnit; Index: source/Expression/ClangASTSource.cpp =================================================================== --- source/Expression/ClangASTSource.cpp +++ source/Expression/ClangASTSource.cpp @@ -514,7 +514,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: 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,30 @@ 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 + VariableListSP vars = frame->GetInScopeVariableList(true); + for (size_t i = 0; i < vars->GetSize(); i++) + vars->GetVariableAtIndex(i)->GetDecl(); + + // Search for declarations matching the name + std::vector 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/Plugins/SymbolFile/DWARF/DWARFASTParser.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -12,6 +12,7 @@ #include "DWARFDefines.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" class DWARFDIE; @@ -27,7 +28,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; @@ -37,12 +37,14 @@ lldb_private::Type *type, lldb_private::CompilerType &clang_type) = 0; + virtual lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) = 0; + virtual lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF (const DWARFDIE &die) = 0; virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0; - }; #endif // SymbolFileDWARF_DWARFASTParser_h_ Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -48,6 +48,9 @@ lldb_private::Type *type, lldb_private::CompilerType &clang_type) override; + virtual lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) override; + virtual lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override; @@ -83,6 +86,9 @@ llvm::DenseMap vbase_offsets; }; + clang::BlockDecl * + ResolveBlockDIE (const DWARFDIE &die); + clang::NamespaceDecl * ResolveNamespaceDIE (const DWARFDIE &die); @@ -136,6 +142,12 @@ uint32_t enumerator_byte_size, const DWARFDIE &parent_die); + lldb_private::Type * + GetTypeForDIE (const DWARFDIE &die); + + clang::Decl * + GetClangDeclForDIE (const DWARFDIE &die); + clang::DeclContext * GetClangDeclContextForDIE (const DWARFDIE &die); @@ -156,11 +168,18 @@ LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die); + void + LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); + typedef llvm::SmallPtrSet DIEPointerSet; typedef llvm::DenseMap DIEToDeclContextMap; typedef llvm::DenseMap DeclContextToDIEMap; + typedef llvm::DenseMap DIEToDeclMap; + typedef llvm::DenseMap DeclToDIEMap; lldb_private::ClangASTContext &m_ast; + DIEToDeclMap m_die_to_decl; + DeclToDIEMap m_decl_to_die; DIEToDeclContextMap m_die_to_decl_ctx; DeclContextToDIEMap m_decl_ctx_to_die; RecordDeclToLayoutMap m_record_decl_to_layout_map; 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, @@ -2040,6 +2039,15 @@ return false; } +CompilerDecl +DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die) +{ + clang::Decl *clang_decl = GetClangDeclForDIE(die); + if (clang_decl != nullptr) + return CompilerDecl(&m_ast, clang_decl); + return CompilerDecl(); +} + CompilerDeclContext DWARFASTParserClang::GetDeclContextForUIDFromDWARF (const DWARFDIE &die) { @@ -2202,7 +2210,6 @@ }; #endif - Function * DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, const DWARFDIE &die) @@ -3175,6 +3182,101 @@ } } +Type * +DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die) +{ + if (die) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + DWARFFormValue type_die_form; + for (size_t i = 0; i < num_attributes; ++i) + { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + + if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) + return dwarf->ResolveTypeUID(DIERef(form_value).GetUID()); + } + } + } + + return nullptr; +} + +clang::Decl * +DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) +{ + if (!die) + return nullptr; + + clang::Decl *decl = m_die_to_decl[die.GetDIE()]; + if (decl != nullptr) + return decl; + + switch (die.Tag()) + { + case DW_TAG_variable: + case DW_TAG_constant: + case DW_TAG_formal_parameter: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + Type *type = GetTypeForDIE(die); + const char *name = die.GetName(); + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + decl = m_ast.CreateVariableDeclaration( + decl_context, + name, + ClangASTContext::GetQualType(type->GetForwardCompilerType())); + break; + } + case DW_TAG_imported_declaration: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + + if (dwarf->UserIDMatches(imported_uid)) + { + CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid); + if (imported_decl) + { + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast((clang::Decl *)imported_decl.GetOpaqueDecl())) + decl = m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl); + } + } + break; + } + case DW_TAG_imported_module: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + + if (dwarf->UserIDMatches(imported_uid)) + { + CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid); + if (imported_decl) + { + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + if (clang::NamespaceDecl *clang_imported_decl = llvm::dyn_cast((clang::DeclContext *)imported_decl.GetOpaqueDeclContext())) + decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, clang_imported_decl); + } + } + break; + } + default: + break; + } + + m_die_to_decl[die.GetDIE()] = decl; + m_decl_to_die[decl].insert(die.GetDIE()); + + return decl; +} + clang::DeclContext * DWARFASTParserClang::GetClangDeclContextForDIE (const DWARFDIE &die) { @@ -3197,6 +3299,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 +3324,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(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 +3414,6 @@ return m_ast.GetTranslationUnitDecl(); } - - - - clang::DeclContext * DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die) { Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h @@ -51,6 +51,12 @@ return lldb_private::CompilerDeclContext(); } + virtual lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) override + { + return lldb_private::CompilerDecl(); + } + private: size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic, std::vector &function_param_types); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -152,6 +152,9 @@ ResolveType (const DWARFDIE &die, bool assert_not_being_parsed = true); + lldb_private::CompilerDecl + GetDeclForUID (lldb::user_id_t uid) override; + lldb_private::CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) override; 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" @@ -1391,6 +1393,26 @@ return false; } +CompilerDecl +SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid) +{ + if (UserIDMatches(type_uid)) + { + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + { + DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); + if (die) + { + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclForUIDFromDWARF(die); + } + } + } + return CompilerDecl(); +} + CompilerDeclContext SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid) { @@ -3057,6 +3079,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: @@ -3741,6 +3765,7 @@ { DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); + DWARFDIE spec_die; if (num_attributes > 0) { const char *name = NULL; @@ -3862,7 +3887,13 @@ } } break; - + case DW_AT_specification: + { + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + spec_die = debug_info->GetDIE(DIERef(form_value)); + 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: @@ -3874,7 +3905,6 @@ default: case DW_AT_abstract_origin: case DW_AT_sibling: - case DW_AT_specification: break; } } @@ -4078,6 +4108,8 @@ // (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; } return var_sp; } 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/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -1756,6 +1756,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 * @@ -8818,9 +8894,94 @@ } //---------------------------------------------------------------------- +// CompilerDecl override functions +//---------------------------------------------------------------------- +lldb::VariableSP +ClangASTContext::DeclGetVariable (void *opaque_decl) +{ + if (llvm::dyn_cast((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(decl_search_it->second); + } + return VariableSP(); +} + +void +ClangASTContext::DeclLinkToObject (void *opaque_decl, std::shared_ptr object) +{ + if (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((clang::Decl*)opaque_decl); + if (nd != nullptr) + return ConstString(nd->getName()); + } + return ConstString(); +} + +//---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- +std::vector +ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name) +{ + std::vector found_decls; + if (opaque_decl_ctx) + { + DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx; + std::set searched; + std::multimap 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(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(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(child)) + { + for (clang::UsingShadowDecl *usd : ud->shadows()) + { + clang::Decl *target = usd->getTargetDecl(); + if (clang::NamedDecl *nd = llvm::dyn_cast(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/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/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 using namespace lldb_private; +std::vector +CompilerDeclContext::FindDeclByName (ConstString name) +{ + std::vector found_decls; + if (IsValid()) + { + std::vector 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/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -15,9 +15,12 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" #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 +92,13 @@ return m_name; } +ConstString +Variable::GetUnqualifiedName() const +{ + return m_name; +} + + bool Variable::NameMatches (const ConstString &name) const { @@ -230,6 +240,22 @@ return sizeof(Variable); } +CompilerDeclContext +Variable::GetDeclContext () +{ + Type *type = GetType(); + return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); +} + +CompilerDecl +Variable::GetDecl () +{ + Type *type = GetType(); + CompilerDecl decl = type->GetSymbolFile()->GetDeclForUID(GetID()); + if (decl) + decl.GetTypeSystem()->DeclLinkToObject(decl.GetOpaqueDecl(), shared_from_this()); + return decl; +} void Variable::CalculateSymbolContext (SymbolContext *sc) Index: test/lang/cpp/nsimport/TestCppNsImport.py =================================================================== --- test/lang/cpp/nsimport/TestCppNsImport.py +++ test/lang/cpp/nsimport/TestCppNsImport.py @@ -16,6 +16,8 @@ self.buildDsym() self.check() + # This test is expected to fail because DW_TAG_imported_declaration and DW_TAG_imported_module are not parsed in SymbolFileDWARF + @expectedFailureAll @dwarf_test def test_with_dwarf_and_run_command(self): """Tests imported namespaces in C++.""" @@ -45,6 +47,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 +76,35 @@ 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("imported") + self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 99, "imported = 99") + + 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: test/lang/cpp/nsimport/main.cpp =================================================================== --- test/lang/cpp/nsimport/main.cpp +++ test/lang/cpp/nsimport/main.cpp @@ -16,13 +16,57 @@ } } -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; +} + +namespace Imported +{ + int imported = 99; +} + +int imported = 89; int main() { + using namespace N; + using namespace Nested; + using namespace Imported; + using Single::single; n = 1; anon = 2; nested = 3; - return 0; // break 0 + global = 4; + return Fun::fun(); // break 0 }