Index: cfe/trunk/lib/CodeGen/CGDebugInfo.h =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.h +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h @@ -491,9 +491,16 @@ llvm::Optional ArgNo, CGBuilderTy &Builder); + struct BlockByRefType { + /// The wrapper struct used inside the __block_literal struct. + llvm::DIType *BlockByRefWrapper; + /// The type as it appears in the source code. + llvm::DIType *WrappedType; + }; + /// Build up structure info for the byref. See \a BuildByRefType. - llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD, - uint64_t *OffSet); + BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD, + uint64_t *OffSet); /// Get context info for the DeclContext of \p Decl. llvm::DIScope *getDeclContextDescriptor(const Decl *D); Index: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp @@ -3565,9 +3565,9 @@ DBuilder.finalizeSubprogram(Fn->getSubprogram()); } -llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, - uint64_t *XOffset) { - +CGDebugInfo::BlockByRefType +CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, + uint64_t *XOffset) { SmallVector EltTys; QualType FType; uint64_t FieldSize, FieldOffset; @@ -3619,23 +3619,21 @@ } FType = Type; - llvm::DIType *FieldTy = getOrCreateType(FType, Unit); + llvm::DIType *WrappedTy = getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); FieldAlign = CGM.getContext().toBits(Align); *XOffset = FieldOffset; - FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize, - FieldAlign, FieldOffset, - llvm::DINode::FlagZero, FieldTy); + llvm::DIType *FieldTy = DBuilder.createMemberType( + Unit, VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset, + llvm::DINode::FlagZero, WrappedTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - - llvm::DINode::DIFlags Flags = llvm::DINode::FlagBlockByrefStruct; - - return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, - nullptr, Elements); + return {DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, + llvm::DINode::FlagZero, nullptr, Elements), + WrappedTy}; } llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, @@ -3656,7 +3654,7 @@ llvm::DIType *Ty; uint64_t XOffset = 0; if (VD->hasAttr()) - Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); + Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType; else Ty = getOrCreateType(VD->getType(), Unit); @@ -3794,7 +3792,7 @@ llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); llvm::DIType *Ty; if (isByRef) - Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); + Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType; else Ty = getOrCreateType(VD->getType(), Unit); @@ -3987,10 +3985,10 @@ if (capture->isByRef()) { TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy); auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0; - - // FIXME: this creates a second copy of this type! + // FIXME: This recomputes the layout of the BlockByRefWrapper. uint64_t xoffset; - fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset); + fieldType = + EmitTypeForVarWithBlocksAttr(variable, &xoffset).BlockByRefWrapper; fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width); fieldType = DBuilder.createMemberType(tunit, name, tunit, line, PtrInfo.Width, Align, offsetInBits, Index: cfe/trunk/test/CodeGenObjC/block-byref-debuginfo.m =================================================================== --- cfe/trunk/test/CodeGenObjC/block-byref-debuginfo.m +++ cfe/trunk/test/CodeGenObjC/block-byref-debuginfo.m @@ -1,16 +1,35 @@ // RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -debug-info-kind=limited -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s -// rdar://problem/14386148 +// CHECK: !DILocalVariable(name: "foo", {{.*}}type: ![[FOOTY:[0-9]+]]) +// CHECK: ![[FOOTY]] = {{.*}}!DICompositeType({{.*}}, name: "Foo" + +// CHECK-NOT: DIFlagBlockByrefStruct +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "__block_literal_1", +// CHECK-SAME: size: 320, elements: ![[BL_ELTS:[0-9]+]]) +// CHECK: ![[BL_ELTS]] = !{{.*}}![[WFOO:[0-9]+]]} + // Test that the foo is aligned at an 8 byte boundary in the DWARF // expression (256) that locates it inside of the byref descriptor: -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "foo", -// CHECK-NOT: line: -// CHECK-SAME: offset: 256 +// CHECK: ![[WFOO]] = !DIDerivedType(tag: DW_TAG_member, name: "foo", +// CHECK-SAME: baseType: ![[PTR:[0-9]+]] +// CHECK-SAME: offset: 256) + +// CHECK: ![[PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, +// CHECK-SAME: baseType: ![[WRAPPER:[0-9]+]] +// CHECK: ![[WRAPPER]] = !DICompositeType(tag: DW_TAG_structure_type, scope: +// CHECK: elements: ![[WR_ELTS:[0-9]+]]) +// CHECK: ![[WR_ELTS]] = !{{.*}}![[WFOO:[0-9]+]]} +// CHECK: ![[WFOO]] = !DIDerivedType(tag: DW_TAG_member, name: "foo", +// CHECK-SAME: baseType: ![[FOOTY]] + +// CHECK: !DILocalVariable(name: "foo", {{.*}}type: ![[FOOTY]]) + struct Foo { unsigned char *data; }; int func() { __attribute__((__blocks__(byref))) struct Foo foo; + ^{ foo.data = 0; }(); return 0; }