From 763d72a1fd94b66bb6299baed6d1a18aeef825d8 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Tue, 2 Aug 2011 22:21:50 +0000 Subject: [PATCH] Fixed a bug in which the DWARF reader did not distinguish appropriately between C++ static methods and non-static methods. This bug made it impossible to call most static methods, either because Clang did not recognize that a method could be called without providing a "this" parameter, or because Clang did not properly mangle the name of the method when searching for it in the target. Also added a testcase. llvm-svn: 136733 --- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 16 ++++-- .../SymbolFile/DWARF/SymbolFileDWARF.h | 1 + lldb/test/lang/cpp/static_methods/Makefile | 5 ++ .../static_methods/TestCPPStaticMethods.py | 51 +++++++++++++++++++ lldb/test/lang/cpp/static_methods/main.cpp | 38 ++++++++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 lldb/test/lang/cpp/static_methods/Makefile create mode 100644 lldb/test/lang/cpp/static_methods/TestCPPStaticMethods.py create mode 100644 lldb/test/lang/cpp/static_methods/main.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 72d70ef99c2a..f33b6446def9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2396,6 +2396,7 @@ SymbolFileDWARF::ParseChildParameters DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *parent_die, bool skip_artificial, + bool &is_static, TypeList* type_list, std::vector& function_param_types, std::vector& function_param_decls, @@ -2481,7 +2482,7 @@ SymbolFileDWARF::ParseChildParameters const DWARFDebugInfoEntry *grandparent_die = parent_die->GetParent(); if (grandparent_die && (grandparent_die->Tag() == DW_TAG_structure_type || grandparent_die->Tag() == DW_TAG_class_type)) - { + { LanguageType language = sc.comp_unit->GetLanguage(); if (language == eLanguageTypeObjC_plus_plus || language == eLanguageTypeC_plus_plus) { @@ -2492,10 +2493,12 @@ SymbolFileDWARF::ParseChildParameters { Type *this_type = ResolveTypeUID (param_type_die_offset); if (this_type) - { + { uint32_t encoding_mask = this_type->GetEncodingMask(); if (encoding_mask & Type::eEncodingIsPointerUID) { + is_static = false; + if (encoding_mask & (1u << Type::eEncodingIsConstUID)) type_quals |= clang::Qualifiers::Const; if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) @@ -3567,6 +3570,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, std::vector function_param_decls; // Parse the function children for the parameters + + const DWARFDebugInfoEntry *class_die = die->GetParent(); + if (class_die && (class_die->Tag() == DW_TAG_structure_type || + class_die->Tag() == DW_TAG_class_type)) + is_static = true; + if (die->HasChildren()) { bool skip_artificial = true; @@ -3574,7 +3583,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, type_sp, dwarf_cu, die, - skip_artificial, + skip_artificial, + is_static, type_list, function_param_types, function_param_decls, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2f6fa783ad1c..56e7abed291d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -275,6 +275,7 @@ protected: DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *parent_die, bool skip_artificial, + bool &is_static, lldb_private::TypeList* type_list, std::vector& function_args, std::vector& function_param_decls, diff --git a/lldb/test/lang/cpp/static_methods/Makefile b/lldb/test/lang/cpp/static_methods/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/lldb/test/lang/cpp/static_methods/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/lldb/test/lang/cpp/static_methods/TestCPPStaticMethods.py new file mode 100644 index 000000000000..c1a03d475909 --- /dev/null +++ b/lldb/test/lang/cpp/static_methods/TestCPPStaticMethods.py @@ -0,0 +1,51 @@ +""" +Tests expressions that distinguish between static and non-static methods. +""" + +from lldbtest import * + +class CPPStaticMethodsTestCase(TestBase): + + mydir = os.path.join("lang", "cpp", "static_methods") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test that static methods are properly distinguished from regular methods""" + self.buildDsym() + self.static_method_commands() + + def test_with_dwarf_and_run_command(self): + """Test that static methods are properly distinguished from regular methods""" + self.buildDwarf() + self.static_method_commands() + + def setUp(self): + TestBase.setUp(self) + self.line = line_number('main.cpp', '// Break at this line') + + def static_method_commands(self): + """Test that static methods are properly distinguished from regular methods""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % self.line) + + self.runCmd("process launch", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + self.expect("expression -- A::getStaticValue()", + startstr = "(int) $0 = 5") + + self.expect("expression -- my_a.getMemberValue()", + startstr = "(int) $1 = 3") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() \ No newline at end of file diff --git a/lldb/test/lang/cpp/static_methods/main.cpp b/lldb/test/lang/cpp/static_methods/main.cpp new file mode 100644 index 000000000000..5141a407d111 --- /dev/null +++ b/lldb/test/lang/cpp/static_methods/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +class A +{ +public: + static int getStaticValue(); + int getMemberValue(); + int a; +}; + +int A::getStaticValue() +{ + return 5; +} + +int A::getMemberValue() +{ + return a; +} + +int main() +{ + A my_a; + + my_a.a = 3; + + printf("%d\n", A::getStaticValue()); // Break at this line + printf("%d\n", my_a.getMemberValue()); +}