Added the ability to create an objective C method for an objective C
interface in ClangASTContext. Also added two bool returning functions that
indicated if an opaque clang qual type is a CXX class type, and if it is an
ObjC class type.
Objective C classes now will get their methods added lazily as they are
encountered. The reason for this is currently, unlike C++, the
DW_TAG_structure_type and owns the ivars, doesn't not also contain the
member functions. This means when we parse the objective C class interface
we either need to find all functions whose names start with "+[CLASS_NAME"
or "-[CLASS_NAME" and add them all to the class, or when we parse each objective
C function, we slowly add it to the class interface definition. Since objective
C's class doesn't change internal bits according to whether it has certain types
of member functions (like C++ does if it has virtual functions, or if it has
user ctors/dtors), I currently chose to lazily populate the class when each
functions is parsed. Another issue we run into with ObjC method declarations
is the "self" and "_cmd" implicit args are not marked as artificial in the
DWARF (DW_AT_artifical), so we currently have to look for the parameters by
name if we are trying to omit artificial function args if the language of the
compile unit is ObjC or ObjC++.
llvm-svn: 114722
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 8a4b136..44b10af 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -476,7 +476,7 @@
}
bool
-SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
+SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* cu, CompUnitSP& compile_unit_sp)
{
if (cu != NULL)
{
@@ -566,7 +566,7 @@
Function *
-SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
+SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
{
DWARFDebugRanges::RangeList func_ranges;
const char *name = NULL;
@@ -641,7 +641,7 @@
{
assert (sc.comp_unit);
size_t functions_added = 0;
- const DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
+ DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnitForUID(sc.comp_unit->GetID());
if (dwarf_cu)
{
DWARFDIECollection function_dies;
@@ -894,7 +894,7 @@
(
const SymbolContext& sc,
Block *parent_block,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *die,
addr_t subprogram_low_pc,
bool parse_siblings,
@@ -1011,7 +1011,7 @@
(
const SymbolContext& sc,
TypeSP& type_sp,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die,
void *class_clang_type,
const LanguageType class_language,
@@ -1107,135 +1107,8 @@
break;
case DW_TAG_subprogram:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- is_a_class = true;
- if (default_accessibility == eAccessNone)
- default_accessibility = eAccessPrivate;
-
- //printf("0x%8.8x: %s (ParesTypes)\n", die->GetOffset(), DW_TAG_value_to_name(tag));
- // Set a bit that lets us know that we are currently parsing this
- const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED);
-
- const char *mangled = NULL;
- dw_offset_t type_die_offset = DW_INVALID_OFFSET;
- Declaration decl;
- bool is_variadic = false;
- bool is_inline = false;
- bool is_virtual = false;
- unsigned type_quals = 0;
- AccessType accessibility = default_accessibility;
-
- clang::FunctionDecl::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
- const char *type_name_cstr = NULL;
- ConstString type_name_dbstr;
-
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- break;
-
- case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
- case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- //case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
- case DW_AT_external:
- if (form_value.Unsigned())
- {
- if (storage == clang::SC_None)
- storage = clang::SC_Extern;
- else
- storage = clang::SC_PrivateExtern;
- }
- break;
- case DW_AT_inline:
- is_inline = form_value.Unsigned() != 0;
- break;
-
-
- case DW_AT_virtuality:
- is_virtual = form_value.Unsigned() != 0;
- break;
-
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_address_class:
- case DW_AT_artificial:
- case DW_AT_calling_convention:
- case DW_AT_data_location:
- case DW_AT_elemental:
- case DW_AT_entry_pc:
- case DW_AT_explicit:
- case DW_AT_frame_base:
- case DW_AT_high_pc:
- case DW_AT_low_pc:
- case DW_AT_object_pointer:
- case DW_AT_prototyped:
- case DW_AT_pure:
- case DW_AT_ranges:
- case DW_AT_recursive:
- case DW_AT_return_addr:
- case DW_AT_segment:
- case DW_AT_specification:
- case DW_AT_start_scope:
- case DW_AT_static_link:
- case DW_AT_trampoline:
- case DW_AT_visibility:
- case DW_AT_vtable_elem_location:
- case DW_AT_abstract_origin:
- case DW_AT_description:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- void *return_clang_type = NULL;
- Type *func_type = ResolveTypeUID(type_die_offset);
- if (func_type)
- return_clang_type = func_type->GetOpaqueClangQualType();
- else
- return_clang_type = type_list->GetClangASTContext().GetBuiltInType_void();
-
- std::vector<void *> function_param_types;
- std::vector<clang::ParmVarDecl*> function_param_decls;
-
- // Parse the function children for the parameters
- bool skip_artificial = true;
-
- ParseChildParameters (sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
-
- void *method_function_proto = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), is_variadic, type_quals);
- if (type_name_cstr)
- {
- clang::CXXMethodDecl *method_decl = type_list->GetClangASTContext().AddMethodToCXXRecordType (class_clang_type,
- type_name_cstr,
- method_function_proto,
- accessibility,
- is_virtual);
- assert (method_decl);
- //m_die_to_decl_ctx[die] = method_decl;
- }
-
- const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(type_sp.get());
- assert(type_sp.get());
- }
- }
+ // Let the type parsing code handle this one for us...
+ ResolveType (dwarf_cu, die);
break;
case DW_TAG_inheritance:
@@ -1376,7 +1249,7 @@
}
CompileUnit*
-SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit* cu, uint32_t cu_idx)
+SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* cu, uint32_t cu_idx)
{
// Check if the symbol vendor already knows about this compile unit?
if (cu->GetUserData() == NULL)
@@ -2026,7 +1899,7 @@
(
const SymbolContext& sc,
TypeSP& type_sp,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die,
bool skip_artificial,
TypeList* type_list,
@@ -2100,17 +1973,36 @@
}
}
- if (skip_artificial && is_artificial)
- continue;
-
- Type *dc_type = ResolveTypeUID(param_type_die_offset);
- if (dc_type)
+ bool skip = false;
+ if (skip_artificial)
{
- function_param_types.push_back (dc_type->GetOpaqueClangQualType());
+ if (is_artificial)
+ skip = true;
+ else
+ {
- clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParameterDeclaration (name, dc_type->GetOpaqueClangQualType(), storage);
- assert(param_var_decl);
- function_param_decls.push_back(param_var_decl);
+ // HACK: Objective C formal parameters "self" and "_cmd"
+ // are not marked as artificial in the DWARF...
+ CompileUnit *cu = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+ if (cu && (cu->GetLanguage() == eLanguageTypeObjC || cu->GetLanguage() == eLanguageTypeObjC_plus_plus))
+ {
+ if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
+ skip = true;
+ }
+ }
+ }
+
+ if (!skip)
+ {
+ Type *type = ResolveTypeUID(param_type_die_offset);
+ if (type)
+ {
+ function_param_types.push_back (type->GetOpaqueClangQualType());
+
+ clang::ParmVarDecl *param_var_decl = type_list->GetClangASTContext().CreateParameterDeclaration (name, type->GetOpaqueClangQualType(), storage);
+ assert(param_var_decl);
+ function_param_decls.push_back(param_var_decl);
+ }
}
}
}
@@ -2130,7 +2022,7 @@
TypeSP& type_sp,
void * enumerator_qual_type,
uint32_t enumerator_byte_size,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die
)
{
@@ -2200,7 +2092,7 @@
SymbolFileDWARF::ParseChildArrayInfo
(
const SymbolContext& sc,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die,
int64_t& first_index,
std::vector<uint64_t>& element_orders,
@@ -2406,7 +2298,7 @@
clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextForDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+SymbolFileDWARF::GetClangDeclContextForDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
{
DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
if (pos != m_die_to_decl_ctx.end())
@@ -2450,14 +2342,14 @@
}
TypeSP
-SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
+SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool &type_is_new)
{
TypeSP type_sp;
AccessType accessibility = eAccessNone;
if (die != NULL)
{
- dw_tag_t tag = die->Tag();
+ const dw_tag_t tag = die->Tag();
if (die->GetUserData() == NULL)
{
type_is_new = true;
@@ -2840,6 +2732,9 @@
Declaration decl;
bool is_variadic = false;
bool is_inline = false;
+ bool is_static = false;
+ bool is_virtual = false;
+
unsigned type_quals = 0;
clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
@@ -2850,7 +2745,7 @@
uint32_t i;
for (i=0; i<num_attributes; ++i)
{
- attr = attributes.AttributeAtIndex(i);
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
@@ -2868,6 +2763,8 @@
case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break;
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
+ case DW_AT_inline: is_inline = form_value.Unsigned() != 0; break;
+ case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break;
case DW_AT_external:
if (form_value.Unsigned())
{
@@ -2877,9 +2774,6 @@
storage = clang::SC_PrivateExtern;
}
break;
- case DW_AT_inline:
- is_inline = form_value.Unsigned() != 0;
- break;
case DW_AT_allocated:
case DW_AT_associated:
@@ -2905,7 +2799,6 @@
case DW_AT_static_link:
case DW_AT_trampoline:
case DW_AT_visibility:
- case DW_AT_virtuality:
case DW_AT_vtable_elem_location:
case DW_AT_abstract_origin:
case DW_AT_description:
@@ -2926,18 +2819,92 @@
std::vector<clang::ParmVarDecl*> function_param_decls;
// Parse the function children for the parameters
- bool skip_artificial = false;
- ParseChildParameters(sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
+ bool skip_artificial = true;
+ ParseChildParameters (sc, type_sp, dwarf_cu, die, skip_artificial, type_list, function_param_types, function_param_decls);
+ // clang_type will get the function prototype clang type after this call
clang_type = type_list->GetClangASTContext().CreateFunctionType (return_clang_type, &function_param_types[0], function_param_types.size(), is_variadic, type_quals);
if (type_name_cstr)
{
- clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
- // Add the decl to our DIE to decl context map
- assert (function_decl);
- m_die_to_decl_ctx[die] = function_decl;
- if (!function_param_decls.empty())
- type_list->GetClangASTContext().SetFunctionParameters (function_decl, &function_param_decls.front(), function_param_decls.size());
+ bool type_handled = false;
+ const DWARFDebugInfoEntry *parent_die = die->GetParent();
+ if (tag == DW_TAG_subprogram)
+ {
+ if (type_name_cstr[1] == '[' && (type_name_cstr[0] == '-' || type_name_cstr[0] == '+'))
+ {
+ // We need to find the DW_TAG_class_type or
+ // DW_TAG_struct_type by name so we can add this
+ // as a member function of the class.
+ const char *class_name_start = type_name_cstr + 2;
+ const char *class_name_end = ::strchr (class_name_start, ' ');
+ SymbolContext empty_sc;
+ void *class_opaque_type = NULL;
+ if (class_name_start < class_name_end)
+ {
+ ConstString class_name (class_name_start, class_name_end - class_name_start);
+ TypeList types;
+ const uint32_t match_count = FindTypes (empty_sc, class_name, true, UINT32_MAX, types);
+ if (match_count > 0)
+ {
+ for (uint32_t i=0; i<match_count; ++i)
+ {
+ Type *type = types.GetTypeAtIndex (i).get();
+ if (ClangASTContext::IsObjCClassType (type->GetOpaqueClangQualType()))
+ {
+ class_opaque_type = type->GetOpaqueClangQualType();
+ break;
+ }
+ }
+ }
+ }
+
+ if (class_opaque_type)
+ {
+ clang::ObjCMethodDecl *objc_method_decl;
+ objc_method_decl = type_list->GetClangASTContext().AddMethodToObjCObjectType (class_opaque_type,
+ type_name_cstr,
+ clang_type,
+ accessibility);
+ type_handled = objc_method_decl != NULL;
+ }
+ }
+ else if (parent_die->Tag() == DW_TAG_class_type ||
+ parent_die->Tag() == DW_TAG_structure_type)
+ {
+ // Look at the parent of this DIE and see if is is
+ // a class or struct and see if this is actually a
+ // C++ method
+ Type *class_type = ResolveType (dwarf_cu, parent_die);
+ if (class_type)
+ {
+ void *class_opaque_type = class_type->GetOpaqueClangQualType ();
+ if (ClangASTContext::IsCXXClassType (class_opaque_type))
+ {
+ clang::CXXMethodDecl *cxx_method_decl;
+ cxx_method_decl = type_list->GetClangASTContext().AddMethodToCXXRecordType (class_opaque_type,
+ type_name_cstr,
+ clang_type,
+ accessibility,
+ is_virtual,
+ is_static,
+ is_inline);
+ type_handled = cxx_method_decl != NULL;
+ }
+ }
+ }
+ }
+
+ if (!type_handled)
+ {
+ // We just have a function that isn't part of a class
+ clang::FunctionDecl *function_decl = type_list->GetClangASTContext().CreateFunctionDeclaration (type_name_cstr, clang_type, storage, is_inline);
+
+ // Add the decl to our DIE to decl context map
+ assert (function_decl);
+ m_die_to_decl_ctx[die] = function_decl;
+ if (!function_param_decls.empty())
+ type_list->GetClangASTContext().SetFunctionParameters (function_decl, &function_param_decls.front(), function_param_decls.size());
+ }
}
type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, 0, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type));
@@ -3154,7 +3121,7 @@
}
size_t
-SymbolFileDWARF::ParseTypes (const SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
+SymbolFileDWARF::ParseTypes (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children)
{
size_t types_added = 0;
while (die != NULL)
@@ -3296,7 +3263,7 @@
SymbolFileDWARF::ParseVariableDIE
(
const SymbolContext& sc,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *die,
const lldb::addr_t func_low_pc
)
@@ -3439,7 +3406,7 @@
SymbolFileDWARF::ParseVariables
(
const SymbolContext& sc,
- const DWARFCompileUnit* dwarf_cu,
+ DWARFCompileUnit* dwarf_cu,
const lldb::addr_t func_low_pc,
const DWARFDebugInfoEntry *orig_die,
bool parse_siblings,