|  | // RUN: %clang_cc1 -fsyntax-only -verify -Wselector-type-mismatch %s | 
|  |  | 
|  | @protocol Proto | 
|  | - (void)protoMethod;      // expected-note {{previous declaration is here}} | 
|  | + (void)classProtoMethod; // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | @protocol ProtoDirectFail | 
|  | - (void)protoMethod __attribute__((objc_direct));      // expected-error {{'objc_direct' attribute cannot be applied to methods declared in an Objective-C protocol}} | 
|  | + (void)classProtoMethod __attribute__((objc_direct)); // expected-error {{'objc_direct' attribute cannot be applied to methods declared in an Objective-C protocol}} | 
|  | @end | 
|  |  | 
|  | __attribute__((objc_root_class)) | 
|  | @interface Root | 
|  | - (void)unavailableInChild; | 
|  | - (void)rootRegular;                                  // expected-note {{previous declaration is here}} | 
|  | + (void)classRootRegular;                             // expected-note {{previous declaration is here}} | 
|  | - (void)rootDirect __attribute__((objc_direct));      // expected-note {{previous declaration is here}}; | 
|  | + (void)classRootDirect __attribute__((objc_direct)); // expected-note {{previous declaration is here}}; | 
|  | - (void)otherRootDirect __attribute__((objc_direct)); // expected-note {{direct method 'otherRootDirect' declared here}} | 
|  | + (void)otherClassRootDirect __attribute__((objc_direct)); // expected-note {{direct method 'otherClassRootDirect' declared here}} | 
|  | + (void)otherOtherClassRootDirect __attribute__((objc_direct)); // expected-note {{direct method 'otherOtherClassRootDirect' declared here}} | 
|  | - (void)notDirectInIface;                             // expected-note {{previous declaration is here}} | 
|  | + (void)classNotDirectInIface;                        // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | __attribute__((objc_direct_members)) | 
|  | @interface Root () | 
|  | - (void)rootExtensionDirect;      // expected-note {{previous declaration is here}} | 
|  | + (void)classRootExtensionDirect; // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | __attribute__((objc_direct_members)) | 
|  | @interface Root(Direct) | 
|  | - (void)rootCategoryDirect;      // expected-note {{previous declaration is here}} | 
|  | + (void)classRootCategoryDirect; // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | @interface Root () | 
|  | - (void)rootExtensionRegular;                                   // expected-note {{previous declaration is here}} | 
|  | + (void)classRootExtensionRegular;                              // expected-note {{previous declaration is here}} | 
|  | - (void)rootExtensionDirect2 __attribute__((objc_direct));      // expected-note {{previous declaration is here}} | 
|  | + (void)classRootExtensionDirect2 __attribute__((objc_direct)); // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | @interface Root (Direct2) | 
|  | - (void)rootCategoryRegular;                                   // expected-note {{previous declaration is here}} | 
|  | + (void)classRootCategoryRegular;                              // expected-note {{previous declaration is here}} | 
|  | - (void)rootCategoryDirect2 __attribute__((objc_direct));      // expected-note {{previous declaration is here}} | 
|  | + (void)classRootCategoryDirect2 __attribute__((objc_direct)); // expected-note {{previous declaration is here}} | 
|  | @end | 
|  |  | 
|  | __attribute__((objc_direct_members)) | 
|  | @interface SubDirectMembers : Root | 
|  | @property int foo; // expected-note {{previous declaration is here}} | 
|  | - (void)unavailableInChild __attribute__((unavailable)); // should not warn | 
|  | - (instancetype)init; | 
|  | @end | 
|  |  | 
|  | @interface Sub : Root <Proto> | 
|  | /* invalid overrides with directs */ | 
|  | - (void)rootRegular __attribute__((objc_direct));               // expected-error {{methods that override superclass methods cannot be direct}} | 
|  | + (void)classRootRegular __attribute__((objc_direct));          // expected-error {{methods that override superclass methods cannot be direct}} | 
|  | - (void)protoMethod __attribute__((objc_direct));               // expected-error {{methods that implement protocol requirements cannot be direct}} | 
|  | + (void)classProtoMethod __attribute__((objc_direct));          // expected-error {{methods that implement protocol requirements cannot be direct}} | 
|  | - (void)rootExtensionRegular __attribute__((objc_direct));      // expected-error {{methods that override superclass methods cannot be direct}} | 
|  | + (void)classRootExtensionRegular __attribute__((objc_direct)); // expected-error {{methods that override superclass methods cannot be direct}} | 
|  | - (void)rootCategoryRegular __attribute__((objc_direct));       // expected-error {{methods that override superclass methods cannot be direct}} | 
|  | + (void)classRootCategoryRegular __attribute__((objc_direct));  // expected-error {{methods that override superclass methods cannot be direct}} | 
|  |  | 
|  | /* invalid overrides of directs */ | 
|  | - (void)rootDirect;                // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | + (void)classRootDirect;           // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | - (void)rootExtensionDirect;       // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | + (void)classRootExtensionDirect;  // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | - (void)rootExtensionDirect2;      // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | + (void)classRootExtensionDirect2; // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | - (void)rootCategoryDirect;        // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | + (void)classRootCategoryDirect;   // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | - (void)rootCategoryDirect2;       // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | + (void)classRootCategoryDirect2;  // expected-error {{cannot override a method that is declared direct by a superclass}} | 
|  | @end | 
|  |  | 
|  | __attribute__((objc_direct_members)) | 
|  | @implementation Root | 
|  | - (void)unavailableInChild { | 
|  | } | 
|  | - (void)rootRegular { | 
|  | } | 
|  | + (void)classRootRegular { | 
|  | } | 
|  | - (void)rootDirect { | 
|  | } | 
|  | + (void)classRootDirect { | 
|  | } | 
|  | - (void)otherRootDirect { | 
|  | } | 
|  | + (void)someRootDirectMethod { // expected-note {{direct method 'someRootDirectMethod' declared here}} | 
|  | } | 
|  | + (void)otherClassRootDirect { | 
|  | [self someRootDirectMethod]; // expected-error {{messaging a Class with a method that is possibly direct}} | 
|  | } | 
|  | + (void)otherOtherClassRootDirect { | 
|  | } | 
|  | - (void)rootExtensionDirect { | 
|  | } | 
|  | + (void)classRootExtensionDirect { | 
|  | } | 
|  | - (void)rootExtensionRegular { | 
|  | } | 
|  | + (void)classRootExtensionRegular { | 
|  | } | 
|  | - (void)rootExtensionDirect2 { | 
|  | } | 
|  | + (void)classRootExtensionDirect2 { | 
|  | } | 
|  | - (void)notDirectInIface __attribute__((objc_direct)) // expected-error {{direct method implementation was previously declared not direct}} | 
|  | { | 
|  | } | 
|  | + (void)classNotDirectInIface __attribute__((objc_direct)) // expected-error {{direct method implementation was previously declared not direct}} | 
|  | { | 
|  | } | 
|  | - (void)direct1 { // expected-note {{direct method 'direct1' declared here}} | 
|  | } | 
|  | - (void)direct2 { // expected-note {{direct method 'direct2' declared here}} | 
|  | } | 
|  | @end | 
|  |  | 
|  | @interface Foo : Root | 
|  | - (id)directMismatch1; // expected-note {{using}} | 
|  | - (id)directMismatch2; // expected-note {{method 'directMismatch2' declared here}} | 
|  | @end | 
|  |  | 
|  | @interface Bar : Root | 
|  | - (void)directMismatch1 __attribute__((objc_direct)); // expected-note {{also found}} | 
|  | - (void)directMismatch2 __attribute__((objc_direct)); // expected-note {{method 'directMismatch2' declared here}} | 
|  | @end | 
|  |  | 
|  | @interface ValidSub : Root | 
|  | @end | 
|  |  | 
|  | @implementation ValidSub | 
|  | - (void)someValidSubMethod { | 
|  | [super otherRootDirect]; // expected-error {{messaging super with a direct method}} | 
|  | } | 
|  | + (void)someValidSubMethod { | 
|  | [super otherOtherClassRootDirect]; // expected-error {{messaging super with a direct method}} | 
|  | } | 
|  | @end | 
|  |  | 
|  | @implementation SubDirectMembers | 
|  | @dynamic foo; // expected-error {{direct property cannot be @dynamic}} | 
|  | - (instancetype)init { | 
|  | return self; | 
|  | } | 
|  | @end | 
|  |  | 
|  | extern void callMethod(id obj, Class cls); | 
|  | extern void useSel(SEL sel); | 
|  |  | 
|  | void callMethod(id obj, Class cls) { | 
|  | [Root otherClassRootDirect]; | 
|  | [cls otherClassRootDirect]; // expected-error {{messaging a Class with a method that is possibly direct}} | 
|  | [obj direct1];              // expected-error {{messaging unqualified id with a method that is possibly direct}} | 
|  | [(Root *)obj direct1]; | 
|  | [obj directMismatch1];              // expected-warning {{multiple methods named 'directMismatch1' found}} | 
|  | useSel(@selector(direct2));         // expected-error {{@selector expression formed with direct selector 'direct2'}} | 
|  | useSel(@selector(directMismatch2)); // expected-warning {{several methods with selector 'directMismatch2' of mismatched types are found for the @selector expression}} | 
|  | } |