diff options
Diffstat (limited to 'test/CodeGenObjC')
35 files changed, 737 insertions, 119 deletions
diff --git a/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m b/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m new file mode 100644 index 0000000..2515c70 --- /dev/null +++ b/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ARM %s +// rdar://7761305 + +@interface I +@property long long LONG_PROP; +@end + +@implementation I +@synthesize LONG_PROP; +@end +// CHECK-ARM: call arm_aapcscc void @objc_copyStruct(i8* %{{.*}}, i8* %{{.*}}, i32 8, i1 zeroext true, i1 zeroext false) +// CHECK-ARM: call arm_aapcscc void @objc_copyStruct(i8* %{{.*}}, i8* %{{.*}}, i32 8, i1 zeroext true, i1 zeroext false) + diff --git a/test/CodeGenObjC/bitfield-gnu.m b/test/CodeGenObjC/bitfield-gnu.m new file mode 100644 index 0000000..7935bda --- /dev/null +++ b/test/CodeGenObjC/bitfield-gnu.m @@ -0,0 +1,5 @@ +// RUN: %clang -S -emit-llvm -fgnu-runtime -o %t %s +typedef enum { A1, A2 } A; +typedef struct { A a : 1; } B; +@interface Obj { B *b; } @end +@implementation Obj @end diff --git a/test/CodeGenObjC/block-6.m b/test/CodeGenObjC/block-6.m new file mode 100644 index 0000000..3720a87 --- /dev/null +++ b/test/CodeGenObjC/block-6.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 | FileCheck %s +// rdar://8893785 + +void MYFUNC() { +// CHECK: [[T1:%.*]] = bitcast i8* ()* +// CHECK-NEXT: [[FORWARDING:%.*]] = getelementptr inbounds [[N_T:%.*]]* [[N:%.*]], i32 0, i32 1 +// CHECK-NEXT: [[T0:%.*]] = load [[N_T]]** [[FORWARDING]] +// CHECK-NEXT: [[OBSERVER:%.*]] = getelementptr inbounds [[N_T]]* [[T0]], i32 0, i32 6 +// CHECK-NEXT: store i8* [[T1]], i8** [[OBSERVER]] + __block id observer = ^{ return observer; }; +} + diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m index bf9ba8d..466dee1 100644 --- a/test/CodeGenObjC/block-var-layout.m +++ b/test/CodeGenObjC/block-var-layout.m @@ -1,6 +1,4 @@ -// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s // RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s struct S { @@ -18,19 +16,38 @@ __weak id wid; void x(id y) {} void y(int a) {} +extern id opaque_id(); + void f() { __block int byref_int = 0; char ch = 'a'; char ch1 = 'b'; char ch2 = 'c'; short sh = 2; - const id bar = (id)0; + const id bar = (id) opaque_id(); id baz = 0; __strong void *strong_void_sta; __block id byref_bab = (id)0; __block void *bl_var1; int i; double dob; +// The patterns here are a sequence of bytes, each saying first how +// many sizeof(void*) chunks to skip (high nibble) and then how many +// to scan (low nibble). A zero byte says that we've reached the end +// of the pattern. +// +// All of these patterns start with 01 3x because the block header on +// LP64 consists of an isa pointer (which we're supposed to scan for +// some reason) followed by three words (2 ints, a function pointer, +// and a descriptor pointer). + +// FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx? +// FIXME: sequences should never end in x0 00 instead of just 00 + +// 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" void (^b)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -41,6 +58,9 @@ void f() { b(); // 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" void (^c)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); @@ -53,7 +73,11 @@ void f() { c(); // Test 3 -void (^d)() = ^{ +// 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" + void (^d)() = ^{ byref_int = sh + ch+ch1+ch2 ; x(bar); x(baz); @@ -64,7 +88,10 @@ void (^d)() = ^{ }; d(); -// Test4 +// Test 4 +// struct S (int, id, int, id, int, id) +// 01 41 11 11 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" struct S s2; void (^e)() = ^{ x(s2.o1); @@ -74,7 +101,7 @@ void (^d)() = ^{ // Test 5 (unions/structs and their nesting): void Test5() { -struct S5 { + struct S5 { int i1; id o1; struct V { @@ -88,36 +115,52 @@ struct S5 { int i3; id o3; }ui; -}; + }; -union U { + union U { void * i1; id o1; int i3; id o3; -}ui; + }ui; -struct S5 s2; -union U u2; -void (^c)() = ^{ + struct S5 s2; + union U u2; + +// struct s2 (int, id, int, id, int, id?), union u2 (id?) +// 01 41 11 12 70 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [6 x i8] c"\01A\11\12p\00" + void (^c)() = ^{ x(s2.ui.o1); x(u2.o1); -}; -c(); - + }; + c(); } -// CHECK-LP64: L_OBJC_CLASS_NAME_: -// CHECK-LP64-NEXT: .asciz "A\024" - -// CHECK-LP64: L_OBJC_CLASS_NAME_1: -// CHECK-LP64-NEXT: .asciz "A\025" - -// CHECK-LP64: L_OBJC_CLASS_NAME_6: -// CHECK-LP64-NEXT: .asciz "A\023!" - -// CHECK-LP64: L_OBJC_CLASS_NAME_11: -// CHECK-LP64-NEXT: .asciz "Q\021\021" +// rdar: //8417746 +void CFRelease(id); +void notifyBlock(id dependentBlock) { + id singleObservationToken; + id token; + void (^b)(); + +// id, id, void(^)() +// 01 33 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" + void (^wrapperBlock)() = ^() { + CFRelease(singleObservationToken); + CFRelease(singleObservationToken); + CFRelease(token); + CFRelease(singleObservationToken); + b(); + }; + wrapperBlock(); +} -// CHECK-LP64: L_OBJC_CLASS_NAME_14: -// CHECK-LP64-NEXT: .asciz "Q\021\022p" +void test_empty_block() { +// 01 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" + void (^wrapperBlock)() = ^() { + }; + wrapperBlock(); +} diff --git a/test/CodeGenObjC/blocks-1.m b/test/CodeGenObjC/blocks-1.m index 1ac9c30..55ce38f 100644 --- a/test/CodeGenObjC/blocks-1.m +++ b/test/CodeGenObjC/blocks-1.m @@ -2,8 +2,8 @@ // RUN: grep "_Block_object_dispose" %t | count 6 // RUN: grep "__copy_helper_block_" %t | count 4 // RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 +// RUN: grep "__Block_byref_object_copy_" %t | count 2 +// RUN: grep "__Block_byref_object_dispose_" %t | count 2 // RUN: grep "i32 135)" %t | count 0 // RUN: grep "_Block_object_assign" %t | count 4 // RUN: grep "objc_read_weak" %t | count 2 @@ -12,8 +12,8 @@ // RUN: grep "_Block_object_dispose" %t | count 6 // RUN: grep "__copy_helper_block_" %t | count 4 // RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 +// RUN: grep "__Block_byref_object_copy_" %t | count 2 +// RUN: grep "__Block_byref_object_dispose_" %t | count 2 // RUN: grep "i32 135)" %t | count 0 // RUN: grep "_Block_object_assign" %t | count 4 // RUN: grep "objc_read_weak" %t | count 2 diff --git a/test/CodeGenObjC/blocks-2.m b/test/CodeGenObjC/blocks-2.m index 0062e84..38b8635 100644 --- a/test/CodeGenObjC/blocks-2.m +++ b/test/CodeGenObjC/blocks-2.m @@ -1,12 +1,37 @@ -// RUN: %clang_cc1 %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -// RUN: grep "objc_assign_strongCast" %t | count 2 -// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -// RUN: grep "objc_assign_strongCast" %t | count 2 +// We run this twice, once as Objective-C and once as Objective-C++. +// RUN: %clang_cc1 %s -emit-llvm -o - -fobjc-gc -fblocks -fexceptions -triple i386-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -fobjc-gc -fblocks -fexceptions -triple i386-apple-darwin10 -x objective-c++ | FileCheck %s -// This should generate a strong cast. -id test3(id x) { +// CHECK: define i8* @{{.*}}test0 +// CHECK: define internal void @__test0_block_invoke_0( +// CHECK: call i8* @objc_assign_strongCast( +// CHECK-NEXT: ret void +id test0(id x) { __block id result; ^{ result = x; }(); return result; } + +// <rdar://problem/8224178>: cleanup __block variables on EH path +// CHECK: define void @{{.*}}test1 +void test1() { + extern void test1_help(void (^x)(void)); + + // CHECK: [[N:%.*]] = alloca [[N_T:%.*]], align 8 + // CHECK: [[T0:%.*]] = getelementptr inbounds [[N_T]]* [[N]], i32 0, i32 4 + // CHECK-NEXT: store double 1.000000e+{{0?}}01, double* [[T0]], align 8 + __block double n = 10; + + // CHECK: invoke void @{{.*}}test1_help + test1_help(^{ n = 20; }); + + // CHECK: [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) + // CHECK-NEXT: ret void + + // CHECK: call i8* @llvm.eh.exception() + // CHECK: [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) + // CHECK: call void @_Unwind_Resume_or_Rethrow( +} diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m index b96a8d9..11fb55b 100644 --- a/test/CodeGenObjC/blocks.m +++ b/test/CodeGenObjC/blocks.m @@ -1,13 +1,12 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s -// rdar://6676764 +// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -fblocks -o - %s | FileCheck %s +// test1. All of this is somehow testing rdar://6676764 struct S { void (^F)(struct S*); } P; @interface T - - (int)foo: (T (^)(T*)) x; @end @@ -19,7 +18,7 @@ void foo(T *P) { -(void) im0; @end -// RUN: grep 'define internal i32 @"__8-\[A im0\]_block_invoke_0"' %t +// CHECK: define internal i32 @"__8-[A im0]_block_invoke_0"( @implementation A -(void) im0 { (void) ^{ return 1; }(); @@ -39,3 +38,52 @@ void foo(T *P) { } @end +// rdar://problem/9006315 +// In-depth test for the initialization of a __weak __block variable. +@interface Test2 -(void) destroy; @end +void test2(Test2 *x) { + extern void test2_helper(void (^)(void)); + // CHECK: define void @test2( + // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]*, + // CHECK-NEXT: [[WEAKX:%.*]] = alloca [[WEAK_T:%.*]], + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:%.*]], + // CHECK-NEXT: store [[TEST2]]* + + // isa=1 for weak byrefs. + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 0 + // CHECK-NEXT: store i8* inttoptr (i32 1 to i8*), i8** [[T0]] + + // Forwarding. + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 1 + // CHECK-NEXT: store [[WEAK_T]]* [[WEAKX]], [[WEAK_T]]** [[T1]] + + // Flags. This is just BLOCK_HAS_COPY_DISPOSE. + // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 2 + // CHECK-NEXT: store i32 33554432, i32* [[T2]] + + // Size. + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 3 + // CHECK-NEXT: store i32 28, i32* [[T3]] + + // Copy and dipose helpers. + // CHECK-NEXT: [[T4:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 4 + // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_{{.*}} to i8*), i8** [[T4]] + // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 5 + // CHECK-NEXT: store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_{{.*}} to i8*), i8** [[T5]] + + // Actually capture the value. + // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]] + // CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 6 + // CHECK-NEXT: store [[TEST2]]* [[CAPTURE]], [[TEST2]]** [[T6]] + + // Then we initialize the block, blah blah blah. + // CHECK: call void @test2_helper( + + // Finally, kill the variable with BLOCK_FIELD_IS_BYREF. We're not + // supposed to pass BLOCK_FIELD_IS_WEAK here. + // CHECK: [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8* + // CHECK: call void @_Block_object_dispose(i8* [[T0]], i32 8) + + __weak __block Test2 *weakX = x; + test2_helper(^{ [weakX destroy]; }); +} diff --git a/test/CodeGenObjC/constant-string-class.m b/test/CodeGenObjC/constant-string-class.m new file mode 100644 index 0000000..12253d6 --- /dev/null +++ b/test/CodeGenObjC/constant-string-class.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fno-constant-cfstrings -fconstant-string-class Foo -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-FRAGILE < %t %s + +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fno-constant-cfstrings -fconstant-string-class Foo -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-NONFRAGILE < %t %s + +// rdar: // 8564463 +// PR6056 + +@interface Object { + id isa; +} +@end + +@interface Foo : Object{ + char *cString; + unsigned int len; +} +- (char *)customString; +@end + +id _FooClassReference[20]; + +@implementation Foo +- (char *)customString { return cString ; } +@end + +int main () { + Foo *string = @"bla"; + return 0; +} + +// CHECK-FRAGILE: @_FooClassReference = common global +// CHECK-NONFRAGILE: @"OBJC_CLASS_$_Object" = external global +// CHECK-NONFRAGILE: "OBJC_CLASS_$_Foo" = unnamed_addr global diff --git a/test/CodeGenObjC/debug-info-default-synth-ivar.m b/test/CodeGenObjC/debug-info-default-synth-ivar.m new file mode 100644 index 0000000..967a361 --- /dev/null +++ b/test/CodeGenObjC/debug-info-default-synth-ivar.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-default-synthesize-properties -emit-llvm -g %s -o %t +// RUN: grep DW_TAG_member %t | count 5 +// rdar://8493239 + +@class NSString; + +@interface InstanceVariablesEverywhereButTheInterface +@end + +@interface InstanceVariablesEverywhereButTheInterface() +{ + NSString *_someString; +} + +@property(readonly) NSString *someString; +@property(readonly) unsigned long someNumber; +@end + +@implementation InstanceVariablesEverywhereButTheInterface +{ + unsigned long _someNumber; +} +@synthesize someString = _someString, someNumber = _someNumber; +@end + +@interface AutomaticSynthesis +{ + int real_ivar; +} +@property(copy) NSString *someString; +@property unsigned long someNumber; +@end + +@implementation AutomaticSynthesis +@end diff --git a/test/CodeGenObjC/debug-info-fnname.m b/test/CodeGenObjC/debug-info-fnname.m new file mode 100644 index 0000000..f336d6b --- /dev/null +++ b/test/CodeGenObjC/debug-info-fnname.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -Os -g %s -o - | FileCheck %s +// Radar 8653152 +@interface A { +} +@end + + +// CHECK: llvm.dbg.lv.-.A.title. +@implementation A +-(int) title { + int x = 1; + return x; +} +@end + diff --git a/test/CodeGenObjC/debug-info-foreach.m b/test/CodeGenObjC/debug-info-foreach.m new file mode 100644 index 0000000..c056e0e --- /dev/null +++ b/test/CodeGenObjC/debug-info-foreach.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-default-synthesize-properties -emit-llvm -g %s -o %t +// RUN: grep DW_TAG_lexical_block %t | count 5 +// rdar://8757124 + +@class NSArray; + +void f(NSArray *a) { + id keys; + for (id thisKey in keys) { + } + for (id thisKey in keys) { + } +} diff --git a/test/CodeGenObjC/debug-info-getter-name.m b/test/CodeGenObjC/debug-info-getter-name.m new file mode 100644 index 0000000..0263f11 --- /dev/null +++ b/test/CodeGenObjC/debug-info-getter-name.m @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -S -g %s -o %t +// RUN: grep "\[InstanceVariablesEverywhereButTheInterface someString\]" %t | count 6 + +//rdar: //8498026 + +@class NSString; + +@interface InstanceVariablesEverywhereButTheInterface +@end + +@interface InstanceVariablesEverywhereButTheInterface() +{ + NSString *_someString; +} + +@property(readonly) NSString *someString; +@property(readonly) unsigned long someNumber; +@end + +@implementation InstanceVariablesEverywhereButTheInterface +{ + unsigned long _someNumber; +} + +@synthesize someString = _someString, someNumber = _someNumber; + +- init { + return self; +} +@end + +@interface AutomaticSynthesis +{ + int real_ivar; +} +@property(copy) NSString *someString; +@property unsigned long someNumber; +@end + +@implementation AutomaticSynthesis +- init +{ + return self; +} +@end + +int main() +{ + return 0; +} diff --git a/test/CodeGenObjC/debug-info-selector.m b/test/CodeGenObjC/debug-info-selector.m new file mode 100644 index 0000000..67642ac --- /dev/null +++ b/test/CodeGenObjC/debug-info-selector.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// Radar 8494540 + +// CHECK: objc_selector +@interface MyClass { +} +- (id)init; +@end + +@implementation MyClass +- (id) init +{ + return self; +} +@end diff --git a/test/CodeGenObjC/debug-info-self.m b/test/CodeGenObjC/debug-info-self.m new file mode 100644 index 0000000..9146ab3 --- /dev/null +++ b/test/CodeGenObjC/debug-info-self.m @@ -0,0 +1,16 @@ +// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_AT_artificial | count 3 +// self and _cmd are marked as DW_AT_artificial. +// abbrev code emits another DT_artificial comment. +// myarg is not marked as DW_AT_artificial. + +@interface MyClass { +} +- (id)init:(int) myarg; +@end + +@implementation MyClass +- (id) init:(int) myarg +{ + return self; +} +@end diff --git a/test/CodeGenObjC/debug-info-static-var.m b/test/CodeGenObjC/debug-info-static-var.m new file mode 100644 index 0000000..3bcf5fd --- /dev/null +++ b/test/CodeGenObjC/debug-info-static-var.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -g -triple x86_64-apple-darwin10 -S -masm-verbose -o - %s | FileCheck %s +// Radar 8801045 +// Do not emit AT_MIPS_linkage_name for static variable i + +// CHECK: DW_TAG_variable +// CHECK-NEXT: .byte 105 ## DW_AT_name +// CHECK-NEXT: .byte 0 +// CHECK-NEXT: DW_AT_type +// CHECK-NEXT: DW_AT_decl_file +// CHECK-NEXT: DW_AT_decl_line +// CHECK-NEXT: DW_AT_location + +@interface A { +} +-(void) foo; +@end + +@implementation A +-(void)foo { + static int i = 1; +} +@end + diff --git a/test/CodeGenObjC/default-property-synthesis.m b/test/CodeGenObjC/default-property-synthesis.m index b3eeb22..72acb76 100644 --- a/test/CodeGenObjC/default-property-synthesis.m +++ b/test/CodeGenObjC/default-property-synthesis.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s // rdar://7923851. // Superclass declares property. Subclass redeclares the same property. diff --git a/test/CodeGenObjC/encode-test-1.m b/test/CodeGenObjC/encode-test-1.m deleted file mode 100644 index af7ad26..0000000 --- a/test/CodeGenObjC/encode-test-1.m +++ /dev/null @@ -1,36 +0,0 @@ -// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s -// RUN: grep -e "{Base=b2b3b4b5}" %t | count 1 -// RUN: grep -e "{Derived=b2b3b4b5b5b4b3}" %t | count 1 - -enum Enum { one, two, three, four }; - -@interface Base { - unsigned a: 2; - int b: 3; - enum Enum c: 4; - unsigned d: 5; -} -@end - -@interface Derived: Base { - signed e: 5; - int f: 4; - enum Enum g: 3; -} -@end - -@implementation Base @end - -@implementation Derived @end - -int main(void) -{ - - const char *en = @encode(Base); -// printf ("%s\n", en); - - const char *ed = @encode(Derived); - // printf ("%s\n", ed); - - return 0; -} diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m index 9d1cf6c..24a90a0 100644 --- a/test/CodeGenObjC/encode-test.m +++ b/test/CodeGenObjC/encode-test.m @@ -1,10 +1,7 @@ // RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s -// RUN: grep -e "\^{Innermost=CC}" %t | count 1 -// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1 -// RUN: grep -e "{B1=#@c}" %t | count 1 -// RUN: grep -e "v12@0:4\[3\[4@]]8" %t | count 1 -// RUN: grep -e "r\^{S=i}" %t | count 1 -// RUN: grep -e "\^{Object=#}" %t | count 1 +// RUN: FileCheck < %t %s +// +// CHECK: @"\01L_OBJC_METH_VAR_TYPE_34" = internal global [16 x i8] c"v12@0:4[3[4@]]8\00" @class Int1; @@ -95,3 +92,55 @@ int main() const char *ee = @encode(MyObj *const); } +// CHECK: @g0 = constant [15 x i8] c"{Innermost=CC}\00" +const char g0[] = @encode(struct Innermost); + +// CHECK: @g1 = constant [38 x i8] c"{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}\00" +const char g1[] = @encode(Derived); + +// CHECK: @g2 = constant [9 x i8] c"{B1=#@c}\00" +const char g2[] = @encode(B1); + +// CHECK: @g3 = constant [8 x i8] c"r^{S=i}\00" +const char g3[] = @encode(const struct S *); + +// CHECK: @g4 = constant [6 x i8] c"{S=i}\00" +const char g4[] = @encode(const struct S); + +// CHECK: @g5 = constant [12 x i8] c"^{Object=#}\00" +const char g5[] = @encode(MyObj * const); + +//// + +enum Enum1X { one, two, three, four }; + +@interface Base1X { + unsigned a: 2; + int b: 3; + enum Enum1X c: 4; + unsigned d: 5; +} +@end + +@interface Derived1X: Base1X { + signed e: 5; + int f: 4; + enum Enum1X g: 3; +} +@end + +@implementation Base1X @end + +@implementation Derived1X @end + +// CHECK: @g6 = constant [18 x i8] c"{Base1X=b2b3b4b5}\00" +const char g6[] = @encode(Base1X); + +// CHECK: @g7 = constant [27 x i8] c"{Derived1X=b2b3b4b5b5b4b3}\00" +const char g7[] = @encode(Derived1X); + +// CHECK: @g8 = constant [7 x i8] c"{s8=D}\00" +struct s8 { + long double x; +}; +const char g8[] = @encode(struct s8); diff --git a/test/CodeGenObjC/exceptions-nonfragile.m b/test/CodeGenObjC/exceptions-nonfragile.m new file mode 100644 index 0000000..57ed1d9 --- /dev/null +++ b/test/CodeGenObjC/exceptions-nonfragile.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fexceptions -O2 -o - %s | FileCheck %s + +// rdar://problem/8535238 +// CHECK: declare void @objc_exception_rethrow() + +void protos() { + extern void foo(); + @try { + foo(); + } @catch (id e) { + @throw; + } +} + +void throwing() { + @throw(@"error!"); +} diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m index b431e37..31805cb 100644 --- a/test/CodeGenObjC/exceptions.m +++ b/test/CodeGenObjC/exceptions.m @@ -29,10 +29,8 @@ void f1() { // CHECK-NEXT: call void @foo() foo(); // CHECK-NEXT: call void @objc_exception_try_exit - // CHECK-NEXT: ret void // CHECK: call void asm sideeffect "", "=*m" - // CHECK-NEXT: ret void } @finally { break; } @@ -65,7 +63,6 @@ int f2() { // CHECK-NEXT: call void @foo() // CHECK-NEXT: call void @objc_exception_try_exit // CHECK-NEXT: [[T:%.*]] = load i32* [[X]] - // CHECK-NEXT: ret i32 [[T]] foo(); } @catch (id) { // Landing pad. Note that we elide the re-enter. @@ -76,10 +73,9 @@ int f2() { // This store is dead. // CHECK-NEXT: store i32 [[T2]], i32* [[X]] - - // CHECK-NEXT: ret i32 [[T2]] x--; } + return x; } @@ -133,3 +129,59 @@ void f3() { // CHECK-NEXT: ret void f3_helper(4, &x); } + +// rdar://problem/8440970 +void f4() { + extern void f4_help(int); + + // CHECK: define void @f4() + // CHECK: [[EXNDATA:%.*]] = alloca [[EXNDATA_T:%.*]], align + // CHECK: call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]]) + // CHECK: call i32 @_setjmp + @try { + // CHECK: call void @f4_help(i32 0) + f4_help(0); + + // The finally cleanup has two threaded entrypoints after optimization: + + // finally.no-call-exit: Predecessor is when the catch throws. + // CHECK: call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]]) + // CHECK-NEXT: call void @f4_help(i32 2) + // CHECK-NEXT: br label + // -> rethrow + + // finally.call-exit: Predecessors are the @try and @catch fallthroughs + // as well as the no-match case in the catch mechanism. The i1 is whether + // to rethrow and should be true only in the last case. + // CHECK: phi i1 + // CHECK-NEXT: phi i8* + // CHECK-NEXT: call void @objc_exception_try_exit([[EXNDATA_T]]* [[EXNDATA]]) + // CHECK-NEXT: call void @f4_help(i32 2) + // CHECK-NEXT: br i1 + // -> ret, rethrow + + // ret: + // CHECK: ret void + + // Catch mechanism: + // CHECK: call i8* @objc_exception_extract([[EXNDATA_T]]* [[EXNDATA]]) + // CHECK-NEXT: call void @objc_exception_try_enter([[EXNDATA_T]]* [[EXNDATA]]) + // CHECK: call i32 @_setjmp + // -> next, finally.no-call-exit + // CHECK: call i32 @objc_exception_match + // -> finally.call-exit, match + } @catch (NSArray *a) { + // match: + // CHECK: call void @f4_help(i32 1) + // CHECK-NEXT: br label + // -> finally.call-exit + f4_help(1); + } @finally { + f4_help(2); + } + + // rethrow: + // CHECK: phi i8* + // CHECK-NEXT: call void @objc_exception_throw(i8* + // CHECK-NEXT: unreachable +} diff --git a/test/CodeGenObjC/implicit-objc_msgSend.m b/test/CodeGenObjC/implicit-objc_msgSend.m index a21e869..322f82e 100644 --- a/test/CodeGenObjC/implicit-objc_msgSend.m +++ b/test/CodeGenObjC/implicit-objc_msgSend.m @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o %t %s -// RUN: grep -F 'declare i8* @objc_msgSend(...)' %t +// RUN: grep -F 'declare i8* @objc_msgSend(i8*, i8*, ...)' %t typedef struct objc_selector *SEL; id f0(id x, SEL s) { diff --git a/test/CodeGenObjC/interface-layout-64.m b/test/CodeGenObjC/interface-layout-64.m index 2800b41..af898bb 100644 --- a/test/CodeGenObjC/interface-layout-64.m +++ b/test/CodeGenObjC/interface-layout-64.m @@ -5,8 +5,8 @@ // RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_const", align 8' %t // RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_const", align 8' %t // RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_const", align 8' %t -// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 16, section "__DATA, __objc_const", align 8' %t -// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 20, section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = hidden global i64 16, section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = hidden global i64 20, section "__DATA, __objc_const", align 8' %t // RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t // RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_const", align 8' %t // RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t diff --git a/test/CodeGenObjC/ivar-layout-64-bitfields.m b/test/CodeGenObjC/ivar-layout-64-bitfields.m index 9710e16..700ce18 100644 --- a/test/CodeGenObjC/ivar-layout-64-bitfields.m +++ b/test/CodeGenObjC/ivar-layout-64-bitfields.m @@ -1,5 +1,10 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s + +#ifdef __cplusplus +typedef bool _Bool; +#endif + @interface I { struct { diff --git a/test/CodeGenObjC/ivar-layout-array0-struct.m b/test/CodeGenObjC/ivar-layout-array0-struct.m new file mode 100644 index 0000000..4300db3 --- /dev/null +++ b/test/CodeGenObjC/ivar-layout-array0-struct.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s + +// rdar://8800513 +@interface NSObject { + id isa; +} +@end + +typedef struct { + id b; +} st; + +@interface Test : NSObject { + int a; + st b[0]; +} +@end + +@implementation Test @end +// CHECK-LP64: L_OBJC_CLASS_NAME_4: +// CHECK-LP64-NEXT: .asciz "\001\020" diff --git a/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m index b474caa..012ccad 100644 --- a/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m +++ b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s -// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s // rdar: // 7824380 @interface Super { diff --git a/test/CodeGenObjC/ivars.m b/test/CodeGenObjC/ivars.m index fe178ab..98c39b7 100644 --- a/test/CodeGenObjC/ivars.m +++ b/test/CodeGenObjC/ivars.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s // RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o - %s +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -o - %s // rdar://6800926 @interface ITF { @@ -12,3 +13,17 @@ void foo(ITF *P) { P->boolfield = 1; } + +// rdar://8368320 +@interface R { + struct { + union { + int x; + char c; + }; + } _union; +} +@end + +@implementation R +@end diff --git a/test/CodeGenObjC/local-static-block.m b/test/CodeGenObjC/local-static-block.m new file mode 100644 index 0000000..a40abb2 --- /dev/null +++ b/test/CodeGenObjC/local-static-block.m @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -emit-llvm %s -o %t-64.ll +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.ll %s +// rdar: // 8390455 + +@class NSArray; + +static NSArray *(^ArrayRecurs)(NSArray *addresses, unsigned long level) = ^(NSArray *addresses, unsigned long level) { + + for(id rawAddress in addresses) + { + NSArray *separatedAddresses = ((NSArray*)0); + separatedAddresses = ArrayRecurs((NSArray *)rawAddress, level+1); + } + return (NSArray *)0; +}; + +void FUNC() +{ + static NSArray *(^ArrayRecurs)(NSArray *addresses, unsigned long level) = ^(NSArray *addresses, unsigned long level) { + + for(id rawAddress in addresses) + { + NSArray *separatedAddresses = ((NSArray*)0); + separatedAddresses = ArrayRecurs((NSArray *)rawAddress, level+1); + } + return (NSArray *)0; + }; + + if (ArrayRecurs) { + static NSArray *(^ArrayRecurs)(NSArray *addresses, unsigned long level) = ^(NSArray *addresses, unsigned long level) { + + for(id rawAddress in addresses) + { + NSArray *separatedAddresses = ((NSArray*)0); + separatedAddresses = ArrayRecurs((NSArray *)rawAddress, level+1); + } + return (NSArray *)0; + }; + } +} + +void FUNC1() +{ + static NSArray *(^ArrayRecurs)(NSArray *addresses, unsigned long level) = ^(NSArray *addresses, unsigned long level) { + + for(id rawAddress in addresses) + { + NSArray *separatedAddresses = ((NSArray*)0); + separatedAddresses = ArrayRecurs((NSArray *)rawAddress, level+1); + } + return (NSArray *)0; + }; +} +// CHECK-LP64: @ArrayRecurs = internal global +// CHECK-LP64: @FUNC.ArrayRecurs = internal global +// CHECK-LP64: @FUNC.ArrayRecurs3 = internal global +// CHECK-LP64: @FUNC1.ArrayRecurs = internal global diff --git a/test/CodeGenObjC/ns-constant-strings.m b/test/CodeGenObjC/ns-constant-strings.m index 3ef5f55..389132b 100644 --- a/test/CodeGenObjC/ns-constant-strings.m +++ b/test/CodeGenObjC/ns-constant-strings.m @@ -31,3 +31,9 @@ int main() { // CHECK-FRAGILE: @_NSConstantStringClassReference = external global // CHECK-NONFRAGILE: @"OBJC_CLASS_$_NSConstantString" = external global + +// CHECK-FRAGILE: @.str = private unnamed_addr constant [6 x i8] c"MyApp\00" +// CHECK-FRAGILE: @.str1 = private unnamed_addr constant [7 x i8] c"MyApp1\00" + +// CHECK-NONFRAGILE: @.str = private unnamed_addr constant [6 x i8] c"MyApp\00" +// CHECK-NONFRAGILE: @.str1 = private unnamed_addr constant [7 x i8] c"MyApp1\00" diff --git a/test/CodeGenObjC/objc-read-weak-byref.m b/test/CodeGenObjC/objc-read-weak-byref.m index 1ddbcaf..fa7a6f9 100644 --- a/test/CodeGenObjC/objc-read-weak-byref.m +++ b/test/CodeGenObjC/objc-read-weak-byref.m @@ -21,5 +21,5 @@ int main() { // CHECK-LP64: callq _objc_read_weak // CHECK-LP64: callq _objc_read_weak -// CHECK-LP32: call L_objc_read_weak -// CHECK-LP32: call L_objc_read_weak +// CHECK-LP32: calll L_objc_read_weak +// CHECK-LP32: calll L_objc_read_weak diff --git a/test/CodeGenObjC/objc2-nonfragile-abi-impl.m b/test/CodeGenObjC/objc2-nonfragile-abi-impl.m index ff94330..cb830b8 100644 --- a/test/CodeGenObjC/objc2-nonfragile-abi-impl.m +++ b/test/CodeGenObjC/objc2-nonfragile-abi-impl.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s // rdar://7547942. @interface Base @end diff --git a/test/CodeGenObjC/objc2-weak-block-call.m b/test/CodeGenObjC/objc2-weak-block-call.m index a3514b0..8cd233e 100644 --- a/test/CodeGenObjC/objc2-weak-block-call.m +++ b/test/CodeGenObjC/objc2-weak-block-call.m @@ -1,7 +1,5 @@ -// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s -// RUN: %clang_cc1 -fblocks -fobjc-gc -triple i386-apple-darwin -S %s -o %t-32.s -// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck -check-prefix LP64 %s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple i386-apple-darwin -emit-llvm %s -o - | FileCheck -check-prefix LP64 %s @interface MyView - (void)MyView_sharedInit; @@ -21,9 +19,6 @@ void foo(MyView *(^obj)(void)) ; } @end -// CHECK-LP64: callq _objc_read_weak -// CHECK-LP64: callq _objc_read_weak - -// CHECK-LP32: call L_objc_read_weak -// CHECK-LP32: call L_objc_read_weak +// CHECK-LP64: call i8* @objc_read_weak +// CHECK-LP32: call i8* @objc_read_weak diff --git a/test/CodeGenObjC/predefined-expr.m b/test/CodeGenObjC/predefined-expr.m index 772093b..43d329e 100644 --- a/test/CodeGenObjC/predefined-expr.m +++ b/test/CodeGenObjC/predefined-expr.m @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -// CHECK: @"__func__.-[Foo instanceTest1]" = private constant [21 x i8] c"-[Foo instanceTest1]\00" -// CHECK: @"__func__.-[Foo instanceTest2:]" = private constant [22 x i8] c"-[Foo instanceTest2:]\00" -// CHECK: @"__func__.-[Foo instanceTest3:withB:]" = private constant [28 x i8] c"-[Foo instanceTest3:withB:]\00" -// CHECK: @"__func__.-[Foo instanceTest4]" = private constant [21 x i8] c"-[Foo instanceTest4]\00" -// CHECK: @"__func__.+[Foo classTest1]" = private constant [18 x i8] c"+[Foo classTest1]\00" -// CHECK: @"__func__.+[Foo classTest2:]" = private constant [19 x i8] c"+[Foo classTest2:]\00" -// CHECK: @"__func__.+[Foo classTest3:withB:]" = private constant [25 x i8] c"+[Foo classTest3:withB:]\00" -// CHECK: @"__func__.+[Foo classTest4]" = private constant [18 x i8] c"+[Foo classTest4]\00" -// CHECK: @"__func__.-[Foo(Category) instanceTestWithCategory]" = private constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00" -// CHECK: @"__func__.+[Foo(Category) classTestWithCategory]" = private constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00" +// CHECK: @"__func__.-[Foo instanceTest1]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest1]\00" +// CHECK: @"__func__.-[Foo instanceTest2:]" = private unnamed_addr constant [22 x i8] c"-[Foo instanceTest2:]\00" +// CHECK: @"__func__.-[Foo instanceTest3:withB:]" = private unnamed_addr constant [28 x i8] c"-[Foo instanceTest3:withB:]\00" +// CHECK: @"__func__.-[Foo instanceTest4]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest4]\00" +// CHECK: @"__func__.+[Foo classTest1]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest1]\00" +// CHECK: @"__func__.+[Foo classTest2:]" = private unnamed_addr constant [19 x i8] c"+[Foo classTest2:]\00" +// CHECK: @"__func__.+[Foo classTest3:withB:]" = private unnamed_addr constant [25 x i8] c"+[Foo classTest3:withB:]\00" +// CHECK: @"__func__.+[Foo classTest4]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest4]\00" +// CHECK: @"__func__.-[Foo(Category) instanceTestWithCategory]" = private unnamed_addr constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00" +// CHECK: @"__func__.+[Foo(Category) classTestWithCategory]" = private unnamed_addr constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00" int printf(const char * _Format, ...); diff --git a/test/CodeGenObjC/property-ref-cast-to-void.m b/test/CodeGenObjC/property-ref-cast-to-void.m new file mode 100644 index 0000000..a365aa5 --- /dev/null +++ b/test/CodeGenObjC/property-ref-cast-to-void.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -emit-llvm -o - %s | FileCheck %s + +// rdar: // 8399655 +@interface TestClass +@property (readonly) int myProperty; +- (int)myProperty; +- (double)myGetter; +@end + +void FUNC () { + TestClass *obj; + (void)obj.myProperty; + (void)obj.myGetter; +} + +// CHECK: call i32 bitcast +// CHECK: call double bitcast diff --git a/test/CodeGenObjC/property-type-mismatch.m b/test/CodeGenObjC/property-type-mismatch.m new file mode 100644 index 0000000..7045947 --- /dev/null +++ b/test/CodeGenObjC/property-type-mismatch.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar://8966864 + +@interface Foo +-(float)myfo; +-(void)setMyfo: (int)p; +@end + +void bar(Foo *x) { + x.myfo++; +} + +// CHECK: [[C1:%.*]] = call float bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: [[I:%.*]] = fadd float [[C1]], 1.000000e+00 +// CHECK: [[CONV:%.*]] = fptosi float [[I]] to i32 +// CHECK: [[T3:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2" +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m index 7160b16..dd0786e 100644 --- a/test/CodeGenObjC/property.m +++ b/test/CodeGenObjC/property.m @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// TODO: actually test most of this instead of just emitting it int printf(const char *, ...); @@ -50,3 +52,54 @@ int printf(const char *, ...); return 10; } @end + +// Test that compound operations only compute the base once. +// CHECK: define void @test2 +A *test2_helper(void); +void test2() { + // CHECK: [[BASE:%.*]] = call [[A:%.*]]* @test2_helper() + // CHECK-NEXT: [[SEL:%.*]] = load i8** + // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* + // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]]) + // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LD]], 1 + // CHECK-NEXT: [[SEL:%.*]] = load i8** + // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* + // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]]) + test2_helper().dyn++; + + // CHECK: [[BASE:%.*]] = call [[A]]* @test2_helper() + // CHECK-NEXT: [[SEL:%.*]] = load i8** + // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* + // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]]) + // CHECK-NEXT: [[ADD:%.*]] = mul nsw i32 [[LD]], 10 + // CHECK-NEXT: [[SEL:%.*]] = load i8** + // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* + // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]]) + test2_helper().dyn *= 10; +} + +// Test aggregate initialization from property reads. +// Not crashing is good enough for the property-specific test. +struct test3_struct { int x,y,z; }; +struct test3_nested { struct test3_struct t; }; +@interface test3_object +@property struct test3_struct s; +@end +void test3(test3_object *p) { + struct test3_struct array[1] = { p.s }; + struct test3_nested agg = { p.s }; +} + +// PR8742 +@interface Test4 {} +@property float f; +@end +// CHECK: define void @test4 +void test4(Test4 *t) { + extern int test4_printf(const char *, ...); + // CHECK: [[TMP:%.*]] = call float {{.*}} @objc_msgSend + // CHECK-NEXT: [[EXT:%.*]] = fpext float [[TMP]] to double + // CHECK-NEXT: call i32 (i8*, ...)* @test4_printf(i8* {{.*}}, double [[EXT]]) + // CHECK-NEXT: ret void + test4_printf("%.2f", t.f); +} |