1/* Test the Modern GNU Objective-C Runtime API. 2 3 This is test 'sel', covering all functions starting with 'sel'. */ 4 5/* { dg-do run } */ 6/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ 7 8/* To get the modern GNU Objective-C Runtime API, you include 9 objc/runtime.h. */ 10#include <objc/runtime.h> 11#include <stdlib.h> 12#include <iostream> 13#include <cstring> 14 15@interface MyRootClass 16{ Class isa; } 17+ alloc; 18- init; 19+ initialize; 20@end 21 22@implementation MyRootClass 23+ alloc { return class_createInstance (self, 0); } 24- init { return self; } 25+ initialize { return self; } 26@end 27 28@protocol MyProtocol 29- (id) variable; 30@end 31 32@protocol MySecondProtocol 33- (id) setVariable: (id)value; 34@end 35 36@interface MySubClass : MyRootClass <MyProtocol> 37{ id variable_ivar; } 38- (void) setVariable: (id)value; 39- (id) variable; 40- (void) method; 41@end 42 43@implementation MySubClass 44- (void) setVariable: (id)value { variable_ivar = value; } 45- (id) variable { return variable_ivar; } 46- (void) method { return; } 47@end 48 49@interface ClassA : MyRootClass 50- (id) conflictingSelectorMethod; 51@end 52 53@implementation ClassA 54- (id) conflictingSelectorMethod { return nil; } 55@end 56 57@interface ClassB : MyRootClass 58- (void) conflictingSelectorMethod; 59@end 60 61@implementation ClassB 62- (void) conflictingSelectorMethod { return; } 63@end 64 65int main () 66{ 67 /* Functions are tested in alphabetical order. */ 68 69#ifdef __GNU_LIBOBJC__ 70 std::cout << "Testing sel_copyTypedSelectorList ()...\n"; 71 { 72 unsigned int count; 73 SEL * list = sel_copyTypedSelectorList ("method", &count); 74 75 /* There should only be two, since 'method' is referenced twice, 76 once with types and once without (in this very test). */ 77 if (count != 2) 78 abort (); 79 80 /* Check that both selectors are not-NULL, and have the correct 81 name. We use @selector() here, which wouldn't really be 82 needed, just to register a second, untyped selector with name 83 'method'. */ 84 if (std::strcmp (sel_getName (list[0]), sel_getName (@selector (method))) != 0) 85 abort (); 86 87 if (std::strcmp (sel_getName (list[1]), sel_getName (@selector (method))) != 0) 88 abort (); 89 90 if (list[2] != NULL) 91 abort (); 92 } 93#endif 94 95 std::cout << "Testing sel_getName () ...\n"; 96 { 97 if (std::strcmp (sel_getName (@selector (variable)), "variable") != 0) 98 abort (); 99 100 if (std::strcmp (sel_getName (NULL), "<null selector>") != 0) 101 abort (); 102 } 103 104#ifdef __GNU_LIBOBJC__ 105 std::cout << "Testing sel_getTypeEncoding () ...\n"; 106 { 107 /* Get a selector from a real class, so it has interesting 108 types. */ 109 Method method = class_getInstanceMethod (objc_getClass ("MySubClass"), 110 @selector (variable)); 111 112 if (std::strcmp (sel_getTypeEncoding (method_getName (method)), 113 method_getTypeEncoding (method)) != 0) 114 abort (); 115 116 if (sel_getTypeEncoding (NULL) != NULL) 117 abort (); 118 } 119#endif 120 121#ifdef __GNU_LIBOBJC__ 122 std::cout << "Testing sel_getTypedSelector () ...\n"; 123 { 124 /* First try with a selector where we know that a typed one has 125 been registered. */ 126 SEL selector = sel_getTypedSelector ("variable"); 127 128 if (selector == NULL) 129 abort (); 130 131 if (sel_getTypeEncoding (selector) == NULL) 132 abort (); 133 134 /* Now try a selector which was never registered. */ 135 selector = sel_getTypedSelector ("not_registered"); 136 137 if (selector != NULL) 138 abort (); 139 140 /* Now try registering a selector with no types. The following 141 line is just a way to have an unused '@selector()' expression 142 without the compiler complaining. */ 143 if (@selector (registered_with_no_types) == NULL) 144 abort (); 145 146 /* Try getting it. Nothing should be returned because it is 147 untyped. */ 148 selector = sel_getTypedSelector ("registered_with_no_types"); 149 150 if (selector != NULL) 151 abort (); 152 153 /* Now try a selector with multiple, conflicting types. NULL 154 should be returned. */ 155 selector = sel_getTypedSelector ("conflictingSelectorMethod"); 156 157 if (selector != NULL) 158 abort (); 159 } 160#endif 161 162 std::cout << "Testing sel_getUid () ...\n"; 163 { 164 if (std::strcmp (sel_getName (sel_getUid ("myMethod")), "myMethod") != 0) 165 abort (); 166 167 if (sel_getUid (NULL) != NULL) 168 abort (); 169 } 170 171 std::cout << "Testing sel_isEqual () ...\n"; 172 { 173 if (! sel_isEqual (@selector (setVariable:), @selector (setVariable:))) 174 abort (); 175 } 176 177 std::cout << "Testing sel_registerName () ...\n"; 178 { 179 if (std::strcmp (sel_getName (sel_registerName ("myMethod")), "myMethod") != 0) 180 abort (); 181 182 if (sel_registerName (NULL) != NULL) 183 abort (); 184 } 185 186#ifdef __GNU_LIBOBJC__ 187 std::cout << "Testing set_registerTypedName () ...\n"; 188 { 189 const char *types = method_getTypeEncoding (class_getInstanceMethod 190 (objc_getClass ("MySubClass"), 191 @selector (variable))); 192 SEL selector = sel_registerTypedName ("aMethod", types); 193 194 if (std::strcmp (sel_getName (selector), "aMethod") != 0) 195 abort (); 196 197 if (std::strcmp (sel_getTypeEncoding (selector), types) != 0) 198 abort (); 199 200 if (sel_registerTypedName (NULL, NULL) != NULL) 201 abort (); 202 203 if (sel_registerTypedName (NULL, types) != NULL) 204 abort (); 205 } 206#endif 207 208 return (0); 209} 210