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,
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,
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
-llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
+llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
SmallVector<llvm::Value *, 5> EltTys;
EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
- bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type);
+ bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);
if (HasCopyAndDispose) {
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",