diff options
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(); +} | 
