// RUN: %clang_cc1 -emit-llvm -fobjc-arc -fblocks -fobjc-runtime-has-weak \ // RUN: -triple arm64-apple-macos11.0 \ // RUN: -fobjc-direct-precondition-thunk %s -o - | FileCheck %s #define nil ((id)0) __attribute__((objc_root_class)) @interface LinkedList @property(direct, readonly, nonatomic) int v; @property(direct, strong, nonatomic) LinkedList* next; @property(direct, readonly, nonatomic) int instanceId; @property(strong, nonatomic, direct) void ( ^ printBlock )( void ); + (instancetype)alloc; - (instancetype)initWithV:(int)v Next:(id)next __attribute__((objc_direct)); - (instancetype)clone __attribute__((objc_direct)); - (void)print __attribute__((objc_direct)); - (instancetype) reverseWithPrev:(id) prev __attribute__((objc_direct)); - (int) size __attribute__((objc_direct)); - (int) sum __attribute__((objc_direct)); - (double) avg __attribute__((objc_direct)); - (int) sumWith:(LinkedList *) __attribute__((ns_consumed)) other __attribute__((objc_direct)); @end @implementation LinkedList static int numInstances=0; - (instancetype)initWithV:(int)v Next:(id)next{ _v = v; _next = next; _instanceId = numInstances; LinkedList* __weak weakSelf = self; _printBlock = ^void(void) { [weakSelf print]; }; numInstances++; return self; } - (instancetype) clone { return [[LinkedList alloc] initWithV:self.v Next:[self.next clone]]; } - (void) print { [self.next print]; } - (LinkedList*) reverseWithPrev:(LinkedList*) prev{ LinkedList* newHead = (self.next == nil) ? self : [self.next reverseWithPrev:self]; self.next = prev; return newHead; } - (int) size { return 1 + [self.next size]; } - (int) sum { return self.v + [self.next sum]; } - (double) avg { return (double)[self sum] / (double)[self size]; } - (int) sumWith:(LinkedList *) __attribute__((ns_consumed)) other { return [self sum] + [other sum]; } @end int main() { // CHECK: call ptr @"-[LinkedList initWithV:Next:]D_thunk" // CHECK: call ptr @"-[LinkedList initWithV:Next:]D_thunk" LinkedList* ll = [[LinkedList alloc] initWithV:8 Next:[[LinkedList alloc] initWithV:7 Next:nil]]; // CHECK: call ptr @"-[LinkedList initWithV:Next:]D_thunk" // CHECK: call ptr @"-[LinkedList next]D_thunk" // CHECK: call void @"-[LinkedList setNext:]D_thunk" ll.next.next = [[LinkedList alloc] initWithV:6 Next:nil]; // CHECK: call void @"-[LinkedList print]D_thunk" [ll print]; // CHECK: call ptr @"-[LinkedList clone]D_thunk" LinkedList* cloned = [ll clone]; // CHECK: call void @"-[LinkedList print]D_thunk" [cloned print]; // CHECK: call ptr @"-[LinkedList printBlock]D_thunk" cloned.printBlock(); // Test ns_consumed parameter with direct method thunk. // CHECK: call i32 @"-[LinkedList sumWith:]D_thunk" int combined = [ll sumWith:[cloned clone]]; // CHECK: call ptr @"-[LinkedList reverseWithPrev:]D_thunk" ll = [ll reverseWithPrev:nil]; // CHECK: call void @"-[LinkedList print]D_thunk" [ll print]; return 0; }