diff options
Diffstat (limited to 'test/CodeGenObjC/property.m')
-rw-r--r-- | test/CodeGenObjC/property.m | 55 |
1 files changed, 54 insertions, 1 deletions
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); +} |