diff options
author | Dan Gohman <gohman@apple.com> | 2011-12-14 19:10:53 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2011-12-14 19:10:53 +0000 |
commit | bd944b41533f161ded3ed98b0949aaf8110bebe2 (patch) | |
tree | 71b47b8202bfb4a9192077e74acdd64334f828f1 | |
parent | 96b4874b5097136a48c7fe5ff2b62534ef837e5f (diff) | |
download | bcm5719-llvm-bd944b41533f161ded3ed98b0949aaf8110bebe2.tar.gz bcm5719-llvm-bd944b41533f161ded3ed98b0949aaf8110bebe2.zip |
It turns out that clang does use pointer-to-function types to
point to ARC-managed pointers sometimes. This fixes rdar://10551239.
llvm-svn: 146577
-rw-r--r-- | llvm/lib/Transforms/Scalar/ObjCARC.cpp | 8 | ||||
-rw-r--r-- | llvm/test/Transforms/ObjCARC/basic.ll | 4 | ||||
-rw-r--r-- | llvm/test/Transforms/ObjCARC/pointer-types.ll | 31 |
3 files changed, 40 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/ObjCARC.cpp b/llvm/lib/Transforms/Scalar/ObjCARC.cpp index ab23884bb04..8e9449f5188 100644 --- a/llvm/lib/Transforms/Scalar/ObjCARC.cpp +++ b/llvm/lib/Transforms/Scalar/ObjCARC.cpp @@ -179,9 +179,13 @@ static bool IsPotentialUse(const Value *Op) { Arg->hasNestAttr() || Arg->hasStructRetAttr()) return false; - // Only consider values with pointer types, and not function pointers. + // Only consider values with pointer types. + // It seemes intuitive to exclude function pointer types as well, since + // functions are never reference-counted, however clang occasionally + // bitcasts reference-counted pointers to function-pointer type + // temporarily. PointerType *Ty = dyn_cast<PointerType>(Op->getType()); - if (!Ty || isa<FunctionType>(Ty->getElementType())) + if (!Ty) return false; // Conservatively assume anything else is a potential use. return true; diff --git a/llvm/test/Transforms/ObjCARC/basic.ll b/llvm/test/Transforms/ObjCARC/basic.ll index c466fa0e254..44c2602e575 100644 --- a/llvm/test/Transforms/ObjCARC/basic.ll +++ b/llvm/test/Transforms/ObjCARC/basic.ll @@ -1528,9 +1528,11 @@ define void @test52(i8** %zz, i8** %pp) { ; Like test52, but the pointer has function type, so it's assumed to ; be not reference counted. +; Oops. That's wrong. Clang sometimes uses function types gratuitously. +; See rdar://10551239. ; CHECK: define void @test53( -; CHECK-NOT: @objc_ +; CHECK: @objc_ ; CHECK: } define void @test53(void ()** %zz, i8** %pp) { %p = load i8** %pp diff --git a/llvm/test/Transforms/ObjCARC/pointer-types.ll b/llvm/test/Transforms/ObjCARC/pointer-types.ll new file mode 100644 index 00000000000..6abc9398643 --- /dev/null +++ b/llvm/test/Transforms/ObjCARC/pointer-types.ll @@ -0,0 +1,31 @@ +; RUN: opt -objc-arc -S < %s | FileCheck %s + +; Don't hoist @objc_release past a use of its pointer, even +; if the use has function type, because clang uses function types +; in dubious ways. +; rdar://10551239 + +; CHECK: define void @test0( +; CHECK: %otherBlock = phi void ()* [ %b1, %if.then ], [ null, %entry ] +; CHECK-NEXT: call void @use_fptr(void ()* %otherBlock) +; CHECK-NEXT: %tmp11 = bitcast void ()* %otherBlock to i8* +; CHECK-NEXT: call void @objc_release(i8* %tmp11) + +define void @test0(i1 %tobool, void ()* %b1) { +entry: + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + br label %if.end + +if.end: ; preds = %if.then, %entry + %otherBlock = phi void ()* [ %b1, %if.then ], [ null, %entry ] + call void @use_fptr(void ()* %otherBlock) + %tmp11 = bitcast void ()* %otherBlock to i8* + call void @objc_release(i8* %tmp11) nounwind + ret void +} + +declare void @use_fptr(void ()*) +declare void @objc_release(i8*) + |