[cfe-commits] r168825 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CGDebugInfo.h lib/Rewrite/Frontend/RewriteModernObjC.cpp lib/Rewrite/Frontend/RewriteObjC.cpp test/CodeGenObjC/block-byref-variable-layout.m
Fariborz Jahanian
fjahanian at apple.com
Wed Nov 28 15:12:17 PST 2012
Author: fjahanian
Date: Wed Nov 28 17:12:17 2012
New Revision: 168825
URL: http://llvm.org/viewvc/llvm-project?rev=168825&view=rev
Log:
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
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/CodeGen/CGBlocks.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
cfe/trunk/test/CodeGenObjC/block-byref-variable-layout.m
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Nov 28 17:12:17 2012
@@ -860,11 +860,8 @@
return cudaConfigureCallDecl;
}
- /// Builds the struct used for __block variables.
- QualType BuildByRefType(StringRef DeclName, QualType Ty) const;
-
/// Returns true iff we need copy/dispose helpers for the given type.
- bool BlockRequiresCopying(QualType Ty) const;
+ bool BlockRequiresCopying(QualType Ty, const VarDecl *D);
/// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Nov 28 17:12:17 2012
@@ -4361,17 +4361,45 @@
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 @@
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,
Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Wed Nov 28 17:12:17 2012
@@ -1922,9 +1922,8 @@
// int32_t __size;
types.push_back(Int32Ty);
-
- bool HasCopyAndDispose =
- (Ty->isObjCRetainableType()) || getContext().getBlockVarCopyInits(D);
+ // Note that this must match *exactly* the logic in buildByrefHelpers.
+ bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
if (HasCopyAndDispose) {
/// void *__copy_helper;
types.push_back(Int8PtrTy);
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed Nov 28 17:12:17 2012
@@ -2229,7 +2229,7 @@
// 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;
@@ -2248,7 +2248,7 @@
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",
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Wed Nov 28 17:12:17 2012
@@ -243,7 +243,7 @@
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
- llvm::DIType EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
+ llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
/// getContextDescriptor - Get context info for the decl.
Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp Wed Nov 28 17:12:17 2012
@@ -5053,7 +5053,7 @@
// Add void *__Block_byref_id_object_copy;
// void *__Block_byref_id_object_dispose; if needed.
QualType Ty = ND->getType();
- bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
+ bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
if (HasCopyAndDispose) {
ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp Wed Nov 28 17:12:17 2012
@@ -4309,7 +4309,7 @@
// Add void *__Block_byref_id_object_copy;
// void *__Block_byref_id_object_dispose; if needed.
QualType Ty = ND->getType();
- bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
+ bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
if (HasCopyAndDispose) {
ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
Modified: cfe/trunk/test/CodeGenObjC/block-byref-variable-layout.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/block-byref-variable-layout.m?rev=168825&r1=168824&r2=168825&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/block-byref-variable-layout.m (original)
+++ cfe/trunk/test/CodeGenObjC/block-byref-variable-layout.m Wed Nov 28 17:12:17 2012
@@ -1,5 +1,14 @@
// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o - | FileCheck %s
+// rdar://12759433
+ at class NSString;
+
+void Test12759433() {
+ __block __unsafe_unretained NSString *uuByref = (__bridge NSString *)(void*)0x102030405060708;
+ void (^block)() = ^{ uuByref = 0; };
+ block();
+}
+// CHECK: %struct.__block_byref_uuByref = type { i8*, %struct.__block_byref_uuByref*, i32, i32, [[ZERO:%.*]]* }
int main() {
__block __weak id wid;
__block long XXX;
More information about the cfe-commits
mailing list