diff options
Diffstat (limited to 'test/CodeGenObjCXX')
22 files changed, 506 insertions, 38 deletions
diff --git a/test/CodeGenObjCXX/arc-cxx11-init-list.mm b/test/CodeGenObjCXX/arc-cxx11-init-list.mm index da214dc38ad2..230d0f197bfb 100644 --- a/test/CodeGenObjCXX/arc-cxx11-init-list.mm +++ b/test/CodeGenObjCXX/arc-cxx11-init-list.mm @@ -41,8 +41,6 @@ extern "C" void extended() { } // CHECK: [[INSTANCE:%.*]] = {{.*}} call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) -// CHECK-NEXT: [[CAST:%.*]] = bitcast [1 x %0*]* %{{.*}} to i8** -// CHECK-NEXT: store i8* [[INSTANCE]], i8** [[CAST]], // CHECK: {{.*}} call void @_Z8externalv() // CHECK: {{.*}} call void @objc_release(i8* {{.*}}) diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm index cc2206d1a9ec..0ae306943186 100644 --- a/test/CodeGenObjCXX/arc-exceptions.mm +++ b/test/CodeGenObjCXX/arc-exceptions.mm @@ -121,4 +121,37 @@ namespace test4 { // CHECK: resume } +// rdar://21397946 +__attribute__((ns_returns_retained)) id test5_helper(unsigned); +void test5(void) { + id array[][2] = { + test5_helper(0), + test5_helper(1), + test5_helper(2), + test5_helper(3) + }; +} +// CHECK-LABEL: define void @_Z5test5v() +// CHECK: [[ARRAY:%.*]] = alloca [2 x [2 x i8*]], align +// CHECK: [[A0:%.*]] = getelementptr inbounds [2 x [2 x i8*]], [2 x [2 x i8*]]* [[ARRAY]], i64 0, i64 0 +// CHECK-NEXT: store [2 x i8*]* [[A0]], +// CHECK-NEXT: [[A00:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 0, i64 0 +// CHECK-NEXT: store i8** [[A00]], +// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 0) +// CHECK: store i8* [[T0]], i8** [[A00]], align +// CHECK-NEXT: [[A01:%.*]] = getelementptr inbounds i8*, i8** [[A00]], i64 1 +// CHECK-NEXT: store i8** [[A01]], +// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 1) +// CHECK: store i8* [[T0]], i8** [[A01]], align +// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A0]], i64 1 +// CHECK-NEXT: store [2 x i8*]* [[A1]], +// CHECK-NEXT: [[A10:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[A1]], i64 0, i64 0 +// CHECK-NEXT: store i8** [[A10]], +// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 2) +// CHECK: store i8* [[T0]], i8** [[A10]], align +// CHECK-NEXT: [[A11:%.*]] = getelementptr inbounds i8*, i8** [[A10]], i64 1 +// CHECK-NEXT: store i8** [[A11]], +// CHECK-NEXT: [[T0:%.*]] = invoke i8* @_Z12test5_helperj(i32 3) +// CHECK: store i8* [[T0]], i8** [[A11]], align + // CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm index 9a61f183c697..f853ea4366a0 100644 --- a/test/CodeGenObjCXX/arc-new-delete.mm +++ b/test/CodeGenObjCXX/arc-new-delete.mm @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=UNOPT +// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -O -disable-llvm-optzns | FileCheck %s -check-prefix=CHECK -check-prefix=OPT typedef __strong id strong_id; typedef __weak id weak_id; @@ -6,8 +7,10 @@ typedef __weak id weak_id; // CHECK-LABEL: define void @_Z8test_newP11objc_object void test_new(id invalue) { // CHECK: [[INVALUEADDR:%.*]] = alloca i8* - // CHECK-NEXT: store i8* null, i8** [[INVALUEADDR]] - // CHECK-NEXT: call void @objc_storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]]) + // UNOPT-NEXT: store i8* null, i8** [[INVALUEADDR]] + // UNOPT-NEXT: call void @objc_storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]]) + // OPT-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[INVALUE:%.*]]) + // OPT-NEXT: store i8* [[T0]], i8** [[INVALUEADDR]] // CHECK: call noalias i8* @_Znwm // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} @@ -15,7 +18,8 @@ void test_new(id invalue) { new strong_id; // CHECK: call noalias i8* @_Znwm // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} - // CHECK-NEXT: store i8* null, i8** + // UNOPT-NEXT: store i8* null, i8** + // OPT-NEXT: call i8* @objc_initWeak(i8** {{.*}}, i8* null) new weak_id; // CHECK: call noalias i8* @_Znwm @@ -24,7 +28,8 @@ void test_new(id invalue) { new __strong id; // CHECK: call noalias i8* @_Znwm // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} - // CHECK-NEXT: store i8* null, i8** + // UNOPT-NEXT: store i8* null, i8** + // OPT-NEXT: call i8* @objc_initWeak(i8** {{.*}}, i8* null) new __weak id; // CHECK: call noalias i8* @_Znwm @@ -36,7 +41,8 @@ void test_new(id invalue) { // CHECK: call i8* @objc_initWeak new __weak id(invalue); - // CHECK: call void @objc_storeStrong + // UNOPT: call void @objc_storeStrong + // OPT: call void @objc_release // CHECK: ret void } @@ -57,8 +63,9 @@ void test_array_new() { // CHECK-LABEL: define void @_Z11test_deletePU8__strongP11objc_objectPU6__weakS0_ void test_delete(__strong id *sptr, __weak id *wptr) { // CHECK: br i1 - // CHECK: load i8*, i8** - // CHECK-NEXT: call void @objc_release + // UNOPT: call void @objc_storeStrong(i8** {{.*}}, i8* null) + // OPT: load i8*, i8** + // OPT-NEXT: call void @objc_release // CHECK: call void @_ZdlPv delete sptr; @@ -77,7 +84,9 @@ void test_array_delete(__strong id *sptr, __weak id *wptr) { // CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]] // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1 - // CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null) + // UNOPT-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null) + // OPT-NEXT: [[T0:%.*]] = load i8*, i8** [[CUR]] + // OPT-NEXT: objc_release(i8* [[T0]]) // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]] // CHECK: call void @_ZdaPv delete [] sptr; diff --git a/test/CodeGenObjCXX/arc-weak.mm b/test/CodeGenObjCXX/arc-weak.mm new file mode 100644 index 000000000000..8fd03379aa69 --- /dev/null +++ b/test/CodeGenObjCXX/arc-weak.mm @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s + +__attribute((objc_root_class)) @interface A @end +@interface B : A @end + +// rdar://problem/23559789 +// Ensure that type differences don't cause an assert here. +void test0(__weak B **src) { + __weak A *dest = *src; +} +// CHECK-LABEL: define void @_Z5test0PU6__weakP1B( +// CHECK: [[SRC:%.*]] = alloca [[B:%.*]]**, align 8 +// CHECK: [[DEST:%.*]] = alloca [[A:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[B]]**, [[B]]*** [[SRC]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8** +// CHECK-NEXT: call void @objc_copyWeak(i8** [[T2]], i8** [[T3]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK: call void @objc_destroyWeak(i8** [[T0]]) + +void test1(__weak B **src) { + __weak A *dest = static_cast<__weak B*&&>(*src); +} +// CHECK-LABEL: define void @_Z5test1PU6__weakP1B( +// CHECK: [[SRC:%.*]] = alloca [[B:%.*]]**, align 8 +// CHECK: [[DEST:%.*]] = alloca [[A:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[B]]**, [[B]]*** [[SRC]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8** +// CHECK-NEXT: call void @objc_moveWeak(i8** [[T2]], i8** [[T3]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK: call void @objc_destroyWeak(i8** [[T0]]) diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm index 4ce59df3e0fd..e3a6349afaf0 100644 --- a/test/CodeGenObjCXX/arc.mm +++ b/test/CodeGenObjCXX/arc.mm @@ -324,3 +324,13 @@ template void test40_helper<int>(); // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]] // CHECK-NEXT: call i8* @objc_retain(i8* [[T0]]) +// Check that moves out of __weak variables are compiled to use objc_moveWeak. +void test41(__weak id &&x) { + __weak id y = static_cast<__weak id &&>(x); +} +// CHECK-LABEL: define void @_Z6test41OU6__weakP11objc_object +// CHECK: [[X:%.*]] = alloca i8** +// CHECK: [[Y:%.*]] = alloca i8* +// CHECK: [[T0:%.*]] = load i8**, i8*** [[X]] +// CHECK-NEXT: call void @objc_moveWeak(i8** [[Y]], i8** [[T0]]) +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Y]]) diff --git a/test/CodeGenObjCXX/block-var-layout.mm b/test/CodeGenObjCXX/block-var-layout.mm index 793d4b99aad6..fc3a056048b3 100644 --- a/test/CodeGenObjCXX/block-var-layout.mm +++ b/test/CodeGenObjCXX/block-var-layout.mm @@ -151,7 +151,7 @@ void notifyBlock(id dependentBlock) { void test_empty_block() { // 01 00 -// CHECK: block variable layout for block: 0x01, 0x00 +// CHECK: block variable layout for block: 0x01, 0x30, 0x00 void (^wrapperBlock)() = ^() { }; wrapperBlock(); diff --git a/test/CodeGenObjCXX/blocks.mm b/test/CodeGenObjCXX/blocks.mm index 62ae428e5ec1..63a1b33f355a 100644 --- a/test/CodeGenObjCXX/blocks.mm +++ b/test/CodeGenObjCXX/blocks.mm @@ -8,6 +8,8 @@ @end void f(int (^bl)(B* b)); +void takeBlock(void (^block)()); +void useValues(...); // Test1 void g() { @@ -59,3 +61,25 @@ void gun() { return foovar; }; } + +// PR24780 +class CaptureThisAndAnotherPointer { + void test(void *ptr) { + takeBlock(^{ useValues(ptr, this); }); + } +}; + +// rdar://problem/23713871 +// Check that we don't crash when using BLOCK_LAYOUT_STRONG. +#pragma clang assume_nonnull begin +@interface NSUUID @end +#pragma clang assume_nonnull end + +struct Wrapper1 { NSUUID *Ref; }; +struct Wrapper2 { Wrapper1 W1; }; + +@implementation B +- (void) captureStrongRef { + __block Wrapper2 W2; +} +@end diff --git a/test/CodeGenObjCXX/debug-info-cyclic.mm b/test/CodeGenObjCXX/debug-info-cyclic.mm index 37a8064baaf1..582ca445f993 100644 --- a/test/CodeGenObjCXX/debug-info-cyclic.mm +++ b/test/CodeGenObjCXX/debug-info-cyclic.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -g -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -debug-info-kind=standalone -emit-llvm %s -o - | FileCheck %s struct B { // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B" diff --git a/test/CodeGenObjCXX/debug-info-line.mm b/test/CodeGenObjCXX/debug-info-line.mm index 6d7321c381f5..98ec2ce77c37 100644 --- a/test/CodeGenObjCXX/debug-info-line.mm +++ b/test/CodeGenObjCXX/debug-info-line.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -gline-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -debug-info-kind=line-tables-only -fblocks -emit-llvm %s -o - | FileCheck %s void fn(); diff --git a/test/CodeGenObjCXX/debug-info.mm b/test/CodeGenObjCXX/debug-info.mm index 04cf66f2cd18..ea5bb62fe75a 100644 --- a/test/CodeGenObjCXX/debug-info.mm +++ b/test/CodeGenObjCXX/debug-info.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -debug-info-kind=limited -emit-llvm %s -o /dev/null // This test passes if clang doesn't crash. diff --git a/test/CodeGenObjCXX/designated-initializers.mm b/test/CodeGenObjCXX/designated-initializers.mm index 41a4271bc8c5..71ffe1fbbd5e 100644 --- a/test/CodeGenObjCXX/designated-initializers.mm +++ b/test/CodeGenObjCXX/designated-initializers.mm @@ -34,3 +34,11 @@ int vals5[3] = { 6 }; // CHECK: @vals5 = global [3 x i32] [i32 1, i32 2, i32 6] + +enum SomeEnum : unsigned char { + blah = 255 +}; +char vals6[] = { + [blah] = 'a' +}; +// CHECK: @vals6 = global [256 x i8] c"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a" diff --git a/test/CodeGenObjCXX/exception-cxx.mm b/test/CodeGenObjCXX/exception-cxx.mm new file mode 100644 index 000000000000..36eec28a0ab7 --- /dev/null +++ b/test/CodeGenObjCXX/exception-cxx.mm @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s + +// rdar://problem/22155434 +namespace test0 { + void foo() { + try { + throw 0; + } catch (int e) { + return; + } + } +// CHECK: define void @_ZN5test03fooEv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +} diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm index 7089de23b933..4d1b5019412a 100644 --- a/test/CodeGenObjCXX/literals.mm +++ b/test/CodeGenObjCXX/literals.mm @@ -22,14 +22,14 @@ void test_array() { // Initializing first element // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]]) - // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0 + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 // CHECK-NEXT: call void @_ZN1XC1Ev // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element - // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 // CHECK-NEXT: invoke void @_ZN1YC1Ev // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) @@ -74,14 +74,14 @@ void test_array_instantiation() { // Initializing first element // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]]) - // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0 + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 // CHECK-NEXT: call void @_ZN1XC1Ev // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element - // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 // CHECK-NEXT: invoke void @_ZN1YC1Ev // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) diff --git a/test/CodeGenObjCXX/mrc-weak.mm b/test/CodeGenObjCXX/mrc-weak.mm new file mode 100644 index 000000000000..17ceb31231a3 --- /dev/null +++ b/test/CodeGenObjCXX/mrc-weak.mm @@ -0,0 +1,183 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE + +@interface Object +- (instancetype) retain; +- (void) run; +@end + +// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" +// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772 +// 772 == 0x304 +// ^ HasMRCWeakIvars +// ^ HasCXXDestructorOnly +// ^ HasCXXStructors + +// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00" +// CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921, +// 134225921 == 0x08002001 +// ^ HasMRCWeakIvars +// ^ HasCXXStructors +// ^ Factory +@interface Foo : Object { + __weak id ivar; +} +@end + +@implementation Foo +// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]" +// CHECK: call void @objc_destroyWeak +@end + + +void test1(__weak id x) {} +// CHECK-LABEL: define void @_Z5test1P11objc_object( +// CHECK: [[X:%.*]] = alloca i8*, +// CHECK-NEXT: objc_initWeak +// CHECK-NEXT: objc_destroyWeak +// CHECK-NEXT: ret void + +void test2(id y) { + __weak id z = y; +} +// CHECK-LABEL: define void @_Z5test2P11objc_object( +// CHECK: [[Y:%.*]] = alloca i8*, +// CHECK-NEXT: [[Z:%.*]] = alloca i8*, +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]]) +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) +// CHECK-NEXT: ret void + +void test3(id y) { + __weak id z; + z = y; +} +// CHECK-LABEL: define void @_Z5test3P11objc_object( +// CHECK: [[Y:%.*]] = alloca i8*, +// CHECK-NEXT: [[Z:%.*]] = alloca i8*, +// CHECK-NEXT: store +// CHECK-NEXT: store i8* null, i8** [[Z]] +// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] +// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]]) +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]]) +// CHECK-NEXT: ret void + +void test4(__weak id *p) { + id y = *p; +} +// CHECK-LABEL: define void @_Z5test4PU6__weakP11objc_object( +// CHECK: [[P:%.*]] = alloca i8**, +// CHECK-NEXT: [[Y:%.*]] = alloca i8*, +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] +// CHECK-NEXT: ret void + +void test5(__weak id *p) { + id y = [*p retain]; +} +// CHECK-LABEL: define void @_Z5test5PU6__weakP11objc_object +// CHECK: [[P:%.*]] = alloca i8**, +// CHECK-NEXT: [[Y:%.*]] = alloca i8*, +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]] +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[Y]] +// CHECK-NEXT: ret void + +void test6(__weak Foo **p) { + Foo *y = [*p retain]; +} +// CHECK-LABEL: define void @_Z5test6PU6__weakP3Foo +// CHECK: [[P:%.*]] = alloca [[FOO:%.*]]**, +// CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*, +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8** +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]* +// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]] +// CHECK-NEXT: ret void + +extern "C" id get_object(void); +extern "C" void use_block(void (^)(void)); + +void test7(void) { + __weak Foo *p = get_object(); + use_block(^{ [p run ]; }); +} +// CHECK-LABEL: define void @_Z5test7v +// CHECK: [[P:%.*]] = alloca [[FOO]]*, +// CHECK: [[T0:%.*]] = call i8* @get_object() +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8* +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) +// CHECK: call void @objc_copyWeak +// CHECK: call void @use_block +// CHECK: call void @objc_destroyWeak + +// CHECK-LABEL: define internal void @__copy_helper_block +// CHECK: @objc_copyWeak + +// CHECK-LABEL: define internal void @__destroy_helper_block +// CHECK: @objc_destroyWeak + +void test8(void) { + __block __weak Foo *p = get_object(); + use_block(^{ [p run ]; }); +} +// CHECK-LABEL: define void @_Z5test8v +// CHECK: call i8* @objc_initWeak +// CHECK-NOT: call void @objc_copyWeak +// CHECK: call void @use_block +// CHECK: call void @objc_destroyWeak + +// CHECK-LABEL: define internal void @__Block_byref_object_copy +// CHECK: call void @objc_moveWeak + +// CHECK-LABEL: define internal void @__Block_byref_object_dispose +// CHECK: call void @objc_destroyWeak + +// CHECK-LABEL: define void @_Z14test9_baselinev() +// CHECK: define internal void @__copy_helper +// CHECK: define internal void @__destroy_helper +void test9_baseline(void) { + Foo *p = get_object(); + use_block(^{ [p run]; }); +} + +// CHECK-LABEL: define void @_Z5test9v() +// CHECK-NOT: define internal void @__copy_helper +// CHECK-NOT: define internal void @__destroy_helper +// CHECK: define void @_Z9test9_finv() +void test9(void) { + __unsafe_unretained Foo *p = get_object(); + use_block(^{ [p run]; }); +} +void test9_fin() {} + +// CHECK-LABEL: define void @_Z6test10v() +// CHECK-NOT: define internal void @__copy_helper +// CHECK-NOT: define internal void @__destroy_helper +// CHECK: define void @_Z10test10_finv() +void test10(void) { + typedef __unsafe_unretained Foo *UnsafeFooPtr; + UnsafeFooPtr p = get_object(); + use_block(^{ [p run]; }); +} +void test10_fin() {} + +// CHECK-LABEL: define weak_odr void @_Z6test11ILj0EEvv() +// CHECK-NOT: define internal void @__copy_helper +// CHECK-NOT: define internal void @__destroy_helper +// CHECK: define void @_Z10test11_finv() +template <unsigned i> void test11(void) { + typedef __unsafe_unretained Foo *UnsafeFooPtr; + UnsafeFooPtr p = get_object(); + use_block(^{ [p run]; }); +} +template void test11<0>(); +void test11_fin() {} diff --git a/test/CodeGenObjCXX/nested-ehlocation.mm b/test/CodeGenObjCXX/nested-ehlocation.mm index de3e3597548e..030bc7c5cd3e 100644 --- a/test/CodeGenObjCXX/nested-ehlocation.mm +++ b/test/CodeGenObjCXX/nested-ehlocation.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -g -stdlib=libc++ -fblocks -fexceptions -x objective-c++ -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -debug-info-kind=limited -stdlib=libc++ -fblocks -fexceptions -x objective-c++ -o - %s | FileCheck %s // Verify that all invoke instructions have a debug location. // Literally: There are no unwind lines that don't end with ", (!dbg 123)". diff --git a/test/CodeGenObjCXX/personality-abuse.mm b/test/CodeGenObjCXX/personality-abuse.mm new file mode 100644 index 000000000000..f5170bf75c09 --- /dev/null +++ b/test/CodeGenObjCXX/personality-abuse.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s + +extern "C" { + int __objc_personality_v0(); +} + +void *abuse_personality_func() { + return (void *)&__objc_personality_v0; +} + +void foo() { + try { + throw 0; + } catch (int e) { + return; + } +} + +// CHECK: define void @_Z3foov() #1 personality i8* bitcast (i32 ()* @__objc_personality_v0 to i8*) diff --git a/test/CodeGenObjCXX/pr14474-gline-tables-only.mm b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm index e927ab96f3c1..6c74ce80db0f 100644 --- a/test/CodeGenObjCXX/pr14474-gline-tables-only.mm +++ b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm @@ -1,6 +1,6 @@ // PR 14474 // RUN: %clang_cc1 -triple i386-apple-macosx10.6.0 -emit-llvm \ -// RUN: -gline-tables-only -x objective-c++ -o /dev/null %s +// RUN: -debug-info-kind=line-tables-only -x objective-c++ -o /dev/null %s typedef signed char BOOL; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; diff --git a/test/CodeGenObjCXX/property-lvalue-capture.mm b/test/CodeGenObjCXX/property-lvalue-capture.mm index b800c39fb3c4..c5a753c8cf23 100644 --- a/test/CodeGenObjCXX/property-lvalue-capture.mm +++ b/test/CodeGenObjCXX/property-lvalue-capture.mm @@ -24,10 +24,10 @@ typedef Quad2<double> Quad2d; } @end -// CHECK: [[TWO:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_, !invariant.load ![[MD_NUM:[0-9]+]] +// CHECK: [[TWO:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_, align 8, !invariant.load ![[MD_NUM:[0-9]+]] // CHECK: [[THREE:%.*]] = bitcast [[ONET:%.*]]* [[ONE:%.*]] to i8* // CHECK: [[CALL:%.*]] = call nonnull %struct.Quad2* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %struct.Quad2* (i8*, i8*)*)(i8* [[THREE]], i8* [[TWO]]) -// CHECK: [[FOUR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2, !invariant.load ![[MD_NUM]] +// CHECK: [[FOUR:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.2, align 8, !invariant.load ![[MD_NUM]] // CHECK: [[FIVE:%.*]] = bitcast [[ONET]]* [[ZERO:%.*]] to i8* // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.Quad2*)*)(i8* [[FIVE]], i8* [[FOUR]], %struct.Quad2* nonnull [[CALL]]) @@ -47,7 +47,7 @@ void test(C *c, const A &a) { } // CHECK: [[ONE1:%.*]] = load %struct.A*, %struct.A** [[AADDR:%.*]], align 8 -// CHECK: [[TWO1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.5, !invariant.load ![[MD_NUM]] +// CHECK: [[TWO1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_.5, align 8, !invariant.load ![[MD_NUM]] // CHECK: [[THREE1:%.*]] = bitcast [[TWOT:%.*]]* [[ZERO1:%.*]] to i8* // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.A*)*)(i8* [[THREE1]], i8* [[TWO1]], %struct.A* dereferenceable({{[0-9]+}}) [[ONE1]]) // CHECK: store %struct.A* [[ONE1]], %struct.A** [[RESULT:%.*]], align 8 diff --git a/test/CodeGenObjCXX/property-object-conditional-exp.mm b/test/CodeGenObjCXX/property-object-conditional-exp.mm index e3fc2d70962f..cdee635a6fbb 100644 --- a/test/CodeGenObjCXX/property-object-conditional-exp.mm +++ b/test/CodeGenObjCXX/property-object-conditional-exp.mm @@ -24,10 +24,10 @@ extern "C" bool CGRectIsEmpty(CGRect); // CHECK: [[SRC:%.*]] = call { i8*, i32 } bitcast (i8* (i8*, i8*, ...)* @objc_msgSend // CHECK-NEXT: bitcast -// CHECK-NEXT:getelementptr { i8*, i32 }, { i8*, i32 }* [[SRC:%.*]] +// CHECK-NEXT:getelementptr inbounds { i8*, i32 }, { i8*, i32 }* [[SRC:%.*]] // CHECK-NEXT:extractvalue // CHECK-NEXT:store -// CHECK-NEXT:getelementptr { i8*, i32 }, { i8*, i32 }* [[SRC:%.*]] +// CHECK-NEXT:getelementptr inbounds { i8*, i32 }, { i8*, i32 }* [[SRC:%.*]] // CHECK-NEXT:extractvalue // CHECK-NEXT:store dataRect = CGRectIsEmpty(virtualBounds) ? self.bounds : virtualBounds; diff --git a/test/CodeGenObjCXX/property-object-reference-2.mm b/test/CodeGenObjCXX/property-object-reference-2.mm index 87cebc10836a..925cc52f9092 100644 --- a/test/CodeGenObjCXX/property-object-reference-2.mm +++ b/test/CodeGenObjCXX/property-object-reference-2.mm @@ -29,7 +29,7 @@ struct TCPPObject @synthesize MyProperty1 = _cppObject1; @end -// CHECK-LABEL: define internal void @__copy_helper_atomic_property_( +// CHECK-LABEL: define internal void @__copy_helper_atomic_property_(%struct.TCPPObject*, %struct.TCPPObject*) # // CHECK: [[TWO:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR:%.*]], align 8 // CHECK: [[THREE:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR1:%.*]], align 8 // CHECK: [[CALL:%.*]] = call i32 @_Z7DEFAULTv() @@ -43,7 +43,7 @@ struct TCPPObject // CHECK: call void @objc_copyCppObjectAtomic(i8* [[THREE]], i8* [[TWO]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__copy_helper_atomic_property_ to i8*)) // CHECK: ret void -// CHECK-LABEL: define internal void @__assign_helper_atomic_property_( +// CHECK-LABEL: define internal void @__assign_helper_atomic_property_(%struct.TCPPObject*, %struct.TCPPObject*) # // CHECK: [[TWO:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR:%.*]], align 8 // CHECK: [[THREE:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR1:%.*]], align 8 // CHECK: [[CALL:%.*]] = call dereferenceable({{[0-9]+}}) %struct.TCPPObject* @_ZN10TCPPObjectaSERKS_(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* dereferenceable({{[0-9]+}}) [[THREE]]) diff --git a/test/CodeGenObjCXX/property-objects.mm b/test/CodeGenObjCXX/property-objects.mm index 73ed21dcb7d8..8e0b6aebe149 100644 --- a/test/CodeGenObjCXX/property-objects.mm +++ b/test/CodeGenObjCXX/property-objects.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -g -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -debug-info-kind=limited -o - | FileCheck %s class S { public: @@ -37,7 +37,7 @@ struct CGRect { // Don't attach debug locations to the prologue instructions. These were // leaking over from the previous function emission by accident. -// CHECK: define internal void @"\01-[I setBounds:]" +// CHECK: define internal void @"\01-[I setBounds:]"({{.*}} { // CHECK-NOT: !dbg // CHECK: call void @llvm.dbg.declare - (void)setFrame:(CGRect)frameRect {} @@ -91,3 +91,133 @@ struct X { void f(A* a) { a.x = X(); } + +// rdar://21801088 +// Ensure that pseudo-objecet expressions that require the RHS to be +// rewritten don't result in crashes or redundant emission of code. +struct B0 { long long x; }; +struct B1 { long long x; }; B1 operator+(B1, B1); +struct B2 { B1 x; }; +struct B3 { B3(); B1 x; operator B1(); }; +@interface B +@property B0 b0; +@property B1 b1; +@property B2 b2; +@property B3 b3; +@end + +int b_makeInt(); + +// Note that there's a promotion from int to long long, so +// the syntactic form of the RHS will be bogus. +void testB0(B *b) { + b.b0 = { b_makeInt() }; +} +void testB1(B *b) { + b.b1 += { b_makeInt() }; +} +// CHECK: define void @_Z6testB0P1B([[B:%.*]]* +// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 +// CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8 +// CHECK: load [[B]]*, [[B]]** [[BVAR]] +// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0 +// CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv() +// CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 +// CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8 +// CHECK-NOT: call +// CHECK: call void @llvm.memcpy +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: ret void + +// CHECK: define void @_Z6testB1P1B([[B]]* +// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 +// CHECK: load [[B]]*, [[B]]** [[BVAR]] +// CHECK-NOT: call +// CHECK: [[T0:%.*]] = call i64 bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: store i64 [[T0]], +// CHECK-NOT: call +// CHECK: [[T0:%.*]] = call i32 @_Z9b_makeIntv() +// CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 +// CHECK-NEXT: store i64 [[T1]], i64* {{.*}}, align 8 +// CHECK-NOT: call +// CHECK: [[T0:%.*]] = call i64 @_Zpl2B1S_ +// CHECK-NOT: call +// CHECK: store i64 [[T0]], +// CHECK-NOT: call +// CHECK: call void @llvm.memcpy +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: ret void + +// Another example of a conversion that needs to be applied +// in the semantic form. +void testB2(B *b) { + b.b2 = { B3() }; +} + +// CHECK: define void @_Z6testB2P1B([[B]]* +// CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 +// CHECK: load [[B]]*, [[B]]** [[BVAR]] +// CHECK-NOT: call +// CHECK: call void @_ZN2B3C1Ev( +// CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev( +// CHECK-NOT: call +// CHECK: store i64 [[T0]], +// CHECK-NOT: call +// CHECK: call void @llvm.memcpy +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: ret void + +// A similar test to B, but using overloaded function references. +struct C1 { + int x; + friend C1 operator+(C1, void(&)()); +}; +@interface C +@property void (*c0)(); +@property C1 c1; +@end + +void c_helper(); +void c_helper(int); + +void testC0(C *c) { + c.c0 = c_helper; + c.c0 = &c_helper; +} +// CHECK: define void @_Z6testC0P1C([[C:%.*]]* +// CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 +// CHECK: load [[C]]*, [[C]]** [[CVAR]] +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv +// CHECK-NOT: call +// CHECK: ret void + +void testC1(C *c) { + c.c1 += c_helper; +} +// CHECK: define void @_Z6testC1P1C([[C]]* +// CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 +// CHECK: load [[C]]*, [[C]]** [[CVAR]] +// CHECK-NOT: call +// CHECK: [[T0:%.*]] = call i32 bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: store i32 [[T0]], +// CHECK-NOT: call +// CHECK: [[T0:%.*]] = call i32 @_Zpl2C1RFvvE({{.*}} @_Z8c_helperv +// CHECK-NOT: call +// CHECK: store i32 [[T0]], +// CHECK-NOT: call +// CHECK: call void @llvm.memcpy +// CHECK-NOT: call +// CHECK: call void bitcast {{.*}} @objc_msgSend +// CHECK-NOT: call +// CHECK: ret void diff --git a/test/CodeGenObjCXX/selector-expr-lvalue.mm b/test/CodeGenObjCXX/selector-expr-lvalue.mm index 508ea83f0d51..bd726863110d 100644 --- a/test/CodeGenObjCXX/selector-expr-lvalue.mm +++ b/test/CodeGenObjCXX/selector-expr-lvalue.mm @@ -1,16 +1,23 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o - %s | FileCheck %s // PR7390 -@interface NSObject {} -- (void)respondsToSelector:(const SEL&)s : (SEL*)s1; -- (void) setPriority:(int)p; +// CHECK: @[[setprioname:[^ ]*]] = {{.*}}"setPriority: +// CHECK-NEXT: @[[setpriosel:[^ ]*]] = {{.*}}getelementptr{{.*}}[[setprioname]] +@interface NSObject +- (void)respondsToSelector:(const SEL &)s ps:(SEL *)s1; +- (void)setPriority:(int)p; - (void)Meth; @end -@implementation NSObject +@implementation NSObject + +// CHECK-LABEL: define internal void @"\01-[NSObject Meth]"( - (void)Meth { - [self respondsToSelector:@selector(setPriority:) : &@selector(setPriority:)]; +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8**, i8**)*){{.*}}, i8** @[[setpriosel]]) + [self respondsToSelector:@selector(setPriority:) ps:&@selector(setPriority:)]; +} +- (void)setPriority:(int)p { +} +- (void)respondsToSelector:(const SEL &)s ps:(SEL *)s1 { } -- (void) setPriority:(int)p{} -- (void)respondsToSelector:(const SEL&)s : (SEL*)s1 {} @end |