getMethod.m 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. TEST_BUILD_OUTPUT
  3. .*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
  4. .*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
  5. .*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
  6. .*getMethod.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\](\n.* note: expanded from macro 'testassert')?
  7. END
  8. */
  9. #include "test.h"
  10. #include "testroot.i"
  11. #include <objc/runtime.h>
  12. #include <objc/message.h>
  13. static int state = 0;
  14. @interface Super : TestRoot @end
  15. @implementation Super
  16. +(void)classMethod { state = 1; }
  17. -(void)instanceMethod { state = 4; }
  18. +(void)classMethodSuperOnly { state = 3; }
  19. -(void)instanceMethodSuperOnly { state = 6; }
  20. @end
  21. @interface Sub : Super @end
  22. @implementation Sub
  23. +(void)classMethod { state = 2; }
  24. -(void)instanceMethod { state = 5; }
  25. @end
  26. typedef void (*imp_t)(id, SEL);
  27. int main()
  28. {
  29. Class Super_cls, Sub_cls;
  30. Class buf[10];
  31. Method m;
  32. SEL sel;
  33. IMP imp;
  34. id bufobj = (__bridge_transfer id)(void*)buf;
  35. // don't use [Super class] to check laziness handing
  36. Super_cls = objc_getClass("Super");
  37. Sub_cls = objc_getClass("Sub");
  38. sel = sel_registerName("classMethod");
  39. m = class_getClassMethod(Super_cls, sel);
  40. testassert(m);
  41. testassert(sel == method_getName(m));
  42. imp = method_getImplementation(m);
  43. testassert(imp == class_getMethodImplementation(object_getClass(Super_cls), sel));
  44. testassert(imp == object_getMethodImplementation(Super_cls, sel));
  45. state = 0;
  46. (*(imp_t)imp)(Super_cls, sel);
  47. testassert(state == 1);
  48. sel = sel_registerName("classMethod");
  49. m = class_getClassMethod(Sub_cls, sel);
  50. testassert(m);
  51. testassert(sel == method_getName(m));
  52. imp = method_getImplementation(m);
  53. testassert(imp == class_getMethodImplementation(object_getClass(Sub_cls), sel));
  54. testassert(imp == object_getMethodImplementation(Sub_cls, sel));
  55. state = 0;
  56. (*(imp_t)imp)(Sub_cls, sel);
  57. testassert(state == 2);
  58. sel = sel_registerName("classMethodSuperOnly");
  59. m = class_getClassMethod(Sub_cls, sel);
  60. testassert(m);
  61. testassert(sel == method_getName(m));
  62. imp = method_getImplementation(m);
  63. testassert(imp == class_getMethodImplementation(object_getClass(Sub_cls), sel));
  64. testassert(imp == object_getMethodImplementation(Sub_cls, sel));
  65. state = 0;
  66. (*(imp_t)imp)(Sub_cls, sel);
  67. testassert(state == 3);
  68. sel = sel_registerName("instanceMethod");
  69. m = class_getInstanceMethod(Super_cls, sel);
  70. testassert(m);
  71. testassert(sel == method_getName(m));
  72. imp = method_getImplementation(m);
  73. testassert(imp == class_getMethodImplementation(Super_cls, sel));
  74. buf[0] = Super_cls;
  75. testassert(imp == object_getMethodImplementation(bufobj, sel));
  76. state = 0;
  77. (*(imp_t)imp)(bufobj, sel);
  78. testassert(state == 4);
  79. sel = sel_registerName("instanceMethod");
  80. m = class_getInstanceMethod(Sub_cls, sel);
  81. testassert(m);
  82. testassert(sel == method_getName(m));
  83. imp = method_getImplementation(m);
  84. testassert(imp == class_getMethodImplementation(Sub_cls, sel));
  85. buf[0] = Sub_cls;
  86. testassert(imp == object_getMethodImplementation(bufobj, sel));
  87. state = 0;
  88. (*(imp_t)imp)(bufobj, sel);
  89. testassert(state == 5);
  90. sel = sel_registerName("instanceMethodSuperOnly");
  91. m = class_getInstanceMethod(Sub_cls, sel);
  92. testassert(m);
  93. testassert(sel == method_getName(m));
  94. imp = method_getImplementation(m);
  95. testassert(imp == class_getMethodImplementation(Sub_cls, sel));
  96. buf[0] = Sub_cls;
  97. testassert(imp == object_getMethodImplementation(bufobj, sel));
  98. state = 0;
  99. (*(imp_t)imp)(bufobj, sel);
  100. testassert(state == 6);
  101. // check class_getClassMethod(cls) == class_getInstanceMethod(cls->isa)
  102. sel = sel_registerName("classMethod");
  103. testassert(class_getClassMethod(Sub_cls, sel) == class_getInstanceMethod(object_getClass(Sub_cls), sel));
  104. sel = sel_registerName("nonexistent");
  105. testassert(! class_getInstanceMethod(Sub_cls, sel));
  106. testassert(! class_getClassMethod(Sub_cls, sel));
  107. testassert(class_getMethodImplementation(Sub_cls, sel) == (IMP)&_objc_msgForward);
  108. buf[0] = Sub_cls;
  109. testassert(object_getMethodImplementation(bufobj, sel) == (IMP)&_objc_msgForward);
  110. #if !__arm64__
  111. testassert(class_getMethodImplementation_stret(Sub_cls, sel) == (IMP)&_objc_msgForward_stret);
  112. testassert(object_getMethodImplementation_stret(bufobj, sel) == (IMP)&_objc_msgForward_stret);
  113. #endif
  114. testassert(! class_getInstanceMethod(NULL, NULL));
  115. testassert(! class_getInstanceMethod(NULL, sel));
  116. testassert(! class_getInstanceMethod(Sub_cls, NULL));
  117. testassert(! class_getClassMethod(NULL, NULL));
  118. testassert(! class_getClassMethod(NULL, sel));
  119. testassert(! class_getClassMethod(Sub_cls, NULL));
  120. succeed(__FILE__);
  121. }