diff options
Diffstat (limited to 'test/CodeGenObjCXX')
-rw-r--r-- | test/CodeGenObjCXX/address-safety-attr.mm | 17 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-attrs.mm | 48 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-blocks.mm | 49 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-exceptions.mm | 67 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-new-delete.mm | 5 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc.mm | 9 | ||||
-rw-r--r-- | test/CodeGenObjCXX/block-var-layout.mm | 21 | ||||
-rw-r--r-- | test/CodeGenObjCXX/exceptions-legacy.mm | 80 | ||||
-rw-r--r-- | test/CodeGenObjCXX/exceptions.mm | 20 | ||||
-rw-r--r-- | test/CodeGenObjCXX/externally-initialized-selectors.mm | 8 | ||||
-rw-r--r-- | test/CodeGenObjCXX/lambda-expressions.mm | 8 | ||||
-rw-r--r-- | test/CodeGenObjCXX/message.mm | 24 | ||||
-rw-r--r-- | test/CodeGenObjCXX/pr14474-gline-tables-only.mm | 25 | ||||
-rw-r--r-- | test/CodeGenObjCXX/property-object-reference-2.mm | 4 | ||||
-rw-r--r-- | test/CodeGenObjCXX/unknown-anytype.mm | 20 |
15 files changed, 368 insertions, 37 deletions
diff --git a/test/CodeGenObjCXX/address-safety-attr.mm b/test/CodeGenObjCXX/address-safety-attr.mm index a3824b9..1b6f0e8 100644 --- a/test/CodeGenObjCXX/address-safety-attr.mm +++ b/test/CodeGenObjCXX/address-safety-attr.mm @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix ASAN %s +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s +// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix=ASAN %s @interface MyClass + (int) addressSafety:(int*)a; @@ -7,14 +7,15 @@ @implementation MyClass -// CHECK-NOT: +[MyClass load]{{.*}} address_safety -// CHECK: +[MyClass load]{{.*}} -// ASAN: +[MyClass load]{{.*}} address_safety +// WITHOUT: +[MyClass load]{{.*}}#0 +// ASAN: +[MyClass load]{{.*}}#0 +(void) load { } -// CHECK-NOT: +[MyClass addressSafety:]{{.*}} address_safety -// CHECK: +[MyClass addressSafety:]{{.*}} -// ASAN: +[MyClass addressSafety:]{{.*}} address_safety +// WITHOUT: +[MyClass addressSafety:]{{.*}}#0 +// ASAN: +[MyClass addressSafety:]{{.*}}#0 + (int) addressSafety:(int*)a { return *a; } @end + +// ASAN: attributes #0 = {{.*}}sanitize_address +// WITHOUT-NOT: attributes #0 = {{.*}}sanitize_address diff --git a/test/CodeGenObjCXX/arc-attrs.mm b/test/CodeGenObjCXX/arc-attrs.mm new file mode 100644 index 0000000..57ccb6c --- /dev/null +++ b/test/CodeGenObjCXX/arc-attrs.mm @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fobjc-arc -O0 -o - %s | FileCheck %s + +id makeObject1() __attribute__((ns_returns_retained)); +id makeObject2() __attribute__((ns_returns_retained)); +void releaseObject(__attribute__((ns_consumed)) id); + +// CHECK: define void @_Z10sanityTestv +void sanityTest() { + // CHECK: [[X:%.*]] = alloca i8*, align 8 + // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z11makeObject1v() + // CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8 + id x = makeObject1(); + + // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z11makeObject2v() + // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]]) + releaseObject(makeObject2()); + + // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) + // CHECK-NEXT: ret void +} + + +template <typename T> +T makeObjectT1() __attribute__((ns_returns_retained)); +template <typename T> +T makeObjectT2() __attribute__((ns_returns_retained)); + +template <typename T> +void releaseObjectT(__attribute__((ns_consumed)) T); + +// CHECK: define void @_Z12templateTestv +void templateTest() { + // CHECK: [[X:%.*]] = alloca i8*, align 8 + // CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectET_v() + // CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8 + id x = makeObjectT1<id>(); + + // CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectET_v() + // CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]]) + releaseObject(makeObjectT2<id>()); + + // CHECK-NEXT: [[OBJ3:%.*]] = call i8* @_Z11makeObject1v() + // CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvT_(i8* [[OBJ3]]) + releaseObjectT(makeObject1()); + + // CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) + // CHECK-NEXT: ret void +} diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm new file mode 100644 index 0000000..810c0e0 --- /dev/null +++ b/test/CodeGenObjCXX/arc-blocks.mm @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s + +// CHECK: [[A:.*]] = type { i64, [10 x i8*] } + +// CHECK: [[LAYOUT0:@.*]] = internal global [3 x i8] c" 9\00" + +// rdar://13045269 +// If a __block variable requires extended layout information *and* +// a copy/dispose helper, be sure to adjust the offsets used in copy/dispose. +namespace test0 { + struct A { + unsigned long count; + id data[10]; + }; + + void foo() { + __block A v; + } + // CHECK: define void @_ZN5test03fooEv() + // CHECK: [[V:%.*]] = alloca [[BYREF_A:%.*]], align 8 + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]]* [[V]], i32 0, i32 4 + // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* [[COPY_HELPER:@.*]] to i8*), i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]]* [[V]], i32 0, i32 5 + // CHECK-NEXT: store i8* bitcast (void (i8*)* [[DISPOSE_HELPER:@.*]] to i8*), i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]]* [[V]], i32 0, i32 6 + // CHECK-NEXT: store i8* getelementptr inbounds ([3 x i8]* [[LAYOUT0]], i32 0, i32 0), i8** [[T0]] + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]]* [[V]], i32 0, i32 7 + // CHECK-NEXT: call void @_ZN5test01AC1Ev([[A]]* [[T0]]) + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]]* [[V]], i32 0, i32 7 + // CHECK-NEXT: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) + // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T0]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void [[COPY_HELPER]]( + // CHECK: [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]]* [[T0]], i32 0, i32 7 + // CHECK-NEXT: load + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_A]]* [[T2]], i32 0, i32 7 + // CHECK-NEXT: call void @_ZN5test01AC1ERKS0_([[A]]* [[T1]], [[A]]* [[T3]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void [[DISPOSE_HELPER]]( + // CHECK: [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]]* [[T0]], i32 0, i32 7 + // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T1]]) + // CHECK-NEXT: ret void +} diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm index fb5300d..b5ed257 100644 --- a/test/CodeGenObjCXX/arc-exceptions.mm +++ b/test/CodeGenObjCXX/arc-exceptions.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - -fobjc-arc-exceptions %s | FileCheck %s @class Ety; @@ -17,12 +17,12 @@ void test0(void) { // CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW:#[0-9]+]] // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind -// CHECK-NEXT: call void @objc_end_catch() nounwind +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]] +// CHECK-NEXT: call void @objc_end_catch() [[NUW]] void test1_helper(void); void test1(void) { @@ -38,10 +38,10 @@ void test1(void) { // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** // CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind -// CHECK-NEXT: call void @objc_end_catch() nounwind +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]] +// CHECK-NEXT: call void @objc_end_catch() [[NUW]] void test2_helper(void); void test2(void) { @@ -56,12 +56,12 @@ void test2(void) { // CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch( // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) [[NUW]] // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind -// CHECK-NEXT: call void @__cxa_end_catch() nounwind +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) [[NUW]] +// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]] void test3_helper(void); void test3(void) { @@ -77,7 +77,48 @@ void test3(void) { // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* // CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** // CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* -// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) [[NUW]] // CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** -// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind -// CHECK-NEXT: call void @__cxa_end_catch() nounwind +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) [[NUW]] +// CHECK-NEXT: call void @__cxa_end_catch() [[NUW]] + +namespace test4 { + struct A { + id single; + id array[2][3]; + + A(); + }; + + A::A() { + throw 0; + } + // CHECK: define void @_ZN5test41AC2Ev( + // CHECK: [[THIS:%.*]] = load [[A:%.*]]** {{%.*}} + // Construct single. + // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 0 + // CHECK-NEXT: store i8* null, i8** [[SINGLE]], align 8 + // Construct array. + // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1 + // CHECK-NEXT: [[T0:%.*]] = bitcast [2 x [3 x i8*]]* [[ARRAY]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 8, i1 false) + // throw 0; + // CHECK: invoke void @__cxa_throw( + // Landing pad from throw site: + // CHECK: landingpad + // - First, destroy all of array. + // CHECK: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]]* [[ARRAY]], i32 0, i32 0, i32 0 + // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds i8** [[ARRAYBEGIN]], i64 6 + // CHECK-NEXT: br label + // CHECK: [[AFTER:%.*]] = phi i8** [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] + // CHECK-NEXT: [[ELT]] = getelementptr inbounds i8** [[AFTER]], i64 -1 + // CHECK-NEXT: call void @objc_storeStrong(i8** [[ELT]], i8* null) [[NUW]] + // CHECK-NEXT: [[DONE:%.*]] = icmp eq i8** [[ELT]], [[ARRAYBEGIN]] + // CHECK-NEXT: br i1 [[DONE]], + // - Next, destroy single. + // CHECK: call void @objc_storeStrong(i8** [[SINGLE]], i8* null) [[NUW]] + // CHECK: br label + // CHECK: resume +} + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm index ce7eb3d..c061e5d 100644 --- a/test/CodeGenObjCXX/arc-new-delete.mm +++ b/test/CodeGenObjCXX/arc-new-delete.mm @@ -5,8 +5,9 @@ typedef __weak id weak_id; // CHECK: define void @_Z8test_newP11objc_object void test_new(id invalue) { - // CHECK: alloca i8* - // CHECK-NEXT: call i8* @objc_retain + // CHECK: [[INVALUEADDR:%.*]] = alloca i8* + // CHECK-NEXT: store i8* null, i8** [[INVALUEADDR]] + // CHECK-NEXT: call void @objc_storeStrong(i8** [[INVALUEADDR]], i8* [[INVALUE:%.*]]) // CHECK: call noalias i8* @_Znwm // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm index f31b993..1888dbe 100644 --- a/test/CodeGenObjCXX/arc.mm +++ b/test/CodeGenObjCXX/arc.mm @@ -61,6 +61,8 @@ void test34(int cond) { // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* + // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8* + // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1 // CHECK-NEXT: store i32 // CHECK-NEXT: store i8* null, i8** [[STRONG]] // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) @@ -74,11 +76,13 @@ void test34(int cond) { // CHECK: [[T0:%.*]] = load i8** [[ARG]] // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] // CHECK-NEXT: br label + // CHECK: [[W0:%.*]] = phi i8* [ [[T0]], {{%.*}} ], [ undef, {{%.*}} ] // CHECK: call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]]) // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null // CHECK-NEXT: br i1 [[T0]], // CHECK: [[T0:%.*]] = load i8** [[TEMP1]] // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[W0]]) // CHECK-NEXT: [[T2:%.*]] = load i8** [[ARG]] // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] // CHECK-NEXT: call void @objc_release(i8* [[T2]]) @@ -89,8 +93,11 @@ void test34(int cond) { // CHECK: [[ARG:%.*]] = phi i8** // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] + // CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]] // CHECK-NEXT: br i1 [[T0]], - // CHECK: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[ARG]]) + // CHECK: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]]) + // CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]] + // CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]] // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] // CHECK-NEXT: br label // CHECK: call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]]) diff --git a/test/CodeGenObjCXX/block-var-layout.mm b/test/CodeGenObjCXX/block-var-layout.mm index f8b6b9c..08dbc02 100644 --- a/test/CodeGenObjCXX/block-var-layout.mm +++ b/test/CodeGenObjCXX/block-var-layout.mm @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -emit-llvm %s -o %t-64.ll -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.ll %s +// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout +// RUN: FileCheck --input-file=%t-64.layout %s +// rdar://12184410 +// rdar://12752901 // See commentary in test/CodeGenObjC/block-var-layout.m, from which // this is largely cloned. @@ -37,7 +39,7 @@ void f() { // Test 1 // byref int, short, char, char, char, id, id, strong void*, byref id // 01 35 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" +// CHECK: block variable layout for block: 0x01, 0x35, 0x10, 0x00 void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -50,7 +52,7 @@ void f() { // Test 2 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id // 01 36 10 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" +// CHECK: 0x01, 0x36, 0x10, 0x00 void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -65,8 +67,7 @@ void f() { // Test 3 // byref int, short, char, char, char, id, id, byref void*, int, double, byref id // 01 34 11 30 00 -// FIXME: we'd get a better format here if we sorted by scannability, not just alignment -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" +// CHECK: block variable layout for block: 0x01, 0x35, 0x30, 0x00 void (^d)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -81,7 +82,7 @@ void (^d)() = ^{ // Test4 // struct S (int, id, int, id, int, id) // 01 41 11 11 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" +// CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 struct S s2; void (^e)() = ^{ x(s2.o1); @@ -119,7 +120,7 @@ void Test5() { // struct s2 (int, id, int, id, int, id?), union u2 (id?) // 01 41 11 12 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\12\00" +// CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); @@ -137,7 +138,7 @@ void notifyBlock(id dependentBlock) { // id, id, void(^)() // 01 33 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" +// CHECK: block variable layout for block: 0x01, 0x33, 0x00 void (^wrapperBlock)() = ^() { CFRelease(singleObservationToken); CFRelease(singleObservationToken); @@ -150,7 +151,7 @@ void notifyBlock(id dependentBlock) { void test_empty_block() { // 01 00 -// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" +// CHECK: block variable layout for block: 0x01, 0x00 void (^wrapperBlock)() = ^() { }; wrapperBlock(); diff --git a/test/CodeGenObjCXX/exceptions-legacy.mm b/test/CodeGenObjCXX/exceptions-legacy.mm new file mode 100644 index 0000000..a31ba36 --- /dev/null +++ b/test/CodeGenObjCXX/exceptions-legacy.mm @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s + +// Test we maintain at least a basic amount of interoperation between +// ObjC and C++ exceptions in the legacy runtime. + +// rdar://12364847 + +void foo(void); + +void test0(id obj) { + @synchronized(obj) { + foo(); + } +} +// CHECK: define void @_Z5test0P11objc_object( +// Enter the @synchronized block. +// CHECK: call i32 @objc_sync_enter(i8* [[OBJ:%.*]]) +// CHECK: call void @objc_exception_try_enter([[BUF_T:%.*]]* [[BUF:%.*]]) +// CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 +// CHECK-NEXT: br i1 [[T2]], + +// Body. +// CHECK: invoke void @_Z3foov() + +// Leave the @synchronized. The reload of obj here is unnecessary. +// CHECK: call void @objc_exception_try_exit([[BUF_T]]* [[BUF]]) +// CHECK-NEXT: [[T0:%.*]] = load i8** +// CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) +// CHECK-NEXT: ret void + +// Real EH cleanup. +// CHECK: [[T0:%.*]] = landingpad +// CHECK-NEXT: cleanup +// CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* [[BUF]]) +// CHECK-NEXT: [[T0:%.*]] = load i8** +// CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) +// CHECK-NEXT: resume + +// ObjC EH "cleanup". +// CHECK: [[T0:%.*]] = load i8** +// CHECK-NEXT: call i32 @objc_sync_exit(i8* [[T0]]) +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_exception_extract([[BUF_T]]* [[BUF]]) +// CHECK-NEXT: call void @objc_exception_throw(i8* [[T0]]) +// CHECK-NEXT: unreachable + +void test1(id obj, bool *failed) { + @try { + foo(); + } @catch (...) { + *failed = true; + } +} +// CHECK: define void @_Z5test1P11objc_objectPb( +// Enter the @try block. +// CHECK: call void @objc_exception_try_enter([[BUF_T]]* [[BUF:%.*]]) +// CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 +// CHECK-NEXT: br i1 [[T2]], + +// Body. +// CHECK: invoke void @_Z3foov() + +// Leave the @try. +// CHECK: call void @objc_exception_try_exit([[BUF_T]]* [[BUF]]) +// CHECK-NEXT: br label +// CHECK: ret void + +// Real EH cleanup. +// CHECK: [[T0:%.*]] = landingpad +// CHECK-NEXT: cleanup +// CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* [[BUF]]) +// CHECK-NEXT: resume + +// Catch handler. Reload of 'failed' address is unnecessary. +// CHECK: [[T0:%.*]] = load i8** +// CHECK-NEXT: store i8 1, i8* [[T0]], +// CHECK-NEXT: br label diff --git a/test/CodeGenObjCXX/exceptions.mm b/test/CodeGenObjCXX/exceptions.mm index ce6d20a..031c222 100644 --- a/test/CodeGenObjCXX/exceptions.mm +++ b/test/CodeGenObjCXX/exceptions.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -o - %s | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s @interface OCType @end void opaque(); @@ -16,3 +16,21 @@ namespace test0 { } } } + +// rdar://12605907 +@interface NSException + + new; +@end +namespace test1 { + + void bar() { + @try { + throw [NSException new]; + } @catch (id i) { + } + } +// CHECK: invoke void @objc_exception_throw(i8* [[CALL:%.*]]) [[NR:#[0-9]+]] +// CHECK: to label [[INVOKECONT1:%.*]] unwind label [[LPAD:%.*]] +} + +// CHECK: attributes [[NR]] = { noreturn } diff --git a/test/CodeGenObjCXX/externally-initialized-selectors.mm b/test/CodeGenObjCXX/externally-initialized-selectors.mm new file mode 100644 index 0000000..87a7c04 --- /dev/null +++ b/test/CodeGenObjCXX/externally-initialized-selectors.mm @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -cc1 -fobjc-runtime=macosx-fragile-10.5 -o - -emit-llvm %s | FileCheck %s +// RUN: %clang_cc1 -cc1 -o - -emit-llvm %s | FileCheck %s + +// CHECK: @"\01L_OBJC_SELECTOR_REFERENCES_" = internal externally_initialized global + +void test(id x) { + [x doSomething]; +} diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm index ec3eb1f..7c1e2e4 100644 --- a/test/CodeGenObjCXX/lambda-expressions.mm +++ b/test/CodeGenObjCXX/lambda-expressions.mm @@ -25,15 +25,19 @@ typedef int (^fp)(); fp global; void f2() { global = []{ return 3; }; } -// MRC: define void @_Z2f2v() nounwind { +// MRC: define void @_Z2f2v() [[NUW:#[0-9]+]] { // MRC: store i8* bitcast (i32 (i8*)* @___Z2f2v_block_invoke to i8*), // MRC-NOT: call // MRC: ret void // ("global" contains a dangling pointer after this function runs.) -// ARC: define void @_Z2f2v() nounwind { +// ARC: define void @_Z2f2v() [[NUW:#[0-9]+]] { // ARC: store i8* bitcast (i32 (i8*)* @___Z2f2v_block_invoke to i8*), // ARC: call i8* @objc_retainBlock // ARC: call void @objc_release // ARC: define internal i32 @___Z2f2v_block_invoke // ARC: call i32 @"_ZZ2f2vENK3$_1clEv + +// ARC: attributes [[NUW]] = { nounwind{{.*}} } + +// MRC: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGenObjCXX/message.mm b/test/CodeGenObjCXX/message.mm new file mode 100644 index 0000000..1268a79 --- /dev/null +++ b/test/CodeGenObjCXX/message.mm @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.7 -emit-llvm -o - %s | FileCheck %s + +// Properly instantiate a non-dependent message expression which +// requires a contextual conversion to ObjC pointer type. +// <rdar://13305374> +@interface Test0 +- (void) foo; +@end +namespace test0 { + struct A { + operator Test0*(); + }; + template <class T> void foo() { + A a; + [a foo]; + } + template void foo<int>(); + // CHECK: define weak_odr void @_ZN5test03fooIiEEvv() + // CHECK: [[T0:%.*]] = call [[TEST0:%.*]]* @_ZN5test01AcvP5Test0Ev( + // CHECK-NEXT: [[T1:%.*]] = load i8** + // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST0]]* [[T0]] to i8* + // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* [[T2]], i8* [[T1]]) + // CHECK-NEXT: ret void +} diff --git a/test/CodeGenObjCXX/pr14474-gline-tables-only.mm b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm new file mode 100644 index 0000000..e927ab9 --- /dev/null +++ b/test/CodeGenObjCXX/pr14474-gline-tables-only.mm @@ -0,0 +1,25 @@ +// PR 14474 +// RUN: %clang_cc1 -triple i386-apple-macosx10.6.0 -emit-llvm \ +// RUN: -gline-tables-only -x objective-c++ -o /dev/null %s + +typedef signed char BOOL; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@interface NSObject <NSObject> { } +@end +@interface NSResponder : NSObject <NSCoding> { } +@end +@protocol NSValidatedUserInterfaceItem - (SEL)action; +@end +@protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id +<NSValidatedUserInterfaceItem>)anItem; +@end +@interface NSRunningApplication : NSObject { } +@end +@interface NSApplication : NSResponder <NSUserInterfaceValidations> { } +@end +@implementation MockCrApp + (NSApplication*)sharedApplication { } +@end diff --git a/test/CodeGenObjCXX/property-object-reference-2.mm b/test/CodeGenObjCXX/property-object-reference-2.mm index 2a38038..25bfdf8 100644 --- a/test/CodeGenObjCXX/property-object-reference-2.mm +++ b/test/CodeGenObjCXX/property-object-reference-2.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.7 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-1.7 -emit-llvm -o - | FileCheck -check-prefix=CHECK-GNUSTEP %s // rdar://6137845 extern int DEFAULT(); @@ -54,3 +55,6 @@ struct TCPPObject // CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[MYPROPERTY:%.*]] to i8* // CHECK: call void @objc_copyCppObjectAtomic(i8* [[TWO]], i8* [[THREE]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__assign_helper_atomic_property_ to i8*)) // CHECK: ret void + +// CHECK-GNUSTEP: objc_getCppObjectAtomic +// CHECK-GNUSTEP: objc_setCppObjectAtomic diff --git a/test/CodeGenObjCXX/unknown-anytype.mm b/test/CodeGenObjCXX/unknown-anytype.mm new file mode 100644 index 0000000..0e146d4 --- /dev/null +++ b/test/CodeGenObjCXX/unknown-anytype.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-support -funknown-anytype -emit-llvm -o - %s | FileCheck %s + +// rdar://13025708 + +@interface A @end +void test0(A *a) { + (void) [a test0: (float) 2.0]; +} +// CHECK: define void @_Z5test0P1A( +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, float)*)( + +@interface B +- (void) test1: (__unknown_anytype) x; +@end +void test1(B *b) { + (void) [b test1: (float) 2.0]; +} +// CHECK: define void @_Z5test1P1B( +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, float)*)( + |