aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2012-11-28 23:12:17 +0000
committerFariborz Jahanian <fjahanian@apple.com>2012-11-28 23:12:17 +0000
commitb15c8984ea300624fbbde385d3907667ce1043fa (patch)
tree81bea997c8078dba2e7a52181299f2df85b0dfd2 /lib/AST/ASTContext.cpp
parenta70c3f8738cc123ded68c183cedd6e93df670c2f (diff)
objective-C blocks: Make sure that identical logic is used
in deciding a copy/dispose field is needed in a byref structure and when generating the copy/dispose helpers. In certain cases, these fields were being added but no copy/dispose was being generated. This was uncovered in ARC, but not in MRR. // rdar://12759433 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168825 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp112
1 files changed, 36 insertions, 76 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c4dbf5d46f..7fee560534 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4361,17 +4361,45 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
return getTagDeclType(BlockDescriptorExtendedType);
}
-bool ASTContext::BlockRequiresCopying(QualType Ty) const {
- if (Ty->isObjCRetainableType())
+/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty"
+/// requires copy/dispose. Note that this must match the logic
+/// in buildByrefHelpers.
+bool ASTContext::BlockRequiresCopying(QualType Ty,
+ const VarDecl *D) {
+ if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) {
+ const Expr *copyExpr = getBlockVarCopyInits(D);
+ if (!copyExpr && record->hasTrivialDestructor()) return false;
+
return true;
- if (getLangOpts().CPlusPlus) {
- if (const RecordType *RT = Ty->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- return RD->hasConstCopyConstructor();
-
+ }
+
+ if (!Ty->isObjCRetainableType()) return false;
+
+ Qualifiers qs = Ty.getQualifiers();
+
+ // If we have lifetime, that dominates.
+ if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
+ assert(getLangOpts().ObjCAutoRefCount);
+
+ switch (lifetime) {
+ case Qualifiers::OCL_None: llvm_unreachable("impossible");
+
+ // These are just bits as far as the runtime is concerned.
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ // Tell the runtime that this is ARC __weak, called by the
+ // byref routines.
+ case Qualifiers::OCL_Weak:
+ // ARC __strong __block variables need to be retained.
+ case Qualifiers::OCL_Strong:
+ return true;
}
+ llvm_unreachable("fell out of lifetime switch!");
}
- return false;
+ return (Ty->isBlockPointerType() || isObjCNSObjectType(Ty) ||
+ Ty->isObjCObjectPointerType());
}
bool ASTContext::getByrefLifetime(QualType Ty,
@@ -4397,74 +4425,6 @@ bool ASTContext::getByrefLifetime(QualType Ty,
return true;
}
-QualType
-ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const {
- // type = struct __Block_byref_1_X {
- // void *__isa;
- // struct __Block_byref_1_X *__forwarding;
- // unsigned int __flags;
- // unsigned int __size;
- // void *__copy_helper; // as needed
- // void *__destroy_help // as needed
- // void *__byref_variable_layout; // Extended layout info. for byref variable as needed
- // int X;
- // } *
-
- bool HasCopyAndDispose = BlockRequiresCopying(Ty);
- bool HasByrefExtendedLayout;
- Qualifiers::ObjCLifetime Lifetime;
-
- // FIXME: Move up
- SmallString<36> Name;
- llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
- ++UniqueBlockByRefTypeID << '_' << DeclName;
- RecordDecl *T;
- T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get(Name.str()));
- 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),
- getPointerType(VoidPtrTy),
- Ty
- };
-
- StringRef FieldNames[] = {
- "__isa",
- "__forwarding",
- "__flags",
- "__size",
- "__copy_helper",
- "__destroy_helper",
- "__byref_variable_layout",
- DeclName,
- };
- bool ByrefKnownLifetime = getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout);
- for (size_t i = 0; i < 8; ++i) {
- if (!HasCopyAndDispose && i >=4 && i <= 5)
- continue;
- if ((!ByrefKnownLifetime || !HasByrefExtendedLayout) && i == 6)
- continue;
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- SourceLocation(),
- &Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false,
- ICIS_NoInit);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- T->completeDefinition();
-
- return getPointerType(getTagDeclType(T));
-}
-
TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
if (!ObjCInstanceTypeDecl)
ObjCInstanceTypeDecl = TypedefDecl::Create(*this,