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
This commit is contained in:
Sean Callanan 2011-08-02 22:21:50 +00:00
parent e8ae02dfb9
commit 763d72a1fd
5 changed files with 108 additions and 3 deletions

View File

@ -2396,6 +2396,7 @@ SymbolFileDWARF::ParseChildParameters
DWARFCompileUnit* dwarf_cu, DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die, const DWARFDebugInfoEntry *parent_die,
bool skip_artificial, bool skip_artificial,
bool &is_static,
TypeList* type_list, TypeList* type_list,
std::vector<clang_type_t>& function_param_types, std::vector<clang_type_t>& function_param_types,
std::vector<clang::ParmVarDecl*>& function_param_decls, std::vector<clang::ParmVarDecl*>& function_param_decls,
@ -2481,7 +2482,7 @@ SymbolFileDWARF::ParseChildParameters
const DWARFDebugInfoEntry *grandparent_die = parent_die->GetParent(); const DWARFDebugInfoEntry *grandparent_die = parent_die->GetParent();
if (grandparent_die && (grandparent_die->Tag() == DW_TAG_structure_type || if (grandparent_die && (grandparent_die->Tag() == DW_TAG_structure_type ||
grandparent_die->Tag() == DW_TAG_class_type)) grandparent_die->Tag() == DW_TAG_class_type))
{ {
LanguageType language = sc.comp_unit->GetLanguage(); LanguageType language = sc.comp_unit->GetLanguage();
if (language == eLanguageTypeObjC_plus_plus || language == eLanguageTypeC_plus_plus) if (language == eLanguageTypeObjC_plus_plus || language == eLanguageTypeC_plus_plus)
{ {
@ -2492,10 +2493,12 @@ SymbolFileDWARF::ParseChildParameters
{ {
Type *this_type = ResolveTypeUID (param_type_die_offset); Type *this_type = ResolveTypeUID (param_type_die_offset);
if (this_type) if (this_type)
{ {
uint32_t encoding_mask = this_type->GetEncodingMask(); uint32_t encoding_mask = this_type->GetEncodingMask();
if (encoding_mask & Type::eEncodingIsPointerUID) if (encoding_mask & Type::eEncodingIsPointerUID)
{ {
is_static = false;
if (encoding_mask & (1u << Type::eEncodingIsConstUID)) if (encoding_mask & (1u << Type::eEncodingIsConstUID))
type_quals |= clang::Qualifiers::Const; type_quals |= clang::Qualifiers::Const;
if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
@ -3567,6 +3570,12 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
std::vector<clang::ParmVarDecl*> function_param_decls; std::vector<clang::ParmVarDecl*> function_param_decls;
// Parse the function children for the parameters // 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()) if (die->HasChildren())
{ {
bool skip_artificial = true; bool skip_artificial = true;
@ -3574,7 +3583,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_sp, type_sp,
dwarf_cu, dwarf_cu,
die, die,
skip_artificial, skip_artificial,
is_static,
type_list, type_list,
function_param_types, function_param_types,
function_param_decls, function_param_decls,

View File

@ -275,6 +275,7 @@ protected:
DWARFCompileUnit* dwarf_cu, DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die, const DWARFDebugInfoEntry *parent_die,
bool skip_artificial, bool skip_artificial,
bool &is_static,
lldb_private::TypeList* type_list, lldb_private::TypeList* type_list,
std::vector<lldb::clang_type_t>& function_args, std::vector<lldb::clang_type_t>& function_args,
std::vector<clang::ParmVarDecl*>& function_param_decls, std::vector<clang::ParmVarDecl*>& function_param_decls,

View File

@ -0,0 +1,5 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -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()

View File

@ -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 <stdio.h>
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());
}