Index: include/lldb/Symbol/Block.h =================================================================== --- include/lldb/Symbol/Block.h +++ include/lldb/Symbol/Block.h @@ -110,6 +110,12 @@ /// /// @see SymbolContextScope //------------------------------------------------------------------ + virtual SymbolContextScope * + GetParentSymbolContextScope (); + + virtual lldb::VariableTreeSP + GetVariables (); + virtual void CalculateSymbolContext(SymbolContext* sc); @@ -478,6 +484,7 @@ RangeList m_ranges; lldb::InlineFunctionInfoSP m_inlineInfoSP; ///< Inlined function information. lldb::VariableListSP m_variable_list_sp; ///< The variable list for all local, static and parameter variables scoped to this block. + lldb::VariableTreeSP m_variable_tree_sp; bool m_parsed_block_info:1, ///< Set to true if this block and it's children have all been parsed m_parsed_block_variables:1, m_parsed_child_blocks:1; Index: include/lldb/Symbol/CompileUnit.h =================================================================== --- include/lldb/Symbol/CompileUnit.h +++ include/lldb/Symbol/CompileUnit.h @@ -131,6 +131,12 @@ /// /// @see SymbolContextScope //------------------------------------------------------------------ + virtual lldb::VariableTreeSP + GetVariables (); + + virtual SymbolContextScope * + GetParentSymbolContextScope (); + virtual void CalculateSymbolContext(SymbolContext* sc); @@ -440,6 +446,7 @@ std::unique_ptr m_line_table_ap; ///< Line table that will get parsed on demand. lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. bool m_is_optimized; /// eLazyBoolYes if this compile unit was compiled with optimization. + lldb::VariableTreeSP m_variable_tree_sp; private: enum Index: include/lldb/Symbol/Function.h =================================================================== --- include/lldb/Symbol/Function.h +++ include/lldb/Symbol/Function.h @@ -422,6 +422,12 @@ /// /// @see SymbolContextScope //------------------------------------------------------------------ + virtual SymbolContextScope * + GetParentSymbolContextScope (); + + virtual lldb::VariableTreeSP + GetVariables (); + virtual void CalculateSymbolContext(SymbolContext* sc); @@ -666,6 +672,7 @@ DWARFExpression m_frame_base; ///< The frame base expression for variables that are relative to the frame pointer. Flags m_flags; uint32_t m_prologue_byte_size; ///< Compute the prologue size once and cache it + lldb::VariableTreeSP m_variable_tree_sp; private: DISALLOW_COPY_AND_ASSIGN(Function); }; Index: include/lldb/Symbol/Symbol.h =================================================================== --- include/lldb/Symbol/Symbol.h +++ include/lldb/Symbol/Symbol.h @@ -354,6 +354,12 @@ /// /// @see SymbolContextScope //------------------------------------------------------------------ + virtual lldb::VariableTreeSP + GetVariables (); + + virtual SymbolContextScope * + GetParentSymbolContextScope (); + virtual void CalculateSymbolContext (SymbolContext *sc); @@ -407,6 +413,7 @@ Mangled m_mangled; // uniqued symbol name/mangled name pair AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any) uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these + lldb::VariableTreeSP m_variable_tree_sp; }; } // namespace lldb_private Index: include/lldb/Symbol/SymbolContextScope.h =================================================================== --- include/lldb/Symbol/SymbolContextScope.h +++ include/lldb/Symbol/SymbolContextScope.h @@ -118,6 +118,18 @@ return NULL; } + virtual lldb::VariableTreeSP + GetVariables () + { + return NULL; + } + + virtual SymbolContextScope * + GetParentSymbolContextScope () + { + return NULL; + } + //------------------------------------------------------------------ /// Dump the object's symbol context to the stream \a s. /// Index: include/lldb/Symbol/VariableTree.h =================================================================== --- /dev/null +++ include/lldb/Symbol/VariableTree.h @@ -0,0 +1,69 @@ +//===-- VariableTree.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_VariableTree_h_ +#define liblldb_VariableTree_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include + +namespace lldb_private { + +class VariableTree : public std::enable_shared_from_this +{ +public: + VariableTree (lldb::VariableListSP &variables, SymbolContextScope *scope); + + VariableTree (lldb::VariableListSP &variables, SymbolContextScope *scope, lldb::VariableListSP &imported_variables); + + ~VariableTree (); + + bool + AddVariable (const lldb::VariableSP &var); + + size_t + AddVariableList (const lldb::VariableListSP &vars); + + size_t + AddImportedVariableList (const lldb::VariableListSP &imported_variables); + + void + Clear (); + + lldb::VariableSP + FindVariable (const ConstString &name); + + lldb::VariableSP + FindVariable (const ConstString &name, lldb::ValueType type); + + lldb::VariableTreeSP + GetParent (); + + size_t + GetSize (); + +private: + lldb::VariableSP + FindRecVariable (const ConstString &name, std::unordered_map &imported_variables); + + lldb::VariableSP + FindRecVariable (const ConstString &name, lldb::ValueType type, std::unordered_map &imported_variables); + + lldb::VariableTreeSP m_parent; + lldb::VariableListSP m_variables; + SymbolContextScope *m_scope, *m_parent_scope; + lldb::VariableListSP m_imported_variables; +}; + +} + +#endif // liblldb_VariableTree_h_ Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -277,6 +277,7 @@ class ValueObjectPrinter; class Variable; class VariableList; +class VariableTree; class Watchpoint; class WatchpointList; class WatchpointOptions; @@ -435,6 +436,7 @@ typedef std::shared_ptr ValueListSP; typedef std::shared_ptr VariableSP; typedef std::shared_ptr VariableListSP; + typedef std::shared_ptr VariableTreeSP; typedef std::shared_ptr ValueObjectListSP; typedef std::shared_ptr WatchpointSP; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -396,6 +396,12 @@ bool parse_siblings, 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 @@ -53,6 +53,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/VariableTree.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" @@ -3651,6 +3652,18 @@ // Let all blocks know they have parse all their variables sc.function->GetBlock (false).SetDidParseVariables (true, true); + + DWARFDIE context_parent_die = GetDeclContextDIEContainingDIE(function_die); + if (context_parent_die && context_parent_die.Tag() == DW_TAG_namespace) + sc.comp_unit->GetVariableList(true); + while (context_parent_die && context_parent_die.Tag() == DW_TAG_namespace) + { + VariableListSP imported_variables(new VariableList()); + ParseVariables(sc, context_parent_die.GetFirstChild(), func_lo_pc, true, false, imported_variables.get()); + sc.function->GetVariables()->AddImportedVariableList(imported_variables); + + context_parent_die = GetDeclContextDIEContainingDIE(context_parent_die); + } return num_variables; } } @@ -3722,6 +3735,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; } @@ -3729,6 +3745,54 @@ return 0; } +void +SymbolFileDWARF::ParseImportedNamespace +( + const SymbolContext &sc, + const DWARFDIE die, + const lldb::addr_t func_low_pc +) +{ + if (die.Tag() == DW_TAG_imported_declaration || die.Tag() == DW_TAG_imported_module) + { + 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(imported_uid); + + if (imported_die) + { + sc.comp_unit->GetVariableList(true); + VariableListSP imported_variables(new VariableList()); + + if (imported_die.Tag() == DW_TAG_variable) + { + VariableSP var = ParseVariableDIE(sc, imported_die, func_low_pc); + if (var) + imported_variables->AddVariable(var); + } + else if (imported_die.Tag() == DW_TAG_namespace) + ParseVariables(sc, imported_die.GetFirstChild(), func_low_pc, true, false, imported_variables.get()); + + SymbolContextScope *scope = nullptr; + if (sc.block != nullptr) + scope = sc.block; + else if (sc.function != nullptr) + scope = sc.function; + else if (sc.comp_unit != nullptr) + scope = sc.comp_unit; + if (scope != nullptr) + scope->GetVariables()->AddImportedVariableList(imported_variables); + } + } + } + } + +} + VariableSP SymbolFileDWARF::ParseVariableDIE ( @@ -3754,6 +3818,7 @@ { DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); + DWARFDIE spec_die; if (num_attributes > 0) { const char *name = NULL; @@ -3878,6 +3943,17 @@ 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_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(spec_uid); + } + break; + } case DW_AT_declaration: case DW_AT_description: case DW_AT_endianity: @@ -3887,7 +3963,6 @@ default: case DW_AT_abstract_origin: case DW_AT_sibling: - case DW_AT_specification: break; } } @@ -3895,7 +3970,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 || (parent_context_die.Tag() == DW_TAG_namespace && parent_context_die.GetAttributeValueAsString(DW_AT_name, nullptr) != nullptr)); ValueType scope = eValueTypeInvalid; @@ -4091,6 +4166,8 @@ // (missing location due to optimization, etc)) so we don't re-parse // this DIE over and over later... m_die_to_variable_sp[die.GetDIE()] = var_sp; + if (spec_die) + m_die_to_variable_sp[spec_die.GetDIE()] = var_sp; } return var_sp; } @@ -4254,7 +4331,9 @@ } } } - } + 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/Block.cpp =================================================================== --- source/Symbol/Block.cpp +++ source/Symbol/Block.cpp @@ -16,6 +16,7 @@ #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/VariableTree.h" using namespace lldb; using namespace lldb_private; @@ -148,6 +149,34 @@ return matching_block; } +SymbolContextScope * +Block::GetParentSymbolContextScope () +{ + SymbolContext sc; + CalculateSymbolContext(&sc); + if (m_parent_scope != nullptr) + return m_parent_scope; + else if (sc.function != nullptr) + return sc.function; + else if (sc.comp_unit != nullptr) + return (SymbolContextScope *)sc.comp_unit; + else if (sc.module_sp) + return sc.module_sp.get(); + else + return nullptr; +} + +VariableTreeSP +Block::GetVariables () +{ + if (!m_variable_tree_sp) + { + VariableListSP vars(GetBlockVariableList(true)); + m_variable_tree_sp.reset(new VariableTree(vars, this)); + } + return m_variable_tree_sp; +} + void Block::CalculateSymbolContext (SymbolContext* sc) { Index: source/Symbol/CMakeLists.txt =================================================================== --- source/Symbol/CMakeLists.txt +++ source/Symbol/CMakeLists.txt @@ -29,5 +29,6 @@ UnwindTable.cpp Variable.cpp VariableList.cpp + VariableTree.cpp VerifyDecl.cpp ) Index: source/Symbol/CompileUnit.cpp =================================================================== --- source/Symbol/CompileUnit.cpp +++ source/Symbol/CompileUnit.cpp @@ -12,6 +12,7 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/VariableTree.h" #include "lldb/Target/LanguageRuntime.h" using namespace lldb; @@ -57,6 +58,23 @@ { } +SymbolContextScope * +CompileUnit::GetParentSymbolContextScope () +{ + return GetModule().get(); +} + +VariableTreeSP +CompileUnit::GetVariables () +{ + if (!m_variable_tree_sp) + { + VariableListSP vars(GetVariableList(true)); + m_variable_tree_sp.reset(new VariableTree(vars, this)); + } + return m_variable_tree_sp; +} + void CompileUnit::CalculateSymbolContext(SymbolContext* sc) { Index: source/Symbol/Function.cpp =================================================================== --- source/Symbol/Function.cpp +++ source/Symbol/Function.cpp @@ -17,6 +17,9 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/VariableTree.h" #include "llvm/Support/Casting.h" using namespace lldb; @@ -378,6 +381,22 @@ m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context); } +VariableTreeSP +Function::GetVariables () +{ + if (!m_variable_tree_sp) + { + VariableListSP vars(new VariableList()); + m_variable_tree_sp.reset(new VariableTree(vars, this)); + } + return m_variable_tree_sp; +} + +SymbolContextScope * +Function::GetParentSymbolContextScope () +{ + return m_comp_unit; +} void Function::CalculateSymbolContext(SymbolContext* sc) Index: source/Symbol/Symbol.cpp =================================================================== --- source/Symbol/Symbol.cpp +++ source/Symbol/Symbol.cpp @@ -16,6 +16,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/VariableTree.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Symbol/SymbolVendor.h" @@ -495,6 +496,25 @@ return ""; } +SymbolContextScope * +Symbol::GetParentSymbolContextScope () +{ + SymbolContext sc; + CalculateSymbolContext(&sc); + return sc.module_sp.get(); +} + +VariableTreeSP +Symbol::GetVariables () +{ + if (!m_variable_tree_sp) + { + VariableListSP vars(new VariableList()); + m_variable_tree_sp.reset(new VariableTree(vars, this)); + } + return m_variable_tree_sp; +} + void Symbol::CalculateSymbolContext (SymbolContext *sc) { Index: source/Symbol/VariableTree.cpp =================================================================== --- /dev/null +++ source/Symbol/VariableTree.cpp @@ -0,0 +1,165 @@ +//===-- VariableTree.h ------------------------------------------*- 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/VariableTree.h" +#include +#include + +using namespace lldb; +using namespace lldb_private; + +VariableTree::VariableTree(VariableListSP &variables, SymbolContextScope *scope) + : m_variables(variables), + m_scope(scope), + m_parent_scope(scope != nullptr ? scope->GetParentSymbolContextScope() : nullptr), + m_imported_variables(new VariableList()) +{ + if (!m_variables) + m_variables.reset(new VariableList()); +} + +VariableTree::VariableTree(VariableListSP &variables, SymbolContextScope *scope, VariableListSP &imported_variables) + : m_variables(variables), + m_scope(scope), + m_parent_scope(scope != nullptr ? scope->GetParentSymbolContextScope() : nullptr), + m_imported_variables(imported_variables) +{ + if (!m_variables) + m_variables.reset(new VariableList()); + if (!m_imported_variables) + m_imported_variables.reset(new VariableList()); +} + +VariableTree::~VariableTree() +{ +} + +bool +VariableTree::AddVariable (const VariableSP &var) +{ + if (!m_variables->FindVariable(var->GetName()) && var->GetSymbolContextScope() == m_scope) + { + m_variables->AddVariable(var); + return true; + } + return false; +} + +VariableTreeSP +VariableTree::GetParent () +{ + if (!m_parent && m_parent_scope != nullptr) + m_parent = m_parent_scope->GetVariables(); + return m_parent; +} + +size_t +VariableTree::AddVariableList (const VariableListSP &vars) +{ + size_t added = 0; + for (size_t i = 0; i < vars->GetSize(); i++) + if (AddVariable(vars->GetVariableAtIndex(i))) + added++; + return added; +} + +void +VariableTree::Clear () +{ + m_variables->Clear(); +} + +size_t +VariableTree::GetSize () +{ + return m_variables->GetSize(); +} + +VariableSP +VariableTree::FindVariable (const ConstString &name) +{ + std::unordered_map imported_variables; + return FindRecVariable(name, imported_variables); +} + +size_t +VariableTree::AddImportedVariableList (const VariableListSP &imported_variables) +{ + if (!imported_variables) + return 0; + + size_t added = 0; + for (size_t i = 0; i < imported_variables->GetSize(); i++) + if (m_imported_variables->AddVariableIfUnique(imported_variables->GetVariableAtIndex(i))) + added++; + return added; +} + +VariableSP +VariableTree::FindVariable (const ConstString &name, ValueType type) +{ + std::unordered_map imported_variables; + return FindRecVariable(name, type, imported_variables); +} + +VariableSP +VariableTree::FindRecVariable (const ConstString &name, std::unordered_map &imported_variables) +{ + for (size_t i = 0; i < m_imported_variables->GetSize(); i++) + { + VariableSP var = m_imported_variables->GetVariableAtIndex(i); + SymbolContextScope *scope = var->GetSymbolContextScope(); + + if (imported_variables.find(scope) == imported_variables.end()) + imported_variables[scope] = VariableListSP(new VariableList()); + imported_variables[scope]->AddVariable(var); + } + + VariableSP node_result = m_variables->FindVariable(name, false); + VariableSP imported_result = imported_variables.find(m_scope) != imported_variables.end() ? imported_variables[m_scope]->FindVariable(name) : VariableSP(); + + VariableSP result; + if (imported_result) + result = imported_result; + else if (node_result) + result = node_result; + + if (!result && GetParent()) + result = GetParent()->FindRecVariable(name, imported_variables); + + return result; +} + +VariableSP +VariableTree::FindRecVariable (const ConstString &name, ValueType type, std::unordered_map &imported_variables) +{ + for (size_t i = 0; i < m_imported_variables->GetSize(); i++) + { + VariableSP var = m_imported_variables->GetVariableAtIndex(i); + SymbolContextScope *scope = var->GetSymbolContextScope(); + + if (imported_variables.find(scope) == imported_variables.end()) + imported_variables[scope] = VariableListSP(new VariableList()); + imported_variables[scope]->AddVariable(var); + } + VariableSP node_result = m_variables->FindVariable(name, type, false); + VariableSP imported_result = imported_variables.find(m_scope) != imported_variables.end() ? imported_variables[m_scope]->FindVariable(name, type) : VariableSP(); + + VariableSP result; + if (imported_result) + result = imported_result; + else if (node_result) + result = node_result; + + if (!result && GetParent()) + result = GetParent()->FindRecVariable(name, imported_variables); + + return result; +} + Index: source/Target/StackFrame.cpp =================================================================== --- source/Target/StackFrame.cpp +++ source/Target/StackFrame.cpp @@ -25,6 +25,7 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/VariableTree.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -606,7 +607,6 @@ return var_list_sp; } - ValueObjectSP StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, DynamicValueType use_dynamic, @@ -628,13 +628,18 @@ bool deref = false; bool address_of = false; ValueObjectSP valobj_sp; - const bool get_file_globals = true; // When looking up a variable for an expression, we need only consider the // variables that are in scope. - VariableListSP var_list_sp (GetInScopeVariableList (get_file_globals)); - VariableList *variable_list = var_list_sp.get(); - if (variable_list) + VariableTreeSP vars; + if (m_sc.block) + vars = m_sc.block->GetVariables(); + else if (m_sc.function) + vars = m_sc.function->GetVariables(); + else if (m_sc.comp_unit) + vars = m_sc.comp_unit->GetVariables(); + + if (vars) { // If first character is a '*', then show pointer contents const char *var_expr = var_expr_cstr; @@ -659,7 +664,7 @@ else name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx); - var_sp = variable_list->FindVariable(name_const_string, false); + var_sp = vars->FindVariable(name_const_string); bool synthetically_added_instance_object = false; @@ -679,7 +684,7 @@ { if (is_instance_method && method_object_name) { - var_sp = variable_list->FindVariable(method_object_name); + var_sp = vars->FindVariable(method_object_name); if (var_sp) { separator_idx = 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,26 @@ 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") + + # 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,32 @@ } } -using namespace N; -using namespace Nested; +namespace Global +{ + int global; +} + +namespace Fun +{ + int fun_var; + int fun() + { + fun_var = 5; + return 0; // break 1 + } +} + +using namespace Global; + +int fun_var = 9; int main() { + using namespace N; + using namespace Nested; n = 1; anon = 2; nested = 3; - return 0; // break 0 + global = 4; + return Fun::fun(); // break 0 }