diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 7dfaaa470801..80fa09be7473 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -15,6 +15,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "CGBlocks.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -1412,12 +1413,21 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, FieldAlign = CGM.getContext().getTypeAlign(FType); } - // We can't know the offset of our ivar in the structure if we're using - // the non-fragile abi and the debugger should ignore the value anyways. - // Call it the FieldNo+1 due to how debuggers use the information, - // e.g. negating the value when it needs a lookup in the dynamic table. - uint64_t FieldOffset = CGM.getLangOpts().ObjCRuntime.isNonFragile() - ? FieldNo+1 : RL.getFieldOffset(FieldNo); + uint64_t FieldOffset; + if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { + // We don't know the runtime offset of an ivar if we're using the + // non-fragile ABI. For bitfields, use the bit offset into the first + // byte of storage of the bitfield. For other fields, use zero. + if (Field->isBitField()) { + FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset( + CGM, ID, Field); + FieldOffset %= CGM.getContext().getCharWidth(); + } else { + FieldOffset = 0; + } + } else { + FieldOffset = RL.getFieldOffset(FieldNo); + } unsigned Flags = 0; if (Field->getAccessControl() == ObjCIvarDecl::Protected) diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 9aa68376bcd0..6932dd709d16 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -78,6 +78,13 @@ uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, CGM.getContext().getCharWidth(); } +unsigned CGObjCRuntime::ComputeBitfieldBitOffset( + CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar) { + return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar); +} + LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceDecl *OID, llvm::Value *BaseValue, diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index bc6589dd69f9..3e77875e6baf 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -277,6 +277,12 @@ public: MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method, QualType resultType, CallArgList &callArgs); + + // FIXME: This probably shouldn't be here, but the code to compute + // it is here. + unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar); }; /// Creates an instance of an Objective-C runtime class. diff --git a/clang/test/CodeGenObjC/debug-info-ivars.m b/clang/test/CodeGenObjC/debug-info-ivars.m new file mode 100644 index 000000000000..24705e1ad658 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-ivars.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s + +__attribute((objc_root_class)) @interface NSObject { + id isa; +} +@end + +@interface BaseClass : NSObject +{ + int i; + unsigned flag_1 : 9; + unsigned flag_2 : 9; + unsigned : 1; + unsigned flag_3 : 9; +} +@end + +@implementation BaseClass +@end + +// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"i", metadata !{{[0-9]*}}, i32 10, i64 32, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [i] [line 10, size 32, align 32, offset 0] [protected] [from int] +// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_1", metadata !{{[0-9]*}}, i32 11, i64 9, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_1] [line 11, size 9, align 32, offset 0] [protected] [from unsigned int] +// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_2", metadata !{{[0-9]*}}, i32 12, i64 9, i64 32, i64 1, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_2] [line 12, size 9, align 32, offset 1] [protected] [from unsigned int] +// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_3", metadata !{{[0-9]*}}, i32 14, i64 9, i64 32, i64 3, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_3] [line 14, size 9, align 32, offset 3] [protected] [from unsigned int] \ No newline at end of file