239 lines · plain
1// Make sure it works on x86-64.2// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=NOTAIL-CALL3 4// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -O2 -disable-llvm-passes -o - %s | FileCheck %s -check-prefix=ATTACHED-CALL5 6// Make sure it works on x86-32.7// RUN: %clang_cc1 -triple i386-apple-darwin11 -fobjc-runtime=macosx-fragile-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL8 9// Make sure it works on ARM64.10// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL11 12// Make sure it works on ARM.13// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL14// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL15 16// Make sure that it's implicitly disabled if the runtime version isn't high enough.17// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED18// RUN: %clang_cc1 -triple arm64-apple-ios8 -fobjc-runtime=ios-8 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED -check-prefix=DISABLED-MARKED19 20@class A;21 22A *makeA(void);23 24void test_assign(void) {25 __unsafe_unretained id x;26 x = makeA();27}28// CHECK-LABEL: define{{.*}} void @test_assign()29// CHECK: [[X:%.*]] = alloca ptr30// CHECK: [[T0:%.*]] = call ptr @makeA()31// CHECK-MARKED-NEXT: call void asm sideeffect32// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])33// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])34// CHECK-NEXT: store ptr [[T2]], ptr [[X]]35// CHECK-OPTIMIZED-NEXT: lifetime.end36// CHECK-NEXT: ret void37 38// DISABLED-LABEL: define{{.*}} void @test_assign()39// DISABLED: [[T0:%.*]] = call ptr @makeA()40// DISABLED-MARKED-NEXT: call void asm sideeffect41// DISABLED-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])42 43// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign()44// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],45// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])46 47void test_assign_assign(void) {48 __unsafe_unretained id x, y;49 x = y = makeA();50}51// CHECK-LABEL: define{{.*}} void @test_assign_assign()52// CHECK: [[X:%.*]] = alloca ptr53// CHECK: [[Y:%.*]] = alloca ptr54// CHECK: [[T0:%.*]] = call ptr @makeA()55// CHECK-MARKED-NEXT: call void asm sideeffect56// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])57// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])58// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]59// CHECK-NEXT: store ptr [[T2]], ptr [[X]]60// CHECK-OPTIMIZED-NEXT: lifetime.end61// CHECK-OPTIMIZED-NEXT: lifetime.end62// CHECK-NEXT: ret void63 64// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_assign()65// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],66// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])67 68void test_strong_assign_assign(void) {69 __strong id x;70 __unsafe_unretained id y;71 x = y = makeA();72}73// CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()74// CHECK: [[X:%.*]] = alloca ptr75// CHECK: [[Y:%.*]] = alloca ptr76// CHECK: [[T0:%.*]] = call ptr @makeA()77// CHECK-MARKED-NEXT: call void asm sideeffect78// CHECK-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])79// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]80// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[X]]81// CHECK-NEXT: store ptr [[T2]], ptr [[X]]82// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]]83// CHECK-OPTIMIZED-NEXT: lifetime.end84// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)85// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]86// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])87// CHECK-OPTIMIZED-NEXT: lifetime.end88// CHECK-NEXT: ret void89 90// ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_assign_assign()91// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],92// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])93 94void test_assign_strong_assign(void) {95 __unsafe_unretained id x;96 __strong id y;97 x = y = makeA();98}99// CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()100// CHECK: [[X:%.*]] = alloca ptr101// CHECK: [[Y:%.*]] = alloca ptr102// CHECK: [[T0:%.*]] = call ptr @makeA()103// CHECK-MARKED-NEXT: call void asm sideeffect104// CHECK-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])105// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[Y]]106// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]107// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]]108// CHECK-NEXT: store ptr [[T2]], ptr [[X]]109// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null)110// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]111// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])112// CHECK-OPTIMIZED-NEXT: lifetime.end113// CHECK-OPTIMIZED-NEXT: lifetime.end114// CHECK-NEXT: ret void115 116// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_strong_assign()117// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],118// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])119 120void test_init(void) {121 __unsafe_unretained id x = makeA();122}123// CHECK-LABEL: define{{.*}} void @test_init()124// CHECK: [[X:%.*]] = alloca ptr125// CHECK: [[T0:%.*]] = call ptr @makeA()126// CHECK-MARKED-NEXT: call void asm sideeffect127// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])128// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])129// CHECK-NEXT: store ptr [[T2]], ptr [[X]]130// CHECK-OPTIMIZED-NEXT: lifetime.end131// CHECK-NEXT: ret void132 133// ATTACHED-CALL-LABEL: define{{.*}} void @test_init()134// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],135// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])136 137void test_init_assignment(void) {138 __unsafe_unretained id x;139 __unsafe_unretained id y = x = makeA();140}141// CHECK-LABEL: define{{.*}} void @test_init_assignment()142// CHECK: [[X:%.*]] = alloca ptr143// CHECK: [[Y:%.*]] = alloca ptr144// CHECK: [[T0:%.*]] = call ptr @makeA()145// CHECK-MARKED-NEXT: call void asm sideeffect146// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])147// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])148// CHECK-NEXT: store ptr [[T2]], ptr [[X]]149// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]150// CHECK-OPTIMIZED-NEXT: lifetime.end151// CHECK-OPTIMIZED-NEXT: lifetime.end152// CHECK-NEXT: ret void153 154// ATTACHED-CALL-LABEL: define{{.*}} void @test_init_assignment()155// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],156// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])157 158void test_strong_init_assignment(void) {159 __unsafe_unretained id x;160 __strong id y = x = makeA();161}162// CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()163// CHECK: [[X:%.*]] = alloca ptr164// CHECK: [[Y:%.*]] = alloca ptr165// CHECK: [[T0:%.*]] = call ptr @makeA()166// CHECK-MARKED-NEXT: call void asm sideeffect167// CHECK-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])168// CHECK-NEXT: store ptr [[T2]], ptr [[X]]169// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]170// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null)171// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]172// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])173// CHECK-OPTIMIZED-NEXT: lifetime.end174// CHECK-OPTIMIZED-NEXT: lifetime.end175// CHECK-NEXT: ret void176 177// ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_init_assignment()178// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],179// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])180 181void test_init_strong_assignment(void) {182 __strong id x;183 __unsafe_unretained id y = x = makeA();184}185// CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()186// CHECK: [[X:%.*]] = alloca ptr187// CHECK: [[Y:%.*]] = alloca ptr188// CHECK: [[T0:%.*]] = call ptr @makeA()189// CHECK-MARKED-NEXT: call void asm sideeffect190// CHECK-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])191// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[X]]192// CHECK-NEXT: store ptr [[T2]], ptr [[X]]193// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]])194// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]195// CHECK-OPTIMIZED-NEXT: lifetime.end196// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)197// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]198// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(ptr [[T0]])199// CHECK-OPTIMIZED-NEXT: lifetime.end200// CHECK-NEXT: ret void201 202// ATTACHED-CALL-LABEL: define{{.*}} void @test_init_strong_assignment()203// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],204// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])205 206void test_ignored(void) {207 makeA();208}209// CHECK-LABEL: define{{.*}} void @test_ignored()210// CHECK: [[T0:%.*]] = call ptr @makeA()211// CHECK-MARKED-NEXT: call void asm sideeffect212// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])213// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])214// CHECK-NEXT: ret void215 216// ATTACHED-CALL-LABEL: define{{.*}} void @test_ignored()217// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],218// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])219 220void test_cast_to_void(void) {221 (void) makeA();222}223// CHECK-LABEL: define{{.*}} void @test_cast_to_void()224// CHECK: [[T0:%.*]] = call ptr @makeA()225// CHECK-MARKED-NEXT: call void asm sideeffect226// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])227// CALL-NEXT: [[T2:%.*]] = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[T0]])228// CHECK-NEXT: ret void229 230// ATTACHED-CALL-LABEL: define{{.*}} void @test_cast_to_void()231// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],232// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])233 234 235// This is always at the end of the module.236 237// CHECK-OPTIMIZED: !llvm.module.flags = !{!0,238// CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}239