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; 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 && bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
(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"); if (type_name_cstr != NULL)
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) static ConstString g_objc_type_name_id("id");
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", static ConstString g_objc_type_name_Class("Class");
die->GetOffset(), static ConstString g_objc_type_name_selector("SEL");
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu)); if (type_name_const_str == g_objc_type_name_id)
clang_type = ast.GetBuiltInType_objc_id(); {
encoding_data_type = Type::eEncodingIsUID; if (log)
encoding_uid = LLDB_INVALID_UID; GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
resolve_state = Type::eResolveStateFull; 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) // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
die->GetOffset(), DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
DW_TAG_value_to_name(die->Tag()),
die->GetName(this, dwarf_cu)); if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
clang_type = ast.GetBuiltInType_objc_Class(); {
encoding_data_type = Type::eEncodingIsUID; if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
encoding_uid = LLDB_INVALID_UID; {
resolve_state = Type::eResolveStateFull; if (!strcmp(struct_name, "objc_object"))
} {
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 'objc_object*', which we overrode to 'id'.",
if (log) die->GetOffset(),
GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", DW_TAG_value_to_name(die->Tag()),
die->GetOffset(), die->GetName(this, dwarf_cu));
DW_TAG_value_to_name(die->Tag()), clang_type = ast.GetBuiltInType_objc_id();
die->GetName(this, dwarf_cu)); encoding_data_type = Type::eEncodingIsUID;
clang_type = ast.GetBuiltInType_objc_selector(); encoding_uid = LLDB_INVALID_UID;
encoding_data_type = Type::eEncodingIsUID; resolve_state = Type::eResolveStateFull;
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_value = frame.EvaluateExpression("mine.unbackedInt", False)
unbacked_error = unbacked_value.GetError() unbacked_error = unbacked_value.GetError()
self.assertTrue (unbacked_error.Success()) 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__': if __name__ == '__main__':
import atexit import atexit

View File

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