Complete out debug info generation for captured __block variables. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84768 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3ab2a0b..5730aaa 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -412,7 +412,10 @@
QualType getBlockParmType(llvm::SmallVector<const Expr *, 8> &BDRDs);
/// This builds the struct used for __block variables.
- QualType BuildByRefType(QualType Ty);
+ QualType BuildByRefType(const char *DeclName, QualType Ty);
+
+ /// Returns true iff we need copy/dispose helpers for the given type.
+ bool BlockRequiresCopying(QualType Ty);
/// getLValueReferenceType - Return the uniqued reference to the type for an
/// lvalue reference to the specified type.
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 673229c..4a0df6b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2741,17 +2741,72 @@
BlockDescriptorType = Rec->getDecl();
}
-QualType ASTContext::BuildByRefType(QualType Ty) {
- // type = struct __Block_byref_1_done {
+bool ASTContext::BlockRequiresCopying(QualType Ty) {
+ if (Ty->isBlockPointerType())
+ return true;
+ if (isObjCNSObjectType(Ty))
+ return true;
+ if (Ty->isObjCObjectPointerType())
+ return true;
+ return false;
+}
+
+QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
+ // type = struct __Block_byref_1_X {
// void *__isa;
- // struct __Block_byref_1_done *__forwarding;
+ // struct __Block_byref_1_X *__forwarding;
// unsigned int __flags;
// unsigned int __size;
- // int done;
+ // void *__copy_helper;
+ // void *__destroy_helper;
+ // int X;
// } *
- // FIXME: Build up reference type.
- return getPointerType(VoidPtrTy);
+ bool HasCopyAndDispose = BlockRequiresCopying(Ty);
+
+ // FIXME: Move up
+ static int UniqueBlockByRefTypeID = 0;
+ char Name[36];
+ sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName);
+ RecordDecl *T;
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get(Name));
+ T->startDefinition();
+ QualType Int32Ty = IntTy;
+ assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
+ QualType FieldTypes[] = {
+ getPointerType(VoidPtrTy),
+ getPointerType(getTagDeclType(T)),
+ Int32Ty,
+ Int32Ty,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy),
+ Ty
+ };
+
+ const char *FieldNames[] = {
+ "__isa",
+ "__forwarding",
+ "__flags",
+ "__size",
+ "__copy_helper",
+ "__destroy_helper",
+ DeclName,
+ };
+
+ for (size_t i = 0; i < 7; ++i) {
+ if (!HasCopyAndDispose && i >=4 && i <= 5)
+ continue;
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*DInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition(*this);
+
+ return getPointerType(getTagDeclType(T));
}
@@ -2799,7 +2854,8 @@
QualType FieldType = E->getType();
if (BDRE && BDRE->isByRef())
- FieldType = BuildByRefType(FieldType);
+ FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(),
+ FieldType);
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
Name, FieldType, /*DInfo=*/0,