diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CodeGenObjC | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CodeGenObjC')
232 files changed, 10562 insertions, 0 deletions
diff --git a/clang/test/CodeGenObjC/2007-04-03-ObjcEH.m b/clang/test/CodeGenObjC/2007-04-03-ObjcEH.m new file mode 100644 index 0000000..f86ff49 --- /dev/null +++ b/clang/test/CodeGenObjC/2007-04-03-ObjcEH.m @@ -0,0 +1,27 @@ +// RUN: %clang -fexceptions -S -emit-llvm %s -o - + +@interface B +-(int)bar; +@end + +@interface A +-(void) Foo:(int) state; +@end + +@implementation A +- (void) Foo:(int) state { + + int wasResponded = 0; + @try { + if (state) { + B * b = 0; + @try { } + @finally { + wasResponded = ![b bar]; + } + } + } + @finally { + } +} +@end diff --git a/clang/test/CodeGenObjC/2007-05-02-Strong.m b/clang/test/CodeGenObjC/2007-05-02-Strong.m new file mode 100644 index 0000000..31553df --- /dev/null +++ b/clang/test/CodeGenObjC/2007-05-02-Strong.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -S %s -fobjc-gc -o /dev/null +typedef int NSInteger; +typedef struct _NSRect { + int origin; + int size; +} NSRect; + +__attribute__((objc_gc(strong))) NSRect *_cachedRectArray; +extern const NSRect NSZeroRect; +@interface A{ +} +-(void)bar:(NSInteger *)rectCount; +@end + +@implementation A + +-(void)bar:(NSInteger *)rectCount { + NSRect appendRect = NSZeroRect; + + _cachedRectArray[*rectCount - 1] = NSZeroRect; +} + +@end diff --git a/clang/test/CodeGenObjC/2007-10-18-ProDescriptor.m b/clang/test/CodeGenObjC/2007-10-18-ProDescriptor.m new file mode 100644 index 0000000..35a0df3 --- /dev/null +++ b/clang/test/CodeGenObjC/2007-10-18-ProDescriptor.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -emit-llvm %s -o /dev/null +@protocol O +@end +@interface O < O > { +} +@end +struct A { +}; +@protocol AB +- (unsigned) ver; +@end +@interface AGy:O < AB > { +} +@end +@implementation AGy +- (unsigned) ver { +} +@end diff --git a/clang/test/CodeGenObjC/2007-10-23-GC-WriteBarrier.m b/clang/test/CodeGenObjC/2007-10-23-GC-WriteBarrier.m new file mode 100644 index 0000000..af8508b --- /dev/null +++ b/clang/test/CodeGenObjC/2007-10-23-GC-WriteBarrier.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-llvm %s -o /dev/null -fobjc-gc +// rdar://5541393 + +typedef unsigned int NSUInteger; +__attribute__((objc_gc(strong))) float *_scores; + +void foo(int i, float f) { + _scores[i] = f; +} diff --git a/clang/test/CodeGenObjC/2008-08-25-incompatible-cond-expr.m b/clang/test/CodeGenObjC/2008-08-25-incompatible-cond-expr.m new file mode 100644 index 0000000..f285cca --- /dev/null +++ b/clang/test/CodeGenObjC/2008-08-25-incompatible-cond-expr.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@protocol P0 +@end +@interface A <P0> +@end + +id f0(int a, id<P0> x, A* p) { + return a ? x : p; +} diff --git a/clang/test/CodeGenObjC/2008-10-23-invalid-icmp.m b/clang/test/CodeGenObjC/2008-10-23-invalid-icmp.m new file mode 100644 index 0000000..ce01bdb --- /dev/null +++ b/clang/test/CodeGenObjC/2008-10-23-invalid-icmp.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@protocol P @end + +int f0(id<P> d) { + return (d != ((void*) 0)); +} diff --git a/clang/test/CodeGenObjC/2008-10-3-EhValue.m b/clang/test/CodeGenObjC/2008-10-3-EhValue.m new file mode 100644 index 0000000..0ed0d89 --- /dev/null +++ b/clang/test/CodeGenObjC/2008-10-3-EhValue.m @@ -0,0 +1,50 @@ +// RUN: %clang -fexceptions -S -emit-llvm %s -o /dev/null + +@interface Object { +@public + Class isa; +} ++initialize; ++alloc; ++new; ++free; +-free; ++(Class)class; +-(Class)class; +-init; +-superclass; +-(const char *)name; +@end + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static Frob* _connection = ((void *)0); + +extern void abort(void); + +void test (Object* sendPort) +{ + int cleanupPorts = 1; + Frob* receivePort = ((void *)0); + + @try { + receivePort = (Frob *) -1; + _connection = (Frob *) -1; + receivePort = ((void *)0); + sendPort = ((void *)0); + cleanupPorts = 0; + @throw [Object new]; + } + @catch(Frob *obj) { + if(!(0)) abort(); + } + @catch(id exc) { + if(!(!receivePort)) abort(); + if(!(!sendPort)) abort(); + if(!(!cleanupPorts)) abort(); + } +} diff --git a/clang/test/CodeGenObjC/2008-11-12-Metadata.m b/clang/test/CodeGenObjC/2008-11-12-Metadata.m new file mode 100644 index 0000000..afd7ce0 --- /dev/null +++ b/clang/test/CodeGenObjC/2008-11-12-Metadata.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-fragile-abi %s -o /dev/null + +@interface A +@end +@protocol P +@end +@interface B : A <P> +{ +} +@end +@implementation B +- (void)test { +} +@end diff --git a/clang/test/CodeGenObjC/2008-11-24-ConstCFStrings.m b/clang/test/CodeGenObjC/2008-11-24-ConstCFStrings.m new file mode 100644 index 0000000..b37f66c --- /dev/null +++ b/clang/test/CodeGenObjC/2008-11-24-ConstCFStrings.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-fragile-abi %s -o - | FileCheck %s + +// CHECK: _unnamed_cfstring_ + +@class NSString; + +@interface A +- (void)bork:(NSString*)msg; +@end + +void func(A *a) { + [a bork:@"Hello world!"]; +} diff --git a/clang/test/CodeGenObjC/2008-11-25-Blocks.m b/clang/test/CodeGenObjC/2008-11-25-Blocks.m new file mode 100644 index 0000000..39364d5 --- /dev/null +++ b/clang/test/CodeGenObjC/2008-11-25-Blocks.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o /dev/null +// rdar://6394879 + +@interface bork +- (id)B:(void (^)())blk; +- (void)C; +@end +@implementation bork +- (id)B:(void (^)())blk { + __attribute__((__blocks__(byref))) bork* new = ((void *)0); + blk(); +} +- (void)C { + __attribute__((__blocks__(byref))) id var; + [self B:^() {}]; +} +@end diff --git a/clang/test/CodeGenObjC/2009-01-21-invalid-debug-info.m b/clang/test/CodeGenObjC/2009-01-21-invalid-debug-info.m new file mode 100644 index 0000000..af912e2 --- /dev/null +++ b/clang/test/CodeGenObjC/2009-01-21-invalid-debug-info.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -S -g -o %t.s %s + +// FIXME: This test case can be removed at some point (since it will +// no longer effectively test anything). The reason it was causing +// trouble was the synthesized self decl in im1 was causing the debug +// info for I1* to be generated, but referring to an invalid compile +// unit. This was later referred to by f1 and created ill formed debug +// information. + +@interface I1 @end + +@implementation I1 +-im0 { return 0; } +@end + +I1 *f1(void) { return 0; } diff --git a/clang/test/CodeGenObjC/2009-01-26-WriteBarrier-2.m b/clang/test/CodeGenObjC/2009-01-26-WriteBarrier-2.m new file mode 100644 index 0000000..d7219f1 --- /dev/null +++ b/clang/test/CodeGenObjC/2009-01-26-WriteBarrier-2.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fblocks -emit-llvm %s -fobjc-gc -o - | FileCheck %s + +// CHECK: objc_assign_strongCast +// rdar://5541393 + +typedef __SIZE_TYPE__ size_t; +void * malloc(size_t size); + +typedef struct { + void (^ivarBlock)(void); +} StructWithBlock_t; + +int main(int argc, char *argv[]) { + StructWithBlock_t *swbp = (StructWithBlock_t *)malloc(sizeof(StructWithBlock_t*)); + __block int i = 10; + // assigning a Block into an struct slot should elicit a write-barrier under GC + swbp->ivarBlock = ^ { ++i; }; + return 0; +} diff --git a/clang/test/CodeGenObjC/2009-02-05-VolatileProp.m b/clang/test/CodeGenObjC/2009-02-05-VolatileProp.m new file mode 100644 index 0000000..1f696ac --- /dev/null +++ b/clang/test/CodeGenObjC/2009-02-05-VolatileProp.m @@ -0,0 +1,10 @@ +// RUN: %clang -fexceptions -S -emit-llvm %s -o /dev/null -pedantic-errors +// rdar://6551276 + +void foo(const unsigned short *); +void bar() { + unsigned short *s[3]; + int i; + @try { } @catch (id anException) { } + foo(2+s[i]); +} diff --git a/clang/test/CodeGenObjC/2009-08-05-utf16.m b/clang/test/CodeGenObjC/2009-08-05-utf16.m new file mode 100644 index 0000000..06458e7 --- /dev/null +++ b/clang/test/CodeGenObjC/2009-08-05-utf16.m @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm -w -x objective-c %s -o - | FileCheck %s +// rdar://7095855 rdar://7115749 + +// CHECK: internal unnamed_addr constant [6 x i16] [i16 105, i16 80, i16 111, i16 100, i16 8482, i16 0], align 2 +void *P = @"iPodâ„¢"; diff --git a/clang/test/CodeGenObjC/2010-02-01-utf16-with-null.m b/clang/test/CodeGenObjC/2010-02-01-utf16-with-null.m new file mode 100644 index 0000000..1863984 --- /dev/null +++ b/clang/test/CodeGenObjC/2010-02-01-utf16-with-null.m @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// rdar://7589850 + +// CHECK-NOT: __ustring +void *P = @"good\0bye"; diff --git a/clang/test/CodeGenObjC/2010-02-09-DbgSelf.m b/clang/test/CodeGenObjC/2010-02-09-DbgSelf.m new file mode 100644 index 0000000..e09adac --- /dev/null +++ b/clang/test/CodeGenObjC/2010-02-09-DbgSelf.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -x objective-c -emit-llvm -g < %s | grep "\"self\", metadata" +// Test to check that "self" argument is assigned a location. + +@interface Foo +-(void) Bar: (int)x ; +@end + + +@implementation Foo +-(void) Bar: (int)x +{ +} +@end + diff --git a/clang/test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m b/clang/test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m new file mode 100644 index 0000000..5186b20 --- /dev/null +++ b/clang/test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -x objective-c -emit-llvm -g < %s | grep subprogram | grep "i32 9" +// Test to check that subprogram start location. + +@interface Foo +-(int) barMethod; +@end + +@implementation Foo +-(int) barMethod { + int i = 0; + int j = 1; + int k = 1; + return i + j + k; +} +@end diff --git a/clang/test/CodeGenObjC/2010-02-23-DbgInheritance.m b/clang/test/CodeGenObjC/2010-02-23-DbgInheritance.m new file mode 100644 index 0000000..7d31b30 --- /dev/null +++ b/clang/test/CodeGenObjC/2010-02-23-DbgInheritance.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm %s -g -o - | FileCheck %s +// CHECK-NOT: DW_TAG_member +// Interface P should not be a member of interface I in debug info. +@interface P +@end + +@interface I : P +@end + +void fn(I *iptr) {} diff --git a/clang/test/CodeGenObjC/2010-03-17-StructRef.m b/clang/test/CodeGenObjC/2010-03-17-StructRef.m new file mode 100644 index 0000000..fd0e646 --- /dev/null +++ b/clang/test/CodeGenObjC/2010-03-17-StructRef.m @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-darwin -fobjc-fragile-abi -o - | FileCheck %s +// Bitfield references must not touch memory outside of the enclosing +// struct. Radar 7639995 +typedef signed char BOOL; +@protocol NSObject +- (id)init; +@end +@interface NSObject <NSObject> {} +@end +@interface IMAVChatParticipant : NSObject { + int _ardRole; + int _state; + int _avRelayStatus; + int _chatEndedReason; + int _chatError; + unsigned _sendingAudio:1; + unsigned _sendingVideo:1; + unsigned _sendingAuxVideo:1; + unsigned _audioMuted:1; + unsigned _videoPaused:1; + unsigned _networkStalled:1; + unsigned _isInitiator:1; + unsigned _isAOLInterop:1; + unsigned _isRecording:1; + unsigned _isUsingICE:1; +} +@end +@implementation IMAVChatParticipant +- (id) init { + self = [super init]; + if ( self ) { + BOOL blah = (BOOL)1; + // We're expecting these three bitfield assignments will generate i8 stores. + _sendingAudio = (BOOL)1; + _isUsingICE = (BOOL)1; + _isUsingICE = blah; + // CHECK: store i8 + // CHECK: store i8 + // CHECK: store i8 + } + return self; +} +@end diff --git a/clang/test/CodeGenObjC/2011-03-08-IVarLookup.m b/clang/test/CodeGenObjC/2011-03-08-IVarLookup.m new file mode 100644 index 0000000..a24b98c --- /dev/null +++ b/clang/test/CodeGenObjC/2011-03-08-IVarLookup.m @@ -0,0 +1,30 @@ +// RUN: %clang -S -emit-llvm -m64 -fobjc-abi-version=2 %s -o /dev/null + +typedef unsigned int UInt_t; + +@interface A +{ +@protected + UInt_t _f1; +} +@end + +@interface B : A { } +@end + +@interface A () +@property (assign) UInt_t f1; +@end + +@interface B () +@property (assign) int x; +@end + +@implementation B +@synthesize x; +- (id) init +{ + _f1 = 0; + return self; +} +@end diff --git a/clang/test/CodeGenObjC/Inputs/literal-support.h b/clang/test/CodeGenObjC/Inputs/literal-support.h new file mode 100644 index 0000000..5680a20 --- /dev/null +++ b/clang/test/CodeGenObjC/Inputs/literal-support.h @@ -0,0 +1,35 @@ +#ifndef OBJC_LITERAL_SUPPORT_H +#define OBJC_LITERAL_SUPPORT_H + +typedef unsigned char BOOL; + +@interface NSNumber @end + +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; +@end + +@interface NSArray +@end + +@interface NSArray (NSArrayCreation) ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; +@end + +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; +@end + +#endif // OBJC_LITERAL_SUPPORT_H diff --git a/clang/test/CodeGenObjC/arc-arm.m b/clang/test/CodeGenObjC/arc-arm.m new file mode 100644 index 0000000..23da3be --- /dev/null +++ b/clang/test/CodeGenObjC/arc-arm.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s + +id test0(void) { + extern id test0_helper(void); + // CHECK: [[T0:%.*]] = call arm_aapcscc i8* @test0_helper() + // CHECK-NEXT: ret i8* [[T0]] + return test0_helper(); +} + +void test1(void) { + extern id test1_helper(void); + // CHECK: [[T0:%.*]] = call arm_aapcscc i8* @test1_helper() + // CHECK-NEXT: call void asm sideeffect "mov\09r7, r7 + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], + // CHECK-NEXT: load + // CHECK-NEXT: call void @objc_release + // CHECK-NEXT: ret void + id x = test1_helper(); +} diff --git a/clang/test/CodeGenObjC/arc-block-copy-escape.m b/clang/test/CodeGenObjC/arc-block-copy-escape.m new file mode 100644 index 0000000..15c0d1d --- /dev/null +++ b/clang/test/CodeGenObjC/arc-block-copy-escape.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fobjc-arc -fblocks -emit-llvm %s -o - | FileCheck %s + +typedef void (^block_t)(void); +void use_block(block_t); +void use_int(int); + +// rdar://problem/10211676 + +void test0(int i) { + block_t block = ^{ use_int(i); }; + // CHECK: define void @test0( + // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) nounwind, !clang.arc.copy_on_escape + // CHECK: ret void +} + +void test1(int i) { + id block = ^{ use_int(i); }; + // CHECK: define void @test1( + // CHECK: call i8* @objc_retainBlock(i8* {{%.*}}) nounwind + // CHECK-NOT: !clang.arc.copy_on_escape + // CHECK: ret void +} diff --git a/clang/test/CodeGenObjC/arc-block-ivar-layout.m b/clang/test/CodeGenObjC/arc-block-ivar-layout.m new file mode 100644 index 0000000..6c82f29 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-block-ivar-layout.m @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// rdar://8991729 + +__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) opaque_id(); + id baz = 0; + __strong id strong_void_sta; + __block id byref_bab = (id)0; + __block id 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). + +// Test 1 +// byref int, short, char, char, char, id, id, strong id, 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); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + b(); + +// Test 2 +// byref int, short, char, char, char, id, id, strong id, 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); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; +} diff --git a/clang/test/CodeGenObjC/arc-blocks.m b/clang/test/CodeGenObjC/arc-blocks.m new file mode 100644 index 0000000..06acf01 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-blocks.m @@ -0,0 +1,523 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +// This shouldn't crash. +void test0(id (^maker)(void)) { + maker(); +} + +int (^test1(int x))(void) { + // CHECK: define i32 ()* @test1( + // CHECK: [[X:%.*]] = alloca i32, + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]] + // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()* + // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) nounwind + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()* + // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8* + // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind + // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()* + // CHECK-NEXT: ret i32 ()* [[T6]] + return ^{ return x; }; +} + +void test2(id x) { +// CHECK: define void @test2( +// CHECK: [[X:%.*]] = alloca i8*, +// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], +// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}}) +// CHECK-NEXT: store i8* [[PARM]], i8** [[X]] +// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]], +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @test2_helper( +// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release +// CHECK-NEXT: ret void + extern void test2_helper(id (^)(void)); + test2_helper(^{ return x; }); +} + +void test3(void (^sink)(id*)) { + __strong id strong; + sink(&strong); + + // CHECK: define void @test3( + // CHECK: [[SINK:%.*]] = alloca void (i8**)* + // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP:%.*]] = alloca i8* + // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8* + // CHECK-NEXT: call i8* @objc_retain( + // CHECK-NEXT: bitcast i8* + // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]] + // CHECK-NEXT: store i8* null, i8** [[STRONG]] + + // CHECK-NEXT: load void (i8**)** [[SINK]] + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: [[BLOCK:%.*]] = bitcast + // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]] + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]] + // CHECK-NEXT: [[F0:%.*]] = load i8** + // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)* + // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]]) + // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8** [[STRONG]] + // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]] + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + + // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + + // CHECK-NEXT: load void (i8**)** [[SINK]] + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @objc_release + // CHECK-NEXT: ret void + +} + +void test4(void) { + id test4_source(void); + void test4_helper(void (^)(void)); + __block id var = test4_source(); + test4_helper(^{ var = 0; }); + + // CHECK: define void @test4() + // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]], + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2 + // 0x02000000 - has copy/dispose helpers + // CHECK-NEXT: store i32 33554432, i32* [[T0]] + // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 + // CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]] + // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 + // 0x42000000 - has signature, copy/dispose helpers + // CHECK: store i32 1107296256, + // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* + // CHECK-NEXT: store i8* [[T0]], i8** + // CHECK: call void @test4_helper( + // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) + // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__Block_byref_object_copy_ + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: load i8** + // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: [[T2:%.*]] = load i8** [[T1]] + // CHECK-NEXT: store i8* [[T2]], i8** [[T0]] + // CHECK-NEXT: store i8* null, i8** [[T1]] + + // CHECK: define internal void @__Block_byref_object_dispose_ + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + + // CHECK: define internal void @__test4_block_invoke_ + // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]], align 8 + // CHECK-NEXT: store i8* null, i8** [[SLOT]], + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__copy_helper_block_ + // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8) + + // CHECK: define internal void @__destroy_helper_block_ + // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8) +} + +void test5(void) { + extern id test5_source(void); + void test5_helper(void (^)(void)); + __unsafe_unretained id var = test5_source(); + test5_helper(^{ (void) var; }); + + // CHECK: define void @test5() + // CHECK: [[VAR:%.*]] = alloca i8* + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + // CHECK: [[T0:%.*]] = call i8* @test5_source() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]], + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // 0x40000000 - has signature but no copy/dispose + // CHECK: store i32 1073741824, i32* + // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]] + // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]] + // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to + // CHECK: call void @test5_helper + // CHECK-NEXT: ret void +} + +void test6(void) { + id test6_source(void); + void test6_helper(void (^)(void)); + __block __weak id var = test6_source(); + test6_helper(^{ var = 0; }); + + // CHECK: define void @test6() + // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]], + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2 + // 0x02000000 - has copy/dispose helpers + // CHECK-NEXT: store i32 33554432, i32* [[T0]] + // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 + // CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6 + // 0x42000000 - has signature, copy/dispose helpers + // CHECK: store i32 1107296256, + // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* + // CHECK-NEXT: store i8* [[T0]], i8** + // CHECK: call void @test6_helper( + // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__Block_byref_object_copy_ + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: load i8** + // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]]) + + // CHECK: define internal void @__Block_byref_object_dispose_ + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) + + // CHECK: define internal void @__test6_block_invoke_ + // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6 + // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__copy_helper_block_ + // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control) + // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8) + + // CHECK: define internal void @__destroy_helper_block_ + // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control) + // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8) +} + +void test7(void) { + id test7_source(void); + void test7_helper(void (^)(void)); + void test7_consume(id); + __weak id var = test7_source(); + test7_helper(^{ test7_consume(var); }); + + // CHECK: define void @test7() + // CHECK: [[VAR:%.*]] = alloca i8*, + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + // CHECK: [[T0:%.*]] = call i8* @test7_source() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // 0x42000000 - has signature, copy/dispose helpers + // CHECK: store i32 1107296256, + // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]]) + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]]) + // CHECK: call void @test7_helper( + // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}}) + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__test7_block_invoke_ + // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[SLOT]]) + // CHECK-NEXT: call void @test7_consume(i8* [[T0]]) + // CHECK-NEXT: ret void + + // CHECK: define internal void @__copy_helper_block_ + // CHECK: getelementptr + // CHECK-NEXT: getelementptr + // CHECK-NEXT: call void @objc_copyWeak( + + // CHECK: define internal void @__destroy_helper_block_ + // CHECK: getelementptr + // CHECK-NEXT: call void @objc_destroyWeak( +} + +@interface Test8 @end +@implementation Test8 +- (void) test { +// CHECK: define internal void @"\01-[Test8 test]" +// CHECK: [[SELF:%.*]] = alloca [[TEST8:%.*]]*, +// CHECK-NEXT: alloca i8* +// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], +// CHECK: store +// CHECK-NEXT: store +// CHECK: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[SELF]], +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]* +// CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]] +// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to +// CHECK: call void @test8_helper( +// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]] +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T2]]) +// CHECK-NEXT: ret void + + extern void test8_helper(void (^)(void)); + test8_helper(^{ (void) self; }); +} +@end + +id test9(void) { + typedef id __attribute__((ns_returns_retained)) blocktype(void); + extern void test9_consume_block(blocktype^); + return ^blocktype { + extern id test9_produce(void); + return test9_produce(); + }(); + +// CHECK: define i8* @test9( +// CHECK: load i8** getelementptr +// CHECK-NEXT: bitcast i8* +// CHECK-NEXT: call i8* +// CHECK-NEXT: call i8* @objc_autoreleaseReturnValue +// CHECK-NEXT: ret i8* + +// CHECK: call i8* @test9_produce() +// CHECK-NEXT: call i8* @objc_retain +// CHECK-NEXT: ret i8* +} + +// rdar://problem/9814099 +// Test that we correctly initialize __block variables +// when the initialization captures the variable. +void test10a(void) { + __block void (^block)(void) = ^{ block(); }; + // CHECK: define void @test10a() + // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]], + + // Zero-initialization before running the initializer. + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6 + // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8 + + // Run the initializer as an assignment. + // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8* + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()* + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1 + // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]] + // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6 + // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8 + // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8 + // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T7]]) + + // Destroy at end of function. + // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6 + // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) + // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] + // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: ret void +} + +// <rdar://problem/10402698>: do this copy and dispose with +// objc_retainBlock/release instead of _Block_object_assign/destroy. +// We can also use _Block_object_assign/destroy with +// BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER. + +// CHECK: define internal void @__Block_byref_object_copy +// CHECK: [[D0:%.*]] = load i8** {{%.*}} +// CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]* +// CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[D1]], i32 0, i32 6 +// CHECK-NEXT: [[S0:%.*]] = load i8** {{%.*}} +// CHECK-NEXT: [[S1:%.*]] = bitcast i8* [[S0]] to [[BYREF_T]]* +// CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[S1]], i32 0, i32 6 +// CHECK-NEXT: [[T0:%.*]] = load void ()** [[S2]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* +// CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8 +// CHECK-NEXT: ret void + +// CHECK: define internal void @__Block_byref_object_dispose +// CHECK: [[T0:%.*]] = load i8** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]* +// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T1]], i32 0, i32 6 +// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]], align 8 +// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T4]]) +// CHECK-NEXT: ret void + +// Test that we correctly assign to __block variables when the +// assignment captures the variable. +void test10b(void) { + __block void (^block)(void); + block = ^{ block(); }; + + // CHECK: define void @test10b() + // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]], + + // Zero-initialize. + // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6 + // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8 + + // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6 + + // The assignment. + // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8* + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()* + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1 + // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]] + // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6 + // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8 + // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8 + // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T7]]) + + // Destroy at end of function. + // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) + // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] + // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: ret void +} + +// rdar://problem/10088932 +void test11_helper(id); +void test11a(void) { + int x; + test11_helper(^{ (void) x; }); + + // CHECK: define void @test11a() + // CHECK: [[X:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 + // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* + // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* + // CHECK-NEXT: call void @test11_helper(i8* [[T4]]) + // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T5]]) + // CHECK-NEXT: ret void +} +void test11b(void) { + int x; + id b = ^{ (void) x; }; + + // CHECK: define void @test11b() + // CHECK: [[X:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8 + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 + // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* + // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8* + // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8 + // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]] + // CHECK-NEXT: call void @objc_release(i8* [[T5]]) + // CHECK-NEXT: ret void +} + +// rdar://problem/9979150 +@interface Test12 +@property (strong) void(^ablock)(void); +@property (nonatomic, strong) void(^nblock)(void); +@end +@implementation Test12 +@synthesize ablock, nblock; +// CHECK: define internal void ()* @"\01-[Test12 ablock]"( +// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true) + +// CHECK: define internal void @"\01-[Test12 setAblock:]"( +// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true) + +// CHECK: define internal void ()* @"\01-[Test12 nblock]"( +// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false) + +// CHECK: define internal void @"\01-[Test12 setNblock:]"( +// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true) +@end + +// rdar://problem/10131784 +void test13(id x) { + extern void test13_helper(id); + extern void test13_use(void(^)(void)); + + void (^b)(void) = (x ? ^{test13_helper(x);} : 0); + test13_use(b); + + // CHECK: define void @test13( + // CHECK: [[X:%.*]] = alloca i8*, align 8 + // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 + // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) + // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8 + // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8 + // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null + // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: br i1 [[T1]], + + // CHECK-NOT: br + // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8 + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8 + // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK-NEXT: br label + // CHECK: br label + // CHECK: [[T0:%.*]] = phi void ()* + // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* + // CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8 + // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]], align 8 + // CHECK-NEXT: call void @test13_use(void ()* [[T0]]) + // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]] + // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + + // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: br i1 [[T0]] + // CHECK: [[T0:%.*]] = load i8** [[CLEANUP_ADDR]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: br label + + // CHECK: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: ret void +} + +// <rdar://problem/10907510> +void test14() { + void (^const x[1])(void) = { ^{} }; +} + +// rdar://11149025 +// Don't make invalid ASTs and crash. +void test15_helper(void (^block)(void), int x); +void test15(int a) { + test15_helper(^{ (void) a; }, ({ a; })); +} diff --git a/clang/test/CodeGenObjC/arc-bridged-cast.m b/clang/test/CodeGenObjC/arc-bridged-cast.m new file mode 100644 index 0000000..eb9045d --- /dev/null +++ b/clang/test/CodeGenObjC/arc-bridged-cast.m @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +typedef const void *CFTypeRef; +typedef const struct __CFString *CFStringRef; + +@interface NSString +@end + +CFTypeRef CFCreateSomething(void); +CFStringRef CFCreateString(void); +CFTypeRef CFGetSomething(void); +CFStringRef CFGetString(void); + +id CreateSomething(void); +NSString *CreateNSString(void); + +// CHECK: define void @bridge_transfer_from_cf +void bridge_transfer_from_cf(int *i) { + // CHECK: store i32 7 + *i = 7; + // CHECK: call i8* @CFCreateSomething() + id obj1 = (__bridge_transfer id)CFCreateSomething(); + // CHECK-NOT: retain + // CHECK: store i32 11 + *i = 11; + // CHECK: call i8* @CFCreateSomething() + // CHECK-NOT: retain + // CHECK: store i32 13 + (void)(__bridge_transfer id)CFCreateSomething(), *i = 13; + // CHECK: call void @objc_release + // CHECK: store i32 17 + *i = 17; + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// CHECK: define void @bridge_from_cf +void bridge_from_cf(int *i) { + // CHECK: store i32 7 + *i = 7; + // CHECK: call i8* @CFCreateSomething() + id obj1 = (__bridge id)CFCreateSomething(); + // CHECK: objc_retainAutoreleasedReturnValue + // CHECK: store i32 11 + *i = 11; + // CHECK: call i8* @CFCreateSomething() + // CHECK-NOT: release + // CHECK: store i32 13 + (void)(__bridge id)CFCreateSomething(), *i = 13; + // CHECK: store i32 17 + *i = 17; + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// CHECK: define void @bridge_retained_of_cf +void bridge_retained_of_cf(int *i) { + *i = 7; + // CHECK: call i8* @CreateSomething() + CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); + // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue + // CHECK: store i32 11 + *i = 11; + // CHECK: call i8* @CreateSomething() + (__bridge_retained CFTypeRef)CreateSomething(), *i = 13; + // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue + // CHECK: store i32 13 + // CHECK: store i32 17 + *i = 17; + // CHECK-NEXT: ret void +} + +// CHECK: define void @bridge_of_cf +void bridge_of_cf(int *i) { + // CHECK: store i32 7 + *i = 7; + // CHECK: call i8* @CreateSomething() + CFTypeRef cf1 = (__bridge CFTypeRef)CreateSomething(); + // CHECK-NOT: retain + // CHECK: store i32 11 + *i = 11; + // CHECK: call i8* @CreateSomething + (__bridge CFTypeRef)CreateSomething(), *i = 13; + // CHECK: store i32 13 + // CHECK-NOT: release + // CHECK: store i32 17 + *i = 17; + // CHECK-NEXT: ret void +} + diff --git a/clang/test/CodeGenObjC/arc-compound-stmt.m b/clang/test/CodeGenObjC/arc-compound-stmt.m new file mode 100644 index 0000000..573ee44 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-compound-stmt.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - %s +// rdar://9694706 + +typedef unsigned long NSUInteger; + +@interface NSString +- (NSString *)stringByAppendingString:(NSString *)aString; +- (NSString *)substringFromIndex:(NSUInteger)from; +@end + +@interface MyClass +- (void)inst; +@end + +@implementation MyClass + +- (void)inst; +{ + NSString *propName; + + NSString *capitalPropName = ({ + NSString *cap; + if (propName) + cap = [cap stringByAppendingString:[propName substringFromIndex:1]]; + cap; + }); +} + +@end diff --git a/clang/test/CodeGenObjC/arc-cond-stmt.m b/clang/test/CodeGenObjC/arc-cond-stmt.m new file mode 100644 index 0000000..d8ee6bb --- /dev/null +++ b/clang/test/CodeGenObjC/arc-cond-stmt.m @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - %s +// rdar://10327068 + +@class NSString; + +@interface NSAssertionHandler { +} + ++ (NSAssertionHandler *)currentHandler; + +- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(int)line ,...; + +@end + +typedef enum +{ + MWRaceOrder_MeetName, + MWRaceOrder_MeetPosition, + MWRaceOrder_MeetDistance, + MWRaceOrder_Name, + MWRaceOrder_Position, + MWRaceOrder_Distance, + MWRaceOrder_Default = MWRaceOrder_Name, + MWRaceOrder_MeetDefault = MWRaceOrder_MeetName, +} MWRaceOrder; + +@interface MWViewMeetController +@property (nonatomic, assign) MWRaceOrder raceOrder; +@end + +@implementation MWViewMeetController + +- (int)orderSegment +{ + switch (self.raceOrder) + { + + default: + { [(NSAssertionHandler *)0 handleFailureInMethod:_cmd object:self file:(NSString*)0 lineNumber:192 ]; }; + break; + } + + return 0; +} + +@synthesize raceOrder; + +@end diff --git a/clang/test/CodeGenObjC/arc-exceptions.m b/clang/test/CodeGenObjC/arc-exceptions.m new file mode 100644 index 0000000..5ef5aba --- /dev/null +++ b/clang/test/CodeGenObjC/arc-exceptions.m @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s + +@class Ety; + +// These first two tests are all PR11732 / rdar://problem/10667070. + +void test0_helper(void); +void test0(void) { + @try { + test0_helper(); + } @catch (Ety *e) { + } +} +// CHECK: define void @test0() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @test0_helper() +// 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: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* +// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] +// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind +// CHECK-NEXT: call void @objc_end_catch() nounwind + +void test1_helper(void); +void test1(void) { + @try { + test1_helper(); + } @catch (__weak Ety *e) { + } +} +// CHECK: define void @test1() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @test1_helper() +// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( +// 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: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind +// CHECK-NEXT: call void @objc_end_catch() nounwind diff --git a/clang/test/CodeGenObjC/arc-foreach.m b/clang/test/CodeGenObjC/arc-foreach.m new file mode 100644 index 0000000..67fad4d --- /dev/null +++ b/clang/test/CodeGenObjC/arc-foreach.m @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -emit-llvm %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// rdar://9503326 +// rdar://9606600 + +extern void use(id); +extern void use_block(void (^)(void)); + +struct NSFastEnumerationState; +@interface NSArray +- (unsigned long) countByEnumeratingWithState: (struct NSFastEnumerationState*) state + objects: (id*) buffer + count: (unsigned long) bufferSize; +@end; + +void test0(NSArray *array) { + // 'x' should be initialized without a retain. + // We should actually do a non-constant capture, and that + // capture should require a retain. + for (id x in array) { + use_block(^{ use(x); }); + } +} + +// CHECK-LP64: define void @test0( +// CHECK-LP64: [[ARRAY:%.*]] = alloca [[ARRAY_T:%.*]]*, +// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*, +// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]], +// CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8 +// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + +// Initialize 'array'. +// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[ARRAY_T:%.*]]* {{%.*}} to i8* +// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) +// CHECK-LP64-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[ARRAY_T]]* +// CHECK-LP64-NEXT: store [[ARRAY_T]]* [[T2]], [[ARRAY_T]]** [[ARRAY]], align 8 + +// Initialize the fast enumaration state. +// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[STATE_T]]* [[STATE]] to i8* +// CHECK-LP64-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 64, i32 8, i1 false) + +// Evaluate the collection expression and retain. +// CHECK-LP64-NEXT: [[T0:%.*]] = load [[ARRAY_T]]** [[ARRAY]], align 8 +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8* +// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-LP64-NEXT: [[SAVED_ARRAY:%.*]] = bitcast i8* [[T2]] to [[ARRAY_T]]* + +// Call the enumeration method. +// CHECK-LP64-NEXT: [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8* +// CHECK-LP64-NEXT: [[SIZE:%.*]] = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, [[STATE_T]]*, [16 x i8*]*, i64)*)(i8* [[T1]], i8* [[T0]], [[STATE_T]]* [[STATE]], [16 x i8*]* [[BUFFER]], i64 16) + +// Check for a nonzero result. +// CHECK-LP64-NEXT: [[T0:%.*]] = icmp eq i64 [[SIZE]], 0 +// CHECK-LP64-NEXT: br i1 [[T0]] + +// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[STATE_T]]* [[STATE]], i32 0, i32 1 +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8*** [[T0]] +// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr i8** [[T1]], i64 +// CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]] +// CHECK-LP64-NEXT: store i8* [[T3]], i8** [[X]] + +// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[X]] +// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]] +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] +// CHECK-LP64: call void @use_block( +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]] +// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) + +// CHECK-LP64: [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8* +// CHECK-LP64-NEXT: [[SIZE:%.*]] = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, [[STATE_T]]*, [16 x i8*]*, i64)*)(i8* [[T1]], i8* [[T0]], [[STATE_T]]* [[STATE]], [16 x i8*]* [[BUFFER]], i64 16) + +// Release the array. +// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8* +// CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]]) + +// Destroy 'array'. +// CHECK-LP64: [[T0:%.*]] = load [[ARRAY_T]]** [[ARRAY]] +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8* +// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-LP64-NEXT: ret void + +// CHECK-LP64: define internal void @__test0_block_invoke +// CHECK-LP64: [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]* +// CHECK-LP64-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64-NEXT: [[T2:%.*]] = load i8** [[T0]], align 8 +// CHECK-LP64-NEXT: call void @use(i8* [[T2]]) + +void test1(NSArray *array) { + for (__weak id x in array) { + use_block(^{ use(x); }); + } +} + +// CHECK-LP64: define void @test1( +// CHECK-LP64: alloca [[ARRAY_T:%.*]]*, +// CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*, +// CHECK-LP64-NEXT: [[STATE:%.*]] = alloca [[STATE_T:%.*]], +// CHECK-LP64-NEXT: alloca [16 x i8*], align 8 +// CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], + +// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[STATE_T]]* [[STATE]], i32 0, i32 1 +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8*** [[T0]] +// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr i8** [[T1]], i64 +// CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]] +// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T3]]) + +// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]]) +// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]]) +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to +// CHECK-LP64: call void @use_block +// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[D0]]) +// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]]) + +// rdar://problem/9817306 +@interface Test2 +- (NSArray *) array; +@end +void test2(Test2 *a) { + for (id x in a.array) { + use(x); + } +} + +// CHECK-LP64: define void @test2( +// CHECK-LP64: [[T0:%.*]] = call [[ARRAY_T]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[ARRAY_T]]* (i8*, i8*)*)( +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8* +// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) +// CHECK-LP64-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[ARRAY_T]]* + +// Make sure it's not immediately released before starting the iteration. +// CHECK-LP64-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[COLL]] to i8* +// CHECK-LP64-NEXT: @objc_msgSend + +// This bitcast is for the mutation check. +// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[COLL]] to i8* +// CHECK-LP64-NEXT: @objc_enumerationMutation + +// This bitcast is for the 'next' message send. +// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[COLL]] to i8* +// CHECK-LP64-NEXT: @objc_msgSend + +// This bitcast is for the final release. +// CHECK-LP64: [[T0:%.*]] = bitcast [[ARRAY_T]]* [[COLL]] to i8* +// CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]]) + + +// Check that the 'continue' label is positioned appropriately +// relative to the collection clenaup. +void test3(NSArray *array) { + for (id x in array) { + if (!x) continue; + use(x); + } + + // CHECK-LP64: define void @test3( + // CHECK-LP64: [[ARRAY:%.*]] = alloca [[ARRAY_T]]*, align 8 + // CHECK-LP64-NEXT: [[X:%.*]] = alloca i8*, align 8 + // CHECK-LP64: [[T0:%.*]] = load i8** [[X]], align 8 + // CHECK-LP64-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null + // CHECK-LP64-NEXT: br i1 [[T1]], + // CHECK-LP64: br label [[L:%[^ ]+]] + // CHECK-LP64: [[T0:%.*]] = load i8** [[X]], align 8 + // CHECK-LP64-NEXT: call void @use(i8* [[T0]]) + // CHECK-LP64-NEXT: br label [[L]] +} diff --git a/clang/test/CodeGenObjC/arc-ivar-layout.m b/clang/test/CodeGenObjC/arc-ivar-layout.m new file mode 100644 index 0000000..7f58a0c --- /dev/null +++ b/clang/test/CodeGenObjC/arc-ivar-layout.m @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// rdar://8991729 + +@interface NSObject { + id isa; +} +@end + +@interface AllPointers : NSObject { + id foo; + id __strong bar; + NSObject *bletch; +} +@end + +@implementation AllPointers +@end +// CHECK-LP64: L_OBJC_CLASS_NAME_1: +// CHECK-LP64-NEXT: .asciz "\003" + +@class NSString, NSNumber; +@interface A : NSObject { + NSString *foo; + NSNumber *bar; + unsigned int bletch; + __weak id delegate; +} +@end + +@interface B : A { + unsigned int x; + NSString *y; + NSString *z; +} +@end + +@implementation A @end + +@implementation B @end + +// CHECK-LP64: L_OBJC_CLASS_NAME_15: +// CHECK-LP64-NEXT: .asciz "\022" + +@interface UnsafePerson { +@public + __unsafe_unretained id name; + __unsafe_unretained id age; + id value; +} +@end + +@implementation UnsafePerson @end +// CHECK-LP64: L_OBJC_CLASS_NAME_20: +// CHECK-LP64-NEXT: .asciz "!" diff --git a/clang/test/CodeGenObjC/arc-literals.m b/clang/test/CodeGenObjC/arc-literals.m new file mode 100644 index 0000000..203c2ad --- /dev/null +++ b/clang/test/CodeGenObjC/arc-literals.m @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +#include "literal-support.h" + +// Check the various selector names we'll be using, in order. + +// CHECK: c"numberWithInt:\00" +// CHECK: c"numberWithUnsignedInt:\00" +// CHECK: c"numberWithUnsignedLongLong:\00" +// CHECK: c"numberWithChar:\00" +// CHECK: c"arrayWithObjects:count:\00" +// CHECK: c"dictionaryWithObjects:forKeys:count:\00" +// CHECK: c"prop\00" + +// CHECK: define void @test_numeric() +void test_numeric() { + // CHECK: {{call.*objc_msgSend.*i32 17}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id ilit = @17; + // CHECK: {{call.*objc_msgSend.*i32 25}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id ulit = @25u; + // CHECK: {{call.*objc_msgSend.*i64 42}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id ulllit = @42ull; + // CHECK: {{call.*objc_msgSend.*i8 signext 97}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id charlit = @'a'; + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_array +void test_array(id a, id b) { + // Retaining parameters + // CHECK: call i8* @objc_retain(i8* + // CHECK: call i8* @objc_retain(i8* + + // Constructing the array + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK: store i8* + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK: store i8* + + // CHECK: {{call i8*.*objc_msgSend.*i64 2}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id arr = @[a, b]; + + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_dictionary +void test_dictionary(id k1, id o1, id k2, id o2) { + // Retaining parameters + // CHECK: call i8* @objc_retain(i8* + // CHECK: call i8* @objc_retain(i8* + // CHECK: call i8* @objc_retain(i8* + // CHECK: call i8* @objc_retain(i8* + + // Constructing the arrays + // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK: store i8* + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0 + // CHECK: store i8* + // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1 + // CHECK: store i8* + // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK: store i8* + + // Constructing the dictionary + // CHECK: {{call i8.*@objc_msgSend}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id dict = @{ k1 : o1, k2 : o2 }; + + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +@interface A +@end + +@interface B +@property (retain) A* prop; +@end + +// CHECK: define void @test_property +void test_property(B *b) { + // Retain parameter + // CHECK: call i8* @objc_retain + + // Invoke 'prop' + // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK: {{call.*@objc_msgSend}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + + // Invoke arrayWithObjects:count: + // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES + // CHECK: {{call.*objc_msgSend}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id arr = @[ b.prop ]; + + // Release b.prop + // CHECK: call void @objc_release + + // Destroy arr + // CHECK: call void @objc_release + + // Destroy b + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} diff --git a/clang/test/CodeGenObjC/arc-no-arc-exceptions.m b/clang/test/CodeGenObjC/arc-no-arc-exceptions.m new file mode 100644 index 0000000..7ae061f --- /dev/null +++ b/clang/test/CodeGenObjC/arc-no-arc-exceptions.m @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O0 -disable-llvm-optzns -o - %s | FileCheck -check-prefix=NO-METADATA %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s -fobjc-arc-exceptions | FileCheck -check-prefix=NO-METADATA %s + +// The front-end should emit clang.arc.no_objc_arc_exceptions in -fobjc-arc-exceptions +// mode when optimization is enabled, and not otherwise. + +void thrower(void); +void not(void) __attribute__((nothrow)); + +// CHECK: define void @test0( +// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions ! +// NO-METADATA: define void @test0( +// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions +// NO-METADATA: } +void test0(void) { + thrower(); + not(); +} + +// CHECK: define void @test1( +// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions ! +// NO-METADATA: define void @test1( +// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions +// NO-METADATA: } +void test1(id x) { + id y = x; + thrower(); + not(); +} + +void NSLog(id, ...); + +// CHECK: define void @test2( +// CHECK: invoke void (i8*, ...)* @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i32* %{{.*}}) +// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions ! +// NO-METADATA: define void @test2( +// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions +// NO-METADATA: } +void test2(void) { + @autoreleasepool { + __attribute__((__blocks__(byref))) int x; + NSLog(@"Address of x outside of block: %p", &x); + } +} + +// CHECK: define void @test3( +// CHECK: invoke void %{{.*}}(i8* %{{.*}}) +// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions ! +// NO-METADATA: define void @test3( +// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions +// NO-METADATA: } +void test3(void) { + @autoreleasepool { + __attribute__((__blocks__(byref))) int x; + ^{ + NSLog(@"Address of x in non-assigned block: %p", &x); + }(); + } +} + +// CHECK: define void @test4( +// CHECK: invoke void %{{.*}}(i8* %{{.*}}) +// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions ! +// NO-METADATA: define void @test4( +// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions +// NO-METADATA: } +void test4(void) { + @autoreleasepool { + __attribute__((__blocks__(byref))) int x; + void (^b)(void) = ^{ + NSLog(@"Address of x in assigned block: %p", &x); + }; + b(); + } +} diff --git a/clang/test/CodeGenObjC/arc-no-runtime.m b/clang/test/CodeGenObjC/arc-no-runtime.m new file mode 100644 index 0000000..3c85e87 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-no-runtime.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s + +// rdar://problem/9224855 +void test0() { + id x = 0; + // CHECK: call void @objc_release( +} + +// CHECK: declare extern_weak void @objc_release( diff --git a/clang/test/CodeGenObjC/arc-property.m b/clang/test/CodeGenObjC/arc-property.m new file mode 100644 index 0000000..6c5180b --- /dev/null +++ b/clang/test/CodeGenObjC/arc-property.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s + +// rdar://problem/10290317 +@interface Test0 +- (void) setValue: (id) x; +@end +void test0(Test0 *t0, id value) { + t0.value = value; +} +// CHECK: define void @test0( +// CHECK: call i8* @objc_retain( +// CHECK: call i8* @objc_retain( +// CHECK: @objc_msgSend +// CHECK: call void @objc_release( +// CHECK: call void @objc_release( diff --git a/clang/test/CodeGenObjC/arc-related-result-type.m b/clang/test/CodeGenObjC/arc-related-result-type.m new file mode 100644 index 0000000..f73aa50 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-related-result-type.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s + +@interface Test0 +- (id) self; +@end +void test0(Test0 *val) { + Test0 *x = [val self]; + +// CHECK: define void @test0( +// CHECK: [[VAL:%.*]] = alloca [[TEST0:%.*]]* +// CHECK-NEXT: [[X:%.*]] = alloca [[TEST0]]* +// CHECK-NEXT: bitcast +// CHECK-NEXT: call i8* @objc_retain( +// CHECK-NEXT: bitcast +// CHECK-NEXT: store +// CHECK-NEXT: load [[TEST0]]** [[VAL]], +// CHECK-NEXT: load +// CHECK-NEXT: bitcast +// CHECK-NEXT: [[T0:%.*]] = call i8* bitcast ( +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]* +// CHECK-NEXT: store [[TEST0]]* [[T2]], [[TEST0]]** [[X]] +// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[X]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[VAL]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-NEXT: ret void +} diff --git a/clang/test/CodeGenObjC/arc-unbridged-cast.m b/clang/test/CodeGenObjC/arc-unbridged-cast.m new file mode 100644 index 0000000..5ab5d02 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-unbridged-cast.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fobjc-arc -o - %s | FileCheck %s +// rdar://9744349 + +typedef const struct __CFString * CFStringRef; + +@interface I +@property CFStringRef P; +- (CFStringRef) CFMeth __attribute__((cf_returns_retained)); +- (CFStringRef) newSomething; +- (CFStringRef) P __attribute__((cf_returns_retained)); +@end + +@implementation I +@synthesize P; +- (id) Meth { + I* p1 = (id)[p1 P]; + id p2 = (id)[p1 CFMeth]; + id p3 = (id)[p1 newSomething]; + return (id) p1.P; +} +- (CFStringRef) CFMeth { return 0; } +- (CFStringRef) newSomething { return 0; } +- (CFStringRef) P { return 0; } +- (void) setP : (CFStringRef)arg {} +@end + +// rdar://9544832 +CFStringRef SomeOtherFunc() __attribute__((cf_returns_retained)); +id MMM() +{ + id obj = (id)((CFStringRef) __builtin___CFStringMakeConstantString ("" "Some CF String" "")); + return 0; +} + +// CHECK-NOT: call i8* @objc_retainAutoreleasedReturnValue diff --git a/clang/test/CodeGenObjC/arc-unopt.m b/clang/test/CodeGenObjC/arc-unopt.m new file mode 100644 index 0000000..c319bf2 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-unopt.m @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s + +// A test to ensure that we generate fused calls at -O0. + +@class Test0; +Test0 *test0(void) { + extern Test0 *test0_helper; + return test0_helper; + + // CHECK: [[LD:%.*]] = load [[TEST0:%.*]]** @test0_helper + // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]* [[LD]] to i8* + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]* + // CHECK-NEXT: ret [[TEST0]]* [[T2]] +} + +id test1(void) { + extern id test1_helper; + return test1_helper; + + // CHECK: [[LD:%.*]] = load i8** @test1_helper + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]]) + // CHECK-NEXT: ret i8* [[T0]] +} + +void test2(void) { + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]]) + // CHECK-NEXT: ret void + __weak id x; +} + +id test3(void) { + extern id test3_helper(void); + // CHECK: [[T0:%.*]] = call i8* @test3_helper() + // CHECK-NEXT: ret i8* [[T0]] + return test3_helper(); +} + +@interface Test4 { id x; } @end +@interface Test4_sub : Test4 { id y; } @end +Test4 *test4(void) { + extern Test4_sub *test4_helper(void); + // CHECK: [[T0:%.*]] = call [[TEST4S:%.*]]* @test4_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST4S]]* [[T0]] to [[TEST4:%.*]]* + // CHECK-NEXT: ret [[TEST4]]* [[T1]] + return test4_helper(); +} + +// rdar://problem/9418404 +@class Test5; +void test5(void) { + Test5 *x, *y; + if ((x = y)) + y = 0; + +// CHECK: define void @test5() +// CHECK: [[X:%.*]] = alloca [[TEST5:%.*]]*, +// CHECK-NEXT: [[Y:%.*]] = alloca [[TEST5:%.*]]*, +// CHECK-NEXT: store [[TEST5]]* null, [[TEST5]]** [[X]], +// CHECK-NEXT: store [[TEST5]]* null, [[TEST5]]** [[Y]], +// CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]** [[Y]], +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]** [[X]] to i8** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST5]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) +// CHECK-NEXT: [[T3:%.*]] = icmp ne [[TEST5]]* [[T0]], null +// CHECK-NEXT: br i1 [[T3]], +} diff --git a/clang/test/CodeGenObjC/arc-weak-property.m b/clang/test/CodeGenObjC/arc-weak-property.m new file mode 100644 index 0000000..0a6b2a6 --- /dev/null +++ b/clang/test/CodeGenObjC/arc-weak-property.m @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s +// rdar://8899430 + +@interface WeakPropertyTest { + __weak id PROP; +} +@property () __weak id PROP; +@end + +@implementation WeakPropertyTest +@synthesize PROP; +@end + +// CHECK: define internal i8* @"\01-[WeakPropertyTest PROP]" +// CHECK: [[SELF:%.*]] = alloca [[WPT:%.*]]*, +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, +// CHECK-NEXT: store [[WPT]]* {{%.*}}, [[WPT]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] +// CHECK-NEXT: [[T0:%.*]] = load [[WPT]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_WeakPropertyTest.PROP" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]]) +// CHECK-NEXT: [[T6:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T5]]) +// CHECK-NEXT: ret i8* [[T6]] + +// CHECK: define internal void @"\01-[WeakPropertyTest setPROP:]" +// CHECK: [[SELF:%.*]] = alloca [[WPT:%.*]]*, +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, +// CHECK-NEXT: [[PROP:%.*]] = alloca i8*, +// CHECK-NEXT: store [[WPT]]* {{%.*}}, [[WPT]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[PROP]] +// CHECK-NEXT: [[V:%.*]] = load i8** [[PROP]] +// CHECK-NEXT: [[T0:%.*]] = load [[WPT]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_WeakPropertyTest.PROP" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[T4]], i8* [[V]]) +// CHECK-NEXT: ret void + +// CHECK: define internal void @"\01-[WeakPropertyTest .cxx_destruct]" +// CHECK: [[SELF:%.*]] = alloca [[WPT:%.*]]*, +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, +// CHECK-NEXT: store [[WPT]]* {{%.*}}, [[WPT]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] +// CHECK-NEXT: [[T0:%.*]] = load [[WPT]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_WeakPropertyTest.PROP" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[WPT]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T4]]) +// CHECK-NEXT: ret void diff --git a/clang/test/CodeGenObjC/arc-with-atthrow.m b/clang/test/CodeGenObjC/arc-with-atthrow.m new file mode 100644 index 0000000..213b05b --- /dev/null +++ b/clang/test/CodeGenObjC/arc-with-atthrow.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-exceptions -o - %s | FileCheck %s +// pr10411 +// rdar://10042689 + +id make(void); +void test() { + @throw make(); +} + +// TODO: We should probably emit this specific pattern without the reclaim. + +// CHECK: define void @test() +// CHECK: [[T0:%.*]] = call i8* @make() +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autorelease(i8* [[T1]]) +// CHECK-NEXT: call void @objc_exception_throw(i8* [[T2]]) noreturn +// CHECK-NEXT: unreachable diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m new file mode 100644 index 0000000..2a98b10 --- /dev/null +++ b/clang/test/CodeGenObjC/arc.m @@ -0,0 +1,1539 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s + +// CHECK: define void @test0 +void test0(id x) { + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{.*}}) + // CHECK-NEXT: store i8* [[PARM]], i8** [[X]] + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) + // CHECK-NEXT: ret void +} + +// CHECK: define i8* @test1(i8* +id test1(id x) { + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[Y:%.*]] = alloca i8* + // CHECK-NEXT: alloca i32 + // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}}) + // CHECK-NEXT: store i8* [[PARM]], i8** [[X]] + // CHECK-NEXT: store i8* null, i8** [[Y]] + // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]] + // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: store i32 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[RET]]) + // CHECK-NEXT: ret i8* [[T1]] + id y; + return y; +} + +@interface Test2 ++ (void) class_method; +- (void) inst_method; +@end +@implementation Test2 + +// The self pointer of a class method is not retained. +// CHECK: define internal void @"\01+[Test2 class_method]" +// CHECK: alloca +// CHECK-NEXT: alloca +// CHECK-NEXT: store +// CHECK-NEXT: store +// CHECK-NEXT: ret void ++ (void) class_method {} + +// The self pointer of an instance method is not retained. +// CHECK: define internal void @"\01-[Test2 inst_method]" +// CHECK: alloca +// CHECK-NEXT: alloca +// CHECK-NEXT: store +// CHECK-NEXT: store +// CHECK-NEXT: ret void +- (void) inst_method {} +@end + +@interface Test3 ++ (id) alloc; +- (id) initWith: (int) x; +- (id) copy; +@end + +// CHECK: define void @test3_unelided() +void test3_unelided() { + extern void test3_helper(void); + + // CHECK: [[X:%.*]] = alloca [[TEST3:%.*]]* + // CHECK-NEXT: store [[TEST3]]* null, [[TEST3]]** [[X]], align + Test3 *x; + + // Call to +alloc. + // CHECK-NEXT: load {{.*}}* @"\01L_OBJC_CLASSLIST_REFERENCES_ + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @objc_release(i8* + [Test3 alloc]; + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]** [[X]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* + // CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[T1]], + // CHECK-NEXT: call void @objc_release(i8* [[COPY]]) nounwind + [x copy]; + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]** [[X]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NEXT: ret void +} + +// CHECK: define void @test3() +void test3() { + // CHECK: [[X:%.*]] = alloca i8* + + id x = [[Test3 alloc] initWith: 5]; + + // Call to +alloc. + // CHECK-NEXT: load {{.*}}* @"\01L_OBJC_CLASSLIST_REFERENCES_ + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend + // CHECK-NEXT: bitcast + + // Call to -initWith: with elided retain of consumed argument. + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[INIT:%.*]] = bitcast + // Assignment for initialization, retention elided. + // CHECK-NEXT: store i8* [[INIT]], i8** [[X]] + + // Call to -copy. + // CHECK-NEXT: [[V:%.*]] = load i8** [[X]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[COPY:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend {{.*}})(i8* [[V]], + + // Assignment to x. + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* [[COPY]], i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + + x = [x copy]; + + // Cleanup for x. + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + + // CHECK-NEXT: ret void +} + +// CHECK: define i8* @test4() +id test4() { + // Call to +alloc. + // CHECK: load {{.*}}* @"\01L_OBJC_CLASSLIST_REFERENCES_ + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend + // CHECK-NEXT: [[ALLOC:%.*]] = bitcast + + // Call to -initWith: with elided retain of consumed argument. + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[ALLOC:%.*]] = bitcast + // CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ALLOC]], + + // Initialization of return value, occuring within full-expression. + // Retain/release elided. + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[INIT:%.*]] = bitcast + // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[INIT]]) + + // CHECK-NEXT: ret i8* [[RET]] + + return [[Test3 alloc] initWith: 6]; +} + +@interface Test5 { +@public + id var; +} +@end + +// CHECK: define void @test5 +void test5(Test5 *x, id y) { + // Prologue. + // CHECK: [[X:%.*]] = alloca [[TEST5:%.*]]*, + // CHECK-NEXT: [[Y:%.*]] = alloca i8* + // CHECK-NEXT: bitcast [[TEST5]]* {{%.*}} to i8* + // CHECK-NEXT: call i8* @objc_retain + // CHECK-NEXT: [[PARMX:%.*]] = bitcast i8* {{%.*}} to [[TEST5]]* + // CHECK-NEXT: store [[TEST5]]* [[PARMX]], [[TEST5]]** [[X]] + // CHECK-NEXT: call i8* @objc_retain + // CHECK-NEXT: store + + // CHECK-NEXT: load [[TEST5]]** [[X]] + // CHECK-NEXT: load i64* @"OBJC_IVAR_$_Test5.var" + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: [[VAR:%.*]] = bitcast + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[VAR]] + // CHECK-NEXT: store i8* null, i8** [[VAR]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + x->var = 0; + + // CHECK-NEXT: [[YVAL:%.*]] = load i8** [[Y]] + // CHECK-NEXT: load [[TEST5]]** [[X]] + // CHECK-NEXT: load i64* @"OBJC_IVAR_$_Test5.var" + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: [[VAR:%.*]] = bitcast + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[YVAL]]) nounwind + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[VAR]] + // CHECK-NEXT: store i8* [[T0]], i8** [[VAR]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + x->var = y; + + // Epilogue. + // CHECK-NEXT: [[TMP:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[TMP]]) nounwind + // CHECK-NEXT: [[T0:%.*]] = load [[TEST5]]** [[X]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST5]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NEXT: ret void +} + +id test6_helper(void) __attribute__((ns_returns_retained)); +// CHECK: define void @test6() +void test6() { + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test6_helper() + // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: ret void + id x = test6_helper(); +} + +void test7_helper(id __attribute__((ns_consumed))); +// CHECK: define void @test7() +void test7() { + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) nounwind + // CHECK-NEXT: call void @test7_helper(i8* [[T1]]) + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: ret void + id x; + test7_helper(x); +} + +id test8_helper(void) __attribute__((ns_returns_retained)); +void test8() { + __unsafe_unretained id x = test8_helper(); + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[T0:%.*]] = call i8* @test8_helper() + // CHECK-NEXT: store i8* [[T0]], i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NOT: imprecise_release + // CHECK-NEXT: ret void +} + +id test9_helper(void) __attribute__((ns_returns_retained)); +void test9() { + id x __attribute__((objc_precise_lifetime)) = test9_helper(); + x = 0; + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test9_helper() + // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] + + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NOT: clang.imprecise_release + + // CHECK-NEXT: ret void +} + +@interface Test10 +@property (retain) Test10 *me; +@end +void test10() { + Test10 *x; + id y = x.me.me; + + // CHECK: define void @test10() + // CHECK: [[X:%.*]] = alloca [[TEST10:%.*]]*, align + // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align + // CHECK-NEXT: store [[TEST10]]* null, [[TEST10]]** [[X]] + // CHECK-NEXT: load [[TEST10]]** [[X]], align + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_{{[0-9]*}}" + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[V:%.*]] = bitcast i8* [[T2]] to [[TEST10]]* + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_{{[0-9]*}}" + // CHECK-NEXT: bitcast + // CHECK-NEXT: [[T0:%.*]] = call [[TEST10]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST10]]* + // CHECK-NEXT: [[T4:%.*]] = bitcast [[TEST10]]* [[T3]] to i8* + // CHECK-NEXT: store i8* [[T4]], i8** [[Y]] + // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST10]]* [[V]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: [[T0:%.*]] = load [[TEST10]]** [[X]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: ret void +} + +void test11(id (*f)(void) __attribute__((ns_returns_retained))) { + // CHECK: define void @test11( + // CHECK: [[F:%.*]] = alloca i8* ()*, align + // CHECK-NEXT: [[X:%.*]] = alloca i8*, align + // CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align + // CHECK-NEXT: [[T0:%.*]] = load i8* ()** [[F]], align + // CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]() + // CHECK-NEXT: store i8* [[T1]], i8** [[X]], align + // CHECK-NEXT: [[T3:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T3]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: ret void + id x = f(); +} + +void test12(void) { + extern id test12_helper(void); + + // CHECK: define void @test12() + // CHECK: [[X:%.*]] = alloca i8*, align + // CHECK-NEXT: [[Y:%.*]] = alloca i8*, align + + __weak id x = test12_helper(); + // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T1]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + + x = test12_helper(); + // CHECK-NEXT: [[T0:%.*]] = call i8* @test12_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[X]], i8* [[T1]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + + id y = x; + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]]) + // CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align + + // CHECK-NEXT: [[T4:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T4]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]]) + // CHECK-NEXT: ret void +} + +// Indirect consuming calls. +void test13(void) { + // CHECK: define void @test13() + // CHECK: [[X:%.*]] = alloca i8*, align + // CHECK-NEXT: store i8* null, i8** [[X]], align + id x; + + typedef void fnty(id __attribute__((ns_consumed))); + extern fnty *test13_func; + // CHECK-NEXT: [[FN:%.*]] = load void (i8*)** @test13_func, align + // CHECK-NEXT: [[X_VAL:%.*]] = load i8** [[X]], align + // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) nounwind + // CHECK-NEXT: call void [[FN]](i8* [[X_TMP]]) + test13_func(x); + + extern fnty ^test13_block; + // CHECK-NEXT: [[TMP:%.*]] = load void (i8*)** @test13_block, align + // CHECK-NEXT: [[BLOCK:%.*]] = bitcast void (i8*)* [[TMP]] to [[BLOCKTY:%.*]]* + // CHECK-NEXT: [[BLOCK_FN_PTR:%.*]] = getelementptr inbounds [[BLOCKTY]]* [[BLOCK]], i32 0, i32 3 + // CHECK-NEXT: [[BLOCK_OPAQUE:%.*]] = bitcast [[BLOCKTY]]* [[BLOCK]] to i8* + // CHECK-NEXT: [[X_VAL:%.*]] = load i8** [[X]], align + // CHECK-NEXT: [[X_TMP:%.*]] = call i8* @objc_retain(i8* [[X_VAL]]) nounwind + // CHECK-NEXT: [[BLOCK_FN_TMP:%.*]] = load i8** [[BLOCK_FN_PTR]] + // CHECK-NEXT: [[BLOCK_FN:%.*]] = bitcast i8* [[BLOCK_FN_TMP]] to void (i8*, i8*)* + // CHECK-NEXT: call void [[BLOCK_FN]](i8* [[BLOCK_OPAQUE]], i8* [[X_TMP]]) + test13_block(x); + + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NEXT: ret void +} + +@interface Test16_super @end +@interface Test16 : Test16_super { + id z; +} +@property (assign) int x; +@property (retain) id y; +- (void) dealloc; +@end +@implementation Test16 +@synthesize x; +@synthesize y; +- (void) dealloc { + // CHECK: define internal void @"\01-[Test16 dealloc]"( + // CHECK: [[SELF:%.*]] = alloca [[TEST16:%.*]]*, align + // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align + // CHECK-NEXT: alloca + // CHECK-NEXT: store [[TEST16]]* {{%.*}}, [[TEST16]]** [[SELF]], align + // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] + // CHECK-NEXT: [[BASE:%.*]] = load [[TEST16]]** [[SELF]] + + // Call super. + // CHECK-NEXT: [[BASE2:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* + // CHECK-NEXT: [[T0:%.*]] = getelementptr + // CHECK-NEXT: store i8* [[BASE2]], i8** [[T0]] + // CHECK-NEXT: load {{%.*}}** @"\01L_OBJC_CLASSLIST_SUP_REFS_$_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: call void bitcast (i8* ({{.*}})* @objc_msgSendSuper2 to void ( + // CHECK-NEXT: ret void +} + +// .cxx_destruct + // CHECK: define internal void @"\01-[Test16 .cxx_destruct]"( + // CHECK: [[SELF:%.*]] = alloca [[TEST16:%.*]]*, align + // CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align + // CHECK-NEXT: store [[TEST16]]* {{%.*}}, [[TEST16]]** [[SELF]], align + // CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] + // CHECK-NEXT: [[BASE:%.*]] = load [[TEST16]]** [[SELF]] + + // Destroy y. + // CHECK-NEXT: [[Y_OFF:%.*]] = load i64* @"OBJC_IVAR_$_Test16.y" + // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[Y_OFF]] + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** + // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) nounwind + + // Destroy z. + // CHECK-NEXT: [[Z_OFF:%.*]] = load i64* @"OBJC_IVAR_$_Test16.z" + // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST16]]* [[BASE]] to i8* + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[Z_OFF]] + // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** + // CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) nounwind + + // CHECK-NEXT: ret void + +@end + +// This shouldn't crash. +@interface Test17A +@property (assign) int x; +@end +@interface Test17B : Test17A +@end +@implementation Test17B +- (int) x { return super.x + 1; } +@end + +void test19() { + // CHECK: define void @test19() + // CHECK: [[X:%.*]] = alloca [5 x i8*], align 16 + // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false) + id x[5]; + + extern id test19_helper(void); + x[2] = test19_helper(); + + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test19_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) nounwind + // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [5 x i8*]* [[X]], i32 0, i64 2 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]] + // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + + // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x i8*]* [[X]], i32 0, i32 0 + // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 5 + // CHECK-NEXT: br label + + // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] + // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] + // CHECK-NEXT: br i1 [[EQ]], + + // CHECK: ret void +} + +void test20(unsigned n) { + // CHECK: define void @test20 + // CHECK: [[N:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* + // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 + + id x[n]; + + // Capture the VLA size. + // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4 + // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 + + // Save the stack pointer. + // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave() + // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]] + + // Allocate the VLA. + // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16 + + // Zero-initialize. + // CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8* + // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8 + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T1]], i32 8, i1 false) + + // Destroy. + // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[VLA]], i64 [[DIM]] + // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq i8** [[VLA]], [[END]] + // CHECK-NEXT: br i1 [[EMPTY]] + + // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] + // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[VLA]] + // CHECK-NEXT: br i1 [[EQ]], + + // CHECK: [[T0:%.*]] = load i8** [[SAVED_STACK]] + // CHECK-NEXT: call void @llvm.stackrestore(i8* [[T0]]) + // CHECK-NEXT: ret void +} + +void test21(unsigned n) { + // CHECK: define void @test21 + // CHECK: [[N:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* + // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 + + id x[2][n][3]; + + // Capture the VLA size. + // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4 + // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64 + + // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave() + // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]] + + + // Allocate the VLA. + // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] + // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16 + + // Zero-initialize. + // CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8* + // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]] + // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24 + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T2]], i32 8, i1 false) + + // Destroy. + // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] + // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x i8*]* [[VLA]], i32 0, i32 0 + // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3 + // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[T1]] + // CHECK-NEXT: [[EMPTY:%.*]] = icmp eq i8** [[BEGIN]], [[END]] + // CHECK-NEXT: br i1 [[EMPTY]] + + // CHECK: [[AFTER:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] + // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds i8** [[AFTER]], i64 -1 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: [[EQ:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] + // CHECK-NEXT: br i1 [[EQ]], + + // CHECK: [[T0:%.*]] = load i8** [[SAVED_STACK]] + // CHECK-NEXT: call void @llvm.stackrestore(i8* [[T0]]) + // CHECK-NEXT: ret void +} + +void test22(_Bool cond) { + id test22_helper(void) __attribute__((ns_returns_retained)); + + // CHECK: define void @test22( + // CHECK: [[COND:%.*]] = alloca i8, + // CHECK-NEXT: [[X:%.*]] = alloca i8*, + // CHECK-NEXT: [[RELVAL:%.*]] = alloca i8* + // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1 + // CHECK-NEXT: zext + // CHECK-NEXT: store + // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 + // CHECK-NEXT: store i1 false, i1* [[RELCOND]] + // CHECK-NEXT: br i1 [[T1]], + // CHECK: br label + // CHECK: [[CALL:%.*]] = call i8* @test22_helper() + // CHECK-NEXT: store i8* [[CALL]], i8** [[RELVAL]] + // CHECK-NEXT: store i1 true, i1* [[RELCOND]] + // CHECK-NEXT: br label + // CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) nounwind + // CHECK-NEXT: store i8* [[T1]], i8** [[X]], + // CHECK-NEXT: [[REL:%.*]] = load i1* [[RELCOND]] + // CHECK-NEXT: br i1 [[REL]], + // CHECK: [[T0:%.*]] = load i8** [[RELVAL]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NEXT: br label + // CHECK: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind + // CHECK-NEXT: ret void + id x = (cond ? 0 : test22_helper()); +} + +// rdar://problem/8922540 +// Note that we no longer emit .release_ivars flags. +// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test23" = internal global [[RO_T:%.*]] { i32 134, +@interface Test23 { id x; } @end +@implementation Test23 @end + +// CHECK-GLOBALS: @"\01l_OBJC_CLASS_RO_$_Test24" = internal global [[RO_T:%.*]] { i32 130, +@interface Test24 {} @end +@implementation Test24 @end + +// rdar://problem/8941012 +@interface Test26 { id x[4]; } @end +@implementation Test26 @end +// CHECK: define internal void @"\01-[Test26 .cxx_destruct]"( +// CHECK: [[SELF:%.*]] = load [[TEST26:%.*]]** +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test26.x" +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST26]]* [[SELF]] to i8* +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[OFFSET]] +// CHECK-NEXT: [[X:%.*]] = bitcast i8* [[T1]] to [4 x i8*]* +// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x i8*]* [[X]], i32 0, i32 0 +// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 4 +// CHECK-NEXT: br label +// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] +// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1 +// CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null) +// CHECK-NEXT: [[ISDONE:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] +// CHECK-NEXT: br i1 [[ISDONE]], +// CHECK: ret void + +// Check that 'init' retains self. +@interface Test27 +- (id) init; +@end +@implementation Test27 +- (id) init { return self; } +// CHECK: define internal i8* @"\01-[Test27 init]" +// CHECK: [[SELF:%.*]] = alloca [[TEST27:%.*]]*, +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, +// CHECK-NEXT: [[DEST:%.*]] = alloca i32 +// CHECK-NEXT: store [[TEST27]]* {{%.*}}, [[TEST27]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] +// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* +// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i32 {{[0-9]+}}, i32* [[DEST]] +// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) +// CHECK-NEXT: ret i8* [[RET]] + +@end + +// rdar://problem/8087194 +@interface Test28 +@property (copy) id prop; +@end +@implementation Test28 +@synthesize prop; +@end +// CHECK: define internal void @"\01-[Test28 .cxx_destruct]" +// CHECK: [[SELF:%.*]] = load [[TEST28:%.*]]** +// CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test28.prop" +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST28]]* [[SELF]] to i8* +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8* [[T0]], i64 [[OFFSET]] +// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to i8** +// CHECK-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null) +// CHECK-NEXT: ret void + +@interface Test29_super +- (id) initWithAllocator: (id) allocator; +@end +@interface Test29 : Test29_super +- (id) init; +- (id) initWithAllocator: (id) allocator; +@end +@implementation Test29 +static id _test29_allocator = 0; +- (id) init { +// CHECK: define internal i8* @"\01-[Test29 init]"([[TEST29:%.*]]* {{%.*}}, +// CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8 +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32 +// CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] + +// Evaluate arguments. Note that the send argument is evaluated +// before the zeroing of self. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]], align 8 +// CHECK-NEXT: [[T1:%.*]] = load i8** @_test29_allocator, align 8 + +// Implicit null of 'self', i.e. direct transfer of ownership. +// CHECK-NEXT: store [[TEST29]]* null, [[TEST29]]** [[SELF]] + +// Actual message send. +// CHECK-NEXT: [[T2:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-NEXT: [[T3:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* +// CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T3]], i8* [[T2]], i8* [[T1]]) + +// Implicit write of result back into 'self'. This is not supposed to +// be detectable because we're supposed to ban accesses to the old +// self value past the delegate init call. +// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* +// CHECK-NEXT: store [[TEST29]]* [[T0]], [[TEST29]]** [[SELF]] + +// Return statement. +// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]] +// CHECK-NEXT: [[CALL:%.*]] = bitcast +// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[CALL]]) nounwind +// CHECK-NEXT: store i32 1, i32* [[CLEANUP]] + +// Cleanup. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + +// Return. +// CHECK-NEXT: ret i8* [[RET]] + return [self initWithAllocator: _test29_allocator]; +} +- (id) initWithAllocator: (id) allocator { +// CHECK: define internal i8* @"\01-[Test29 initWithAllocator:]"( +// CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8 +// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: alloca +// CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32 +// CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]] +// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]] +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) +// CHECK-NEXT: store i8* [[T0]], i8** [[ALLOCATOR]] + +// Evaluate arguments. Note that the send argument is evaluated +// before the zeroing of self. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = load i8** [[ALLOCATOR]], align 8 + +// Implicit null of 'self', i.e. direct transfer of ownership. +// CHECK-NEXT: store [[TEST29]]* null, [[TEST29]]** [[SELF]] + +// Actual message send. +// CHECK: [[CALL:%.*]] = call {{.*}} @objc_msgSendSuper2 + +// Implicit write of result back into 'self'. This is not supposed to +// be detectable because we're supposed to ban accesses to the old +// self value past the delegate init call. +// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* +// CHECK-NEXT: store [[TEST29]]* [[T0]], [[TEST29]]** [[SELF]] + +// Assignment. +// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CALL]] to [[TEST29]]* +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST29]]* +// CHECK-NEXT: [[T4:%.*]] = load [[TEST29]]** [[SELF]], align +// CHECK-NEXT: store [[TEST29]]* [[T3]], [[TEST29]]** [[SELF]], align +// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST29]]* [[T4]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T5]]) + +// Return statement. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* +// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind +// CHECK-NEXT: store i32 1, i32* [[CLEANUP]] + +// Cleanup. +// CHECK-NEXT: [[T0:%.*]] = load i8** [[ALLOCATOR]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release + +// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + +// Return. +// CHECK-NEXT: ret i8* [[RET]] + self = [super initWithAllocator: allocator]; + return self; +} +@end + +typedef struct Test30_helper Test30_helper; +@interface Test30 +- (id) init; +- (Test30_helper*) initHelper; +@end +@implementation Test30 { +char *helper; +} +- (id) init { +// CHECK: define internal i8* @"\01-[Test30 init]"([[TEST30:%.*]]* {{%.*}}, +// CHECK: [[RET:%.*]] = alloca [[TEST30]]* +// CHECK-NEXT: alloca i8* +// CHECK-NEXT: alloca i32 +// CHECK-NEXT: store [[TEST30]]* {{%.*}}, [[TEST30]]** [[SELF]] +// CHECK-NEXT: store + +// Call. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* +// CHECK-NEXT: [[CALL:%.*]] = call [[TEST30_HELPER:%.*]]* bitcast {{.*}} @objc_msgSend {{.*}}(i8* [[T2]], i8* [[T1]]) + +// Assignment. +// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST30_HELPER]]* [[CALL]] to i8* +// CHECK-NEXT: [[T1:%.*]] = load [[TEST30]]** [[SELF]] +// CHECK-NEXT: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_Test30.helper" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST30]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[IVAR]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT#: [[T5:%.*]] = load i8** [[T4]] +// CHECK-NEXT#: [[T6:%.*]] = call i8* @objc_retain(i8* [[T0]]) +// CHECK-NEXT#: call void @objc_release(i8* [[T5]]) +// CHECK-NEXT: store i8* [[T0]], i8** [[T4]] + +// Return. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* +// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i32 1 + +// Cleanup. +// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) + +// Epilogue. +// CHECK-NEXT: ret i8* [[RET]] + self->helper = [self initHelper]; + return self; +} +- (Test30_helper*) initHelper { +// CHECK: define internal [[TEST30_HELPER]]* @"\01-[Test30 initHelper]"( +// CHECK: alloca +// CHECK-NEXT: alloca +// CHECK-NEXT: store +// CHECK-NEXT: store +// CHECK-NEXT: ret [[TEST30_HELPER]]* null + return 0; +} + +@end + +__attribute__((ns_returns_retained)) id test32(void) { +// CHECK: define i8* @test32() +// CHECK: [[CALL:%.*]] = call i8* @test32_helper() +// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) +// CHECK-NEXT: ret i8* [[T0]] + extern id test32_helper(void); + return test32_helper(); +} + +@class Test33_a; +@interface Test33 +- (void) give: (Test33_a **) x; +- (void) take: (Test33_a **) x; +- (void) giveStrong: (out __strong Test33_a **) x; +- (void) takeStrong: (inout __strong Test33_a **) x; +- (void) giveOut: (out Test33_a **) x; +@end +void test33(Test33 *ptr) { + Test33_a *a; + [ptr give: &a]; + [ptr take: &a]; + [ptr giveStrong: &a]; + [ptr takeStrong: &a]; + [ptr giveOut: &a]; + + // CHECK: define void @test33([[TEST33:%.*]]* + // CHECK: [[PTR:%.*]] = alloca [[TEST33]]* + // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]]* + // CHECK-NEXT: [[TEMP0:%.*]] = alloca [[A_T]]* + // CHECK-NEXT: [[TEMP1:%.*]] = alloca [[A_T]]* + // CHECK-NEXT: [[TEMP2:%.*]] = alloca [[A_T]]* + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_retain + // CHECK-NEXT: bitcast + // CHECK-NEXT: store + // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[A]] + + // CHECK-NEXT: load [[TEST33]]** [[PTR]] + // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[T0]], [[A_T]]** [[TEMP0]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP0]]) + // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[TEMP0]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* + // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] + // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T5]]) + + // CHECK-NEXT: load [[TEST33]]** [[PTR]] + // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[T0]], [[A_T]]** [[TEMP1]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP1]]) + // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[TEMP1]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* + // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] + // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T5]]) + + // CHECK-NEXT: load [[TEST33]]** [[PTR]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[A]]) + + // CHECK-NEXT: load [[TEST33]]** [[PTR]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[A]]) + + // 'out' + // CHECK-NEXT: load [[TEST33]]** [[PTR]] + // CHECK-NEXT: store [[A_T]]* null, [[A_T]]** [[TEMP2]] + // CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_msgSend{{.*}}, [[A_T]]** [[TEMP2]]) + // CHECK-NEXT: [[T0:%.*]] = load [[A_T]]** [[TEMP2]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[A_T]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A_T]]* + // CHECK-NEXT: [[T4:%.*]] = load [[A_T]]** [[A]] + // CHECK-NEXT: store [[A_T]]* [[T3]], [[A_T]]** [[A]] + // CHECK-NEXT: [[T5:%.*]] = bitcast [[A_T]]* [[T4]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T5]]) + + // CHECK-NEXT: load + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_release + // CHECK-NEXT: load + // CHECK-NEXT: bitcast + // CHECK-NEXT: objc_release + // CHECK-NEXT: ret void +} + +void test34(int cond) { + __strong id strong; + __weak id weak; + extern void test34_sink(id *); + test34_sink(cond ? &strong : 0); + test34_sink(cond ? &weak : 0); + + // CHECK: define void @test34( + // CHECK: [[COND:%.*]] = alloca i32 + // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* + // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* + // CHECK-NEXT: store i32 + // CHECK-NEXT: store i8* null, i8** [[STRONG]] + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) + + // CHECK-NEXT: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] + // CHECK-NEXT: br label + // CHECK: call void @test34_sink(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: [[T2:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: br label + + // CHECK: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[ARG]]) + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] + // CHECK-NEXT: br label + // CHECK: call void @test34_sink(i8** [[T1]]) + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[TEMP2]] + // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]]) + // CHECK-NEXT: br label + + // CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) + // CHECK: ret void +} + +// CHECK: define void @test36 +void test36(id x) { + // CHECK: [[X:%.*]] = alloca i8* + + // CHECK: call i8* @objc_retain + // CHECK: call i8* @objc_retain + // CHECK: call i8* @objc_retain + id array[3] = { @"A", x, @"y" }; + + // CHECK: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + x = 0; + + // CHECK: br label + // CHECK: call void @objc_release + // CHECK: br i1 + + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +@class Test37; +void test37(void) { + extern void test37_helper(id *); + Test37 *var; + test37_helper(&var); + + // CHECK: define void @test37() + // CHECK: [[VAR:%.*]] = alloca [[TEST37:%.*]]*, + // CHECK-NEXT: [[TEMP:%.*]] = alloca i8* + // CHECK-NEXT: store [[TEST37]]* null, [[TEST37]]** [[VAR]] + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]** [[VAR]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8* + // CHECK-NEXT: store i8* [[T1]], i8** [[TEMP]] + // CHECK-NEXT: call void @test37_helper(i8** [[TEMP]]) + // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]] + // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST37]]* + // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST37]]* [[T1]] to i8* + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST37]]* + // CHECK-NEXT: [[T5:%.*]] = load [[TEST37]]** [[VAR]] + // CHECK-NEXT: store [[TEST37]]* [[T4]], [[TEST37]]** [[VAR]] + // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST37]]* [[T5]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T6]]) + + // CHECK-NEXT: [[T0:%.*]] = load [[TEST37]]** [[VAR]] + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: ret void +} + +@interface Test43 @end +@implementation Test43 +- (id) test __attribute__((ns_returns_retained)) { + extern id test43_produce(void); + return test43_produce(); + // CHECK: call i8* @test43_produce() + // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue( + // CHECK-NEXT: ret +} +@end + +@interface Test45 +@property (retain) id x; +@end +@implementation Test45 +@synthesize x; +@end +// CHECK: define internal i8* @"\01-[Test45 x]"( +// CHECK: [[CALL:%.*]] = call i8* @objc_getProperty( +// CHECK-NEXT: ret i8* [[CALL]] + +// rdar://problem/9315552 +void test46(__weak id *wp, __weak volatile id *wvp) { + extern id test46_helper(void); + + // TODO: this is sub-optimal, we should retain at the actual call site. + + // CHECK: [[T0:%.*]] = call i8* @test46_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8*** {{%.*}}, align 8 + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]]) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]]) + // CHECK-NEXT: store i8* [[T4]], i8** + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + id x = *wp = test46_helper(); + + // CHECK: [[T0:%.*]] = call i8* @test46_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8*** {{%.*}}, align 8 + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]]) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]]) + // CHECK-NEXT: store i8* [[T4]], i8** + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + id y = *wvp = test46_helper(); +} + +// rdar://problem/9378887 +void test47(void) { + extern id test47_helper(void); + id x = x = test47_helper(); + + // CHECK: define void @test47() + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test47_helper() + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) + // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* [[T0]], i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: [[T3:%.*]] = load i8** [[X]] + // CHECK-NEXT: store i8* [[T2]], i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T3]]) + // CHECK-NEXT: [[T4:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T4]]) + // CHECK-NEXT: ret void +} + +void test48(void) { + extern id test48_helper(void); + __weak id x = x = test48_helper(); + // CHECK: define void @test48() + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_initWeak(i8** [[X]], i8* null) + // CHECK-NEXT: [[T1:%.*]] = call i8* @test48_helper() + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[X]], i8* [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_storeWeak(i8** [[X]], i8* [[T3]]) + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]]) + // CHECK-NEXT: ret void +} + +void test49(void) { + extern id test49_helper(void); + __autoreleasing id x = x = test49_helper(); + // CHECK: define void @test49() + // CHECK: [[X:%.*]] = alloca i8* + // CHECK-NEXT: store i8* null, i8** [[X]] + // CHECK-NEXT: [[CALL:%.*]] = call i8* @test49_helper() + // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]]) + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autorelease(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T2]], i8** [[X]] + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) + // CHECK-NEXT: store i8* [[T3]], i8** [[X]] + // CHECK-NEXT: ret void +} + +// rdar://9380136 +id x(); +void test50(id y) { + ({x();}); +// CHECK: [[T0:%.*]] = call i8* @objc_retain +// CHECK: call void @objc_release +} + + +// rdar://9400762 +struct CGPoint { + float x; + float y; +}; +typedef struct CGPoint CGPoint; + +@interface Foo +@property (assign) CGPoint point; +@end + +@implementation Foo +@synthesize point; +@end + +// rdar://problem/9400398 +id test52(void) { + id test52_helper(int) __attribute__((ns_returns_retained)); + return ({ int x = 5; test52_helper(x); }); + +// CHECK: define i8* @test52() +// CHECK: [[X:%.*]] = alloca i32 +// CHECK-NEXT: store i32 5, i32* [[X]], +// CHECK-NEXT: [[T0:%.*]] = load i32* [[X]], +// CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) +// CHECK-NEXT: ret i8* [[T2]] +} + +// rdar://problem/9400644 +void test53(void) { + id test53_helper(void); + id x = ({ id y = test53_helper(); y; }); + (void) x; +// CHECK: define void @test53() +// CHECK: [[X:%.*]] = alloca i8*, +// CHECK-NEXT: [[Y:%.*]] = alloca i8*, +// CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper() +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[Y]], +// CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]], +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = load i8** [[Y]] +// CHECK-NEXT: call void @objc_release(i8* [[T2]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[X]], +// CHECK-NEXT: load i8** [[X]], +// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: ret void +} + +// <rdar://problem/9758798> +// CHECK: define void @test54(i32 %first, ...) +void test54(int first, ...) { + __builtin_va_list arglist; + // CHECK: call void @llvm.va_start + __builtin_va_start(arglist, first); + // CHECK: call i8* @objc_retain + id obj = __builtin_va_arg(arglist, id); + // CHECK: call void @llvm.va_end + __builtin_va_end(arglist); + // CHECK: call void @objc_release + // CHECK: ret void +} + +// PR10228 +@interface Test55Base @end +@interface Test55 : Test55Base @end +@implementation Test55 (Category) +- (void) dealloc {} +@end +// CHECK: define internal void @"\01-[Test55(Category) dealloc]"( +// CHECK-NOT: ret +// CHECK: call void bitcast (i8* ({{%.*}}*, i8*, ...)* @objc_msgSendSuper2 to void ({{%.*}}*, i8*)*)( + +// rdar://problem/8024350 +@protocol Test56Protocol ++ (id) make __attribute__((ns_returns_retained)); +@end +@interface Test56<Test56Protocol> @end +@implementation Test56 +// CHECK: define internal i8* @"\01+[Test56 make]"( ++ (id) make { + extern id test56_helper(void); + // CHECK: [[T0:%.*]] = call i8* @test56_helper() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: ret i8* [[T1]] + return test56_helper(); +} +@end +void test56_test(void) { + id x = [Test56 make]; + // CHECK: define void @test56_test() + // CHECK: [[X:%.*]] = alloca i8*, align 8 + // CHECK: [[T0:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)( + // CHECK-NEXT: store i8* [[T0]], i8** [[X]] + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: ret void +} + +// rdar://problem/9784964 +@interface Test57 +@property (nonatomic, strong) id strong; +@property (nonatomic, weak) id weak; +@property (nonatomic, unsafe_unretained) id unsafe; +@end +@implementation Test57 +@synthesize strong, weak, unsafe; +@end +// CHECK: define internal i8* @"\01-[Test57 strong]"( +// CHECK: [[T0:%.*]] = load [[TEST57:%.*]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.strong" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = load i8** [[T4]] +// CHECK-NEXT: ret i8* [[T5]] + +// CHECK: define internal i8* @"\01-[Test57 weak]"( +// CHECK: [[T0:%.*]] = load [[TEST57]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.weak" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]]) +// CHECK-NEXT: [[T6:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T5]]) +// CHECK-NEXT: ret i8* [[T6]] + +// CHECK: define internal i8* @"\01-[Test57 unsafe]"( +// CHECK: [[T0:%.*]] = load [[TEST57]]** {{%.*}} +// CHECK-NEXT: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_Test57.unsafe" +// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST57]]* [[T0]] to i8* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]] +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8** +// CHECK-NEXT: [[T5:%.*]] = load i8** [[T4]] +// CHECK-NEXT: ret i8* [[T5]] + +// rdar://problem/9821110 +@interface Test58 +- (char*) interior __attribute__((objc_returns_inner_pointer)); +// Should we allow this on properties? +@end +extern Test58 *test58_helper(void); + +// CHECK: define void @test58a() +void test58a(void) { + // CHECK: [[T0:%.*]] = call [[TEST58:%.*]]* @test58_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* + // CHECK-NEXT: store [[TEST58]]* [[T3]] + // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* + // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST58]]* [[T3]] to i8* + // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast + // CHECK-NEXT: store i8* [[T6]], i8** + // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release + // CHECK-NEXT: ret void + Test58 *ptr = test58_helper(); + char *c = [(ptr) interior]; +} + +// CHECK: define void @test58b() +void test58b(void) { + // CHECK: [[T0:%.*]] = call [[TEST58:%.*]]* @test58_helper() + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) + // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST58]]* + // CHECK-NEXT: store [[TEST58]]* [[T3]] + // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** + // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast + // CHECK-NEXT: store i8* [[T3]], i8** + // CHECK-NEXT: [[T0:%.*]] = load [[TEST58]]** + // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST58]]* [[T0]] to i8* + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind + // CHECK-NOT: clang.imprecise_release + // CHECK-NEXT: ret void + __attribute__((objc_precise_lifetime)) Test58 *ptr = test58_helper(); + char *c = [ptr interior]; +} + +// rdar://problem/9842343 +void test59(void) { + extern id test59_getlock(void); + extern void test59_body(void); + @synchronized (test59_getlock()) { + test59_body(); + } + + // CHECK: define void @test59() + // CHECK: [[T0:%.*]] = call i8* @test59_getlock() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: call void @objc_sync_enter(i8* [[T1]]) + // CHECK-NEXT: call void @test59_body() + // CHECK-NEXT: call void @objc_sync_exit(i8* [[T1]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + // CHECK-NEXT: ret void +} + +// Verify that we don't try to reclaim the result of performSelector. +// rdar://problem/9887545 +@interface Test61 +- (id) performSelector: (SEL) selector; +- (void) test61_void; +- (id) test61_id; +@end +void test61(void) { + // CHECK: define void @test61() + // CHECK: [[Y:%.*]] = alloca i8*, align 8 + + extern id test61_make(void); + + // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T3:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]]) + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + [test61_make() performSelector: @selector(test61_void)]; + + // CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T3:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ + // CHECK-NEXT: [[T4:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[T1]], i8* [[T3]], i8* [[T2]]) + // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]]) + // CHECK-NEXT: store i8* [[T5]], i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + id y = [test61_make() performSelector: @selector(test61_id)]; + + // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: ret void +} + +// rdar://problem/9891815 +void test62(void) { + // CHECK: define void @test62() + // CHECK: [[I:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[CLEANUP_VALUE:%.*]] = alloca i8* + // CHECK-NEXT: [[CLEANUP_REQUIRED:%.*]] = alloca i1 + extern id test62_make(void); + extern void test62_body(void); + + // CHECK-NEXT: store i32 0, i32* [[I]], align 4 + // CHECK-NEXT: br label + + // CHECK: [[T0:%.*]] = load i32* [[I]], align 4 + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 20 + // CHECK-NEXT: br i1 [[T1]], + + for (unsigned i = 0; i != 20; ++i) { + // CHECK: [[T0:%.*]] = load i32* [[I]], align 4 + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK-NEXT: store i1 false, i1* [[CLEANUP_REQUIRED]] + // CHECK-NEXT: br i1 [[T1]], + // CHECK: [[T0:%.*]] = call i8* @test62_make() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_VALUE]] + // CHECK-NEXT: store i1 true, i1* [[CLEANUP_REQUIRED]] + // CHECK-NEXT: [[T2:%.*]] = icmp ne i8* [[T1]], null + // CHECK-NEXT: br label + // CHECK: [[COND:%.*]] = phi i1 [ false, {{%.*}} ], [ [[T2]], {{%.*}} ] + // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_REQUIRED]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[CLEANUP_VALUE]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: br label + // CHECK: br i1 [[COND]] + // CHECK: call void @test62_body() + // CHECK-NEXT: br label + // CHECK: br label + if (i != 0 && test62_make() != 0) + test62_body(); + } + + // CHECK: [[T0:%.*]] = load i32* [[I]], align 4 + // CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 1 + // CHECK-NEXT: store i32 [[T1]], i32* [[I]] + // CHECK-NEXT: br label + + // CHECK: ret void +} + +// rdar://9971982 +@class NSString; + +@interface Person { + NSString *name; +} +@property NSString *address; +@end + +@implementation Person +@synthesize address; +@end +// CHECK: call i8* @objc_getProperty +// CHECK: call void @objc_setProperty + +// Verify that we successfully parse and preserve this attribute in +// this position. +@interface Test66 +- (void) consume: (id __attribute__((ns_consumed))) ptr; +@end +void test66(void) { + extern Test66 *test66_receiver(void); + extern id test66_arg(void); + [test66_receiver() consume: test66_arg()]; +} +// CHECK: define void @test66() +// CHECK: [[T0:%.*]] = call [[TEST66:%.*]]* @test66_receiver() +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST66]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST66]]* +// CHECK-NEXT: [[T4:%.*]] = call i8* @test66_arg() +// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]]) +// CHECK-NEXT: [[T6:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8* +// CHECK-NEXT: [[SIX:%.*]] = icmp eq i8* [[T7]], null +// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label [[CALL:%.*]] +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]]) +// CHECK-NEXT: br label [[CONT:%.*]] +// CHECK: call void @objc_release(i8* [[T5]]) nounwind +// CHECK-NEXT: br label [[CONT:%.*]] +// CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T8]]) +// CHECK-NEXT: ret void + +// rdar://problem/9953540 +Class test67_helper(void); +void test67(void) { + Class cl = test67_helper(); +} +// CHECK: define void @test67() +// CHECK: [[CL:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper() +// CHECK-NEXT: store i8* [[T0]], i8** [[CL]], align 8 +// CHECK-NEXT: ret void + +Class test68_helper(void); +void test68(void) { + __strong Class cl = test67_helper(); +} +// CHECK: define void @test68() +// CHECK: [[CL:%.*]] = alloca i8*, align 8 +// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper() +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8 +// CHECK-NEXT: [[T2:%.*]] = load i8** [[CL]] +// CHECK-NEXT: call void @objc_release(i8* [[T2]]) +// CHECK-NEXT: ret void + +// rdar://problem/10564852 +@interface Test69 @end +@implementation Test69 +- (id) foo { return self; } +@end +// CHECK: define internal i8* @"\01-[Test69 foo]"( +// CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[TEST69]]** [[SELF]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8* +// CHECK-NEXT: ret i8* [[T1]] + +// rdar://problem/10907547 +void test70(id i) { + // CHECK: define void @test70 + // CHECK: store i8* null, i8** + // CHECK: store i8* null, i8** + // CHECK: [[ID:%.*]] = call i8* @objc_retain(i8* + // CHECK: store i8* [[ID]], i8** + id x[3] = { + [2] = i + }; +} diff --git a/clang/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m b/clang/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m new file mode 100644 index 0000000..535cbbb --- /dev/null +++ b/clang/test/CodeGenObjC/arm-atomic-scalar-setter-getter.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -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/clang/test/CodeGenObjC/assign.m b/clang/test/CodeGenObjC/assign.m new file mode 100644 index 0000000..82da800 --- /dev/null +++ b/clang/test/CodeGenObjC/assign.m @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s + +struct s0 { + int x; +}; + +@interface C0 +@property int x0; +@property _Complex int x1; +@property struct s0 x2; +@end + +// Check that we get exactly the message sends we expect, and no more. +// +// CHECK: define void @f0 +void f0(C0 *a) { +// CHECK: objc_msgSend + int l0 = (a.x0 = 1); + +// CHECK: objc_msgSend + _Complex int l1 = (a.x1 = 1); + +// CHECK: objc_msgSend + struct s0 l2 = (a.x2 = (struct s0) { 1 }); + +// CHECK: objc_msgSend +// CHECK: objc_msgSend + int l3 = (a.x0 += 1); + +// CHECK: objc_msgSend +// CHECK: objc_msgSend + _Complex int l4 = (a.x1 += 1); + +// CHECK-NOT: objc_msgSend +// CHECK: } +} diff --git a/clang/test/CodeGenObjC/atomic-aggregate-property.m b/clang/test/CodeGenObjC/atomic-aggregate-property.m new file mode 100644 index 0000000..978299b --- /dev/null +++ b/clang/test/CodeGenObjC/atomic-aggregate-property.m @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// rdar: // 7849824 + +struct s { + double a, b, c, d; +}; + +struct s1 { + int i; + id j; + id k; +}; + +@interface A +@property (readwrite) double x; +@property (readwrite) struct s y; +@property (nonatomic, readwrite) struct s1 z; +@end + +@implementation A +@synthesize x; +@synthesize y; +@synthesize z; +@end +// CHECK-LP64: define internal double @"\01-[A x]"( +// CHECK-LP64: load atomic i64* {{%.*}} unordered, align 8 + +// CHECK-LP64: define internal void @"\01-[A setX:]"( +// CHECK-LP64: store atomic i64 {{%.*}}, i64* {{%.*}} unordered, align 8 + +// CHECK-LP64: define internal void @"\01-[A y]"( +// CHECK-LP64: call void @objc_copyStruct(i8* {{%.*}}, i8* {{%.*}}, i64 32, i1 zeroext true, i1 zeroext false) + +// CHECK-LP64: define internal void @"\01-[A setY:]"( +// CHECK-LP64: call void @objc_copyStruct(i8* {{%.*}}, i8* {{%.*}}, i64 32, i1 zeroext true, i1 zeroext false) + +// CHECK-LP64: define internal void @"\01-[A z]"( +// CHECK-LP64: call i8* @objc_memmove_collectable( + +// CHECK-LP64: define internal void @"\01-[A setZ:]"( +// CHECK-LP64: call i8* @objc_memmove_collectable( diff --git a/clang/test/CodeGenObjC/attr-availability.m b/clang/test/CodeGenObjC/attr-availability.m new file mode 100644 index 0000000..375a5be --- /dev/null +++ b/clang/test/CodeGenObjC/attr-availability.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin8.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_4 %s +// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin9.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_5 %s +// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin10.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_6 %s + +// CHECK-10_4: @"OBJC_CLASS_$_WeakClass1" = extern_weak global +// CHECK-10_5: @"OBJC_CLASS_$_WeakClass1" = external global +// CHECK-10_6: @"OBJC_CLASS_$_WeakClass1" = external global +__attribute__((availability(macosx,introduced=10.5))) +@interface WeakClass1 @end + +@implementation WeakClass1(MyCategory) @end + +@implementation WeakClass1(YourCategory) @end + +// CHECK-10_4: @"OBJC_CLASS_$_WeakClass2" = extern_weak global +// CHECK-10_5: @"OBJC_CLASS_$_WeakClass2" = extern_weak global +// CHECK-10_6: @"OBJC_CLASS_$_WeakClass2" = external global +__attribute__((availability(macosx,introduced=10.6))) +@interface WeakClass2 @end + +@implementation WeakClass2(MyCategory) @end + +@implementation WeakClass2(YourCategory) @end + diff --git a/clang/test/CodeGenObjC/attr-strong.c b/clang/test/CodeGenObjC/attr-strong.c new file mode 100644 index 0000000..f1474bc --- /dev/null +++ b/clang/test/CodeGenObjC/attr-strong.c @@ -0,0 +1,9 @@ +// RUN: %clang -emit-llvm -S -o %t %s + +struct s0 { + void *a; +}; +struct s0 * __attribute__((objc_gc(strong))) g0; +void f0(void) { + g0->a = 0; +} diff --git a/clang/test/CodeGenObjC/auto-property-synthesize-protocol.m b/clang/test/CodeGenObjC/auto-property-synthesize-protocol.m new file mode 100644 index 0000000..49a4037 --- /dev/null +++ b/clang/test/CodeGenObjC/auto-property-synthesize-protocol.m @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-default-synthesize-properties -emit-llvm %s -o - | FileCheck %s +// rdar://10907410 + +@protocol P +@optional +@property int auto_opt_window; +@property int no_auto_opt_window; +@end + +@interface I<P> +@property int auto_opt_window; +@end + +@implementation I +@end + +@protocol P1 +@property int auto_req_window; +@property int no_auto_req_window; // expected-note {{property declared here}} +@end + +@interface I1<P1> +@property int auto_req_window; +@end + +@implementation I1 // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} +@end + +// CHECK: define internal i32 @"\01-[I auto_opt_window]"( +// CHECK: define internal void @"\01-[I setAuto_opt_window:]"( +// CHECK: define internal i32 @"\01-[I1 auto_req_window]"( +// CHECK: define internal void @"\01-[I1 setAuto_req_window:]"( + +// CHECK-NOT: define internal i32 @"\01-[I1 no_auto_opt_window]"( +// CHECK-NOT: define internal void @"\01-[I1 setNo_auto_opt_window:]"( +// CHECK-NOT: define internal i32 @"\01-[I no_auto_req_window]"( +// CHECK-NOT: define internal void @"\01-[I setNo_auto_req_window:]"( diff --git a/clang/test/CodeGenObjC/autorelease.m b/clang/test/CodeGenObjC/autorelease.m new file mode 100644 index 0000000..9260c3f --- /dev/null +++ b/clang/test/CodeGenObjC/autorelease.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-arc -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fobjc-runtime-has-arc -o - %s | FileCheck %s +// rdar://8881826 +// rdar://9412038 + +@interface I +{ + id ivar; +} +- (id) Meth; ++ (id) MyAlloc;; +@end + +@implementation I +- (id) Meth { + @autoreleasepool { + id p = [I MyAlloc]; + if (!p) + return ivar; + } + return 0; +} ++ (id) MyAlloc { + return 0; +} +@end + +// CHECK: call i8* @objc_autoreleasePoolPush +// CHECK: [[T:%.*]] = load i8** [[A:%.*]] +// CHECK: call void @objc_autoreleasePoolPop diff --git a/clang/test/CodeGenObjC/bitfield-1.m b/clang/test/CodeGenObjC/bitfield-1.m new file mode 100644 index 0000000..648ab2a --- /dev/null +++ b/clang/test/CodeGenObjC/bitfield-1.m @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple i386-pc-linux-gnu -fobjc-fragile-abi -emit-llvm -o %t %s + +@interface Object +- (id) alloc; +- (id) init; +@end + +extern void abort(void); + +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object +{ + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +- (void)setValues; +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +- (void)checkValues; +@end + +@implementation Base +-(void)setValues { + full = 1; + full2 = 2; + _refs = 3; + field2 = 1; + f3 = 6; + cc = 7; + g = 8; + r2 = 9; + r3 = 10; + r4 = 1; + r5 = 12; + c = 13; +} +@end + +@implementation Derived +-(void)checkValues { + CHECK_IF(full == 1); + CHECK_IF(full2 == 2); + CHECK_IF(_refs == 3); + CHECK_IF(field2 == 1); + CHECK_IF(f3 == 6); + CHECK_IF(cc == 7); + CHECK_IF(g == 8); + CHECK_IF(r2 == 9); + CHECK_IF(r3 == 10); + CHECK_IF(r4 == 1); + CHECK_IF(r5 == 12); + CHECK_IF(c == 13); +} +@end + +int main(void) { + Derived *obj = [[Derived alloc] init]; + + [obj setValues]; + [obj checkValues]; + + return 0; +} diff --git a/clang/test/CodeGenObjC/bitfield-access.m b/clang/test/CodeGenObjC/bitfield-access.m new file mode 100644 index 0000000..521d2e5 --- /dev/null +++ b/clang/test/CodeGenObjC/bitfield-access.m @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o %t1 %s +// RUN: FileCheck -check-prefix=CHECK-I386 < %t1 %s + +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -fobjc-fragile-abi -target-abi apcs-gnu -emit-llvm -o %t2 %s +// RUN: FileCheck -check-prefix=CHECK-ARM < %t2 %s + +@interface I0 { +@public + unsigned x:15; + unsigned y: 1; +} +@end + +// Check that we don't try to use an i32 load here, which would reach beyond the +// end of the structure. +// +// CHECK-I386: define i32 @f0( +// CHECK-I386: [[t0_0:%.*]] = load i16* {{.*}}, align 1 +// CHECK-I386: lshr i16 [[t0_0]], 7 +// CHECK-I386: } +int f0(I0 *a) { + return a->y; +} + +// Check that we can handled straddled loads. +// +// CHECK-ARM: define i32 @f1( +// CHECK-ARM: [[t1_ptr:%.*]] = getelementptr +// CHECK-ARM: [[t1_base:%.*]] = bitcast i8* [[t1_ptr]] to i32* +// CHECK-ARM: [[t1_0:%.*]] = load i32* [[t1_base]], align 1 +// CHECK-ARM: lshr i32 [[t1_0]], 1 +// CHECK-ARM: [[t1_base_2_cast:%.*]] = bitcast i32* %{{.*}} to i8* +// CHECK-ARM: [[t1_base_2:%.*]] = getelementptr i8* [[t1_base_2_cast]] +// CHECK-ARM: [[t1_1:%.*]] = load i8* [[t1_base_2]], align 1 +// CHECK-ARM: and i8 [[t1_1:%.*]], 1 +// CHECK-ARM: } +@interface I1 { +@public + unsigned x: 1; + unsigned y:32; +} +@end + +int f1(I1 *a) { return a->y; } diff --git a/clang/test/CodeGenObjC/bitfield-gnu.m b/clang/test/CodeGenObjC/bitfield-gnu.m new file mode 100644 index 0000000..7935bda --- /dev/null +++ b/clang/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/clang/test/CodeGenObjC/bitfield-ivar-metadata.m b/clang/test/CodeGenObjC/bitfield-ivar-metadata.m new file mode 100644 index 0000000..9ab3fef --- /dev/null +++ b/clang/test/CodeGenObjC/bitfield-ivar-metadata.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface INTF +{ + unsigned ivar1; + unsigned ivar2; + unsigned char BDIVAR3:1; + unsigned char BDIVAR4:1; +} +@end + +@implementation INTF +@end + + diff --git a/clang/test/CodeGenObjC/bitfield-ivar-offsets.m b/clang/test/CodeGenObjC/bitfield-ivar-offsets.m new file mode 100644 index 0000000..b0c848f --- /dev/null +++ b/clang/test/CodeGenObjC/bitfield-ivar-offsets.m @@ -0,0 +1,25 @@ +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// RUN: grep -F '@"OBJC_IVAR_$_I0._b0" = global i64 0, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._b1" = global i64 0, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._b2" = global i64 1, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._x" = global i64 2, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._b3" = global i64 4, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._y" = global i64 6, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0._b4" = global i64 7, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep -F '@"OBJC_IVAR_$_I0." = global' %t | count 0 + +@interface I0 { + unsigned _b0:4; + unsigned _b1:5; + unsigned _b2:5; + char _x; + unsigned _b3:9; + char _y; + char _b4:3; + char : 0; +} +@end + +@implementation I0 +@end diff --git a/clang/test/CodeGenObjC/bitfield_encoding.m b/clang/test/CodeGenObjC/bitfield_encoding.m new file mode 100644 index 0000000..17fd4a4 --- /dev/null +++ b/clang/test/CodeGenObjC/bitfield_encoding.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: grep "ib1b14" %t | count 1 +// RUN: %clang_cc1 -triple i386-unknown-unknown -fobjc-fragile-abi -fgnu-runtime -emit-llvm -o %t %s +// RUN: grep "ib32i1b33i14" %t | count 1 + +struct foo{ + int a; + int b:1; + int c:14; +}; + +const char *encoding = @encode(struct foo); diff --git a/clang/test/CodeGenObjC/block-6.m b/clang/test/CodeGenObjC/block-6.m new file mode 100644 index 0000000..140fa88 --- /dev/null +++ b/clang/test/CodeGenObjC/block-6.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 -fobjc-fragile-abi | FileCheck %s +// rdar://8893785 + +void MYFUNC() { +// CHECK: define void @MYFUNC() +// CHECK: [[OBSERVER_SLOT:%.*]] = alloca [[OBSERVER_T:%.*]], align 8 + +// CHECK: [[T0:%.*]] = getelementptr inbounds [[OBSERVER_T]]* [[OBSERVER_SLOT]], i32 0, i32 1 +// CHECK: store [[OBSERVER_T]]* [[OBSERVER_SLOT]], [[OBSERVER_T]]** [[T0]] + +// CHECK: [[T1:%.*]] = bitcast i8* ()* +// CHECK: [[FORWARDING:%.*]] = getelementptr inbounds [[OBSERVER_T]]* [[OBSERVER_SLOT]], i32 0, i32 1 +// CHECK-NEXT: [[T0:%.*]] = load [[OBSERVER_T]]** [[FORWARDING]] +// CHECK-NEXT: [[OBSERVER:%.*]] = getelementptr inbounds [[OBSERVER_T]]* [[T0]], i32 0, i32 6 +// CHECK-NEXT: store i8* [[T1]], i8** [[OBSERVER]] + __block id observer = ^{ return observer; }; +} + diff --git a/clang/test/CodeGenObjC/block-var-layout.m b/clang/test/CodeGenObjC/block-var-layout.m new file mode 100644 index 0000000..1d0ce2d --- /dev/null +++ b/clang/test/CodeGenObjC/block-var-layout.m @@ -0,0 +1,166 @@ +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -O0 -emit-llvm %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s + +struct S { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + id o3; +}; + +__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) 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); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + 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); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; + c(); + +// 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" + void (^d)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x(wid); + bl_var1 = 0; + y(i + dob); + x(byref_bab); + }; + d(); + +// 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); + }; + e(); +} + +// Test 5 (unions/structs and their nesting): +void Test5() { + struct S5 { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + union UI { + void * i1; + id o1; + int i3; + id o3; + }ui; + }; + + union U { + void * i1; + id o1; + int i3; + id o3; + }ui; + + 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(); +} + +// 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(); +} + +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/clang/test/CodeGenObjC/blocks-1.m b/clang/test/CodeGenObjC/blocks-1.m new file mode 100644 index 0000000..64da359 --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-1.m @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-fragile-abi +// 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_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 +// RUN: grep "objc_assign_weak" %t | count 3 +// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-fragile-abi +// 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_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 +// RUN: grep "objc_assign_weak" %t | count 3 + +@interface NSDictionary @end + +void test1(NSDictionary * dict) { + ^{ (void)dict; }(); +} + +@interface D +@end + +void foo() { + __block __weak D *weakSelf; + D *l; + l = weakSelf; + weakSelf = l; +} + +void (^__weak b)(void); + +void test2() { + __block int i = 0; + b = ^ { ++i; }; +} diff --git a/clang/test/CodeGenObjC/blocks-2.m b/clang/test/CodeGenObjC/blocks-2.m new file mode 100644 index 0000000..591d63b --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-2.m @@ -0,0 +1,38 @@ +// 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 -fobjc-fragile-abi | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -fobjc-gc -fblocks -fexceptions -triple i386-apple-darwin10 -fobjc-fragile-abi -x objective-c++ | FileCheck %s + + +// 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: landingpad { i8*, i32 } personality + // CHECK-NEXT: cleanup + // CHECK: [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8* + // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) + // CHECK: resume { i8*, i32 } +} diff --git a/clang/test/CodeGenObjC/blocks-3.m b/clang/test/CodeGenObjC/blocks-3.m new file mode 100644 index 0000000..55e215c --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-3.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -fblocks -o %t %s + +// 1x for the declaration +// 1x for the object-pointer byref copy helper +// 1x for the block-pointer byref copy helper +// 8x for the block copy helper +// RUN: grep 'object_assign' %t | count 11 + +// RUN: grep 'object_dispose' %t | count 29 + +int main() { + typedef id aid __attribute__((aligned(1))); + __block aid a1; + __block id a2 __attribute__((aligned(2))); + __block id a3 __attribute__((aligned(4))); + __block id a4 __attribute__((aligned(8))); + __block id a5, a6, a7; + __block void (^b)(); + ^{ a1=a2=a3=a4=a5=a6=a7=0; b = 0; }(); + return 0; +} diff --git a/clang/test/CodeGenObjC/blocks-4.m b/clang/test/CodeGenObjC/blocks-4.m new file mode 100644 index 0000000..b3d0998 --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-4.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -fobjc-exceptions -fblocks -o %t %s +// rdar://7590273 + +void EXIT(id e); + +@interface NSBlockOperation { +} ++(id)blockOperationWithBlock:(void (^)(void))block ; +@end + +void FUNC() { + [NSBlockOperation blockOperationWithBlock:^{ + @try { + + } + @catch (id exception) { + EXIT(exception); + } + }]; + +} diff --git a/clang/test/CodeGenObjC/blocks-5.m b/clang/test/CodeGenObjC/blocks-5.m new file mode 100644 index 0000000..caa8d66 --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-5.m @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -fblocks -o %t %s + +// rdar: // 8064140 + +@interface IDEWorkspaceDocument +{ + id _defaultEditorStateTree; +} +- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, unsigned char *stop))block ; +@end + + + +int foo(); +extern void DVT (volatile const void * object, volatile const void * selector, const char * functionName); +@implementation IDEWorkspaceDocument + +- (void)stateSavingDefaultEditorStatesForURLs { + [_defaultEditorStateTree enumerateKeysAndObjectsUsingBlock:^(id identifier, id urlsToEditorStates, unsigned char *stop) { + do{ +if (foo() ) + DVT(&self,&_cmd,__PRETTY_FUNCTION__); + +}while(0); + + do{ + DVT(&self,&_cmd,__PRETTY_FUNCTION__); + }while(0); + + + }]; + +} + +- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, unsigned char *stop))block {} + +@end diff --git a/clang/test/CodeGenObjC/blocks-ivar-debug.m b/clang/test/CodeGenObjC/blocks-ivar-debug.m new file mode 100644 index 0000000..d0cf1f1 --- /dev/null +++ b/clang/test/CodeGenObjC/blocks-ivar-debug.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -g %s -fblocks -S -o %t +// Radar 7959934 + +@interface NSObject { + struct objc_object *isa; +} +@end +@interface Foo : NSObject { + int _prop; +} +@end + +@implementation Foo +- (int)doSomething { + int (^blk)(void) = ^{ return _prop; }; + return blk(); +} + +@end + diff --git a/clang/test/CodeGenObjC/blocks.m b/clang/test/CodeGenObjC/blocks.m new file mode 100644 index 0000000..f478c07 --- /dev/null +++ b/clang/test/CodeGenObjC/blocks.m @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -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 + +void foo(T *P) { + [P foo: 0]; +} + +@interface A +-(void) im0; +@end + +// CHECK: define internal i32 @"__8-[A im0]_block_invoke_0"( +@implementation A +-(void) im0 { + (void) ^{ return 1; }(); +} +@end + +@interface B : A @end +@implementation B +-(void) im1 { + ^(void) { [self im0]; }(); +} +-(void) im2 { + ^{ [super im0]; }(); +} +-(void) im3 { + ^{ ^{[super im0];}(); }(); +} +@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: [[T6:%.*]] = getelementptr inbounds [[WEAK_T]]* [[WEAKX]], i32 0, i32 6 + // CHECK-NEXT: [[CAPTURE:%.*]] = load [[TEST2]]** [[X]] + // 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]; }); +} + +// rdar://problem/9124263 +// In the test above, check that the use in the invocation function +// doesn't require a read barrier. +// CHECK: define internal void @__test2_block_invoke_ +// CHECK: [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]* +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]] +// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[WEAK_T]]{{.*}}* +// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T2]], i32 0, i32 1 +// CHECK-NEXT: [[T4:%.*]] = load [[WEAK_T]]{{.*}}** [[T3]] +// CHECK-NEXT: [[WEAKX:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T4]], i32 0, i32 6 +// CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[WEAKX]], align 4 diff --git a/clang/test/CodeGenObjC/builtins.m b/clang/test/CodeGenObjC/builtins.m new file mode 100644 index 0000000..cb2995d --- /dev/null +++ b/clang/test/CodeGenObjC/builtins.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s + +void test0(id receiver, SEL sel, const char *str) { + short s = ((short (*)(id, SEL, const char*)) objc_msgSend)(receiver, sel, str); +} +// CHECK: define void @test0( +// CHECK: call signext i16 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i16 (i8*, i8*, i8*)*)( diff --git a/clang/test/CodeGenObjC/catch-lexical-block.m b/clang/test/CodeGenObjC/catch-lexical-block.m new file mode 100644 index 0000000..f4a6a22 --- /dev/null +++ b/clang/test/CodeGenObjC/catch-lexical-block.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -g -fobjc-exceptions -emit-llvm %s -o - | FileCheck %s +@interface Foo @end +void f0() { + @try { + @throw @"a"; + } @catch(Foo *e) { + } +} + +// We should have 4 lexical blocks here at the moment, including one +// for the catch block. +// CHECK: lexical_block +// CHECK: lexical_block +// CHECK: lexical_block +// CHECK: auto_variable +// CHECK: lexical_block diff --git a/clang/test/CodeGenObjC/category-class.m b/clang/test/CodeGenObjC/category-class.m new file mode 100644 index 0000000..5a82c14 --- /dev/null +++ b/clang/test/CodeGenObjC/category-class.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// PR7431 + +// CHECK: module asm "\09.lazy_reference .objc_class_name_A" +// CHECK: module asm "\09.objc_category_name_A_foo=0" +// CHECK: module asm "\09.globl .objc_category_name_A_foo" + +@interface A +@end +@interface A(foo) +- (void)foo_myStuff; +@end +@implementation A(foo) +- (void)foo_myStuff { +} +@end + diff --git a/clang/test/CodeGenObjC/category-super-class-meth.m b/clang/test/CodeGenObjC/category-super-class-meth.m new file mode 100644 index 0000000..6f02aff --- /dev/null +++ b/clang/test/CodeGenObjC/category-super-class-meth.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface BASE ++ (int) BaseMeth; +@end + +@interface Child: BASE +@end + +@interface Child (Categ) ++ (int) flushCache2; +@end + +@implementation Child @end + +@implementation Child (Categ) ++ (int) flushCache2 { [super BaseMeth]; } +@end + diff --git a/clang/test/CodeGenObjC/class-getter-dotsyntax.m b/clang/test/CodeGenObjC/class-getter-dotsyntax.m new file mode 100644 index 0000000..bc142ce --- /dev/null +++ b/clang/test/CodeGenObjC/class-getter-dotsyntax.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface Test { } ++ (Test *)crash; ++ (void)setCrash: (int)value; +@end + +@implementation Test +static int _value; +- (void)cachesPath +{ + static Test *cachesPath; + + if (!cachesPath) { + Test *crash = Test.crash; + } +} ++ (Test *)crash{ return 0; } ++ (void)setCrash: (int)value{ _value = value; } +@end + diff --git a/clang/test/CodeGenObjC/class-type.m b/clang/test/CodeGenObjC/class-type.m new file mode 100644 index 0000000..45aae25 --- /dev/null +++ b/clang/test/CodeGenObjC/class-type.m @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fobjc-fragile-abi -emit-llvm -o - %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s + + +@interface I0 { + struct { int a; } a; +} +@end + +@class I2; + +@interface I1 { + I2 *_imageBrowser; +} +@end + +@implementation I1 +@end + +@interface I2 : I0 +@end + +@implementation I2 +@end + + +// Implementations without interface declarations. +// rdar://6804402 +@class foo; +@implementation foo +@end + +@implementation bar +@end + diff --git a/clang/test/CodeGenObjC/compatibility-alias.m b/clang/test/CodeGenObjC/compatibility-alias.m new file mode 100644 index 0000000..fcc53b8 --- /dev/null +++ b/clang/test/CodeGenObjC/compatibility-alias.m @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface Int1 @end + +typedef Int1 Int1Typedef; +@compatibility_alias Int1Alias Int1Typedef; + +@implementation Int1Alias @end diff --git a/clang/test/CodeGenObjC/complex-double-abi.m b/clang/test/CodeGenObjC/complex-double-abi.m new file mode 100644 index 0000000..08246d5 --- /dev/null +++ b/clang/test/CodeGenObjC/complex-double-abi.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-apple-macosx10.7.2 %s -o - | FileCheck %s +// rdar://10331109 + +@interface CNumber +- (double _Complex)sum; +@end + +double _Complex foo(CNumber *x) { + return [x sum]; +} + +// CHECK: [[T4:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[R1:%.*]], [[MSGCALL:%.*]] ] +// CHECK: [[T5:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[I1:%.*]], [[MSGCALL:%.*]] ] + +// CHECK: store double [[T4]] +// CHECK: store double [[T5]] diff --git a/clang/test/CodeGenObjC/complex-property.m b/clang/test/CodeGenObjC/complex-property.m new file mode 100644 index 0000000..8c3aef9 --- /dev/null +++ b/clang/test/CodeGenObjC/complex-property.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// rdar: // 7351147 + +@interface A +@property __complex int COMPLEX_PROP; +- (__complex int)y; +- (void) setY : (__complex int)rhs; +@end + +void f0(A *a) { + _Complex int a1 = 25 + 10i; + a.COMPLEX_PROP += a1; + a.y += a1; +} + +// CHECK-LP64: internal global [13 x i8] c"COMPLEX_PROP +// CHECK-LP64: internal global [17 x i8] c"setCOMPLEX_PROP + +// rdar: // 7351147 +@interface B +@property (assign) _Complex float f_complex_ivar; +@end + +@implementation B + +@synthesize f_complex_ivar = _f_complex_ivar; +-(void) unary_f_complex: (_Complex float) a0 { + self.f_complex_ivar = a0; +} + +@end + diff --git a/clang/test/CodeGenObjC/constant-string-class-1.m b/clang/test/CodeGenObjC/constant-string-class-1.m new file mode 100644 index 0000000..5f1e882 --- /dev/null +++ b/clang/test/CodeGenObjC/constant-string-class-1.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fno-constant-cfstrings -fconstant-string-class OFConstantString -emit-llvm -o %t %s +// pr9914 + +@interface OFConstantString ++ class; +@end + +@interface OFString +- (void)XMLElementBySerializing; +@end + +@implementation OFString + +- (void)XMLElementBySerializing +{ + id str = @"object"; + + [OFConstantString class]; +} + +@end + +// CHECK: @"OBJC_CLASS_$_OFConstantString" = external global diff --git a/clang/test/CodeGenObjC/constant-string-class.m b/clang/test/CodeGenObjC/constant-string-class.m new file mode 100644 index 0000000..ea049a5 --- /dev/null +++ b/clang/test/CodeGenObjC/constant-string-class.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -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 -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" = global diff --git a/clang/test/CodeGenObjC/constant-strings.m b/clang/test/CodeGenObjC/constant-strings.m new file mode 100644 index 0000000..c308d7a --- /dev/null +++ b/clang/test/CodeGenObjC/constant-strings.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=CHECK-NEXT < %t %s + +// Check that we set alignment 1 on the string. +// +// CHECK-NEXT: @.str = {{.*}}constant [13 x i8] c"Hello World!\00", align 1 + +// RUN: %clang_cc1 -fgnu-runtime -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=CHECK-GNU < %t %s +// CHECK-GNU: NXConstantString + +// RUN: %clang_cc1 -fgnu-runtime -fconstant-string-class NSConstantString -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=CHECK-GNU-WITH-CLASS < %t %s +// CHECK-GNU-WITH-CLASS: NSConstantString +id a = @"Hello World!"; + diff --git a/clang/test/CodeGenObjC/continuation-class.m b/clang/test/CodeGenObjC/continuation-class.m new file mode 100644 index 0000000..6f903a0 --- /dev/null +++ b/clang/test/CodeGenObjC/continuation-class.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface Object +- (id)new; +@end + +@interface ReadOnly : Object +{ + int _object; + int _Anotherobject; +} +@property(readonly) int object; +@property(readonly) int Anotherobject; +@end + +@interface ReadOnly () +@property(readwrite) int object; +@property(readwrite, setter = myAnotherobjectSetter:) int Anotherobject; +@end + +@implementation ReadOnly +@synthesize object = _object; +@synthesize Anotherobject = _Anotherobject; +- (void) myAnotherobjectSetter : (int)val { + _Anotherobject = val; +} +@end + +int main(int argc, char **argv) { + ReadOnly *test = [ReadOnly new]; + test.object = 12345; + test.Anotherobject = 200; + return test.object - 12345 + test.Anotherobject - 200; +} + diff --git a/clang/test/CodeGenObjC/deadcode_strip_used_var.m b/clang/test/CodeGenObjC/deadcode_strip_used_var.m new file mode 100644 index 0000000..3137ceb --- /dev/null +++ b/clang/test/CodeGenObjC/deadcode_strip_used_var.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -emit-llvm -o %t -triple i386-apple-darwin10 -fobjc-fragile-abi +// RUN: grep "llvm.used" %t | count 1 +// RUN: %clang_cc1 %s -emit-llvm -o %t -triple x86_64-apple-darwin10 -fobjc-fragile-abi +// RUN: grep "llvm.used" %t | count 1 + + +__attribute__((used)) static int XXXXXX __attribute__ ((section ("__DATA,__Xinterpose"))) ; +__attribute__((used)) static int YYYY __attribute__ ((section ("__DATA,__Xinterpose"))) ; + diff --git a/clang/test/CodeGenObjC/debug-info-block-helper.m b/clang/test/CodeGenObjC/debug-info-block-helper.m new file mode 100644 index 0000000..83db0c9 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-block-helper.m @@ -0,0 +1,30 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -emit-llvm -fblocks -g -triple x86_64-apple-darwin10 -fobjc-fragile-abi %s -o - | FileCheck %s +extern void foo(void(^)(void)); + +// CHECK: metadata !{i32 786478, i32 0, metadata !27, metadata !"__destroy_helper_block_", metadata !"__destroy_helper_block_", metadata !"", metadata !27, i32 24, metadata !43, i1 true, i1 true, i32 0, i32 0, null, i32 0, i1 false, void (i8*)* @__destroy_helper_block_, null, null, metadata !45, i32 24} ; [ DW_TAG_subprogram ] + +@interface NSObject { + struct objc_object *isa; +} +@end + +@interface A:NSObject @end +@implementation A +- (void) helper { + int master = 0; + __block int m2 = 0; + __block int dbTransaction = 0; + int (^x)(void) = ^(void) { (void) self; + (void) master; + (void) dbTransaction; + m2++; + return m2; + + }; + master = x(); +} +@end + +void foo(void(^x)(void)) {} + diff --git a/clang/test/CodeGenObjC/debug-info-blocks.m b/clang/test/CodeGenObjC/debug-info-blocks.m new file mode 100644 index 0000000..71ae8a6 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-blocks.m @@ -0,0 +1,55 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -masm-verbose -S -fblocks -g -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed %s -o - | FileCheck %s + +//Radar 9279956 +//CHECK: ## DW_OP_deref +//CHECK-NEXT: ## DW_OP_plus_uconst + +typedef unsigned int NSUInteger; + +@protocol NSObject +@end + +@interface NSObject <NSObject> +- (id)init; ++ (id)alloc; +@end + +@interface NSDictionary : NSObject +- (NSUInteger)count; +@end + +@interface NSMutableDictionary : NSDictionary +@end + +@interface A : NSObject { +@public + int ivar; +} +@end + +static void run(void (^block)(void)) +{ + block(); +} + +@implementation A + +- (id)init +{ + if ((self = [super init])) { + run(^{ + NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; + ivar = 42 + (int)[d count]; + }); + } + return self; +} + +@end + +int main() +{ + A *a = [[A alloc] init]; + return 0; +} diff --git a/clang/test/CodeGenObjC/debug-info-class-extension.m b/clang/test/CodeGenObjC/debug-info-class-extension.m new file mode 100644 index 0000000..e1573f0 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-class-extension.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK: AT_APPLE_objc_complete_type + +@interface I1 +@end + +@implementation I1 { +int myi2; +} +int myi; +@end + +void foo(I1 *iptr) {} + diff --git a/clang/test/CodeGenObjC/debug-info-class-extension2.m b/clang/test/CodeGenObjC/debug-info-class-extension2.m new file mode 100644 index 0000000..bae12dc --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-class-extension2.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s +// CHECK: AT_APPLE_objc_complete_type + +@interface Foo {} @end + +@interface Foo () { + int *bar; +} +@end + +@implementation Foo +@end + +void bar(Foo *fptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-class-extension3.m b/clang/test/CodeGenObjC/debug-info-class-extension3.m new file mode 100644 index 0000000..f49bef8 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-class-extension3.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK-NOT: AT_APPLE_objc_complete_type + +@interface Foo {} @end + +@interface Foo () { + int *bar; +} +@end + +void bar(Foo *fptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-crash-2.m b/clang/test/CodeGenObjC/debug-info-crash-2.m new file mode 100644 index 0000000..a2acd9d --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-crash-2.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -g -S %s -o - +@class Bar; +@interface Foo +@property (strong, nonatomic) Bar *window; +@end + +@interface Foo__ : Foo +@end +@implementation Foo__ +@end + +@implementation Foo +@synthesize window = _window; +@end + diff --git a/clang/test/CodeGenObjC/debug-info-crash.m b/clang/test/CodeGenObjC/debug-info-crash.m new file mode 100644 index 0000000..5504356 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-crash.m @@ -0,0 +1,41 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-fragile-abi -fblocks -g -S %s -o - + +// rdar://7556129 +@implementation test +- (void)wait { + ^{}; +} +@end + +// PR4894 +@interface I0 { + I0 *_iv0; +} +@end +@protocol P0 @end + +@interface I1 @end +@implementation I1 +- (I0<P0> *) im0 { + // CHECK: @"\01-[I1 im0]" + // CHECK: llvm.dbg.func.start + return 0; +} +@end + +// PR4541 +@class NSString; +@interface NSAttributedString +- (NSString *)string; +@end +@interface NSMutableAttributedString : NSAttributedString +@end +@class NSImage; +@implementation CYObjectsController ++ (void)initialize { +} ++ (NSAttributedString *)attributedStringWithString:(id)string image:(NSImage *)image { + NSMutableAttributedString *attrStr; +} +@end diff --git a/clang/test/CodeGenObjC/debug-info-default-synth-ivar.m b/clang/test/CodeGenObjC/debug-info-default-synth-ivar.m new file mode 100644 index 0000000..30d751e --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-default-synth-ivar.m @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -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/clang/test/CodeGenObjC/debug-info-fwddecl.m b/clang/test/CodeGenObjC/debug-info-fwddecl.m new file mode 100644 index 0000000..ebdc5f2 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-fwddecl.m @@ -0,0 +1,5 @@ +// RUN: %clang -fverbose-asm -g -S -emit-llvm %s -o - | FileCheck %s +@class ForwardObjcClass; +ForwardObjcClass *ptr = 0; + +// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] diff --git a/clang/test/CodeGenObjC/debug-info-getter-name.m b/clang/test/CodeGenObjC/debug-info-getter-name.m new file mode 100644 index 0000000..3939f35 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-getter-name.m @@ -0,0 +1,54 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -fexceptions -fobjc-exceptions -g %s -o - | FileCheck %s + +// CHECK: {{.*}}, metadata !"-[InstanceVariablesEverywhereButTheInterface someString]", {{.*}}} ; [ DW_TAG_subprogram ] + +//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 +@synthesize someString; +@synthesize someNumber; +- init +{ + return self; +} +@end + +int main() +{ + return 0; +} diff --git a/clang/test/CodeGenObjC/debug-info-impl.m b/clang/test/CodeGenObjC/debug-info-impl.m new file mode 100644 index 0000000..8ad5903 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-impl.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -S -emit-llvm %s -o - | FileCheck %s +// CHECK: metadata !{i32 {{.*}}, metadata {{.*}}, metadata !"Circle", metadata {{.*}}, i32 11, i64 64, i64 64, i32 0, i32 512, null, metadata {{.*}}, i32 16, i32 0} ; [ DW_TAG_structure_type ] +@interface NSObject { + struct objc_object *isa; +} +@end + +@interface Shape : NSObject + +@end +@interface Circle : Shape + +@end +@implementation Circle + +@end diff --git a/clang/test/CodeGenObjC/debug-info-linkagename.m b/clang/test/CodeGenObjC/debug-info-linkagename.m new file mode 100644 index 0000000..b606e5d --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-linkagename.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -g -S -o %t %s +// RUN: not grep "001-[F bar" %t +// Linkage name should not use 001 prefix in debug info. + +@interface F +-(int) bar; +@end + +@implementation F +-(int) bar { + return 42; +} +@end + +extern int f(F *fn) { + return [fn bar]; +} + diff --git a/clang/test/CodeGenObjC/debug-info-property.m b/clang/test/CodeGenObjC/debug-info-property.m new file mode 100644 index 0000000..dd105a5 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-property.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK: AT_APPLE_property_name +// CHECK: AT_APPLE_property_attribute +// CHECK: AT_APPLE_property +@interface I1 { +int p1; +} +@property int p1; +@end + +@implementation I1 +@synthesize p1; +@end diff --git a/clang/test/CodeGenObjC/debug-info-property2.m b/clang/test/CodeGenObjC/debug-info-property2.m new file mode 100644 index 0000000..4cd76c1 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-property2.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK: AT_APPLE_property_name +@interface C { + int _base; +} +@property int base; +@end + +@implementation C +@synthesize base = _base; +@end + +void foo(C *cptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-property3.m b/clang/test/CodeGenObjC/debug-info-property3.m new file mode 100644 index 0000000..f96ec44 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-property3.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s + +// CHECK: metadata !"p1", metadata !6, i32 5, metadata !"", metadata !"", i32 2316, metadata !9} ; [ DW_TAG_APPLE_property ] +@interface I1 +@property int p1; +@end + +@implementation I1 +@synthesize p1; +@end + +void foo(I1 *iptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-property4.m b/clang/test/CodeGenObjC/debug-info-property4.m new file mode 100644 index 0000000..6d9973c --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-property4.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fobjc-default-synthesize-properties -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK: AT_APPLE_property_name +// CHECK-NOT: AT_APPLE_property_getter +// CHECK-NOT: AT_APPLE_property_setter +// CHECK: AT_APPLE_property_attribute +// CHECK: AT_APPLE_property + + +@interface I1 +@property int p1; +@end + +@implementation I1 +@end + +void foo(I1 *ptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-property5.m b/clang/test/CodeGenObjC/debug-info-property5.m new file mode 100644 index 0000000..3521574 --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-property5.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fobjc-default-synthesize-properties -masm-verbose -S -g %s -o - | FileCheck %s + +// CHECK: AT_APPLE_property_name +// CHECK: AT_APPLE_property_getter +// CHECK: AT_APPLE_property_setter +// CHECK: AT_APPLE_property_attribute +// CHECK: AT_APPLE_property + +@interface BaseClass2 +{ + int _baseInt; +} +- (int) myGetBaseInt; +- (void) mySetBaseInt: (int) in_int; +@property(getter=myGetBaseInt,setter=mySetBaseInt:) int baseInt; +@end + +@implementation BaseClass2 + +- (int) myGetBaseInt +{ + return _baseInt; +} + +- (void) mySetBaseInt: (int) in_int +{ + _baseInt = 2 * in_int; +} +@end + + +void foo(BaseClass2 *ptr) {} diff --git a/clang/test/CodeGenObjC/debug-info-pubtypes.m b/clang/test/CodeGenObjC/debug-info-pubtypes.m new file mode 100644 index 0000000..658430d --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-pubtypes.m @@ -0,0 +1,14 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang -cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o - | FileCheck %s + +// CHECK: !5 = metadata !{i32 {{.*}}, metadata !6, metadata !"H", metadata !6, i32 6, i64 0, i64 8, i32 0, i32 512, null, metadata !2, i32 16, i32 0} ; [ DW_TAG_structure_type ] + +@interface H +-(void) foo; +@end + +@implementation H +-(void) foo { +} +@end + diff --git a/clang/test/CodeGenObjC/debug-info-selector.m b/clang/test/CodeGenObjC/debug-info-selector.m new file mode 100644 index 0000000..67642ac --- /dev/null +++ b/clang/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/clang/test/CodeGenObjC/debug-info-self.m b/clang/test/CodeGenObjC/debug-info-self.m new file mode 100644 index 0000000..9146ab3 --- /dev/null +++ b/clang/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/clang/test/CodeGenObjC/debug-info-static-var.m b/clang/test/CodeGenObjC/debug-info-static-var.m new file mode 100644 index 0000000..c65e77c --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-static-var.m @@ -0,0 +1,23 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -g -triple x86_64-apple-darwin10 -fobjc-fragile-abi -S -masm-verbose -o - %s | FileCheck %s +// Radar 8801045 +// Do not emit AT_MIPS_linkage_name for static variable i + +// CHECK: Lset6 = Lstring3-Lsection_str ## DW_AT_name +// CHECK-NEXT: .long Lset6 +// 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/clang/test/CodeGenObjC/debug-info-synthesis.m b/clang/test/CodeGenObjC/debug-info-synthesis.m new file mode 100644 index 0000000..7e263cf --- /dev/null +++ b/clang/test/CodeGenObjC/debug-info-synthesis.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -emit-llvm -g -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +# 1 "foo.m" 1 +# 1 "foo.m" 2 +# 1 "./foo.h" 1 +@interface NSObject { + struct objc_object *isa; +} +@end +@class NSDictionary; + +@interface Foo : NSObject {} +@property (strong, nonatomic) NSDictionary *dict; +@end +# 2 "foo.m" 2 + + + + +@implementation Foo +@synthesize dict = _dict; + +- (void) bork { +} +@end + +int main(int argc, char *argv[]) { + @autoreleasepool { + Foo *f = [Foo new]; + [f bork]; + } +} + +// CHECK: !7 = metadata !{i32 {{.*}}, metadata !"./foo.h" +// CHECK: !31 = metadata !{i32 {{.*}}, i32 0, metadata !7, metadata !"-[Foo dict]", metadata !"-[Foo dict]", metadata !"", metadata !7, i32 8, metadata !32, i1 true, i1 true, i32 0, i32 0, null, i32 320, i1 false, %1* (%0*, i8*)* @"\01-[Foo dict]", null, null, metadata !34, i32 8} ; [ DW_TAG_subprogram ] diff --git a/clang/test/CodeGenObjC/debug-property-synth.m b/clang/test/CodeGenObjC/debug-property-synth.m new file mode 100644 index 0000000..954620a --- /dev/null +++ b/clang/test/CodeGenObjC/debug-property-synth.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s +// Radar 9468526 +@interface I { + int _p1; +} +@property int p1; +@end + +@implementation I +@synthesize p1 = _p1; +@end + +int main() { + I *myi; + myi.p1 = 2; + return 0; +} + +// FIXME: Make this test ir files. +// CHECK: .loc 2 6 0 diff --git a/clang/test/CodeGenObjC/default-property-synthesis.m b/clang/test/CodeGenObjC/default-property-synthesis.m new file mode 100644 index 0000000..7d7296b --- /dev/null +++ b/clang/test/CodeGenObjC/default-property-synthesis.m @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// rdar://7923851. + +// Superclass declares property. Subclass redeclares the same property. +// Do not @synthesize-by-default in the subclass. P1 +// Superclass declares a property. Subclass declares a different property with the same name +// (such as different type or attributes). Do not @synthesize-by-default in the subclass. P2 +// Superclass conforms to a protocol that declares a property. Subclass redeclares the +// same property. Do not @synthesize-by-default in the subclass. P3 +// Superclass conforms to a protocol that declares a property. Subclass conforms to the +// same protocol or a derived protocol. Do not @synthesize-by-default in the subclass. P4 + + +@protocol PROTO + @property int P3; + @property int P4; +@end + +@protocol PROTO1 <PROTO> + @property int IMP1; +@end + +@interface Super <PROTO> + @property int P1; + @property (copy) id P2; +@end + +@interface Sub : Super <PROTO1> + @property int P1; + @property (nonatomic, retain) id P2; // expected-warning {{property 'P2' 'copy' attribute does not match the property inherited from 'Super'}} \ + // expected-warning {{property 'P2' 'atomic' attribute does not match the property inherited from 'Super'}} + @property int P3; + @property int IMP2; +@end + +@implementation Sub +@end + diff --git a/clang/test/CodeGenObjC/dot-syntax-1.m b/clang/test/CodeGenObjC/dot-syntax-1.m new file mode 100644 index 0000000..417bcb4 --- /dev/null +++ b/clang/test/CodeGenObjC/dot-syntax-1.m @@ -0,0 +1,264 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +int printf(const char *, ...); + +@interface Root +-(id) alloc; +-(id) init; +@end + +// Property above methods... + +@interface Top0 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot0 : Top0 +-(int) x; +-(void) setX: (int) arg; +@end + +@implementation Top0 +-(int) _getX { + printf("-[ Top0 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top0 _setX: %d ]\n", arg); +} +@end + +@implementation Bot0 +-(int) x { + printf("-[ Bot0 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot0 _setX: %d ]\n", arg); +} +@end + +// Methods above property... + +@interface Top1 : Root +-(int) x; +-(void) setX: (int) arg; +@end + +@interface Bot1 : Top1 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top1 +-(int) x { + printf("-[ Top1 x ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top1 setX: %d ]\n", arg); +} +@end + +@implementation Bot1 +-(int) _getX { + printf("-[ Bot1 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot1 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 1) + +@interface Top2 : Root +-(int) x; +-(void) _setX: (int) arg; +@end + +@interface Bot2 : Top2 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top2 +-(int) x { + printf("-[ Top2 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top2 _setX: %d ]\n", arg); +} +@end + +@implementation Bot2 +-(int) _getX { + printf("-[ Bot2 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot2 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 2) + +@interface Top3 : Root +-(int) _getX; +-(void) setX: (int) arg; +@end + +@interface Bot3 : Top3 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top3 +-(int) _getX { + printf("-[ Top3 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top3 setX: %d ]\n", arg); +} +@end + +@implementation Bot3 +-(int) x { + printf("-[ Bot3 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot3 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 3) + +@interface Top4 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot4 : Top4 +-(int) _getX; +-(void) setX: (int) arg; +@end + +@implementation Top4 +-(int) x { + printf("-[ Top4 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top4 _setX: %d ]\n", arg); +} +@end + +@implementation Bot4 +-(int) _getX { + printf("-[ Bot4 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot4 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 4) + +@interface Top5 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot5 : Top5 +-(int) x; +-(void) _setX: (int) arg; +@end + +@implementation Top5 +-(int) _getX { + printf("-[ Top5 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top5 setX: %d ]\n", arg); +} +@end + +@implementation Bot5 +-(int) x { + printf("-[ Bot5 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot5 _setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top6 : Root +-(int) x; +@end + +@interface Bot6 : Top6 +-(void) setX: (int) arg; +@end + +@implementation Top6 +-(int) x { + printf("-[ Top6 x ]\n"); + return 0; +} +@end + +@implementation Bot6 +-(void) setX: (int) arg { + printf("-[ Bot5 setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top7 : Root +-(void) setX: (int) arg; +@end + +@interface Bot7 : Top7 +-(int) x; +@end + +@implementation Top7 +-(void) setX: (int) arg { + printf("-[ Top7 setX: %d ]\n", arg); +} +@end + +@implementation Bot7 +-(int) x { + printf("-[ Bot7 x ]\n"); + return 0; +} +@end + +// + +// FIXME: Two more (thats it?) interesting cases. Method access on +// getter w/o setter and method access on setter w/o getter. + +int main() { +#define test(N) { \ + Bot##N *ob = [[Bot##N alloc] init]; \ + int x = ob.x; \ + ob.x = 10; } + + test(0); + test(1); + test(2); + test(3); + test(4); + test(5); + // test(6); + // test(7); + + return 0; +} + diff --git a/clang/test/CodeGenObjC/dot-syntax-2.m b/clang/test/CodeGenObjC/dot-syntax-2.m new file mode 100644 index 0000000..020868a --- /dev/null +++ b/clang/test/CodeGenObjC/dot-syntax-2.m @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// rdar: // 8062778 + +@interface NSDictionary @end + +@interface NSMutableDictionary : NSDictionary +@end + +@interface MutableMyClass +- (NSMutableDictionary *)myDict; +- (void)setMyDict:(NSDictionary *)myDict; + +- (NSMutableDictionary *)myLang; +- (void)setMyLang:(NSDictionary *)myLang; +@end + +@interface AnotherClass @end + +@implementation AnotherClass +- (void)foo +{ + MutableMyClass * myObject; + NSDictionary * newDict; + myObject.myDict = newDict; + myObject.myLang = newDict; +} +@end diff --git a/clang/test/CodeGenObjC/dot-syntax.m b/clang/test/CodeGenObjC/dot-syntax.m new file mode 100644 index 0000000..6282ea4 --- /dev/null +++ b/clang/test/CodeGenObjC/dot-syntax.m @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +int printf(const char *, ...); + +@interface Root +-(id) alloc; +-(id) init; +@end + +typedef struct { + float x, y, z[2]; +} S; + +@interface A : Root { + int myX; + // __complex myY; + S myZ; +} + +@property int x; +//@property __complex int y; +@property S z; +@end + +@implementation A +-(int) x { + printf("-[A x] = %d\n", myX); + return myX; +} +-(void) setX: (int) arg { + myX = arg; + printf("-[A setX: %d]\n", myX); +} + +// FIXME: Add back +#if 0 +-(__complex int) y { + printf("-[A y] = (%d, %d)\n", __real myY, __imag myY); + return myY; +} +-(void) setY: (__complex int) arg { + myY = arg; + printf("-[A setY: (%d, %d)]\n", __real myY, __imag myY); +} +#endif + +-(S) z { + printf("-[A z] = { %f, %f, { %f, %f } }\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); + return myZ; +} +-(void) setZ: (S) arg { + myZ = arg; + printf("-[A setZ: { %f, %f, { %f, %f } } ]\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); +} + +@end + +int main() { +#define SWAP(T,a,b) { T a_tmp = a; a = b; b = a_tmp; } + A *a = [[A alloc] init]; + A *b = [[A alloc] init]; + int a0 = 23; + // __complex a1 = 25 + 10i; + S a2 = { 246, 458, {275, 12} }; + int b0 = 42673; + // __complex b1 = 15 + 13i; + S b2 = { 26, 2, {367, 13} }; + + a.x = a0; + // a.y = a1; + a.z = a2; + + a.x += a0; + // a.y += a1; + // Yay, no compound assign of structures. A GCC extension in the + // works, perhaps? + + b.x = b0; + // b.y = b1; + b.z = b2; + + int x0 = (b.x = b0); + printf("(b.x = b0): %d\n", x0); + + // int x1 = __real (b.y = b1); + // printf("__real (b.y = b1) = %d\n", x1); + + float x2 = (b.z = b2).x; + printf("(b.z = b2).x: %f\n", x2); + + SWAP(int, a.x, b.x); + // SWAP(__complex int, a.y, b.y); + SWAP(S, a.z, b.z); + + return 0; +} diff --git a/clang/test/CodeGenObjC/encode-cstyle-method.m b/clang/test/CodeGenObjC/encode-cstyle-method.m new file mode 100644 index 0000000..ea63023 --- /dev/null +++ b/clang/test/CodeGenObjC/encode-cstyle-method.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// rdar: // 7445205 + +@interface Foo +- (id)test:(id)one, id two; +@end + +@implementation Foo +- (id)test:(id )one, id two {return two; } @end + +// CHECK-LP64: internal global [11 x i8] c"@24@0:8@16 diff --git a/clang/test/CodeGenObjC/encode-test-2.m b/clang/test/CodeGenObjC/encode-test-2.m new file mode 100644 index 0000000..9e14237 --- /dev/null +++ b/clang/test/CodeGenObjC/encode-test-2.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s +// RUN: grep -e "@\\\22<X>\\\22" %t +// RUN: grep -e "@\\\22<X><Y>\\\22" %t +// RUN: grep -e "@\\\22<X><Y><Z>\\\22" %t +// RUN: grep -e "@\\\22Foo<X><Y><Z>\\\22" %t +// RUN: grep -e "{Intf=@@@@#}" %t + +@protocol X, Y, Z; +@class Foo; + +@protocol Proto +@end + +@interface Intf <Proto> +{ +id <X> IVAR_x; +id <X, Y> IVAR_xy; +id <X, Y, Z> IVAR_xyz; +Foo <X, Y, Z> *IVAR_Fooxyz; +Class <X> IVAR_Classx; +} +@end + +@implementation Intf +@end + +int main() +{ + const char * en = @encode(Intf); +} diff --git a/clang/test/CodeGenObjC/encode-test-3.m b/clang/test/CodeGenObjC/encode-test-3.m new file mode 100644 index 0000000..4b39cd7 --- /dev/null +++ b/clang/test/CodeGenObjC/encode-test-3.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s +// RUN: grep -e "\^i" %t | count 1 +// RUN: grep -e "\[0i\]" %t | count 1 + +int main() { + int n; + + const char * inc = @encode(int[]); + const char * vla = @encode(int[n]); +} + +// PR3648 +int a[sizeof(@encode(int)) == 2 ? 1 : -1]; // Type is char[2] +const char *B = @encode(int); +char (*c)[2] = &@encode(int); // @encode is an lvalue + +char d[] = @encode(int); // infer size. +char e[1] = @encode(int); // truncate +char f[2] = @encode(int); // fits +char g[3] = @encode(int); // zero fill + diff --git a/clang/test/CodeGenObjC/encode-test-4.m b/clang/test/CodeGenObjC/encode-test-4.m new file mode 100644 index 0000000..2624bc7 --- /dev/null +++ b/clang/test/CodeGenObjC/encode-test-4.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s -O2 | grep "ret i32 1" +typedef long Integer; +typedef enum : Integer { Red, Green, Blue} Color; +typedef enum { Cyan, Magenta, Yellow, Key } PrintColor; + +int a() { + return @encode(int) == @encode(int) && + @encode(Color) == @encode(long) && + @encode(PrintColor) == @encode(int); +} diff --git a/clang/test/CodeGenObjC/encode-test-5.m b/clang/test/CodeGenObjC/encode-test-5.m new file mode 100644 index 0000000..a27ffb7 --- /dev/null +++ b/clang/test/CodeGenObjC/encode-test-5.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin9 -emit-llvm -o %t %s + +// RUN: grep ji.00 %t | count 1 +char *a = @encode(_Complex int); + +// RUN: grep jf.00 %t | count 1 +char *b = @encode(_Complex float); + +// RUN: grep jd.00 %t | count 1 +char *c = @encode(_Complex double); + +// RUN: grep "t.00" %t | count 1 +char *e = @encode(__int128_t); + +// RUN: grep "T.00" %t | count 1 +char *f = @encode(__uint128_t); diff --git a/clang/test/CodeGenObjC/encode-test.m b/clang/test/CodeGenObjC/encode-test.m new file mode 100644 index 0000000..02af5da --- /dev/null +++ b/clang/test/CodeGenObjC/encode-test.m @@ -0,0 +1,167 @@ +// RUN: %clang_cc1 -triple i686-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// 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; + +struct Innermost { + unsigned char a, b; +}; + +@interface Int1 { + signed char a, b; + struct Innermost *innermost; +} +@end + +@implementation Int1 +@end + +@interface Base +{ + struct objc_class *isa; + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +@end + +@implementation Base +@end + +@implementation Derived +@end + +@interface B1 +{ + struct objc_class *isa; + Int1 *sBase; + char c; +} +@end + +@implementation B1 +@end + +@interface Test +{ + int ivar; + __attribute__((objc_gc(weak))) SEL selector; +} +-(void) test3: (Test* [3] [4])b ; +- (SEL**) meth : (SEL) arg : (SEL*****) arg1 : (SEL*)arg2 : (SEL**) arg3; +@end + +@implementation Test +-(void) test3: (Test* [3] [4])b {} +- (SEL**) meth : (SEL) arg : (SEL*****) arg1 : (SEL*)arg2 : (SEL**) arg3 {} +@end + +struct S { int iS; }; + +@interface Object +{ + Class isa; +} +@end +typedef Object MyObj; + +int main() +{ + const char *en = @encode(Derived); + const char *eb = @encode(B1); + const char *es = @encode(const struct S *); + const char *ec = @encode(const struct S); + 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); + +// CHECK: @g9 = constant [11 x i8] c"{S9=i[0i]}\00" +struct S9 { + int x; + int flex[]; +}; +const char g9[] = @encode(struct S9); + +struct f +{ + int i; + struct{} g[4]; + int tt; +}; + +// CHECK: @g10 = constant [14 x i8] c"{f=i[0{?=}]i}\00" +const char g10[] = @encode(struct f); + +// rdar://9622422 +// CHECK: @g11 = constant [2 x i8] c"v\00" +const char g11[] = @encode(void); diff --git a/clang/test/CodeGenObjC/exceptions-nonfragile.m b/clang/test/CodeGenObjC/exceptions-nonfragile.m new file mode 100644 index 0000000..1f38926 --- /dev/null +++ b/clang/test/CodeGenObjC/exceptions-nonfragile.m @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -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!"); +} + +// rdar://problem/9431547 +void die(void) __attribute__((nothrow, noreturn)); +void test2(void) { + @try { + die(); + } @finally { + extern void test2_helper(void); + test2_helper(); + } + + // CHECK: define void @test2() + // CHECK-NOT: call void @test2_helper() +} diff --git a/clang/test/CodeGenObjC/exceptions.m b/clang/test/CodeGenObjC/exceptions.m new file mode 100644 index 0000000..24fb657 --- /dev/null +++ b/clang/test/CodeGenObjC/exceptions.m @@ -0,0 +1,183 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -fexceptions -fobjc-exceptions -O2 -o - %s | FileCheck %s +// +// <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes + +// Just check that we don't emit any dead blocks. +@interface NSArray @end +void f0() { + @try { + @try { + @throw @"a"; + } @catch(NSArray *e) { + } + } @catch (id e) { + } +} + +// CHECK: define void @f1() +void f1() { + extern void foo(void); + + while (1) { + // CHECK: call void @objc_exception_try_enter + // CHECK-NEXT: getelementptr + // CHECK-NEXT: call i32 @_setjmp( + // CHECK-NEXT: icmp + // CHECK-NEXT: br i1 + @try { + // CHECK: call void asm sideeffect "", "*m" + // CHECK-NEXT: call void @foo() + foo(); + // CHECK-NEXT: call void @objc_exception_try_exit + + // CHECK: call void asm sideeffect "", "=*m" + } @finally { + break; + } + } +} + +// Test that modifications to local variables are respected under +// optimization. rdar://problem/8160285 + +// CHECK: define i32 @f2() +int f2() { + extern void foo(void); + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 5, i32* [[X]] + int x = 0; + x += 5; + + // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp + // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0 + // CHECK-NEXT: br i1 [[CAUGHT]] + @try { + // CHECK: store i32 6, i32* [[X]] + x++; + // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]] + // CHECK-NEXT: call void @foo() + // CHECK-NEXT: call void @objc_exception_try_exit + // CHECK-NEXT: [[T:%.*]] = load i32* [[X]] + foo(); + } @catch (id) { + // Landing pad. Note that we elide the re-enter. + // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* [[X]] + // CHECK-NEXT: call i8* @objc_exception_extract + // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]] + // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1 + + // This store is dead. + // CHECK-NEXT: store i32 [[T2]], i32* [[X]] + x--; + } + + return x; +} + +// Test that the cleanup destination is saved when entering a finally +// block. rdar://problem/8293901 +// CHECK: define void @f3() +void f3() { + extern void f3_helper(int, int*); + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 0, i32* [[X]] + int x = 0; + + // CHECK: call void @objc_exception_try_enter( + // CHECK: call i32 @_setjmp + // CHECK-NEXT: icmp eq + // CHECK-NEXT: br i1 + + @try { + // CHECK: call void @f3_helper(i32 0, i32* [[X]]) + // CHECK: call void @objc_exception_try_exit( + f3_helper(0, &x); + } @finally { + // CHECK: [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ] + // CHECK: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp + @try { + // CHECK: call void @f3_helper(i32 1, i32* [[X]]) + // CHECK: call void @objc_exception_try_exit( + f3_helper(1, &x); + } @finally { + // CHECK: [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ] + // CHECK: call void @f3_helper(i32 2, i32* [[X]]) + f3_helper(2, &x); + + // This loop is large enough to dissuade the optimizer from just + // duplicating the finally block. + while (x) f3_helper(3, &x); + + // This is a switch or maybe some chained branches, but relying + // on a specific result from the optimizer is really unstable. + // CHECK: [[DEST2]] + } + + // This is a switch or maybe some chained branches, but relying + // on a specific result from the optimizer is really unstable. + // CHECK: [[DEST1]] + } + + // CHECK: call void @f3_helper(i32 4, i32* [[X]]) + // 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/clang/test/CodeGenObjC/for-in.m b/clang/test/CodeGenObjC/for-in.m new file mode 100644 index 0000000..26fe792 --- /dev/null +++ b/clang/test/CodeGenObjC/for-in.m @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -emit-llvm %s -o %t + +void p(const char*, ...); + +@interface NSArray ++(NSArray*) arrayWithObjects: (id) first, ...; +-(unsigned) count; +@end +@interface NSString +-(const char*) cString; +@end + +#define S(n) @#n +#define L1(n) S(n+0),S(n+1) +#define L2(n) L1(n+0),L1(n+2) +#define L3(n) L2(n+0),L2(n+4) +#define L4(n) L3(n+0),L3(n+8) +#define L5(n) L4(n+0),L4(n+16) +#define L6(n) L5(n+0),L5(n+32) + +void t0() { + NSArray *array = [NSArray arrayWithObjects: L1(0), (void*)0]; + + p("array.length: %d\n", [array count]); + unsigned index = 0; + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} + p("element %d: %s\n", index++, [i cString]); + } +} + +void t1() { + NSArray *array = [NSArray arrayWithObjects: L6(0), (void*)0]; + + p("array.length: %d\n", [array count]); + unsigned index = 0; + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} + index++; + if (index == 10) + continue; + p("element %d: %s\n", index, [i cString]); + if (index == 55) + break; + } +} + +// rdar://problem/9027663 +void t2(NSArray *array) { + for (NSArray *array in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} + } +} diff --git a/clang/test/CodeGenObjC/forward-class-impl-metadata.m b/clang/test/CodeGenObjC/forward-class-impl-metadata.m new file mode 100644 index 0000000..371abf2 --- /dev/null +++ b/clang/test/CodeGenObjC/forward-class-impl-metadata.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface BASE { +@private + void* _reserved; +} +@end + +@class PVR; + +@interface PVRHandldler +{ + PVR *_imageBrowser; +} +@end + +@implementation PVRHandldler @end + + +@interface PVR : BASE +@end + +@implementation PVR +@end + +// Reopen of an interface after use. + +@interface A { +@public + int x; +} +@property int p0; +@end + +int f0(A *a) { + return a.p0; +} + +@implementation A +@synthesize p0 = _p0; +@end + +@interface B +@end +@class B; +@implementation B +@end diff --git a/clang/test/CodeGenObjC/forward-decl-param.m b/clang/test/CodeGenObjC/forward-decl-param.m new file mode 100644 index 0000000..d54a888 --- /dev/null +++ b/clang/test/CodeGenObjC/forward-decl-param.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - + +// <rdar://problem/9123036> crash due to forward-declared struct in +// protocol method parameter. + +@protocol P +- (void) A:(struct z) z; +@end +@interface I < P > +@end +@implementation I +@end + +@interface I2 +- (void) A:(struct z2) z2; +@end +@implementation I2 +@end + diff --git a/clang/test/CodeGenObjC/fp2ret.m b/clang/test/CodeGenObjC/fp2ret.m new file mode 100644 index 0000000..9c956ae --- /dev/null +++ b/clang/test/CodeGenObjC/fp2ret.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_32 %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_64 %s +// +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -fobjc-fragile-abi -emit-llvm -target-abi apcs-gnu -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-ARMV7 %s + +@interface A +-(_Complex long double) complexLongDoubleValue; +@end + + +// CHECK-X86_32: define void @t0() +// CHECK-X86_32: call void bitcast {{.*}} @objc_msgSend_stret to +// CHECK-X86_32: } +// +// CHECK-X86_64: define void @t0() +// CHECK-X86_64: call { x86_fp80, x86_fp80 } bitcast {{.*}} @objc_msgSend_fp2ret to +// CHECK-X86_64: } +// +// CHECK-ARMV7: define void @t0() +// CHECK-ARMV7: call i128 bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: } +void t0() { + [(A*)0 complexLongDoubleValue]; +} diff --git a/clang/test/CodeGenObjC/fpret.m b/clang/test/CodeGenObjC/fpret.m new file mode 100644 index 0000000..bf111e0 --- /dev/null +++ b/clang/test/CodeGenObjC/fpret.m @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_32 %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_64 %s +// +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -fobjc-fragile-abi -emit-llvm -target-abi apcs-gnu -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-ARMV7 %s + +@interface A +-(float) floatValue; +-(double) doubleValue; +-(long double) longDoubleValue; +@end + + +// CHECK-X86_32: define void @t0() +// CHECK-X86_32: call float bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_32: call double bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_32: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_32: } +// +// CHECK-X86_64: define void @t0() +// CHECK-X86_64: call float bitcast {{.*}} @objc_msgSend to +// CHECK-X86_64: call double bitcast {{.*}} @objc_msgSend to +// CHECK-X86_64: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_64: } +// +// CHECK-ARMV7: define void @t0() +// CHECK-ARMV7: call float bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: } +void t0() { + [(A*)0 floatValue]; + [(A*)0 doubleValue]; + [(A*)0 longDoubleValue]; +} diff --git a/clang/test/CodeGenObjC/function-decay.m b/clang/test/CodeGenObjC/function-decay.m new file mode 100644 index 0000000..161f907 --- /dev/null +++ b/clang/test/CodeGenObjC/function-decay.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - + +@interface I0 @end +@implementation I0 +- (void) im0: (int (void)) a0 { +} +@end + +void func(int pf(void)) { +} diff --git a/clang/test/CodeGenObjC/gc-weak-attribute.m b/clang/test/CodeGenObjC/gc-weak-attribute.m new file mode 100644 index 0000000..032c7c6 --- /dev/null +++ b/clang/test/CodeGenObjC/gc-weak-attribute.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck %s +// rdar://10073896 + +@interface I +{ + __weak id wObject; +} +@property (readwrite, weak) id representedObject; +@property (readwrite, weak) id wObject; +@property (readwrite, weak) __weak id wRandom; +@property (readwrite, assign) __weak id wAnother; +@end + +@implementation I +@synthesize representedObject; +@synthesize wObject; +@synthesize wRandom; +@synthesize wAnother; +@end +// CHECK: call i8* @objc_read_weak +// CHECK: call i8* @objc_assign_weak +// CHECK: call i8* @objc_read_weak +// CHECK: call i8* @objc_assign_weak +// CHECK: call i8* @objc_read_weak +// CHECK: call i8* @objc_assign_weak +// CHECK: call i8* @objc_read_weak +// CHECK: call i8* @objc_assign_weak + diff --git a/clang/test/CodeGenObjC/gc.m b/clang/test/CodeGenObjC/gc.m new file mode 100644 index 0000000..b672181 --- /dev/null +++ b/clang/test/CodeGenObjC/gc.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck %s + +void test0(void) { + extern id test0_helper(void); + __attribute__((objc_precise_lifetime)) id x = test0_helper(); + test0_helper(); + // CHECK: define void @test0() + // CHECK: [[T0:%.*]] = call i8* @test0_helper() + // CHECK-NEXT: store i8* [[T0]], i8** [[X:%.*]], align 8 + // CHECK-NEXT: call i8* @test0_helper() + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8 + // CHECK-NEXT: call void asm sideeffect "", "r"(i8* [[T0]]) nounwind + // CHECK-NEXT: ret void +} diff --git a/clang/test/CodeGenObjC/gnu-exceptions.m b/clang/test/CodeGenObjC/gnu-exceptions.m new file mode 100644 index 0000000..8917bf3 --- /dev/null +++ b/clang/test/CodeGenObjC/gnu-exceptions.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fobjc-exceptions -fgnu-runtime -o - %s | FileCheck %s + +void opaque(void); +void log(int i); + +@class C; + +// CHECK: define void @test0() { +void test0() { + @try { + // CHECK: invoke void @opaque() + opaque(); + + // CHECK: call void @log(i32 1) + + } @catch (C *c) { + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*) + // CHECK-NEXT: catch i8* getelementptr inbounds ([2 x i8]* @0, i64 0, i64 0) + // CHECK: br i1 + + // CHECK: call void @log(i32 0) + + // CHECK: call void @objc_exception_throw + + log(0); + } + + log(1); +} diff --git a/clang/test/CodeGenObjC/hidden-visibility.m b/clang/test/CodeGenObjC/hidden-visibility.m new file mode 100644 index 0000000..9f5071d --- /dev/null +++ b/clang/test/CodeGenObjC/hidden-visibility.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fvisibility hidden -emit-llvm -o - %s | FileCheck %s +// CHECK: @"OBJC_IVAR_$_I.P" = hidden +// CHECK: @"OBJC_CLASS_$_I" = hidden +// CHECK: @"OBJC_METACLASS_$_I" = hidden +// CHECK: @"\01l_OBJC_PROTOCOL_$_Prot0" = weak hidden + +@interface I { + int P; +} + +@property int P; +@end + +@implementation I +@synthesize P; +@end + + +@protocol Prot0; + +id f0() { + return @protocol(Prot0); +} + + diff --git a/clang/test/CodeGenObjC/hidden.m b/clang/test/CodeGenObjC/hidden.m new file mode 100644 index 0000000..0b77e73 --- /dev/null +++ b/clang/test/CodeGenObjC/hidden.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +__attribute__((visibility("hidden"))) +@interface Hidden ++(void) bar; +@end + +@implementation Hidden ++(void) bar {} +@end + +__attribute__((visibility("default"))) +@interface Default ++(void) bar; +@end + +@implementation Default ++(void) bar {} +@end diff --git a/clang/test/CodeGenObjC/id-isa-codegen.m b/clang/test/CodeGenObjC/id-isa-codegen.m new file mode 100644 index 0000000..8cac750 --- /dev/null +++ b/clang/test/CodeGenObjC/id-isa-codegen.m @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP32 %s + +typedef struct objc_class *Class; + +typedef struct objc_object { + Class isa; +} *id; + +@interface I ++ (Class) class; +- (void)meth : (id)object : (id)src_object; ++ (unsigned char) isSubclassOfClass:(Class)aClass ; +@end + +@implementation I ++ (Class) class {return 0;} ++ (unsigned char) isSubclassOfClass:(Class)aClass {return 0;} +- (void)meth : (id)object : (id)src_object { + [object->isa isSubclassOfClass:[I class]]; + + [(*object).isa isSubclassOfClass:[I class]]; + + object->isa = src_object->isa; + (*src_object).isa = (*object).isa; +} +@end + + +// rdar 7470820 +static Class MyClass; + +Class Test(const void *inObject1) { + if(((id)inObject1)->isa == MyClass) + return ((id)inObject1)->isa; + return (id)0; +} + +// rdar 7609722 +@interface Foo { +@public + id isa; +} ++(id)method; +@end + +id Test2() { + if([Foo method]->isa) + return (*[Foo method]).isa; + return [Foo method]->isa; +} + +// rdar 7709015 +@interface Cat {} +@end + +@interface SuperCat : Cat {} ++(void)geneticallyAlterCat:(Cat *)cat; +@end + +@implementation SuperCat ++ (void)geneticallyAlterCat:(Cat *)cat { + Class dynamicSubclass; + ((id)cat)->isa = dynamicSubclass; +} +@end +// CHECK-LP64: %{{.*}} = load i8** % +// CHECK-NEXT: %{{.*}} = bitcast i8* %{{.*}} to i8** +// CHECK-NEXT: store i8* %{{.*}}, i8** %{{.*}} + +// CHECK-LP32: %{{.*}} = load i8** % +// CHECK-NEXT: %{{.*}} = bitcast i8* %{{.*}} to i8** +// CHECK-NEXT: store i8* %{{.*}}, i8** %{{.*}} diff --git a/clang/test/CodeGenObjC/illegal-UTF8.m b/clang/test/CodeGenObjC/illegal-UTF8.m new file mode 100644 index 0000000..4762e80 --- /dev/null +++ b/clang/test/CodeGenObjC/illegal-UTF8.m @@ -0,0 +1,6 @@ +// RUN: %clang %s -S -m64 -o - + +@class NSString; + + +NSString *S = @"\xff\xff___WAIT___"; // expected-warning {{input conversion stopped due to an input byte that does not belong to the input codeset UTF-8}} diff --git a/clang/test/CodeGenObjC/image-info.m b/clang/test/CodeGenObjC/image-info.m new file mode 100644 index 0000000..613b272 --- /dev/null +++ b/clang/test/CodeGenObjC/image-info.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-FRAGILE < %t %s + +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-NONFRAGILE < %t %s + +// CHECK-FRAGILE: !llvm.module.flags = !{!0, !1, !2, !3} +// CHECK-FRAGILE: !0 = metadata !{i32 1, metadata !"Objective-C Version", i32 1} +// CHECK-FRAGILE-NEXT: !1 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0} +// CHECK-FRAGILE-NEXT: !2 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__OBJC, __image_info,regular"} +// CHECK-FRAGILE-NEXT: !3 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0} + +// CHECK-NONFRAGILE: !llvm.module.flags = !{!0, !1, !2, !3} +// CHECK-NONFRAGILE: !0 = metadata !{i32 1, metadata !"Objective-C Version", i32 2} +// CHECK-NONFRAGILE-NEXT: !1 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0} +// CHECK-NONFRAGILE-NEXT: !2 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"} +// CHECK-NONFRAGILE-NEXT: !3 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0} diff --git a/clang/test/CodeGenObjC/implicit-objc_msgSend.m b/clang/test/CodeGenObjC/implicit-objc_msgSend.m new file mode 100644 index 0000000..aff0fe4 --- /dev/null +++ b/clang/test/CodeGenObjC/implicit-objc_msgSend.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: grep -F 'declare i8* @objc_msgSend(i8*, i8*, ...)' %t + +typedef struct objc_selector *SEL; +id f0(id x, SEL s) { + return objc_msgSend(x, s); +} diff --git a/clang/test/CodeGenObjC/implicit-property.m b/clang/test/CodeGenObjC/implicit-property.m new file mode 100644 index 0000000..db1da31 --- /dev/null +++ b/clang/test/CodeGenObjC/implicit-property.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm -triple=i686-apple-darwin8 -o %t %s +// RUNX: %clang_cc1 -emit-llvm -o %t %s + +@interface A + -(void) setOk:(int)arg; + -(int) ok; + + -(void) setX:(int)arg; + -(int) x; +@end + +void f0(A *a) { + a.x = 1; + a.ok = a.x; +} + diff --git a/clang/test/CodeGenObjC/instance-method-metadata.m b/clang/test/CodeGenObjC/instance-method-metadata.m new file mode 100644 index 0000000..ec24c28 --- /dev/null +++ b/clang/test/CodeGenObjC/instance-method-metadata.m @@ -0,0 +1,35 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -o %t %s +// RUN: FileCheck < %t %s + +// rdar://9072317 + +/** The problem looks like clang getting confused when a single translation unit + contains a protocol with a property and two classes that implement that protocol + and synthesize the property. +*/ + +@protocol Proto +@property (assign) id prop; +@end + +@interface NSObject @end + +@interface Foo : NSObject <Proto> { int x; } @end + +@interface Bar : NSObject <Proto> @end + +@implementation Foo +@synthesize prop; +@end + +@implementation Bar +@synthesize prop; +@end + +// CHECK: l_OBJC_$_INSTANCE_METHODS_Bar: +// CHECK-NEXT .long 24 +// CHECK-NEXT .long 2 +// CHECK-NEXT .quad L_OBJC_METH_VAR_NAME_ +// CHECK-NEXT .quad L_OBJC_METH_VAR_TYPE_ +// CHECK-NEXT .quad "-[Bar prop]" diff --git a/clang/test/CodeGenObjC/interface-layout-64.m b/clang/test/CodeGenObjC/interface-layout-64.m new file mode 100644 index 0000000..4fdda45 --- /dev/null +++ b/clang/test/CodeGenObjC/interface-layout-64.m @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && + +// RUN: grep '@"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = hidden global i64 16, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = hidden global i64 20, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I10.iv1" = global i64 4, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_IVAR_$_I12.iv2" = global i64 8, section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '_OBJC_CLASS_RO_$_I3" = internal global .* { i32 0, i32 8, i32 13, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I4" = internal global .* { i32 0, i32 13, i32 14, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I5" = internal global .* { i32 0, i32 14, i32 24, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I6" = internal global .* { i32 2, i32 0, i32 1, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I8" = internal global .* { i32 0, i32 8, i32 16, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I9" = internal global .* { i32 2, i32 0, i32 4, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I10" = internal global .* { i32 0, i32 4, i32 5, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I11" = internal global .* { i32 0, i32 5, i32 5, .*' %t +// RUN: grep '_OBJC_CLASS_RO_$_I12" = internal global .* { i32 0, i32 8, i32 12, .*' %t + + +/* + Compare to: + gcc -m64 -S -o - interface-layout-64.m | grep '^_OBJC_IVAR_$_*.*' -A 1 + and + gcc -m64 -S -o - interface-layout-64.m | grep '^l.*_CLASS_RO_$_I[0-9]*' -A 3 + */ + +struct s0 { + double x; +}; + +@interface I2 { + struct s0 _iv1; +} +@end + +@interface I3 : I2 { + unsigned int _iv2 :1; + unsigned : 0; + unsigned int _iv3 : 3; +} +@end + +@interface I4 : I3 { + char _iv4; +} +@end + +@interface I5 : I4 { + char _iv5; +} + +@property int prop0; +@end + +@implementation I3 +@end + +@implementation I4 +@end + +@interface I5 () +@property int prop1; +@property char prop2; +@end + +@implementation I5 +@synthesize prop0 = _iv6_synth; +@synthesize prop1 = _iv7_synth; +@synthesize prop2 = _iv5; +@end + +// The size rounds up to the next available byte. +@interface I6 { + unsigned iv0 : 2; +} +@end +@implementation I6 +@end + +// The start of the subclass includes padding for its own alignment. +@interface I7 { + char a; +} +@end +@interface I8 : I7 { + double b; +} +@end +@implementation I8 +@end + +// Padding bit-fields +@interface I9 { + unsigned iv0 : 2; + unsigned : 0; +} +@end +@implementation I9 +@end +@interface I10 : I9 { + unsigned iv1 : 2; +} +@end +@implementation I10 +@end + +// Empty structures +@interface I11 : I10 +@end +@implementation I11 +@end +@interface I12 : I11 { + unsigned iv2; +} +@end +@implementation I12 +@end diff --git a/clang/test/CodeGenObjC/interface.m b/clang/test/CodeGenObjC/interface.m new file mode 100644 index 0000000..0ca64ec --- /dev/null +++ b/clang/test/CodeGenObjC/interface.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -O3 -emit-llvm -o %t %s +// RUN: grep 'ret i32 385' %t + +void *alloca(); + +@interface I0 { +@public + int iv0; + int iv1; + int iv2; +} +@end + +static int f0(I0 *a0) { + return (*(a0 + 2)).iv0; +} + +static int f1(I0 *a0) { + return a0[2].iv1; +} + +static int f2(I0 *a0) { + return (*(a0 - 1)).iv2; +} + +int g0(void) { + I0 *a = alloca(sizeof(*a) * 4); + a[2].iv0 = 5; + a[2].iv1 = 7; + a[2].iv2 = 11; + return f0(a) * f1(a) * f2(&a[3]); +} + + diff --git a/clang/test/CodeGenObjC/ivar-base-as-invariant-load.m b/clang/test/CodeGenObjC/ivar-base-as-invariant-load.m new file mode 100644 index 0000000..8b660cf --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-base-as-invariant-load.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -x objective-c %s -o - | FileCheck %s +// rdar://10840980 + +@interface A { + struct { + unsigned char a : 1; + unsigned char b : 1; + unsigned char c : 1; + } _flags; +} + +@end + +@implementation A + +- (id)init { + _flags.a = 1; + _flags.b = 1; + _flags.c = 1; + + return self; +} + +@end + +// CHECK: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 +// CHECK: [[T2:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 +// CHECK: [[T3:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 + diff --git a/clang/test/CodeGenObjC/ivar-layout-64-bitfields.m b/clang/test/CodeGenObjC/ivar-layout-64-bitfields.m new file mode 100644 index 0000000..acc734a --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-layout-64-bitfields.m @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s + +#ifdef __cplusplus +typedef bool _Bool; +#endif + +@interface I +{ + struct { + unsigned int d : 1; + } bitfield; +} +@end + +@implementation I +@end + +@interface J +{ + struct { + unsigned short _reserved : 16; + + _Bool _draggedNodesAreDeletable: 1; + _Bool _draggedOutsideOutlineView : 1; + _Bool _adapterRespondsTo_addRootPaths : 1; + _Bool _adapterRespondsTo_moveDataNodes : 1; + _Bool _adapterRespondsTo_removeRootDataNode : 1; + _Bool _adapterRespondsTo_doubleClickDataNode : 1; + _Bool _adapterRespondsTo_selectDataNode : 1; + _Bool _adapterRespondsTo_textDidEndEditing : 1; + + _Bool _adapterRespondsTo_updateAndSaveRoots : 1; + _Bool _adapterRespondsTo_askToDeleteRootNodes : 1; + _Bool _adapterRespondsTo_contextMenuForSelectedNodes : 1; + _Bool _adapterRespondsTo_pasteboardFilenamesForNodes : 1; + _Bool _adapterRespondsTo_writeItemsToPasteboard : 1; + _Bool _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; + } _flags; +} +@end + +@implementation J +@end + + diff --git a/clang/test/CodeGenObjC/ivar-layout-64.m b/clang/test/CodeGenObjC/ivar-layout-64.m new file mode 100644 index 0000000..ea4cdce --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-layout-64.m @@ -0,0 +1,94 @@ +// RUNX: llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o %t %s && +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t +// RUNX: llvm-gcc -ObjC++ -m64 -fobjc-gc -emit-llvm -S -o %t %s && +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o - ivar-layout-64.m | \ + grep 'OBJC_CLASS_NAME.* =.*global' | \ + sed -e 's#, section.*# ...#' | \ + sed -e 's#_[0-9]*"#_NNN#' | \ + sort + +*/ + +@interface B @end + +@interface A { + struct s0 { + int f0; + int f1; + } f0; + id f1; +__weak B *f2; + int f3 : 5; + struct s1 { + int *f0; + int *f1; + } f4[2][1]; +} +@end + +@interface C : A +@property int p3; +@end + +@implementation C +@synthesize p3 = _p3; +@end + +@interface A() +@property int p0; +@property (assign) __strong id p1; +@property (assign) __weak id p2; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation A +@synthesize p0 = _p0; +@synthesize p1 = _p1; +@synthesize p2 = _p2; +@end + +@interface D : A +@property int p3; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation D +@synthesize p3 = _p3; +@end + +typedef unsigned short UInt16; + + +typedef signed char BOOL; +typedef unsigned int FSCatalogInfoBitmap; + +@interface NSFileLocationComponent { + @private + + id _specifierOrStandardizedPath; + BOOL _carbonCatalogInfoAndNameAreValid; + FSCatalogInfoBitmap _carbonCatalogInfoMask; + id _name; + id _containerComponent; + id _presentableName; + id _iconAsAttributedString; +} +@end + +@implementation NSFileLocationComponent @end + diff --git a/clang/test/CodeGenObjC/ivar-layout-array0-struct.m b/clang/test/CodeGenObjC/ivar-layout-array0-struct.m new file mode 100644 index 0000000..7ef32f6 --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-layout-array0-struct.m @@ -0,0 +1,23 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -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/clang/test/CodeGenObjC/ivar-layout-no-optimize.m b/clang/test/CodeGenObjC/ivar-layout-no-optimize.m new file mode 100644 index 0000000..85bba8a --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-layout-no-optimize.m @@ -0,0 +1,20 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -x objective-c++ -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s + +@interface NSObject { + id isa; +} +@end + +@interface AllPointers : NSObject { + id foo; + void *__strong bar; NSObject *bletch;} +@end +@implementation AllPointers +@end + +// CHECK-LP64: L_OBJC_CLASS_NAME_6: +// CHECK-LP64-NEXT: .asciz "\004" diff --git a/clang/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m b/clang/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m new file mode 100644 index 0000000..65e17a8 --- /dev/null +++ b/clang/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// rdar: // 7824380 + +@interface Super { + int ivar_super_a : 5; +} +@end + +@interface A : Super { +@public + int ivar_a : 5; +} +@end + +int f0(A *a) { + return a->ivar_a; +} + +@interface A () { +@public + int ivar_ext_a : 5; + int ivar_ext_b : 5; +}@end + +int f1(A *a) { + return a->ivar_ext_a + a->ivar_a; +} + +@interface A () { +@public + int ivar_ext2_a : 5; + int ivar_ext2_b : 5; +}@end + +int f2(A* a) { + return a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} + +@implementation A { +@public + int ivar_b : 5; + int ivar_c : 5; + int ivar_d : 5; +} +@end + +int f3(A *a) { + return a->ivar_d + a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} + diff --git a/clang/test/CodeGenObjC/ivars.m b/clang/test/CodeGenObjC/ivars.m new file mode 100644 index 0000000..6c8a72d --- /dev/null +++ b/clang/test/CodeGenObjC/ivars.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -o - %s + +// rdar://6800926 +@interface ITF { +@public + unsigned field :1 ; + _Bool boolfield :1 ; +} +@end + +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/clang/test/CodeGenObjC/link-errors.m b/clang/test/CodeGenObjC/link-errors.m new file mode 100644 index 0000000..0d19681 --- /dev/null +++ b/clang/test/CodeGenObjC/link-errors.m @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: grep '.lazy_reference .objc_class_name_A' %t | count 1 +// RUN: grep '.lazy_reference .objc_class_name_Unknown' %t | count 1 +// RUN: grep '.lazy_reference .objc_class_name_Protocol' %t | count 1 +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -DWITH_IMPL -emit-llvm -o %t %s +// RUN: grep '.lazy_reference .objc_class_name_Root' %t | count 1 + +@interface Root +-(id) alloc; +-(id) init; +@end + +@protocol P; + +@interface A : Root +@end + +@interface A (Category) ++(void) foo; +@end + +#ifdef WITH_IMPL +@implementation A +@end +#endif + +@interface Unknown ++test; +@end + + +int main() { + id x = @protocol(P); + [ A alloc ]; + [ A foo ]; + [ Unknown test ]; + return 0; +} + diff --git a/clang/test/CodeGenObjC/local-static-block.m b/clang/test/CodeGenObjC/local-static-block.m new file mode 100644 index 0000000..7a7b6f6 --- /dev/null +++ b/clang/test/CodeGenObjC/local-static-block.m @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fobjc-fragile-abi -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/clang/test/CodeGenObjC/message-arrays.m b/clang/test/CodeGenObjC/message-arrays.m new file mode 100644 index 0000000..3e8697f --- /dev/null +++ b/clang/test/CodeGenObjC/message-arrays.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +void f0(id a) { + // This should have an implicit cast + [ a print: "hello" ]; +} + +@interface A +-(void) m: (int) arg0, ...; +@end + +int f1(A *a) { + // This should also get an implicit cast (for the vararg) + [a m: 1, "test"]; +} diff --git a/clang/test/CodeGenObjC/messages-2.m b/clang/test/CodeGenObjC/messages-2.m new file mode 100644 index 0000000..7c9d81c --- /dev/null +++ b/clang/test/CodeGenObjC/messages-2.m @@ -0,0 +1,175 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NF + +// Most of this test is apparently just verifying that we don't crash. + +int printf(const char *, ...); + +@interface Root +@end + +typedef struct { + int x, y, z[10]; +} MyPoint; +typedef struct { + float width, height; +} MySize; + +@interface A : Root ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; ++(float) returnAFloat; ++(double) returnADouble; ++(MyPoint) returnAPoint; ++(void) printThisSize: (MySize) arg0; ++(MySize) returnASize; + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; +-(float) returnAFloat; +-(double) returnADouble; +-(MyPoint) returnAPoint; +-(void) printThisSize: (MySize) arg0; +-(MySize) returnASize; +@end +@interface B : A +@end + +@implementation A ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("(CLASS) theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} ++(float) returnAFloat { + return 15.; +} ++(double) returnADouble { + return 25.; +} ++(MyPoint) returnAPoint { + MyPoint x = { 35, 45 }; + return x; +} ++(void) printThisSize: (MySize) arg0 { + printf("(CLASS) theSize: { %f, %f }\n", + arg0.width, arg0.height); +} ++(MySize) returnASize { + MySize x = { 32, 44 }; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} +-(float) returnAFloat { + return 10.; +} +-(double) returnADouble { + return 20.; +} +-(MyPoint) returnAPoint { + MyPoint x = { 30, 40 }; + return x; +} +-(void) printThisSize: (MySize) arg0 { + printf("theSize: { %f, %f }\n", + arg0.width, arg0.height); +} +-(MySize) returnASize { + MySize x = { 22, 34 }; + return x; +} +@end + +@implementation B ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} ++(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} ++(float) returnAFloat { + return [ super returnAFloat ]*2; +} ++(double) returnADouble { + return [ super returnADouble ]*2; +} ++(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} ++(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} +-(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} +-(float) returnAFloat { + return [ super returnAFloat ]*2; +} +-(double) returnADouble { + return [ super returnADouble ]*2; +} +-(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} +-(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} +-(const float) returnAConstFloat { + return 5; +} +@end + +// rdar://problem/7854674 +// CHECK: define void @test0([[A:%.*]]* +// CHECK-NF: define void @test0([[A:%.*]]* +void test0(A *x) { + // CHECK: [[X:%.*]] = alloca [[A]]* + // CHECK-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]], + // CHECK: [[T0:%.*]] = load [[A]]** [[X]] + // CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* + // CHECK-NEXT: icmp eq i8* [[T1]], null + // CHECK-NEXT: br i1 + // CHECK: call {{.*}} @objc_msgSend_stret to + // CHECK-NEXT: br label + // CHECK: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8* + // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false) + // CHECK-NEXT: br label + + // CHECK-NF: [[X:%.*]] = alloca [[A]]* + // CHECK-NF-NEXT: [[POINT:%.*]] = alloca [[POINT_T:%.*]], + // CHECK-NF: [[T0:%.*]] = load [[A]]** [[X]] + // CHECK-NF: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* + // CHECK-NF-NEXT: icmp eq i8* [[T1]], null + // CHECK-NF-NEXT: br i1 + // CHECK-NF: call {{.*}} @objc_msgSend_stret to + // CHECK-NF-NEXT: br label + // CHECK-NF: [[T0:%.*]] = bitcast [[POINT_T]]* [[POINT]] to i8* + // CHECK-NF-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 48, i32 4, i1 false) + // CHECK-NF-NEXT: br label + MyPoint point = [x returnAPoint]; +} diff --git a/clang/test/CodeGenObjC/messages.m b/clang/test/CodeGenObjC/messages.m new file mode 100644 index 0000000..6f39602 --- /dev/null +++ b/clang/test/CodeGenObjC/messages.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-MAC +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-MAC-NF +// RUN: %clang_cc1 -fobjc-fragile-abi -fgnu-runtime -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-GNU +// RUN: %clang_cc1 -fgnu-runtime -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-GNU-NF + +typedef struct { + int x; + int y; + int z[10]; +} MyPoint; + +void f0(id a) { + int i; + MyPoint pt = { 1, 2}; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( + [a print0]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( + [a print1: 10]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( + [a print2: 10 and: "hello" and: 2.2]; + + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( + [a takeStruct: pt ]; + + void *s = @selector(print0); + for (i=0; i<2; ++i) + // CHECK-MAC: call {{.*}} @objc_msgSend to + // CHECK-MAC-NF: call {{.*}} @objc_msgSend to + // CHECK-GNU: call {{.*}} @objc_msg_lookup( + // CHECK-GNU-NF: call {{.*}} @objc_msg_lookup_sender( + [a performSelector:s]; +} diff --git a/clang/test/CodeGenObjC/metadata-symbols-32.m b/clang/test/CodeGenObjC/metadata-symbols-32.m new file mode 100644 index 0000000..a7bcf01 --- /dev/null +++ b/clang/test/CodeGenObjC/metadata-symbols-32.m @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && + +// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*section "__OBJC,__category,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CATEGORY_CLASS_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CATEGORY_INSTANCE_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASSEXT_A" = internal global .*section "__OBJC,__class_ext,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*section "__OBJC,__class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_METHODS_A" = internal global .*section "__OBJC,__cls_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_A" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4' %t + +// Clang's Obj-C 32-bit doesn't emit ivars for the root class. +// RUNX: grep '@"\\01L_OBJC_CLASS_VARIABLES_A" = internal global .*section "__OBJC,__class_vars,regular,no_dead_strip", align 4' %t && + +// RUN: grep '@"\\01L_OBJC_INSTANCE_METHODS_A" = internal global .*section "__OBJC,__inst_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_INSTANCE_VARIABLES_A" = internal global .*section "__OBJC,__instance_vars,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_PROTOCOL_CLASS_METHODS_P" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_PROTOCOL_INSTANCE_METHODS_P" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_SYMBOLS" = internal global .*section "__OBJC,__symbols,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .*section "__OBJC,__property,regular,no_dead_strip", align 4' %t +// RUN: grep "\.lazy_reference \.objc_class_name_J0" %t + + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m32 -emit-llvm -S -o - metadata-symbols-32.m | \ + grep '=.*global' | \ + sed -e 's#global.*, section#global ... section#' | \ + sort + +*/ + +@interface B +@end +@interface C +@end + +@protocol P ++(void) fm0; +-(void) im0; +@end + +@interface A<P> { + int _ivar; +} + +@property (assign) int ivar; + ++(void) fm0; +-(void) im0; +@end + +@implementation A +@synthesize ivar = _ivar; ++(void) fm0 { +} +-(void) im0 { +} +@end + +@implementation A (Cat) ++(void) fm1 { +} +-(void) im1 { +} +@end + +@interface J0 +@end + +@implementation J0(Category) @end + +void *f0() { + [B im0]; + [C im1]; +} + diff --git a/clang/test/CodeGenObjC/metadata-symbols-64.m b/clang/test/CodeGenObjC/metadata-symbols-64.m new file mode 100644 index 0000000..57f5d50 --- /dev/null +++ b/clang/test/CodeGenObjC/metadata-symbols-64.m @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed -emit-llvm -o %t %s +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && + +// RUN: grep '@"OBJC_CLASS_$_A" = global' %t +// RUN: grep '@"OBJC_CLASS_$_B" = external global' %t +// RUN: grep '@"OBJC_IVAR_$_A._ivar" = global .* section "__DATA, __objc_ivar", align 8' %t +// RUN: grep '@"OBJC_METACLASS_$_A" = global .* section "__DATA, __objc_data", align 8' %t +// RUN: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_[0-9]*" = internal global .* section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t +// RUN: grep '@"\\01L_OBJC_CLASSLIST_SUP_REFS_$_[0-9]*" = internal global .* section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8' %t | count 2 +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .* section "__TEXT,__objc_classname,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .* section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t +// RUN: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .* section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t +// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__objc_methname,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__objc_methtype,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_CLASS_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_INSTANCE_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_INSTANCE_VARIABLES_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .* section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t +// RUN: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t +// RUN: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .* section "__DATA,__datacoal_nt,coalesced", align 8' %t +// RUN: grep '@"\\01l_objc_msgSend_fixup_alloc" = weak hidden global .* section "__DATA, __objc_msgrefs, coalesced", align 16' %t +// RUN: grep '@_objc_empty_cache = external global' %t +// RUN: grep '@_objc_empty_vtable = external global' %t +// RUN: grep '@objc_msgSend_fixup(' %t +// RUN: grep '@objc_msgSend_fpret(' %t + + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m64 -emit-llvm -S -o - metadata-symbols-64.m | \ + grep '=.*global' | \ + sed -e 's#global.*, section#global ... section#' | \ + sort + +*/ + +@interface B +@end +@interface C +@end + +@protocol P ++(void) fm0; +-(void) im0; +@end + +@interface A<P> { + int _ivar; +} + +@property (assign) int ivar; + ++(void) fm0; +-(void) im0; +@end + +@implementation A +@synthesize ivar = _ivar; ++(void) fm0 { +} +-(void) im0 { +} +@end + +@implementation A (Cat) ++(void) fm1 { +} +-(void) im1 { +} +@end + +@interface D : A +@end + +@implementation D ++(void) fm2 { + [super fm1]; +} +-(void) im2 { + [super im1]; +} +@end + +// Test for FP dispatch method APIs +@interface Example +@end + +float FLOAT; +double DOUBLE; +long double LONGDOUBLE; +id ID; + +@implementation Example + - (double) RET_DOUBLE + { + return DOUBLE; + } + - (float) RET_FLOAT + { + return FLOAT; + } + - (long double) RET_LONGDOUBLE + { + return LONGDOUBLE; + } +@end + +void *f0(id x) { + Example* pe; + double dd = [pe RET_DOUBLE]; + dd = [pe RET_FLOAT]; + dd = [pe RET_LONGDOUBLE]; + + [B im0]; + [C im1]; + [D alloc]; +} + diff --git a/clang/test/CodeGenObjC/metadata_symbols.m b/clang/test/CodeGenObjC/metadata_symbols.m new file mode 100644 index 0000000..576a55b --- /dev/null +++ b/clang/test/CodeGenObjC/metadata_symbols.m @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck -check-prefix=CHECK-X86_64 < %t %s +// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 + +// CHECK-X86_64: @"OBJC_CLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64: @"OBJC_METACLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64: @"\01L_OBJC_CLASS_NAME_" = {{.*}}, section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-X86_64: @"OBJC_EHTYPE_$_EH1" = weak global {{.*}}, section "__DATA,__datacoal_nt,coalesced", align 8 +// CHECK-X86_64: @"OBJC_EHTYPE_$_EH2" = external global +// CHECK-X86_64: @"OBJC_EHTYPE_$_EH3" = global {{.*}}, section "__DATA,__objc_const", align 8 +// CHECK-X86_64: @"\01L_OBJC_LABEL_CLASS_$" = internal global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8 +// CHECK-X86_64: define internal void @"\01-[A im0]" +// CHECK-X86_64: define internal void @"\01-[A(Cat) im1]" + +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-X86_64-HIDDEN < %t %s + +// CHECK-X86_64-HIDDEN: @"OBJC_CLASS_$_A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64-HIDDEN: @"OBJC_METACLASS_$_A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_EH1" = weak hidden global {{.*}}, section "__DATA,__datacoal_nt,coalesced" +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_EH2" = external global +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_EH3" = hidden global {{.*}}, section "__DATA,__objc_const", align 8 +// CHECK-X86_64-HIDDEN: define internal void @"\01-[A im0]" +// CHECK-X86_64-HIDDEN: define internal void @"\01-[A(Cat) im1]" + +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-exceptions -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-ARMV6 < %t %s + +// CHECK-ARMV6: @"OBJC_CLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 4 +// CHECK-ARMV6: @"OBJC_METACLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 4 +// CHECK-ARMV6: @"\01L_OBJC_CLASS_NAME_" = {{.*}}, section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-ARMV6: @"OBJC_EHTYPE_$_EH1" = weak global {{.*}}, section "__DATA,__datacoal_nt,coalesced", align 4 +// CHECK-ARMV6: @"OBJC_EHTYPE_$_EH2" = external global +// CHECK-ARMV6: @"OBJC_EHTYPE_$_EH3" = global {{.*}}, section "__DATA,__objc_const", align 4 +// CHECK-ARMV6: @"\01L_OBJC_LABEL_CLASS_$" = internal global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 4 +// CHECK-ARMV6: define internal void @"\01-[A im0]" +// CHECK-ARMV6: define internal void @"\01-[A(Cat) im1]" + +@interface A +@end + +@implementation A +-(void) im0 { +} +@end + +@implementation A (Cat) +-(void) im1 { +} +@end + +@interface EH1 +@end + +__attribute__((__objc_exception__)) +@interface EH2 +@end + +__attribute__((__objc_exception__)) +@interface EH3 +@end + +void f1(); + +void f0(id x) { + @try { + f1(); + } @catch (EH1 *x) { + } @catch (EH2 *x) { + } @catch (EH3 *x) { + } +} + +@implementation EH3 +@end diff --git a/clang/test/CodeGenObjC/misc-atomic-property.m b/clang/test/CodeGenObjC/misc-atomic-property.m new file mode 100644 index 0000000..f2645dc --- /dev/null +++ b/clang/test/CodeGenObjC/misc-atomic-property.m @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar: //8808439 + +typedef struct { +#ifdef __LP64__ + unsigned char b[15]; +#else + unsigned char b[7]; +#endif +} bools_minus_one; + +typedef struct { +#ifdef __LP64__ + unsigned char b[16]; +#else + unsigned char b[8]; +#endif +} bools; + + +@interface Foo +{ +#ifndef __LP64__ + bools x; + bools_minus_one y; +#endif +} +@property(assign) bools bools_p; +@property(assign) bools_minus_one bools_minus_one_p; +@end + +@implementation Foo +@synthesize bools_p=x; +@synthesize bools_minus_one_p=y; +@end + +#ifdef __LP64__ +typedef __int128_t dword; +#else +typedef long long int dword; +#endif + +@interface Test_dwords +{ +#ifndef __LP64__ + dword dw; +#endif +} +@property(assign) dword dword_p; +@end + +@implementation Test_dwords +@synthesize dword_p=dw; +@end + + +@interface Test_floats +{ + float fl; + double d; + long double ld; +} +@property(assign) float fl_p; +@property(assign) double d_p; +@property(assign) long double ld_p; +@end + +@implementation Test_floats +@synthesize fl_p = fl; +@synthesize d_p = d; +@synthesize ld_p = ld; +@end + +// CHECK: call void @objc_copyStruct +// CHECK: call void @objc_copyStruct +// CHECK: call void @objc_copyStruct +// CHECK: call void @objc_copyStruct +// CHECK: call void @objc_copyStruct +// CHECK: call void @objc_copyStruct diff --git a/clang/test/CodeGenObjC/mrr-autorelease.m b/clang/test/CodeGenObjC/mrr-autorelease.m new file mode 100644 index 0000000..f7a13fd --- /dev/null +++ b/clang/test/CodeGenObjC/mrr-autorelease.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar://8881826 +// rdar://9423507 + +@interface I +{ + id ivar; +} +- (id) Meth; +@end + +@implementation I +- (id) Meth { + @autoreleasepool { + } + return 0; +} +@end + +// CHECK-NOT: call i8* @objc_getClass +// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend diff --git a/clang/test/CodeGenObjC/nested-rethrow.m b/clang/test/CodeGenObjC/nested-rethrow.m new file mode 100644 index 0000000..5576c16 --- /dev/null +++ b/clang/test/CodeGenObjC/nested-rethrow.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -fobjc-exceptions %s -o - | FileCheck %s + + +extern int printf(const char*, ...); + +int main() +{ + @try { + @throw @"foo"; + } @catch (id e) { + @try { +// CHECK: call void @objc_exception_throw + @throw; + } @catch (id e) { + if (e) { + printf("caught \n"); + } else { + printf("caught (WRONG)\n"); + } + } @catch (...) { + printf("caught nothing (WRONG)\n"); + } + } +} + diff --git a/clang/test/CodeGenObjC/newproperty-nested-synthesis-1.m b/clang/test/CodeGenObjC/newproperty-nested-synthesis-1.m new file mode 100644 index 0000000..4831c22 --- /dev/null +++ b/clang/test/CodeGenObjC/newproperty-nested-synthesis-1.m @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface Object +- (id) new; +@end + +@interface Tester : Object +@property char PropertyAtomic_char; +@property short PropertyAtomic_short; +@property int PropertyAtomic_int; +@property long PropertyAtomic_long; +@property long long PropertyAtomic_longlong; +@property float PropertyAtomic_float; +@property double PropertyAtomic_double; +@property(assign) id PropertyAtomic_id; +@property(retain) id PropertyAtomicRetained_id; +@property(copy) id PropertyAtomicRetainedCopied_id; +@property(retain) id PropertyAtomicRetainedGCOnly_id; +@property(copy) id PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@implementation Tester +@dynamic PropertyAtomic_char; +@dynamic PropertyAtomic_short; +@dynamic PropertyAtomic_int; +@dynamic PropertyAtomic_long; +@dynamic PropertyAtomic_longlong; +@dynamic PropertyAtomic_float; +@dynamic PropertyAtomic_double; +@dynamic PropertyAtomic_id; +@dynamic PropertyAtomicRetained_id; +@dynamic PropertyAtomicRetainedCopied_id; +@dynamic PropertyAtomicRetainedGCOnly_id; +@dynamic PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@interface SubClass : Tester +{ + char PropertyAtomic_char; + short PropertyAtomic_short; + int PropertyAtomic_int; + long PropertyAtomic_long; + long long PropertyAtomic_longlong; + float PropertyAtomic_float; + double PropertyAtomic_double; + id PropertyAtomic_id; + id PropertyAtomicRetained_id; + id PropertyAtomicRetainedCopied_id; + id PropertyAtomicRetainedGCOnly_id; + id PropertyAtomicRetainedCopiedGCOnly_id; +} +@end + +@implementation SubClass +@synthesize PropertyAtomic_char; +@synthesize PropertyAtomic_short; +@synthesize PropertyAtomic_int; +@synthesize PropertyAtomic_long; +@synthesize PropertyAtomic_longlong; +@synthesize PropertyAtomic_float; +@synthesize PropertyAtomic_double; +@synthesize PropertyAtomic_id; +@synthesize PropertyAtomicRetained_id; +@synthesize PropertyAtomicRetainedCopied_id; +@synthesize PropertyAtomicRetainedGCOnly_id; +@synthesize PropertyAtomicRetainedCopiedGCOnly_id; +@end + +int main() +{ + SubClass *f = [SubClass new]; + f.PropertyAtomic_int = 1; + + f.PropertyAtomic_int += 3; + + f.PropertyAtomic_int -= 4; + return f.PropertyAtomic_int; +} diff --git a/clang/test/CodeGenObjC/next-objc-dispatch.m b/clang/test/CodeGenObjC/next-objc-dispatch.m new file mode 100644 index 0000000..4288b2d --- /dev/null +++ b/clang/test/CodeGenObjC/next-objc-dispatch.m @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s \ +// RUN: -fobjc-dispatch-method=legacy | \ +// RUN: FileCheck -check-prefix CHECK-FRAGILE_LEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-dispatch-method=legacy | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_LEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-dispatch-method=non-legacy | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_NONLEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-dispatch-method=mixed | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_MIXED %s +// +// <rdar://problem/7866951> + +// There are basically four ways that we end up doing message dispatch for the +// NeXT runtime. They are: +// (1) fragile ABI, legacy dispatch +// (2) non-fragile ABI, legacy dispatch +// (2) non-fragile ABI, non-legacy dispatch +// (2) non-fragile ABI, mixed dispatch +// +// Note that fragile ABI and non-fragile ABI legacy dispatch are not the same, +// they use some different API calls (objc_msgSendSuper vs objc_msgSendSuper2). + +// CHECK-FRAGILE_LEGACY: ModuleID +// CHECK-FRAGILE_LEGACY-NOT: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-FRAGILE_LEGACY-NOT: declare i8* @objc_msgSend_fixup( +// CHECK-FRAGILE_LEGACY: declare i8* @objc_msgSendSuper( +// CHECK-FRAGILE_LEGACY: declare i8* @objc_msgSend( + +// CHECK-NONFRAGILE_LEGACY: ModuleID +// CHECK-NONFRAGILE_LEGACY-NOT: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_LEGACY-NOT: declare i8* @objc_msgSend_fixup( +// CHECK-NONFRAGILE_LEGACY: declare i8* @objc_msgSendSuper2( +// CHECK-NONFRAGILE_LEGACY: declare i8* @objc_msgSend( + +// CHECK-NONFRAGILE_NONLEGACY: ModuleID +// CHECK-NONFRAGILE_NONLEGACY: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_NONLEGACY: declare i8* @objc_msgSend_fixup( + +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSendSuper2( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSend_fixup( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSend( + +@interface NSObject ++ (id)alloc; +- (id)init; +@end + +@interface I0 : NSObject +-(void) im0; +@end + +@implementation I0 ++(id) alloc { + return [super alloc]; +} +-(id) init { + [super init]; + return self; +} +-(void) im0 {} +@end + +void f0(I0 *a) { + [I0 alloc]; + [a im0]; +} diff --git a/clang/test/CodeGenObjC/no-category-class.m b/clang/test/CodeGenObjC/no-category-class.m new file mode 100644 index 0000000..3969f91 --- /dev/null +++ b/clang/test/CodeGenObjC/no-category-class.m @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fobjc-fragile-abi -emit-llvm -o %t %s + +@interface NSObject +@end + +@implementation NSObject(IBXLIFFIntegration) +@end + diff --git a/clang/test/CodeGenObjC/no-vararg-messaging.m b/clang/test/CodeGenObjC/no-vararg-messaging.m new file mode 100644 index 0000000..3f9d934 --- /dev/null +++ b/clang/test/CodeGenObjC/no-vararg-messaging.m @@ -0,0 +1,19 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -o - %s | FileCheck %s +// rdar://9048030 + +@interface Foo ++(id)alloc; +-(id)init; +-(id)self; +-(id)retain; +-(void)release; +-(id)autorelease; +@end + +void test(void) +{ + [[[[[[Foo alloc] init] retain] autorelease] self] release]; +} + +// CHECK-NOT: xorb diff --git a/clang/test/CodeGenObjC/non-lazy-classes.m b/clang/test/CodeGenObjC/non-lazy-classes.m new file mode 100644 index 0000000..5d82901 --- /dev/null +++ b/clang/test/CodeGenObjC/non-lazy-classes.m @@ -0,0 +1,32 @@ +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t +// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t + +@interface A @end +@implementation A ++(void) load { +} +@end + +@interface A (Cat) @end +@implementation A (Cat) ++(void) load { +} +@end + +@interface B @end +@implementation B +-(void) load { +} +@end + +@interface B (Cat) @end +@implementation B (Cat) +-(void) load { +} +@end + +@interface C : A @end +@implementation C +@end diff --git a/clang/test/CodeGenObjC/nonlazy-msgSend.m b/clang/test/CodeGenObjC/nonlazy-msgSend.m new file mode 100644 index 0000000..73157c7 --- /dev/null +++ b/clang/test/CodeGenObjC/nonlazy-msgSend.m @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: grep -F 'declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind' %t + +void f0(id x) { + [x foo]; +} diff --git a/clang/test/CodeGenObjC/ns-constant-strings.m b/clang/test/CodeGenObjC/ns-constant-strings.m new file mode 100644 index 0000000..d04793c --- /dev/null +++ b/clang/test/CodeGenObjC/ns-constant-strings.m @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -fno-constant-cfstrings -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-FRAGILE < %t %s + +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fno-constant-cfstrings -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix CHECK-NONFRAGILE < %t %s + +@interface NSString @end + +@interface NSSimpleCString : NSString { +@protected + char *bytes; + unsigned int numBytes; +} +@end + +@interface NSConstantString : NSSimpleCString +@end + +#if OBJC_API_VERSION >= 2 +extern Class _NSConstantStringClassReference; +#else +extern struct objc_class _NSConstantStringClassReference; +#endif + +const NSConstantString *appKey = @"MyApp"; + +int main() { + const NSConstantString *appKey = @"MyApp"; + const NSConstantString *appKey1 = @"MyApp1"; +} + +// 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/clang/test/CodeGenObjC/ns_consume_null_check.m b/clang/test/CodeGenObjC/ns_consume_null_check.m new file mode 100644 index 0000000..e3b6075 --- /dev/null +++ b/clang/test/CodeGenObjC/ns_consume_null_check.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-dispatch-method=mixed -o - %s | FileCheck %s +// rdar://10444476 + +@interface NSObject +- (id) new; +@end + +@interface MyObject : NSObject +- (char)isEqual:(id) __attribute__((ns_consumed)) object; +@end + +MyObject *x; + +void foo() +{ + id obj = [NSObject new]; + [x isEqual : obj]; +} + +// CHECK: [[TMP:%.*]] = alloca i8 +// CHECK: [[FIVE:%.*]] = call i8* @objc_retain +// CHECK-NEXT: [[SIX:%.*]] = bitcast +// CHECK-NEXT: [[SEVEN:%.*]] = icmp eq i8* [[SIX]], null +// CHECK-NEXT: br i1 [[SEVEN]], label [[NULLINIT:%.*]], label [[CALL_LABEL:%.*]] +// CHECK: [[FN:%.*]] = load i8** getelementptr inbounds +// CHECK-NEXT: [[EIGHT:%.*]] = bitcast i8* [[FN]] +// CHECK-NEXT: [[CALL:%.*]] = call signext i8 [[EIGHT]] +// CHECK-NEXT store i8 [[CALL]], i8* [[TMP]] +// CHECK-NEXT br label [[CONT:%.*]] +// CHECK: call void @objc_release(i8* [[FIVE]]) nounwind +// CHECK-NEXT: call void @llvm.memset +// CHECK-NEXT br label [[CONT]] diff --git a/clang/test/CodeGenObjC/objc-align.m b/clang/test/CodeGenObjC/objc-align.m new file mode 100644 index 0000000..f3c586e --- /dev/null +++ b/clang/test/CodeGenObjC/objc-align.m @@ -0,0 +1,44 @@ +// 32-bit + +// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*, section "__OBJC,__category,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_C" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_C" = internal global .*, section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_METACLASS_C" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*, section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t +// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*, section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t + +// 64-bit + +// RUNX: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o %t %s && +// RUNX: grep '@"OBJC_CLASS_$_A" = global' %t && +// RUNX: grep '@"OBJC_CLASS_$_C" = global' %t && +// RUNX: grep '@"OBJC_METACLASS_$_A" = global' %t && +// RUNX: grep '@"OBJC_METACLASS_$_C" = global' %t && +// RUNX: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_0" = internal global .*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .*, section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .*, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_RO_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .*, section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_METACLASS_RO_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .*, section "__DATA,__datacoal_nt,coalesced", align 8' %t && + + +@interface A @end +@implementation A +@end +@implementation A (Cat) +@end +@protocol P +@end +@interface C <P> +@end +@implementation C +@end diff --git a/clang/test/CodeGenObjC/objc-arc-container-subscripting.m b/clang/test/CodeGenObjC/objc-arc-container-subscripting.m new file mode 100644 index 0000000..8924916 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-arc-container-subscripting.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fobjc-arc -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s + +@interface NSMutableArray +- (id)objectAtIndexedSubscript:(int)index; +- (void)setObject:(id)object atIndexedSubscript:(int)index; +@end + +id func() { + NSMutableArray *array; + array[3] = 0; + return array[3]; +} + +// CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind +// CHECK: [[ARRAY:%.*]] = load %0** +// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8* +// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]]) +// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind +// CHECK: ret i8* [[EIGHT]] + diff --git a/clang/test/CodeGenObjC/objc-assign-ivar.m b/clang/test/CodeGenObjC/objc-assign-ivar.m new file mode 100644 index 0000000..d0a1a0f --- /dev/null +++ b/clang/test/CodeGenObjC/objc-assign-ivar.m @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_ivar' %t | count 14 + +typedef struct { + id element; + id elementArray[10]; + __strong id cfElement; + __strong id cfElementArray[10]; +} struct_with_ids_t; + + +@interface NSString @end + +@interface Foo { +@public +// assignments to any/all of these fields should generate objc_assign_ivar + __strong id dict; + __strong id dictArray[3]; + id ivar; + id array[10]; + id nsobject; + NSString *stringArray[10]; + struct_with_ids_t inner; + + Foo *obj[20]; + short idx[5]; +} +@end + +// The test cases +int IvarAssigns; +void *rhs = 0; +#define ASSIGNTEST(expr, global) expr = rhs + +void testIvars() { + Foo *foo; + ASSIGNTEST(foo->ivar, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->dict, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->dictArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->array[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->nsobject, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->stringArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.element, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.elementArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.cfElement, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.cfElementArray[0], IvarAssigns); // objc_assign_ivar + int counter=1; + ASSIGNTEST(foo->obj[5], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->obj[++counter], IvarAssigns); // objc_assign_ivar + foo->idx[++counter] = 15; + ASSIGNTEST(foo->obj[foo->idx[2]], IvarAssigns); // objc_assign_ivar +} diff --git a/clang/test/CodeGenObjC/objc-container-subscripting-1.m b/clang/test/CodeGenObjC/objc-container-subscripting-1.m new file mode 100644 index 0000000..91b7f46 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-container-subscripting-1.m @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s + +typedef unsigned int size_t; +@protocol P @end + +@interface NSMutableArray +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +@end + +@interface NSMutableDictionary +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +int main() { + NSMutableArray *array; + id val; + + id oldObject = array[10]; +// CHECK: [[ARR:%.*]] = load {{%.*}} [[array:%.*]], align 8 +// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" +// CHECK-NEXT: [[ARRC:%.*]] = bitcast {{%.*}} [[ARR]] to i8* +// CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ARRC]], i8* [[SEL]], i32 10) +// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8 + + val = (array[10] = oldObject); +// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8 +// CHECK-NEXT: [[FOUR:%.*]] = load i8** [[oldObject:%.*]], align 8 +// CHECK-NEXT: [[FIVE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2" +// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8* +// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10) +// CHECK-NEXT: store i8* [[FOUR]], i8** [[val:%.*]] + + NSMutableDictionary *dictionary; + id key; + id newObject; + oldObject = dictionary[key]; +// CHECK: [[SEVEN:%.*]] = load {{%.*}} [[DICTIONARY:%.*]], align 8 +// CHECK-NEXT: [[EIGHT:%.*]] = load i8** [[KEY:%.*]], align 8 +// CHECK-NEXT: [[TEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_4" +// CHECK-NEXT: [[ELEVEN:%.*]] = bitcast {{%.*}} [[SEVEN]] to i8* +// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[ELEVEN]], i8* [[TEN]], i8* [[EIGHT]]) +// CHECK-NEXT: store i8* [[CALL1]], i8** [[oldObject:%.*]], align 8 + + + val = (dictionary[key] = newObject); +// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8 +// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8** [[KEY]], align 8 +// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8** [[NEWOBJECT:%.*]], align 8 +// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_6" +// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8* +// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]]) +// CHECK-NEXT: store i8* [[FOURTEEN]], i8** [[val:%.*]] +} + diff --git a/clang/test/CodeGenObjC/objc-container-subscripting.m b/clang/test/CodeGenObjC/objc-container-subscripting.m new file mode 100644 index 0000000..fd8f8ef --- /dev/null +++ b/clang/test/CodeGenObjC/objc-container-subscripting.m @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o /dev/null + +typedef unsigned int size_t; +@protocol P @end + +@interface NSMutableArray +#if __has_feature(objc_subscripting) +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +#endif +@end + +#if __has_feature(objc_subscripting) +@interface XNSMutableArray +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +#endif +@end + +@interface NSMutableDictionary +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +@class NSString; + +int main() { + NSMutableArray<P> * array; + id oldObject = array[10]; + + array[10] = oldObject; + + id unknown_array; + oldObject = unknown_array[1]; + + unknown_array[1] = oldObject; + + NSMutableDictionary *dictionary; + NSString *key; + id newObject; + oldObject = dictionary[key]; + dictionary[key] = newObject; // replace oldObject with newObject + +} + diff --git a/clang/test/CodeGenObjC/objc-dictionary-literal.m b/clang/test/CodeGenObjC/objc-dictionary-literal.m new file mode 100644 index 0000000..b335582 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-dictionary-literal.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null +// rdar://10614657 + +@interface NSNumber ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithInt:(int)value; +@end + +@protocol NSCopying @end +typedef unsigned long NSUInteger; + +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt; +@end + +@interface NSString<NSCopying> +@end + +int main() { + NSDictionary *dict = @{ @"name":@666 }; + NSDictionary *dict1 = @{ @"name":@666 }; + NSDictionary *dict2 = @{ @"name":@666 }; + return 0; +} diff --git a/clang/test/CodeGenObjC/objc-gc-aggr-assign.m b/clang/test/CodeGenObjC/objc-gc-aggr-assign.m new file mode 100644 index 0000000..dfdf02e --- /dev/null +++ b/clang/test/CodeGenObjC/objc-gc-aggr-assign.m @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix C %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix CP %s + +static int count; + +typedef struct S { + int ii; +} SS; + +struct type_s { + SS may_recurse; + id id_val; +}; + +@interface NamedObject +{ + struct type_s type_s_ivar; +} +- (void) setSome : (struct type_s) arg; +- (struct type_s) getSome; +@property(assign) struct type_s aggre_prop; +@end + +@implementation NamedObject +- (void) setSome : (struct type_s) arg + { + type_s_ivar = arg; + } +- (struct type_s) getSome + { + return type_s_ivar; + } +@synthesize aggre_prop = type_s_ivar; +@end + +struct type_s some = {{1234}, (id)0}; + +struct type_s get(void) +{ + return some; +} + +void f(const struct type_s *in, struct type_s *out) { + *out = *in; +} + +#ifdef __cplusplus +struct Derived : type_s { }; + +void foo(Derived* src, Derived* dest) { + *dest = *src; +} +#endif + +// CHECK-C: call i8* @objc_memmove_collectable +// CHECK-C: call i8* @objc_memmove_collectable +// CHECK-C: call i8* @objc_memmove_collectable + +// CHECK-CP: call i8* @objc_memmove_collectable +// CHECK-CP: call i8* @objc_memmove_collectable +// CHECK-CP: call i8* @objc_memmove_collectable +// CHECK-CP: call i8* @objc_memmove_collectable diff --git a/clang/test/CodeGenObjC/objc-literal-debugger-test.m b/clang/test/CodeGenObjC/objc-literal-debugger-test.m new file mode 100644 index 0000000..389ef22 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-literal-debugger-test.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-objc-literal -emit-llvm -o - %s | FileCheck %s + +int main() { + id l = @'a'; + l = @'a'; + l = @42; + l = @-42; + l = @42u; + l = @3.141592654f; + l = @__objc_yes; + l = @__objc_no; + l = @{ @"name":@666 }; + l = @[ @"foo", @"bar" ]; +} + +// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind diff --git a/clang/test/CodeGenObjC/objc-literal-tests.m b/clang/test/CodeGenObjC/objc-literal-tests.m new file mode 100644 index 0000000..c513d49 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-literal-tests.m @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s +// rdar://10111397 + +#if __has_feature(objc_bool) +#define YES __objc_yes +#define NO __objc_no +#else +#define YES ((BOOL)1) +#define NO ((BOOL)0) +#endif + +#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 +typedef unsigned long NSUInteger; +typedef long NSInteger; +#else +typedef unsigned int NSUInteger; +typedef int NSInteger; +#endif +typedef signed char BOOL; + +@interface NSNumber @end + +@interface NSNumber (NSNumberCreation) +#if __has_feature(objc_array_literals) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value ; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ; +#endif +@end + +@interface NSDate ++ (NSDate *) date; +@end + +#if __has_feature(objc_dictionary_literals) +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt; +@end +#endif + +id NSUserName(); + +// CHECK: define i32 @main() nounwind +int main() { + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 97 + NSNumber *aNumber = @'a'; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42 + NSNumber *fortyTwo = @42; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 -42 + NSNumber *negativeFortyTwo = @-42; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42 + NSNumber *positiveFortyTwo = @+42; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42 + NSNumber *fortyTwoUnsigned = @42u; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42 + NSNumber *fortyTwoLong = @42l; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42 + NSNumber *fortyTwoLongLong = @42ll; + // CHECK: call{{.*}}@objc_msgSend{{.*}}float 0x400921FB60000000 + NSNumber *piFloat = @3.141592654f; + // CHECK: call{{.*}}@objc_msgSend{{.*}}double 0x400921FB54411744 + NSNumber *piDouble = @3.1415926535; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1 + NSNumber *yesNumber = @__objc_yes; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0 + NSNumber *noNumber = @__objc_no; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1 + NSNumber *yesNumber1 = @YES; + // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0 + NSNumber *noNumber1 = @NO; +NSDictionary *dictionary = @{@"name" : NSUserName(), + @"date" : [NSDate date] }; + return __objc_yes == __objc_no; +} + +// rdar://10579122 +typedef BOOL (^foo)(void); +extern void bar(foo a); + +void baz(void) { + bar(^(void) { return YES; }); +} diff --git a/clang/test/CodeGenObjC/objc-read-weak-byref.m b/clang/test/CodeGenObjC/objc-read-weak-byref.m new file mode 100644 index 0000000..8fe1436 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-read-weak-byref.m @@ -0,0 +1,26 @@ +// REQUIRES: x86-registered-target,x86-64-registered-target +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -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 -fobjc-fragile-abi -S %s -o %t-32.s +// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s + +@interface NSObject +- copy; +@end + +int main() { + NSObject *object = 0; + __weak __block NSObject* weak_object = object; + void (^callback) (void) = [^{ + if (weak_object) + [weak_object copy]; + } copy]; + callback(); + return 0; +} + +// CHECK-LP64: callq _objc_read_weak +// CHECK-LP64: callq _objc_read_weak + +// CHECK-LP32: calll L_objc_read_weak +// CHECK-LP32: calll L_objc_read_weak diff --git a/clang/test/CodeGenObjC/objc2-assign-global.m b/clang/test/CodeGenObjC/objc2-assign-global.m new file mode 100644 index 0000000..36c95f7 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-assign-global.m @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_global' %t | count 26 + +@class NSObject; +typedef const struct __CFDictionary * CFDictionaryRef; +typedef struct { + id element; + id elementArray[10]; + __strong CFDictionaryRef cfElement; + __strong CFDictionaryRef cfElementArray[10]; +} struct_with_ids_t; + + +// assignments to these should generate objc_assign_global +@interface A +@end + +typedef struct s0 { + A *a[4]; +} T; + +T g0; + +extern id FileExternID; +static id FileStaticID; +id GlobalId; +id GlobalArray[20]; +NSObject *GlobalObject; +NSObject *GlobalObjectArray[20]; +__strong CFDictionaryRef Gdict; +__strong CFDictionaryRef Gdictarray[10]; +struct_with_ids_t GlobalStruct; +struct_with_ids_t GlobalStructArray[10]; + +#define ASSIGNTEST(expr, global) expr = rhs +void *rhs = 0; + +int main() { + static id staticGlobalId; + static id staticGlobalArray[20]; + static NSObject *staticGlobalObject; + static NSObject *staticGlobalObjectArray[20]; + static __strong CFDictionaryRef staticGdict; + static __strong CFDictionaryRef staticGdictarray[10]; + static struct_with_ids_t staticGlobalStruct; + static struct_with_ids_t staticGlobalStructArray[10]; + extern id ExID; + id localID; + + ASSIGNTEST(GlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(GlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + ExID = 0; + localID = 0; + FileStaticID = 0; + FileExternID=0; + g0.a[0] = 0; + ((T*) &g0)->a[0] = 0; +} diff --git a/clang/test/CodeGenObjC/objc2-ivar-assign.m b/clang/test/CodeGenObjC/objc2-ivar-assign.m new file mode 100644 index 0000000..af76800 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-ivar-assign.m @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_ivar %t | count 6 + +@interface I @end + +typedef I TI; +typedef I* TPI; + +typedef id ID; + +@interface MyClass { +} + +@property id property; +@property I* propertyI; + +@property TI* propertyTI; + +@property TPI propertyTPI; + +@property ID propertyID; +@end + +@implementation MyClass + @synthesize property=_property; + @synthesize propertyI; + @synthesize propertyTI=_propertyTI; + @synthesize propertyTPI=_propertyTPI; + @synthesize propertyID = _propertyID; +@end + +int main () { + MyClass *myObj; + myObj.property = 0; + myObj.propertyI = 0; + myObj.propertyTI = 0; + myObj.propertyTPI = 0; + myObj.propertyID = 0; + return 0; +} diff --git a/clang/test/CodeGenObjC/objc2-legacy-dispatch.m b/clang/test/CodeGenObjC/objc2-legacy-dispatch.m new file mode 100644 index 0000000..a6b2000 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-legacy-dispatch.m @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fobjc-dispatch-method=mixed -triple i386-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_NEW_DISPATCH %s +// +// CHECK_NEW_DISPATCH: define void @f0 +// CHECK_NEW_DISPATCH: bitcast {{.*}}objc_msgSend_fixup_alloc +// CHECK_NEW_DISPATCH: define void @f1 +// CHECK_NEW_DISPATCH: load {{.*}}OBJC_SELECTOR_REFERENCES +// +// RUN: %clang_cc1 -fobjc-dispatch-method=legacy -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_OLD_DISPATCH %s +// +// CHECK_OLD_DISPATCH: define void @f0 +// CHECK_OLD_DISPATCH: load {{.*}}OBJC_SELECTOR_REFERENCES +// CHECK_OLD_DISPATCH: define void @f1 +// CHECK_OLD_DISPATCH: load {{.*}}OBJC_SELECTOR_REFERENCES + +@interface A ++(id) alloc; +-(int) im0; +@end + +void f0(void) { + [A alloc]; +} + +void f1(A *a) { + [a im0]; +} diff --git a/clang/test/CodeGenObjC/objc2-new-gc-api-strongcast.m b/clang/test/CodeGenObjC/objc2-new-gc-api-strongcast.m new file mode 100644 index 0000000..1044ba5 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-new-gc-api-strongcast.m @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fblocks -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_strongCast' %t | count 4 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fblocks -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_strongCast' %t | count 4 + +@interface DSATextSearch @end + +DSATextSearch **_uniqueIdToIdentifierArray = (0); +void foo (int _nextId) +{ + _uniqueIdToIdentifierArray[_nextId] = 0; // objc_assign_strongCast +} + +typedef struct { + unsigned long state; + id *itemsPtr; + void (^bp)(); + unsigned long *mutationsPtr; + unsigned long extra[5]; +} NSFastEnumerationState; + +void foo1 (NSFastEnumerationState * state) +{ + state->itemsPtr = 0; + state->bp = ^{}; +} + diff --git a/clang/test/CodeGenObjC/objc2-no-strong-cast.m b/clang/test/CodeGenObjC/objc2-no-strong-cast.m new file mode 100644 index 0000000..0824f40 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-no-strong-cast.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface PDFViewPrivateVars +{ +@public + __attribute__((objc_gc(strong))) char *addedTooltips; +} +@end + +@interface PDFView +{ + PDFViewPrivateVars *_pdfPriv; +} +@end + +@implementation PDFView +- (void) addTooltipsForPage +{ + _pdfPriv->addedTooltips[4] = 1; +} +@end + diff --git a/clang/test/CodeGenObjC/objc2-no-write-barrier.m b/clang/test/CodeGenObjC/objc2-no-write-barrier.m new file mode 100644 index 0000000..d439368 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-no-write-barrier.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep 'objc_assign' %t | count 0 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep 'objc_assign' %t | count 0 + +typedef struct { + int ival; + id submenu; +} XCBinderContextMenuItem; + +id actionMenuForDataNode(void) { + XCBinderContextMenuItem menusToCreate[] = { + {1, 0} + }; + return 0; +} + +XCBinderContextMenuItem GmenusToCreate[] = { + {1, 0} +}; diff --git a/clang/test/CodeGenObjC/objc2-nonfragile-abi-impl.m b/clang/test/CodeGenObjC/objc2-nonfragile-abi-impl.m new file mode 100644 index 0000000..c785a5d --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-nonfragile-abi-impl.m @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s +// rdar://7547942. + +@interface Base @end + +@interface Sub1 : Base @end + +@implementation Sub1 @end + +@implementation Base { +@private + id ivar; +} +@end + diff --git a/clang/test/CodeGenObjC/objc2-property-encode.m b/clang/test/CodeGenObjC/objc2-property-encode.m new file mode 100644 index 0000000..0f18d6f --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-property-encode.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s +// RUN: grep -e "T@\\\\22NSString\\\\22" %t +@interface NSString @end + +typedef NSString StoreVersionID ; + +@interface Parent + @property(retain) StoreVersionID* foo; +@end + +@implementation Parent +@dynamic foo; +@end diff --git a/clang/test/CodeGenObjC/objc2-protocol-enc.m b/clang/test/CodeGenObjC/objc2-protocol-enc.m new file mode 100644 index 0000000..0db0cb8 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-protocol-enc.m @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm -o %t %s +// RUN: grep -e "T@\\\22<X>\\\22" %t +// RUN: grep -e "T@\\\22<X><Y>\\\22" %t +// RUN: grep -e "T@\\\22<X><Y><Z>\\\22" %t +// RUN: grep -e "T@\\\22Foo<X><Y><Z>\\\22" %t + +@protocol X, Y, Z; +@class Foo; + +@protocol Proto +@property (copy) id <X> x; +@property (copy) id <X, Y> xy; +@property (copy) id <X, Y, Z> xyz; +@property(copy) Foo <X, Y, Z> *fooxyz; +@end + +@interface Intf <Proto> +{ +id <X> IVAR_x; +id <X, Y> IVAR_xy; +id <X, Y, Z> IVAR_xyz; +Foo <X, Y, Z> *IVAR_Fooxyz; +} +@end + +@implementation Intf +@dynamic x, xy, xyz, fooxyz; +@end + +/** +This protocol should generate the following metadata: +struct objc_property_list __Protocol_Test_metadata = { + sizeof(struct objc_property), 4, + { + { "x", "T@\"<X>\"" }, + { "xy", "T@\"<X><Y>\"" }, + { "xyz", "T@\"<X><Y><Z>\"" }, + { "fooxyz", "T@\"Foo<X><Y><Z>\"" } + } +}; + +"T@\"<X><Y><Z>\",D +*/ diff --git a/clang/test/CodeGenObjC/objc2-retain-codegen.m b/clang/test/CodeGenObjC/objc2-retain-codegen.m new file mode 100644 index 0000000..d5b473e --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-retain-codegen.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fobjc-fragile-abi -fobjc-gc-only -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-unknown-unknown -fobjc-fragile-abi -fobjc-gc-only -emit-llvm -o %t %s + +@interface I0 { + I0 *_f0; +} +@property (retain) id p0; +@end + +@implementation I0 + @synthesize p0 = _f0; +@end + diff --git a/clang/test/CodeGenObjC/objc2-strong-cast-1.m b/clang/test/CodeGenObjC/objc2-strong-cast-1.m new file mode 100644 index 0000000..9bb750f --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-strong-cast-1.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-unknown-unknown -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s + +@interface I { + __attribute__((objc_gc(strong))) int *i_IdocumentIDs; + __attribute__((objc_gc(strong))) long *l_IdocumentIDs; + __attribute__((objc_gc(strong))) long long *ll_IdocumentIDs; + __attribute__((objc_gc(strong))) float *IdocumentIDs; + __attribute__((objc_gc(strong))) double *d_IdocumentIDs; +} +- (void) _getResultsOfMatches; +@end + +@implementation I +-(void) _getResultsOfMatches { + IdocumentIDs[2] = IdocumentIDs[3]; + d_IdocumentIDs[2] = d_IdocumentIDs[3]; + l_IdocumentIDs[2] = l_IdocumentIDs[3]; + ll_IdocumentIDs[2] = ll_IdocumentIDs[3]; + i_IdocumentIDs[2] = i_IdocumentIDs[3]; +} + +@end + diff --git a/clang/test/CodeGenObjC/objc2-strong-cast-block-import.m b/clang/test/CodeGenObjC/objc2-strong-cast-block-import.m new file mode 100644 index 0000000..adec376 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-strong-cast-block-import.m @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc-only -fblocks -emit-llvm -o - %s | FileCheck %s +// rdar://10150823 + +@interface Test { +@package + Test ** __strong objects; +} +@end + +id newObject(); +void runWithBlock(void(^)(int i)); + +@implementation Test + +- (void)testWithObjectInBlock { + Test **children = objects; + runWithBlock(^(int i){ + children[i] = newObject(); + }); +} + +@end +// CHECK: call i8* @objc_assign_strongCast +// CHECK: call i8* @objc_assign_strongCast + diff --git a/clang/test/CodeGenObjC/objc2-strong-cast.m b/clang/test/CodeGenObjC/objc2-strong-cast.m new file mode 100644 index 0000000..7291c4e --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-strong-cast.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -fobjc-gc -emit-llvm -o %t %s + +@interface I { + __attribute__((objc_gc(strong))) signed long *_documentIDs; + __attribute__((objc_gc(strong))) id *IdocumentIDs; +} +- (void) _getResultsOfMatches; +@end + +@implementation I +-(void) _getResultsOfMatches { + _documentIDs[2] = _documentIDs[3]; + IdocumentIDs[2] = IdocumentIDs[3]; +} + +@end + diff --git a/clang/test/CodeGenObjC/objc2-weak-assign.m b/clang/test/CodeGenObjC/objc2-weak-assign.m new file mode 100644 index 0000000..e5c67c5 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-assign.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -e "objc_assign_weak" %t | grep -e "call" | count 6 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -e "objc_assign_weak" %t | grep -e "call" | count 6 + +__weak id* x; +id* __weak y; +id* __weak* z; + +__weak id* a1[20]; +id* __weak a2[30]; +id** __weak a3[40]; + +void foo (__weak id *param) { + *param = 0; +} + +int main() +{ + *x = 0; + *y = 0; + **z = 0; + + a1[3] = 0; + a2[3] = 0; + a3[3][4] = 0; +} + diff --git a/clang/test/CodeGenObjC/objc2-weak-block-call.m b/clang/test/CodeGenObjC/objc2-weak-block-call.m new file mode 100644 index 0000000..94c54e7 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-block-call.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -emit-llvm %s -o - | FileCheck -check-prefix LP64 %s +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple i386-apple-darwin -fobjc-fragile-abi -emit-llvm %s -o - | FileCheck -check-prefix LP64 %s + +@interface MyView +- (void)MyView_sharedInit; +@end + +void foo(MyView *(^obj)(void)) ; + +@implementation MyView +- (void)MyView_sharedInit { + + __block __weak MyView *weakSelf = self; + foo( + ^{ + return weakSelf; + }); + +} +@end + +// CHECK-LP64: call i8* @objc_read_weak +// CHECK-LP32: call i8* @objc_read_weak + diff --git a/clang/test/CodeGenObjC/objc2-weak-compare.m b/clang/test/CodeGenObjC/objc2-weak-compare.m new file mode 100644 index 0000000..75cf689 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-compare.m @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple i386-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s + +@interface PBXTarget +{ + +PBXTarget * __weak _lastKnownTarget; +PBXTarget * __weak _KnownTarget; +PBXTarget * result; +} +- Meth; +@end + +extern void foo(); +@implementation PBXTarget +- Meth { + if (_lastKnownTarget != result) + foo(); + if (result != _lastKnownTarget) + foo(); + + if (_lastKnownTarget != _KnownTarget) + foo(); +} + +@end diff --git a/clang/test/CodeGenObjC/objc2-weak-import-attribute.m b/clang/test/CodeGenObjC/objc2-weak-import-attribute.m new file mode 100644 index 0000000..201e24b --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-import-attribute.m @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s + +__attribute__((weak_import)) @interface WeakRootClass @end + +__attribute__((weak_import)) @interface WeakClass : WeakRootClass +@end + +@interface MySubclass : WeakClass @end + +@implementation MySubclass @end + +@implementation WeakClass(MyCategory) @end + + +__attribute__((weak_import)) +@interface WeakClass1 @end + +@implementation WeakClass1(MyCategory) @end + +@implementation WeakClass1(YourCategory) @end + + __attribute__((weak_import)) +@interface WeakClass3 ++ message; +@end + +int main() { + [WeakClass3 message]; +} + +// CHECK-X86-64: OBJC_METACLASS_$_WeakRootClass" = extern_weak global +// CHECK-X86-64: OBJC_METACLASS_$_WeakClass" = extern_weak global +// CHECK-X86-64: OBJC_CLASS_$_WeakClass" = extern_weak global +// CHECK-X86-64: OBJC_CLASS_$_WeakClass1" = extern_weak global +// CHECK-X86-64: OBJC_CLASS_$_WeakClass3" = extern_weak global + +// Root is being implemented here. No extern_weak. +__attribute__((weak_import)) @interface Root @end + +@interface Super : Root @end + +@interface Sub : Super @end + +@implementation Sub @end + +@implementation Root @end + +// CHECK-NOT-X86-64: OBJC_METACLASS_$_Root" = extern_weak global diff --git a/clang/test/CodeGenObjC/objc2-weak-ivar-debug.m b/clang/test/CodeGenObjC/objc2-weak-ivar-debug.m new file mode 100644 index 0000000..83262a8 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-ivar-debug.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -g -emit-llvm -o - %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -g -emit-llvm -o - %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -g -emit-llvm -o - %s +// RUN: %clang_cc1 -x objective-c++ -triple i386-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -g -emit-llvm -o - %s + +// rdar://7252252 +@interface Loop { +@public + __weak Loop *_loop; +} +@end + +@implementation Loop @end + +void loop(Loop *L) { + L->_loop = 0; +} diff --git a/clang/test/CodeGenObjC/objc2-weak-ivar.m b/clang/test/CodeGenObjC/objc2-weak-ivar.m new file mode 100644 index 0000000..78ccdf8 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-weak-ivar.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +@class NSObject; + +@interface Foo { +@public + __weak NSObject *nsobject; +} +@end + +@implementation Foo @end diff --git a/clang/test/CodeGenObjC/objc2-write-barrier-2.m b/clang/test/CodeGenObjC/objc2-write-barrier-2.m new file mode 100644 index 0000000..eae2551 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-write-barrier-2.m @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_global' %t | count 7 +// RUN: grep -F '@objc_assign_ivar' %t | count 5 +// RUN: grep -F '@objc_assign_strongCast' %t | count 8 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_global' %t | count 7 +// RUN: grep -F '@objc_assign_ivar' %t | count 5 +// RUN: grep -F '@objc_assign_strongCast' %t | count 8 + +extern id **somefunc(void); +extern id *somefunc2(void); + + +// Globals + +id W, *X, **Y; + +void func(id a, id *b, id **c) { + static id w, *x, **y; + W = a; + w = a; + X = b; + x = b; + Y = c; + y = c; +} + +// Instances + +@interface something { + id w, *x, **y; +} +@end + +@implementation something +- (void)amethod { + id badIdea = *somefunc2(); + w = badIdea; + x = &badIdea; + y = &x; +} +@end + +typedef struct { + int junk; + id alfred; +} AStruct; + +void funct2(AStruct *aptr) { + id **ppptr = somefunc(); + aptr->alfred = 0; + **ppptr = aptr->alfred; + *ppptr = somefunc2(); +} + +typedef const struct __CFString * CFStringRef; +@interface DSATextSearch { +__strong CFStringRef *_documentNames; + struct { + id *innerNames; + struct { + id *nestedDeeperNames; + struct I { + id *is1; + id is2[5]; + } arrI [3]; + } inner_most; + } inner; + +} +- filter; +@end +@implementation DSATextSearch +- filter { + int filteredPos = 0; + _documentNames[filteredPos] = 0; // storing into an element of array ivar. objc_assign_strongCast is needed. + inner.innerNames[filteredPos] = 0; + inner.inner_most.nestedDeeperNames[filteredPos] = 0; + inner.inner_most.arrI[3].is1[5] = 0; + inner.inner_most.arrI[3].is2[5] = 0; +} +@end + diff --git a/clang/test/CodeGenObjC/objc2-write-barrier-3.m b/clang/test/CodeGenObjC/objc2-write-barrier-3.m new file mode 100644 index 0000000..4ef1b8a --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-write-barrier-3.m @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fblocks -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_ivar %t | count 3 +// RUN: grep objc_assign_strongCast %t | count 6 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_ivar %t | count 3 +// RUN: grep objc_assign_strongCast %t | count 6 + +struct Slice { + void *__strong * items; +}; + +typedef struct Slice Slice; + +@interface ISlice { +@public + void *__strong * IvarItem; +} +@end + +typedef void (^observer_block_t)(id object); +@interface Observer { +@public + observer_block_t block; +} +@end + + +void foo (int i) { + // storing into an array of strong pointer types. + void *__strong* items; + items[i] = 0; + + // storing indirectly into an array of strong pointer types. + void *__strong* *vitems; + *vitems[i] = 0; + + Slice *slice; + slice->items = 0; + // storing into a struct element of an array of strong pointer types. + slice->items[i] = 0; + + ISlice *islice; + islice->IvarItem = 0; + // Storing into an ivar of an array of strong pointer types. + islice->IvarItem[i] = (void*)0; + + Observer *observer; + observer->block = 0; +} diff --git a/clang/test/CodeGenObjC/objc2-write-barrier-4.m b/clang/test/CodeGenObjC/objc2-write-barrier-4.m new file mode 100644 index 0000000..4089920 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-write-barrier-4.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_global %t | count 3 +// RUN: grep objc_assign_strongCast %t | count 2 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_global %t | count 3 +// RUN: grep objc_assign_strongCast %t | count 2 + +@interface A +@end + +typedef struct s0 { + A *a[4]; +} T; + +T g0; + +void f0(id x) { + g0.a[0] = x; +} + +void f1(id x) { + ((T*) &g0)->a[0] = x; +} + +void f2(unsigned idx) +{ + id *keys; + keys[idx] = 0; +} + diff --git a/clang/test/CodeGenObjC/objc2-write-barrier-5.m b/clang/test/CodeGenObjC/objc2-write-barrier-5.m new file mode 100644 index 0000000..122fa9f --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-write-barrier-5.m @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_ivar %t | count 0 +// RUN: grep objc_assign_strongCast %t | count 8 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep objc_assign_ivar %t | count 0 +// RUN: grep objc_assign_strongCast %t | count 8 + +@interface TestUnarchiver +{ + void *allUnarchivedObjects; +} +@end + +@implementation TestUnarchiver + +struct unarchive_list { + int ifield; + id *list; +}; + +- (id)init { + (*((struct unarchive_list *)allUnarchivedObjects)).list = 0; + ((struct unarchive_list *)allUnarchivedObjects)->list = 0; + (**((struct unarchive_list **)allUnarchivedObjects)).list = 0; + (*((struct unarchive_list **)allUnarchivedObjects))->list = 0; + return 0; +} + +@end + +// rdar://10191569 +@interface I +{ + struct S { + id _timer; + } *p_animationState; +} +@end + +@implementation I +- (void) Meth { + p_animationState->_timer = 0; + (*p_animationState)._timer = 0; + (&(*p_animationState))->_timer = 0; +} +@end diff --git a/clang/test/CodeGenObjC/objc2-write-barrier.m b/clang/test/CodeGenObjC/objc2-write-barrier.m new file mode 100644 index 0000000..bf2dfb9 --- /dev/null +++ b/clang/test/CodeGenObjC/objc2-write-barrier.m @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_global' %t | count 21 +// RUN: grep -F '@objc_assign_ivar' %t | count 11 +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o %t %s +// RUN: grep -F '@objc_assign_global' %t | count 21 +// RUN: grep -F '@objc_assign_ivar' %t | count 11 + + +typedef const struct __CFDictionary * CFDictionaryRef; + +// callouts to these are generated with cc -fobjc-gc + +int GlobalAssigns; +int IvarAssigns; +int StrongCastAssigns; + + +// The test case elements; +@class NSObject; +@class NSString; + +typedef struct { + id element; + id elementArray[10]; + __strong CFDictionaryRef cfElement; + __strong CFDictionaryRef cfElementArray[10]; +} struct_with_ids_t; + +@interface Foo { +@public +// assignments to any/all of these fields should generate objc_assign_ivar + __strong CFDictionaryRef dict; + __strong CFDictionaryRef dictArray[3]; + id ivar; + id array[10]; + NSObject *nsobject; + NSString *stringArray[10]; + struct_with_ids_t inner; +} + +@end + +// assignments to these should generate objc_assign_global +id GlobalId; +id GlobalArray[20]; +NSObject *GlobalObject; +NSObject *GlobalObjectArray[20]; +__strong CFDictionaryRef Gdict; +__strong CFDictionaryRef Gdictarray[10]; +struct_with_ids_t GlobalStruct; +struct_with_ids_t GlobalStructArray[10]; + + +// The test cases +void* rhs = 0; + +#define ASSIGNTEST(expr, global) expr = (typeof(expr))rhs + +int testGlobals() { + // Everything in this function generates assign_global intercepts + int counter = 0; + + static id staticGlobalId; + static id staticGlobalArray[20]; + static NSObject *staticGlobalObject; + static NSObject *staticGlobalObjectArray[20]; + static __strong CFDictionaryRef staticGdict; + static __strong CFDictionaryRef staticGdictarray[10]; + static struct_with_ids_t staticGlobalStruct; + static struct_with_ids_t staticGlobalStructArray[10]; + + ASSIGNTEST(GlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(Gdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(GlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalId, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObject, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdict, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGdictarray[1], GlobalAssigns); // objc_assign_global + + ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns); // objc_assign_global + ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global + + return counter; +} + + +int testIvars() { + Foo *foo; + int counter = 0; + + ASSIGNTEST(foo->ivar, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->dict, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->dictArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->array[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->nsobject, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->stringArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.element, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.elementArray[0], IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.cfElement, IvarAssigns); // objc_assign_ivar + ASSIGNTEST(foo->inner.cfElementArray[0], IvarAssigns); // objc_assign_ivar + + return counter; +} diff --git a/clang/test/CodeGenObjC/object-incr-decr-1.m b/clang/test/CodeGenObjC/object-incr-decr-1.m new file mode 100644 index 0000000..19c12cb --- /dev/null +++ b/clang/test/CodeGenObjC/object-incr-decr-1.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm %s -o %t + +@interface Foo +{ + double d1,d3,d4; +} +@end + +Foo* foo() +{ + Foo *f; + + // Both of these crash clang nicely + ++f; + --f; + f--; + f++; + return f; +} diff --git a/clang/test/CodeGenObjC/optimized-setter.m b/clang/test/CodeGenObjC/optimized-setter.m new file mode 100644 index 0000000..0e1b388 --- /dev/null +++ b/clang/test/CodeGenObjC/optimized-setter.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s +// rdar://10179974 + +@interface I +// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, NO) +@property (nonatomic, retain) id nonatomicProperty; + +// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., NO, YES) +@property (nonatomic, copy) id nonatomicPropertyCopy; + +// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, NO) +@property (retain) id atomicProperty; + +// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset); +// objc_setProperty(..., YES, YES) +@property (copy) id atomicPropertyCopy; +@end + +@implementation I +@synthesize nonatomicProperty; +@synthesize nonatomicPropertyCopy; +@synthesize atomicProperty; +@synthesize atomicPropertyCopy; +@end + +// CHECK: call void @objc_setProperty_nonatomic +// CHECK: call void @objc_setProperty_nonatomic_copy +// CHECK: call void @objc_setProperty_atomic +// CHECK: call void @objc_setProperty_atomic_copy + diff --git a/clang/test/CodeGenObjC/overloadable.m b/clang/test/CodeGenObjC/overloadable.m new file mode 100644 index 0000000..4fd1429 --- /dev/null +++ b/clang/test/CodeGenObjC/overloadable.m @@ -0,0 +1,10 @@ +// rdar://6657613 +// RUN: %clang_cc1 -emit-llvm %s -o %t + +@class C; + +// RUN: grep _Z1fP11objc_object %t | count 1 +void __attribute__((overloadable)) f(id c) { } + +// RUN: grep _Z1fP1C %t | count 1 +void __attribute__((overloadable)) f(C *c) { } diff --git a/clang/test/CodeGenObjC/predefined-expr.m b/clang/test/CodeGenObjC/predefined-expr.m new file mode 100644 index 0000000..009bbcd --- /dev/null +++ b/clang/test/CodeGenObjC/predefined-expr.m @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi %s -emit-llvm -o - | FileCheck %s + +// 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, ...); + +@interface Foo +@end + +@implementation Foo + +- (void)instanceTest1 { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + +- (void)instanceTest2:(int)i { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + +- (void)instanceTest3:(int)a withB:(double)b { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + +- (int)instanceTest4 { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); + return 0; +} + ++ (void)classTest1 { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + ++ (void)classTest2:(int)i { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + ++ (void)classTest3:(int)a withB:(double)b { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + ++ (int)classTest4 { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); + return 0; +} + +@end + +@interface Foo (Category) +@end + +@implementation Foo (Category) + +- (void)instanceTestWithCategory { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + ++ (void)classTestWithCategory { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__); +} + +@end diff --git a/clang/test/CodeGenObjC/property-aggregate.m b/clang/test/CodeGenObjC/property-aggregate.m new file mode 100644 index 0000000..f4211b6 --- /dev/null +++ b/clang/test/CodeGenObjC/property-aggregate.m @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s + +// This structure's size is not a power of two, so the property does +// not get native atomics, even though x86-64 can do unaligned atomics +// with a lock prefix. +struct s3 { char c[3]; }; + +// This structure's size is, so it does, because it can. +// FIXME: But we don't at the moment; the backend doesn't know how to generate +// correct code. +struct s4 { char c[4]; }; + +@interface Test0 +@property struct s3 s3; +@property struct s4 s4; +@end +@implementation Test0 +@synthesize s3, s4; +@end + +// CHECK: define internal i24 @"\01-[Test0 s3]"( +// CHECK: call void @objc_copyStruct + +// CHECK: define internal void @"\01-[Test0 setS3:]"( +// CHECK: call void @objc_copyStruct + +// CHECK: define internal i32 @"\01-[Test0 s4]"( +// CHECK: call void @objc_copyStruct + +// CHECK: define internal void @"\01-[Test0 setS4:]"( +// CHECK: call void @objc_copyStruct diff --git a/clang/test/CodeGenObjC/property-agrr-getter.m b/clang/test/CodeGenObjC/property-agrr-getter.m new file mode 100644 index 0000000..6d8f1d6 --- /dev/null +++ b/clang/test/CodeGenObjC/property-agrr-getter.m @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +typedef struct { + unsigned f0; +} s0; + +@interface A +- (s0) f0; +@end + +@implementation A +-(s0) f0{ while (1) {} } +- (unsigned) bar { + return self.f0.f0; +} +@end + + +typedef struct _NSSize { + float width; + float height; +} NSSize; + + +@interface AnObject +{ + NSSize size; +} + +@property NSSize size; + +@end + +float f () +{ + AnObject* obj; + return (obj.size).width; +} + +// rdar://problem/9272392 +void test3(AnObject *obj) { + obj.size; + (void) obj.size; +} diff --git a/clang/test/CodeGenObjC/property-category-impl.m b/clang/test/CodeGenObjC/property-category-impl.m new file mode 100644 index 0000000..734f9a3 --- /dev/null +++ b/clang/test/CodeGenObjC/property-category-impl.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// rdar : // 8093297 + +@interface Foo @end + +@protocol Proto +@property (readonly) int proto_property; +@end + +@interface Foo (Category) <Proto> @end + +@implementation Foo (Category) +-(int)proto_property { return 0; } +@end + + +// CHECK: l_OBJC_$_PROP_LIST_Foo_$_Category" = internal global +// CHECK: l_OBJC_$_CATEGORY_Foo_$_Category" = internal global +// CHECK: l_OBJC_$_PROP_LIST_Foo_$_Category diff --git a/clang/test/CodeGenObjC/property-complex.m b/clang/test/CodeGenObjC/property-complex.m new file mode 100644 index 0000000..3cdd2ec --- /dev/null +++ b/clang/test/CodeGenObjC/property-complex.m @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o %t %s + +@interface I0 { +@public + _Complex float iv0; +} + +@property(assign) _Complex float p0; + +-(_Complex float) im0; +-(void) setIm0: (_Complex float) a0; +@end + +@implementation I0 +@dynamic p0; + +-(id) init { + self->iv0 = 5.0 + 2.0i; + return self; +} + +-(_Complex float) im0 { + printf("im0: %.2f + %.2fi\n", __real iv0, __imag iv0); + return iv0 + (.1 + .2i); +} +-(void) setIm0: (_Complex float) a0 { + printf("setIm0: %.2f + %.2fi\n", __real a0, __imag a0); + iv0 = a0 + (.3 + .4i); +} + +-(_Complex float) p0 { + printf("p0: %.2f + %.2fi\n", __real iv0, __imag iv0); + return iv0 + (.5 + .6i); +} +-(void) setP0: (_Complex float) a0 { + printf("setP0: %.2f + %.2fi\n", __real a0, __imag a0); + iv0 = a0 + (.7 + .8i); +} +@end + +void f0(I0 *a0) { + float l0 = __real a0.im0; + float l1 = __imag a0->iv0; + _Complex float l2 = (a0.im0 = a0.im0); + _Complex float l3 = a0->iv0; + _Complex float l4 = (a0->iv0 = a0->iv0); + _Complex float l5 = a0->iv0; + _Complex float l6 = (a0.p0 = a0.p0); + _Complex float l7 = a0->iv0; + _Complex float l8 = [a0 im0]; + printf("l0: %.2f + %.2fi\n", __real l0, __imag l0); + printf("l1: %.2f + %.2fi\n", __real l1, __imag l1); + printf("l2: %.2f + %.2fi\n", __real l2, __imag l2); + printf("l3: %.2f + %.2fi\n", __real l3, __imag l3); + printf("l4: %.2f + %.2fi\n", __real l4, __imag l4); + printf("l5: %.2f + %.2fi\n", __real l5, __imag l5); + printf("l6: %.2f + %.2fi\n", __real l6, __imag l6); + printf("l7: %.2f + %.2fi\n", __real l7, __imag l7); + printf("l8: %.2f + %.2fi\n", __real l8, __imag l8); +} diff --git a/clang/test/CodeGenObjC/property-dbg.m b/clang/test/CodeGenObjC/property-dbg.m new file mode 100644 index 0000000..42ab611 --- /dev/null +++ b/clang/test/CodeGenObjC/property-dbg.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep DW_AT_name +@interface Foo { + int i; +} +@property int i; +@end + +@implementation Foo +@synthesize i; +@end + +int bar(Foo *f) { + int i = 1; + f.i = 2; + i = f.i; + return i; +} diff --git a/clang/test/CodeGenObjC/property-getter-dot-syntax.m b/clang/test/CodeGenObjC/property-getter-dot-syntax.m new file mode 100644 index 0000000..f22b051 --- /dev/null +++ b/clang/test/CodeGenObjC/property-getter-dot-syntax.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@protocol NSObject +- (void *)description; +@end + +int main() +{ + id<NSObject> eggs; + void *eggsText= eggs.description; +} diff --git a/clang/test/CodeGenObjC/property-incr-decr-1.m b/clang/test/CodeGenObjC/property-incr-decr-1.m new file mode 100644 index 0000000..d75c02e --- /dev/null +++ b/clang/test/CodeGenObjC/property-incr-decr-1.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface Object +- (id) new; +@end + +@interface SomeClass : Object +{ + int _myValue; +} +@property int myValue; +@end + +@implementation SomeClass +@synthesize myValue=_myValue; +@end + +int main() +{ + int val; + SomeClass *o = [SomeClass new]; + o.myValue = -1; + val = o.myValue++; /* val -1, o.myValue 0 */ + val += o.myValue--; /* val -1. o.myValue -1 */ + val += ++o.myValue; /* val -1, o.myValue 0 */ + val += --o.myValue; /* val -2, o.myValue -1 */ + return ++o.myValue + (val+2); +} + diff --git a/clang/test/CodeGenObjC/property-list-in-class.m b/clang/test/CodeGenObjC/property-list-in-class.m new file mode 100644 index 0000000..e801485 --- /dev/null +++ b/clang/test/CodeGenObjC/property-list-in-class.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// CHECK: l_OBJC_$_PROP_LIST_C2" = internal global { i32, i32, [3 x %struct._prop_t] } { i32 16, i32 3 + +@protocol P +@property int i; +@end + +@protocol P1 +@property int i1; +@end + +@protocol P2 < P1> +@property int i2; +@end + +@interface C1 { id isa; } @end + +@interface C2 : C1 <P, P2> { + int i; +} +@property int i2; +@end + +@implementation C1 ++(void)initialize { } +@end + +@implementation C2 +@synthesize i; +@synthesize i1; +@synthesize i2; +@end diff --git a/clang/test/CodeGenObjC/property-ref-cast-to-void.m b/clang/test/CodeGenObjC/property-ref-cast-to-void.m new file mode 100644 index 0000000..ad1689f --- /dev/null +++ b/clang/test/CodeGenObjC/property-ref-cast-to-void.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin9 -fobjc-fragile-abi -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/clang/test/CodeGenObjC/property-setter-attr.m b/clang/test/CodeGenObjC/property-setter-attr.m new file mode 100644 index 0000000..d155ca8 --- /dev/null +++ b/clang/test/CodeGenObjC/property-setter-attr.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm -triple=i686-apple-darwin8 -o %t %s +// RUN: grep -e "SiSetOtherThings:" %t + +@interface A +@property(setter=iSetOtherThings:) int otherThings; +@end + +@implementation A +@dynamic otherThings; +@end diff --git a/clang/test/CodeGenObjC/property-type-mismatch.m b/clang/test/CodeGenObjC/property-type-mismatch.m new file mode 100644 index 0000000..b920b45 --- /dev/null +++ b/clang/test/CodeGenObjC/property-type-mismatch.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -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/clang/test/CodeGenObjC/property.m b/clang/test/CodeGenObjC/property.m new file mode 100644 index 0000000..16881d6 --- /dev/null +++ b/clang/test/CodeGenObjC/property.m @@ -0,0 +1,168 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// TODO: actually test most of this instead of just emitting it + +int printf(const char *, ...); + +@interface Root +-(id) alloc; +-(id) init; +@end + +@interface A : Root { + int x; + int y, ro, z; + id ob0, ob1, ob2, ob3, ob4; +} +@property int x; +@property int y; +@property int z; +@property(readonly) int ro; +@property(assign) id ob0; +@property(retain) id ob1; +@property(copy) id ob2; +@property(retain, nonatomic) id ob3; +@property(copy, nonatomic) id ob4; +@end + +@implementation A +@dynamic x; +@synthesize y; +@synthesize z = z; +@synthesize ro; +@synthesize ob0; +@synthesize ob1; +@synthesize ob2; +@synthesize ob3; +@synthesize ob4; +-(int) y { + return x + 1; +} +-(void) setZ: (int) arg { + x = arg - 1; +} +@end + +@interface A (Cat) +@property int dyn; +@end + +@implementation A (Cat) +-(int) dyn { + 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); +} + +@interface Test5 { + unsigned _x : 5; +} +@property unsigned x; +@end +@implementation Test5 +@synthesize x = _x; +@end + +// rdar://problem/10410531 +@interface Test6 +@property void (*prop)(void); +@end + +void test6_func(void); +void test6(Test6 *a) { + a.prop = test6_func; +} + +// rdar://problem/10507455 +@interface Test7 +@property unsigned char x; +@end +void test7(Test7 *t) { + t.x &= 2; + t.x |= 5; + t.x ^= 8; +} +// CHECK: define void @test7([[TEST7:%.*]]* +// CHECK: [[T:%.*]] = alloca [[TEST7]]*, +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast +// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 +// CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], 2 +// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: call void bitcast +// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast +// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 +// CHECK-NEXT: [[T4:%.*]] = or i32 [[T3]], 5 +// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: call void bitcast +// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast +// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 +// CHECK-NEXT: [[T4:%.*]] = xor i32 [[T3]], 8 +// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES +// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* +// CHECK-NEXT: call void bitcast +// CHECK-NEXT: ret void diff --git a/clang/test/CodeGenObjC/protocol-in-extended-class.m b/clang/test/CodeGenObjC/protocol-in-extended-class.m new file mode 100644 index 0000000..a924084 --- /dev/null +++ b/clang/test/CodeGenObjC/protocol-in-extended-class.m @@ -0,0 +1,29 @@ +// REQUIRES: x86-registered-target,x86-64-registered-target +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -triple i386-apple-darwin -fobjc-fragile-abi -S %s -o %t-32.s +// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s + +@protocol MyProtocol +@end + +@protocol ExtendedProtocol +@end + +@interface ItDoesntWork<MyProtocol> { +} +-(void) Meth; +@end + +@interface ItDoesntWork() <MyProtocol, ExtendedProtocol> +@end + +@implementation ItDoesntWork +-(void) Meth { + ItDoesntWork <MyProtocol, ExtendedProtocol> *p = 0; + } +@end + +// CHECK-LP64: l_OBJC_PROTOCOL_$_ExtendedProtocol: + +// CHECK-LP32: L_OBJC_PROTOCOL_ExtendedProtocol: diff --git a/clang/test/CodeGenObjC/protocol-property-synth.m b/clang/test/CodeGenObjC/protocol-property-synth.m new file mode 100644 index 0000000..c998d63 --- /dev/null +++ b/clang/test/CodeGenObjC/protocol-property-synth.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface BaseClass { + id _delegate; +} +@end + +@protocol MyProtocol +@optional +@property(assign) id delegate; +@end + +@protocol AnotherProtocol +@optional +@property(assign) id myanother; +@end + +@protocol SubProtocol <MyProtocol> +@property(assign) id another; +@end + +@interface SubClass : BaseClass <SubProtocol, AnotherProtocol> { +} + +@end + +@implementation BaseClass @end + +@implementation SubClass +@synthesize delegate = _Subdelegate; +@synthesize another; +@synthesize myanother; +@end diff --git a/clang/test/CodeGenObjC/protocols-lazy.m b/clang/test/CodeGenObjC/protocols-lazy.m new file mode 100644 index 0000000..1c551fb --- /dev/null +++ b/clang/test/CodeGenObjC/protocols-lazy.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-apple-darwin8 -fobjc-fragile-abi -o %t %s +// RUNX: llvm-gcc -S -emit-llvm -o %t %s && + +// No object generated +// RUN: grep OBJC_PROTOCOL_P0 %t | count 0 +@protocol P0; + +// No object generated +// RUN: grep OBJC_PROTOCOL_P1 %t | count 0 +@protocol P1 -im1; @end + +// Definition triggered by protocol reference. +// RUN: grep OBJC_PROTOCOL_P2 %t | count 3 +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P2 %t | count 3 +@protocol P2 -im1; @end +void f0() { id x = @protocol(P2); } + +// Forward definition triggered by protocol reference. +// RUN: grep OBJC_PROTOCOL_P3 %t | count 3 +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P3 %t | count 0 +@protocol P3; +void f1() { id x = @protocol(P3); } + +// Definition triggered by class reference. +// RUN: grep OBJC_PROTOCOL_P4 %t | count 3 +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P4 %t | count 3 +@protocol P4 -im1; @end +@interface I0<P4> @end +@implementation I0 -im1 { return 0; }; @end + +// Definition following forward reference. +// RUN: grep OBJC_PROTOCOL_P5 %t | count 3 +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P5 %t | count 3 +@protocol P5; +void f2() { id x = @protocol(P5); } // This generates a forward + // reference, which has to be + // updated on the next line. +@protocol P5 -im1; @end + +// Protocol reference following definition. +// RUN: grep OBJC_PROTOCOL_P6 %t | count 4 +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P6 %t | count 3 +@protocol P6 -im1; @end +@interface I1<P6> @end +@implementation I1 -im1 { return 0; }; @end +void f3() { id x = @protocol(P6); } + diff --git a/clang/test/CodeGenObjC/protocols.m b/clang/test/CodeGenObjC/protocols.m new file mode 100644 index 0000000..6dadb11 --- /dev/null +++ b/clang/test/CodeGenObjC/protocols.m @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +void p(const char*, ...); + +@interface Root ++(int) maxValue; +-(int) conformsTo: (id) x; +@end + +@protocol P0; + +@protocol P1 ++(void) classMethodReq0; +-(void) methodReq0; +@optional ++(void) classMethodOpt1; +-(void) methodOpt1; +@required ++(void) classMethodReq2; +-(void) methodReq2; +@end + +@protocol P2 +//@property(readwrite) int x; +@end + +@protocol P3<P1, P2> +-(id <P1>) print0; +-(void) print1; +@end + +void foo(const id a) { + void *p = @protocol(P3); +} + +int main() { + Protocol *P0 = @protocol(P0); + Protocol *P1 = @protocol(P1); + Protocol *P2 = @protocol(P2); + Protocol *P3 = @protocol(P3); + +#define Pbool(X) p(#X ": %s\n", X ? "yes" : "no"); + Pbool([P0 conformsTo: P1]); + Pbool([P1 conformsTo: P0]); + Pbool([P1 conformsTo: P2]); + Pbool([P2 conformsTo: P1]); + Pbool([P3 conformsTo: P1]); + Pbool([P1 conformsTo: P3]); + + return 0; +} + +// rdar://problem/7992749 +typedef Root<P1> P1Object; +int test10() { + return [P1Object maxValue]; +} diff --git a/clang/test/CodeGenObjC/rdr-6732143-dangling-block-reference.m b/clang/test/CodeGenObjC/rdr-6732143-dangling-block-reference.m new file mode 100644 index 0000000..a93ca03 --- /dev/null +++ b/clang/test/CodeGenObjC/rdr-6732143-dangling-block-reference.m @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-fragile-abi -emit-llvm -fobjc-exceptions %s -o - + +void f0(id x) { + @synchronized (x) { + do { ; } while(0); + @try { + } @finally { + } + } +} diff --git a/clang/test/CodeGenObjC/related-result-type.m b/clang/test/CodeGenObjC/related-result-type.m new file mode 100644 index 0000000..ef38661 --- /dev/null +++ b/clang/test/CodeGenObjC/related-result-type.m @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +@interface NSObject ++ (id)alloc; +- (id)init; +- (id)retain; +@end + +@interface NSString : NSObject +@end + +// CHECK: define void @test1() +void test1() { + // CHECK: {{call.*@objc_msgSend}} + // CHECK: {{call.*@objc_msgSend}} + // CHECK: {{call.*@objc_msgSend}} + // CHECK: bitcast i8* + NSString *str1 = [[[NSString alloc] init] retain]; +} + +// CHECK: define void @test2() +void test2() { + // CHECK: {{call.*@objc_msgSend}} + // CHECK: {{call.*@objc_msgSend}} + // CHECK: {{call.*@objc_msgSend}} + // CHECK: bitcast i8* + NSString *str1 = NSString.alloc.init.retain; +} + +@interface Test2 : NSString +- (id)init; +@end + +@implementation Test2 +// CHECK: define internal i8* @"\01-[Test2 init]" +- (id)init { + // CHECK: {{call.*@objc_msgSendSuper}} + // CHECK-NEXT: bitcast i8* + return [super init]; +} +@end + +@interface Test3 : NSString +- (id)init; +@end + +@implementation Test3 +// CHECK: define internal i8* @"\01-[Test3 init]" +- (id)init { + // CHECK: {{call.*@objc_msgSendSuper}} + // CHECK-NEXT: bitcast i8* + return [super init]; +} +@end diff --git a/clang/test/CodeGenObjC/return-objc-object.mm b/clang/test/CodeGenObjC/return-objc-object.mm new file mode 100644 index 0000000..95cce23 --- /dev/null +++ b/clang/test/CodeGenObjC/return-objc-object.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | FileCheck %s + +@protocol P1 @end +@interface NSOperationQueue +{ + char ch[64]; + double d; +} +@end + +NSOperationQueue &f(); +NSOperationQueue<P1> &f1(); + +void call_once() { + f(); + f1(); +} +// CHECK: call %0* @_Z1fv() +// CHECK: call %0* @_Z2f1v() diff --git a/clang/test/CodeGenObjC/runtime-fns.m b/clang/test/CodeGenObjC/runtime-fns.m new file mode 100644 index 0000000..203d87f --- /dev/null +++ b/clang/test/CodeGenObjC/runtime-fns.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1 +// RUN: %clang_cc1 -DWITHDEF -emit-llvm -o %t %s +// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1 + +id objc_msgSend(int x); + +@interface A @end + +@implementation A +-(void) f0 { + objc_msgSend(12); +} + +-(void) hello { +} +@end + +void f0(id x) { + [x hello]; +} + +#ifdef WITHDEF +// This isn't a very good send function. +id objc_msgSend(int x) { + return 0; +} + +// rdar://6800430 +void objc_assign_weak(id value, id *location) { +} + +#endif diff --git a/clang/test/CodeGenObjC/sel-as-builtin-type.m b/clang/test/CodeGenObjC/sel-as-builtin-type.m new file mode 100644 index 0000000..72a8564 --- /dev/null +++ b/clang/test/CodeGenObjC/sel-as-builtin-type.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// pr5025 +// radar 7405040 + +typedef const struct objc_selector { + void *sel_id; + const char *sel_types; +} *SEL; + +@interface I2 ++(id) dictionary; +@end + +@implementation I3; // expected-warning {{cannot find interface declaration for 'I3'}} ++(void) initialize { + I2 *a0 = [I2 dictionary]; +} +@end + +int func(SEL s1, SEL s2) +{ + return s1->sel_id == s2->sel_id; +} diff --git a/clang/test/CodeGenObjC/selector-ref-invariance.m b/clang/test/CodeGenObjC/selector-ref-invariance.m new file mode 100644 index 0000000..e356419 --- /dev/null +++ b/clang/test/CodeGenObjC/selector-ref-invariance.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fblocks -o - %s | FileCheck %s + +// rdar://6027699 + +void test(id x) { +// CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", !invariant.load +// CHECK: @objc_msgSend + [x foo]; +} diff --git a/clang/test/CodeGenObjC/simplify-exceptions.mm b/clang/test/CodeGenObjC/simplify-exceptions.mm new file mode 100644 index 0000000..d0baf80 --- /dev/null +++ b/clang/test/CodeGenObjC/simplify-exceptions.mm @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm \ +// RUN: -fexceptions -fobjc-exceptions \ +// RUN: -o %t %s +// RUN: FileCheck < %t %s +// +// <rdar://problem/7471679> [irgen] [eh] Exception code built with clang (x86_64) crashes + +// Check that we don't emit unnecessary personality function references. +struct t0_A { t0_A(); }; +struct t0_B { t0_A a; }; + +// CHECK: define {{.*}} @_Z2t0v(){{.*}} { +// CHECK-NOT: objc_personality +// CHECK: } +t0_B& t0() { + static t0_B x; + return x; +} diff --git a/clang/test/CodeGenObjC/stand-alone-implementation.m b/clang/test/CodeGenObjC/stand-alone-implementation.m new file mode 100644 index 0000000..8245f01 --- /dev/null +++ b/clang/test/CodeGenObjC/stand-alone-implementation.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s + +// radar 7547942 +// Allow injection of ivars into implementation's implicit class. + +@implementation INTFSTANDALONE // expected-warning {{cannot find interface declaration for 'INTFSTANDALONE'}} +{ + id IVAR1; + id IVAR2; +} +- (id) Meth { return IVAR1; } +@end + +// CHECK-X86-64: @"OBJC_IVAR_$_INTFSTANDALONE.IVAR1" +// CHECK-X86-64: @"OBJC_IVAR_$_INTFSTANDALONE.IVAR2" + diff --git a/clang/test/CodeGenObjC/super-classmethod-category.m b/clang/test/CodeGenObjC/super-classmethod-category.m new file mode 100644 index 0000000..c19663c --- /dev/null +++ b/clang/test/CodeGenObjC/super-classmethod-category.m @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface SUPER ++ (void)Meth; +@end + +@interface CURRENT : SUPER ++ (void)Meth; +@end + +@implementation CURRENT(CAT) ++ (void)Meth { [super Meth]; } +@end diff --git a/clang/test/CodeGenObjC/super-dotsyntax-property.m b/clang/test/CodeGenObjC/super-dotsyntax-property.m new file mode 100644 index 0000000..9dfde2d --- /dev/null +++ b/clang/test/CodeGenObjC/super-dotsyntax-property.m @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface B +{ + int _parent; +} +@property int parent; + +(int) classGetter; + +(void) setClassGetter:(int) arg; + + -(int) getter; + -(void) setGetter:(int)arg; +@end + +@interface A : B +@end + +@implementation A ++(int) classGetter { + return 0; +} + ++(int) classGetter2 { + super.classGetter = 100; + return super.classGetter; +} + +-(void) method { + super.getter = 200; + int x = super.getter; +} +-(void) setParent : (int) arg { + super.parent = arg + super.parent; + +} +@end + +void f0() { + int l1 = A.classGetter; + int l2 = [A classGetter2]; +} diff --git a/clang/test/CodeGenObjC/super-dotsyntax-struct-property.m b/clang/test/CodeGenObjC/super-dotsyntax-struct-property.m new file mode 100644 index 0000000..a7910a0 --- /dev/null +++ b/clang/test/CodeGenObjC/super-dotsyntax-struct-property.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// rdar: // 8203426 + + +typedef double CGFloat; +struct CGPoint { + CGFloat x; + CGFloat y; +}; +typedef struct CGPoint CGPoint; + + + +struct CGSize { + CGFloat width; + CGFloat height; +}; +typedef struct CGSize CGSize; + + +struct CGRect { + CGPoint origin; + CGSize size; +}; +typedef struct CGRect CGRect; + +@interface UIView { +} +@property CGRect frame; +@end + +@interface crashclass : UIView { + +} + +@end + +@implementation crashclass +- (void)setFrame:(CGRect)frame +{ + super.frame = frame; + [super setFrame:frame]; +} + +@end +// CHECK-NOT: declare void @objc_msgSendSuper2_stret +// CHECK: declare i8* @objc_msgSendSuper2 diff --git a/clang/test/CodeGenObjC/super-message-fragileabi.m b/clang/test/CodeGenObjC/super-message-fragileabi.m new file mode 100644 index 0000000..0135919 --- /dev/null +++ b/clang/test/CodeGenObjC/super-message-fragileabi.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm %s -o - | FileCheck %s + +@class Some; + +@protocol Proto +- (id)initSome:(Some *)anArg; +@end + + +@interface Table <Proto> +@end + +@interface BetterTable: Table + +- (id)initSome:(Some *)arg; + +@end + +@implementation BetterTable + +- (id)initSome:(Some *)arg { + + if(self=[super initSome:arg]) + { + ; + } +// CHECK: load %struct._objc_class** getelementptr inbounds (%struct._objc_class* @"\01L_OBJC_CLASS_BetterTable", i32 0, i32 1) + + return self; +} +@end + diff --git a/clang/test/CodeGenObjC/synchronized.m b/clang/test/CodeGenObjC/synchronized.m new file mode 100644 index 0000000..4997bb7 --- /dev/null +++ b/clang/test/CodeGenObjC/synchronized.m @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-apple-darwin9 -fobjc-fragile-abi -o - %s -O2 | FileCheck %s + +@interface MyClass +{ +} +- (void)method; +@end + +@implementation MyClass + +// CHECK: define internal void @"\01-[MyClass method]" +- (void)method +{ + // CHECK: call void @objc_sync_enter + // CHECK: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp + @synchronized(self) { + } +} + +@end + +// CHECK: define void @foo( +void foo(id a) { + // CHECK: [[A:%.*]] = alloca i8* + // CHECK: [[SYNC:%.*]] = alloca i8* + + // CHECK: store i8* [[AVAL:%.*]], i8** [[A]] + // CHECK-NEXT: call void @objc_sync_enter(i8* [[AVAL]]) + // CHECK-NEXT: store i8* [[AVAL]], i8** [[SYNC]] + // CHECK-NEXT: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp + @synchronized(a) { + // This is unreachable, but the optimizers can't know that. + // CHECK: call void asm sideeffect "", "=*m,=*m,=*m"(i8** [[A]], i8** [[SYNC]] + // CHECK: call void @objc_sync_exit + // CHECK: call i8* @objc_exception_extract + // CHECK: call void @objc_exception_throw + // CHECK: unreachable + + // CHECK: call void @objc_exception_try_exit + // CHECK: [[T:%.*]] = load i8** [[SYNC]] + // CHECK-NEXT: call void @objc_sync_exit + // CHECK: ret void + return; + } + +} + +// CHECK: define i32 @f0( +int f0(id a) { + // TODO: we can optimize the ret to a constant if we can figure out + // either that x isn't stored to within the synchronized block or + // that the synchronized block can't longjmp. + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 1, i32* [[X]] + int x = 0; + @synchronized((x++, a)) { + } + + // CHECK: [[T:%.*]] = load i32* [[X]] + // CHECK: ret i32 [[T]] + return x; +} + +// CHECK: define void @f1( +void f1(id a) { + // Check that the return doesn't go through the cleanup. + extern void opaque(void); + opaque(); + + // CHECK: call void @opaque() + // CHECK-NEXT: ret void + + @synchronized(({ return; }), a) { + return; + } +} diff --git a/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m b/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m new file mode 100644 index 0000000..6bc7ac8 --- /dev/null +++ b/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: grep '@"OBJC_IVAR_$_XCOrganizerDeviceNodeInfo.viewController"' %t + +@interface XCOrganizerNodeInfo +@property (readonly, retain) id viewController; +@end + +@interface XCOrganizerDeviceNodeInfo : XCOrganizerNodeInfo +@end + +@interface XCOrganizerDeviceNodeInfo() +@property (retain) id viewController; +@end + +@implementation XCOrganizerDeviceNodeInfo +@synthesize viewController; +@end + diff --git a/clang/test/CodeGenObjC/synthesize_ivar.m b/clang/test/CodeGenObjC/synthesize_ivar.m new file mode 100644 index 0000000..e4fbe10 --- /dev/null +++ b/clang/test/CodeGenObjC/synthesize_ivar.m @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s + +@interface I +@property int IP; +@end + +@implementation I +@synthesize IP; +- (int) Meth { + return IP; +} +@end + +// Test for synthesis of ivar for a property +// declared in continuation class. +@interface OrganizerViolatorView +@end + +@interface OrganizerViolatorView() +@property (retain) id bindingInfo; +@end + +@implementation OrganizerViolatorView +@synthesize bindingInfo; +@end + +// <rdar://problem/7336352> [irgen] crash in synthesized property construction + +@interface I0 @end +@protocol P0 @end +@interface I1 { + I0<P0> *iv0; +} +@property (assign, readwrite) id p0; +@end +@implementation I1 +@synthesize p0 = iv0; +@end diff --git a/clang/test/CodeGenObjC/terminate.m b/clang/test/CodeGenObjC/terminate.m new file mode 100644 index 0000000..a862058 --- /dev/null +++ b/clang/test/CodeGenObjC/terminate.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime-has-terminate -o - %s | FileCheck %s -check-prefix=CHECK-WITH +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s -check-prefix=CHECK-WITHOUT + +void destroy(void**); + +// rdar://problem/9519113 +void test0(void) { + void test0_helper(void); + void *ptr __attribute__((cleanup(destroy))); + test0_helper(); + + // CHECK-WITH: define void @test0() + // CHECK-WITH: [[PTR:%.*]] = alloca i8*, + // CHECK-WITH: call void @destroy(i8** [[PTR]]) + // CHECK-WITH-NEXT: ret void + // CHECK-WITH: invoke void @destroy(i8** [[PTR]]) + // CHECK-WITH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) + // CHECK-WITH-NEXT: catch i8* null + // CHECK-WITH-NEXT: call void @objc_terminate() + + // CHECK-WITHOUT: define void @test0() + // CHECK-WITHOUT: [[PTR:%.*]] = alloca i8*, + // CHECK-WITHOUT: call void @destroy(i8** [[PTR]]) + // CHECK-WITHOUT-NEXT: ret void + // CHECK-WITHOUT: invoke void @destroy(i8** [[PTR]]) + // CHECK-WITHOUT: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) + // CHECK-WITHOUT-NEXT: catch i8* null + // CHECK-WITHOUT-NEXT: call void @abort() +} diff --git a/clang/test/CodeGenObjC/try.m b/clang/test/CodeGenObjC/try.m new file mode 100644 index 0000000..56b8e64 --- /dev/null +++ b/clang/test/CodeGenObjC/try.m @@ -0,0 +1,10 @@ +// REQUIRES: x86-registered-target,x86-64-registered-target +// RUN: %clang_cc1 %s -fobjc-exceptions -S -o - -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -fobjc-exceptions -S -o - -triple=x86_64-apple-darwin9 + +// rdar://6757213 - Don't crash if the internal proto for +// __objc_personality_v0 mismatches with an actual one. +void __objc_personality_v0() { } +void test1(void) { + @try { } @catch (...) { } +} diff --git a/clang/test/CodeGenObjC/undefined-protocol.m b/clang/test/CodeGenObjC/undefined-protocol.m new file mode 100644 index 0000000..d87a5c9 --- /dev/null +++ b/clang/test/CodeGenObjC/undefined-protocol.m @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -emit-llvm-only -fgnu-runtime %s + +@protocol MadeUpProtocol; + +@interface Object <MadeUpProtocol> @end +@implementation Object @end diff --git a/clang/test/CodeGenObjC/unname-bf-metadata.m b/clang/test/CodeGenObjC/unname-bf-metadata.m new file mode 100644 index 0000000..c1208c1 --- /dev/null +++ b/clang/test/CodeGenObjC/unname-bf-metadata.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// Test that meta-data for ivar lists with unnamed bitfield are generated. +// +@interface Foo { +@private + int first; + int :1; + int third :1; + int :1; + int fifth :1; +} +@end +@implementation Foo +@end diff --git a/clang/test/CodeGenObjC/variadic-sends.m b/clang/test/CodeGenObjC/variadic-sends.m new file mode 100644 index 0000000..94d7baf --- /dev/null +++ b/clang/test/CodeGenObjC/variadic-sends.m @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-32 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s + +@interface A +-(void) im0; +-(void) im1: (int) x; +-(void) im2: (int) x, ...; +@end + +void f0(A *a) { + // CHECK-X86-32: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*) + // CHECK-X86-64: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*) + [a im0]; +} + +void f1(A *a) { + // CHECK-X86-32: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*) + // CHECK-X86-64: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*) + [a im1: 1]; +} + +void f2(A *a) { + // CHECK-X86-32: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*) + // CHECK-X86-64: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*) + [a im2: 1, 2]; +} + +@interface B : A @end +@implementation B : A +-(void) foo { + // CHECK-X86-32: call void bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32)*) + // CHECK-X86-64: call void bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32)*) + [super im1: 1]; +} +-(void) bar { + // CHECK-X86-32: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*) + // CHECK-X86-64: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*) + [super im2: 1, 2]; +} + +@end diff --git a/clang/test/CodeGenObjC/x86_64-struct-return-gc.m b/clang/test/CodeGenObjC/x86_64-struct-return-gc.m new file mode 100644 index 0000000..76407d6 --- /dev/null +++ b/clang/test/CodeGenObjC/x86_64-struct-return-gc.m @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -fobjc-gc -emit-llvm -o - %s | FileCheck %s +struct Coerce { + id a; +}; + +struct Coerce coerce_func(void); + +// CHECK: define void @Coerce_test() +void Coerce_test(void) { + struct Coerce c; + + // CHECK: call i8* @coerce_func + // CHECK: call i8* @objc_memmove_collectable( + c = coerce_func(); +} + +struct Indirect { + id a; + int b[10]; +}; + +struct Indirect indirect_func(void); + +// CHECK: define void @Indirect_test() +void Indirect_test(void) { + struct Indirect i; + + // CHECK: call void @indirect_func(%struct.Indirect* sret + // CHECK: call i8* @objc_memmove_collectable( + i = indirect_func(); +} |