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 { 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 &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; @@ -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> 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 @@ -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 + FindDeclByName (ConstString name); + //---------------------------------------------------------------------- /// Checks if this decl context represents a method of a class. /// 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 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 @@ -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/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: 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: 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 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 @@ -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/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -83,6 +83,9 @@ llvm::DenseMap 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 DIEPointerSet; typedef llvm::DenseMap DIEToDeclContextMap; typedef llvm::DenseMap 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(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/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,6 +3701,9 @@ } } + 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; } @@ -3704,6 +3711,70 @@ 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,7 +3947,6 @@ default: case DW_AT_abstract_origin: case DW_AT_sibling: - case DW_AT_specification: break; } } @@ -3873,7 +3954,7 @@ 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/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 @@ -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::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) +{ + 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((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 @@ -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: 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: 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 }