Index: include/lldb/Symbol/Variable.h =================================================================== --- include/lldb/Symbol/Variable.h +++ include/lldb/Symbol/Variable.h @@ -36,7 +36,8 @@ Declaration* decl, const DWARFExpression& location, bool external, - bool artificial); + bool artificial, + bool static_member = false); virtual ~Variable(); @@ -99,6 +100,11 @@ return m_artificial; } + bool IsStaticMember() const + { + return m_static_member; + } + DWARFExpression & LocationExpression() { @@ -171,7 +177,8 @@ DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() uint8_t m_external:1, // Visible outside the containing compile unit? 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_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. private: Variable(const Variable& rhs); Variable& operator=(const Variable& rhs); Index: include/lldb/Symbol/VariableList.h =================================================================== --- include/lldb/Symbol/VariableList.h +++ include/lldb/Symbol/VariableList.h @@ -48,10 +48,10 @@ RemoveVariableAtIndex (size_t idx); lldb::VariableSP - FindVariable (const ConstString& name); + FindVariable (const ConstString& name, bool include_static_members = true); lldb::VariableSP - FindVariable (const ConstString& name, lldb::ValueType value_type); + FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members = true); uint32_t FindVariableIndex (const lldb::VariableSP &var_sp); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -7410,7 +7410,6 @@ return 0; } - VariableSP SymbolFileDWARF::ParseVariableDIE ( @@ -7566,6 +7565,9 @@ } } + const DWARFDebugInfoEntry *parent_context_die = GetDeclContextDIEContainingDIE(dwarf_cu, die); + bool is_static_member = die->GetParent()->Tag() == DW_TAG_compile_unit && (parent_context_die->Tag() == DW_TAG_class_type || parent_context_die->Tag() == DW_TAG_structure_type); + ValueType scope = eValueTypeInvalid; const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); @@ -7743,7 +7745,8 @@ &decl, location, is_external, - is_artificial)); + is_artificial, + is_static_member)); var_sp->SetLocationIsConstantValueData (location_is_const_value_data); } Index: source/Symbol/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -44,7 +44,8 @@ Declaration* decl_ptr, const DWARFExpression& location, bool external, - bool artificial + bool artificial, + bool static_member ) : UserID(uid), m_name(name), @@ -55,7 +56,8 @@ m_declaration(decl_ptr), m_location(location), m_external(external), - m_artificial(artificial) + m_artificial(artificial), + m_static_member(static_member) { } Index: source/Symbol/VariableList.cpp =================================================================== --- source/Symbol/VariableList.cpp +++ source/Symbol/VariableList.cpp @@ -100,7 +100,7 @@ } VariableSP -VariableList::FindVariable(const ConstString& name) +VariableList::FindVariable(const ConstString& name, bool include_static_members) { VariableSP var_sp; iterator pos, end = m_variables.end(); @@ -108,15 +108,18 @@ { if ((*pos)->NameMatches(name)) { - var_sp = (*pos); - break; + if (include_static_members || !(*pos)->IsStaticMember()) + { + var_sp = (*pos); + break; + } } } return var_sp; } VariableSP -VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type) +VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members) { VariableSP var_sp; iterator pos, end = m_variables.end(); @@ -124,8 +127,11 @@ { if ((*pos)->NameMatches(name) && (*pos)->GetScope() == value_type) { - var_sp = (*pos); - break; + if (include_static_members || !(*pos)->IsStaticMember()) + { + var_sp = (*pos); + break; + } } } return var_sp; Index: source/Target/StackFrame.cpp =================================================================== --- source/Target/StackFrame.cpp +++ source/Target/StackFrame.cpp @@ -659,7 +659,7 @@ else name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx); - var_sp = variable_list->FindVariable(name_const_string); + var_sp = variable_list->FindVariable(name_const_string, false); bool synthetically_added_instance_object = false; Index: test/lang/cpp/scope/Makefile =================================================================== --- /dev/null +++ test/lang/cpp/scope/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Index: test/lang/cpp/scope/TestCppScope.py =================================================================== --- /dev/null +++ test/lang/cpp/scope/TestCppScope.py @@ -0,0 +1,83 @@ +""" +Test scopes in C++. +""" +import lldb +from lldbtest import * +import lldbutil + +class TestCppScopes(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @dsym_test + def test_with_dsym_and_run_command(self): + self.buildDsym() + self.check() + + @dwarf_test + def test_with_dwarf_and_run_command(self): + self.buildDwarf() + self.check() + + def setUp(self): + TestBase.setUp(self) + + def check(self): + # Get main source file + src_file = "main.cpp" + src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(src_file_spec.IsValid(), "Main source file") + + # Get the path of the executable + cwd = os.getcwd() + exe_file = "a.out" + exe_path = os.path.join(cwd, exe_file) + + # Load the executable + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target.IsValid(), VALID_TARGET) + + # Break on main function + main_breakpoint = target.BreakpointCreateBySourceRegex("// break here", src_file_spec) + self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + args = None + env = None + process = target.LaunchSimple(args, env, cwd) + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + + # 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 result for scopes of variables + + global_variables = frame.GetVariables(True, True, True, False) + global_variables_assert = { + 'A::a': 1111, + 'B::a': 2222, + 'C::a': 3333, + '::a': 4444, + 'a': 4444 + } + + self.assertTrue(global_variables.GetSize() == 4, "target variable returns all variables") + for variable in global_variables: + name = variable.GetName() + self.assertTrue(name in global_variables_assert, "target variable returns wrong variable " + name) + + for name in global_variables_assert: + value = frame.EvaluateExpression(name) + assert_value = global_variables_assert[name] + self.assertTrue(value.IsValid() and value.GetValueAsSigned() == assert_value, name + " = " + str(assert_value)) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Index: test/lang/cpp/scope/main.cpp =================================================================== --- /dev/null +++ test/lang/cpp/scope/main.cpp @@ -0,0 +1,25 @@ +class A { +public: + static int a; + int b; +}; + +class B { +public: + static int a; + int b; +}; + +struct C { + static int a; +}; + +int A::a = 1111; +int B::a = 2222; +int C::a = 3333; +int a = 4444; + +int main() // break here +{ + return 0; +}