Clang sometimes emits "objc_object*" rather than "id"

for id types with protocols on them.  We detect this
and report "id" instead.

Also added a testcase.

<rdar://problem/12595644>

llvm-svn: 171431
This commit is contained in:
Sean Callanan 2013-01-03 00:05:56 +00:00
parent 895809159a
commit 8258705dbd
3 changed files with 82 additions and 39 deletions

View File

@ -5511,51 +5511,80 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break;
}
if (clang_type == NULL && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID))
if (clang_type == NULL && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
{
if (type_name_cstr != NULL && sc.comp_unit != NULL &&
(sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus))
bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
if (translation_unit_is_objc)
{
static ConstString g_objc_type_name_id("id");
static ConstString g_objc_type_name_Class("Class");
static ConstString g_objc_type_name_selector("SEL");
if (type_name_const_str == g_objc_type_name_id)
if (type_name_cstr != NULL)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_id();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
static ConstString g_objc_type_name_id("id");
static ConstString g_objc_type_name_Class("Class");
static ConstString g_objc_type_name_selector("SEL");
if (type_name_const_str == g_objc_type_name_id)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_id();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
}
else if (type_name_const_str == g_objc_type_name_Class)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_Class();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
}
else if (type_name_const_str == g_objc_type_name_selector)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_selector();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
}
}
else if (type_name_const_str == g_objc_type_name_Class)
else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_Class();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
}
else if (type_name_const_str == g_objc_type_name_selector)
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_selector();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
// Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
{
if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
{
if (!strcmp(struct_name, "objc_object"))
{
if (log)
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.",
die->GetOffset(),
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu));
clang_type = ast.GetBuiltInType_objc_id();
encoding_data_type = Type::eEncodingIsUID;
encoding_uid = LLDB_INVALID_UID;
resolve_state = Type::eResolveStateFull;
}
}
}
}
}
}

View File

@ -124,6 +124,11 @@ class ObjCPropertyTestCase(TestBase):
unbacked_value = frame.EvaluateExpression("mine.unbackedInt", False)
unbacked_error = unbacked_value.GetError()
self.assertTrue (unbacked_error.Success())
idWithProtocol_value = frame.EvaluateExpression("mine.idWithProtocol", False)
idWithProtocol_error = idWithProtocol_value.GetError()
self.assertTrue (idWithProtocol_error.Success())
self.assertTrue (idWithProtocol_value.GetTypeName() == "id")
if __name__ == '__main__':
import atexit

View File

@ -1,5 +1,11 @@
#import <Foundation/Foundation.h>
@protocol MyProtocol
-(const char *)hello;
@end
@interface BaseClass : NSObject
{
int _backedInt;
@ -18,6 +24,7 @@
@property(getter=myGetUnbackedInt,setter=mySetUnbackedInt:) int unbackedInt;
@property int backedInt;
@property (nonatomic, assign) id <MyProtocol> idWithProtocol;
@end
@implementation BaseClass
@ -79,6 +86,8 @@ main ()
int unbackedInt = mine.unbackedInt;
id idWithProtocol = mine.idWithProtocol;
NSLog (@"Results for %p: nonexistant: %d backed: %d unbacked: %d accessCount: %d.",
mine,
nonexistant,