aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp57
1 files changed, 54 insertions, 3 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 42a6704d8a..442714a5a6 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -40,7 +40,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
bool FreeMem, unsigned size_reserve) :
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
- sigjmp_bufDecl(0), BlockDescriptorType(0), SourceMgr(SM), LangOpts(LOpts),
+ sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
+ SourceMgr(SM), LangOpts(LOpts),
LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
@@ -2714,7 +2715,7 @@ QualType ASTContext::getBlockDescriptorType() {
const char *FieldNames[] = {
"reserved",
- "Size",
+ "Size"
};
for (size_t i = 0; i < 2; ++i) {
@@ -2741,6 +2742,53 @@ void ASTContext::setBlockDescriptorType(QualType T) {
BlockDescriptorType = Rec->getDecl();
}
+QualType ASTContext::getBlockDescriptorExtendedType() {
+ if (BlockDescriptorExtendedType)
+ return getTagDeclType(BlockDescriptorExtendedType);
+
+ RecordDecl *T;
+ // FIXME: Needs the FlagAppleBlock bit.
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor_withcopydispose"));
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ UnsignedLongTy,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy)
+ };
+
+ const char *FieldNames[] = {
+ "reserved",
+ "Size",
+ "CopyFuncPtr",
+ "DestroyFuncPtr"
+ };
+
+ for (size_t i = 0; i < 4; ++i) {
+ 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);
+
+ BlockDescriptorExtendedType = T;
+
+ return getTagDeclType(BlockDescriptorExtendedType);
+}
+
+void ASTContext::setBlockDescriptorExtendedType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid BlockDescriptorType");
+ BlockDescriptorExtendedType = Rec->getDecl();
+}
+
bool ASTContext::BlockRequiresCopying(QualType Ty) {
if (Ty->isBlockPointerType())
return true;
@@ -2811,6 +2859,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
QualType ASTContext::getBlockParmType(
+ bool BlockHasCopyDispose,
llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
// FIXME: Move up
static int UniqueBlockParmTypeID = 0;
@@ -2824,7 +2873,9 @@ QualType ASTContext::getBlockParmType(
IntTy,
IntTy,
getPointerType(VoidPtrTy),
- getPointerType(getBlockDescriptorType()),
+ (BlockHasCopyDispose ?
+ getPointerType(getBlockDescriptorExtendedType()) :
+ getPointerType(getBlockDescriptorType()))
};
const char *FieldNames[] = {