From f9096e450bb6047ab330c94749f5e80178a62b09 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 14 Dec 2011 19:10:53 +0000 Subject: [PATCH] It turns out that clang does use pointer-to-function types to point to ARC-managed pointers sometimes. This fixes rdar://10551239. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146577 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/ObjCARC.cpp | 8 ++++-- test/Transforms/ObjCARC/basic.ll | 4 ++- test/Transforms/ObjCARC/pointer-types.ll | 31 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/Transforms/ObjCARC/pointer-types.ll diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp index ab23884bb04..8e9449f5188 100644 --- a/lib/Transforms/Scalar/ObjCARC.cpp +++ b/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(Op->getType()); - if (!Ty || isa(Ty->getElementType())) + if (!Ty) return false; // Conservatively assume anything else is a potential use. return true; diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll index c466fa0e254..44c2602e575 100644 --- a/test/Transforms/ObjCARC/basic.ll +++ b/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/test/Transforms/ObjCARC/pointer-types.ll b/test/Transforms/ObjCARC/pointer-types.ll new file mode 100644 index 00000000000..6abc9398643 --- /dev/null +++ b/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*) + -- 2.34.1