diff mbox

ObjC/ObjC++: Fix PR objc/47075 ("Missed deprecation warnings for @property when using getter/setter directly")

Message ID A3B0D9EF-7BFE-4314-9A74-C07A801F4D43@meta-innovation.com
State New
Headers show

Commit Message

Nicola Pero Dec. 28, 2010, 4 p.m. UTC
This patch fixes the deprecation warnings with the new @property syntax.

The deprecation warnings were generated directly from the @property  
when the property was used with a dot-syntax
notation.  That is nice and simple but unfortunately it doesn't cover  
the case where the property getter or setter are simply
called directly as normal Objective-C methods - so in that case the  
deprecation warnings were completely missing. :-(

This patch changes the way the deprecation warnings for a @property  
are generated to fix things.  In the new scheme, the setter
and getter methods corresponding to the @property are themselves  
marked as deprecated, and the deprecation warnings are
not generated directly from the @property, so that you get the  
deprecation warnings when you use the methods directly, as well
as when you use them through the dot-syntax.  There is a complication  
though, which is that our implementation always generates
a getter call for Objective-C 2.0 dotsyntax expressions, even if it  
doesn't use it later.  So, we need to prevent the deprecation
warning for a getter for a dotsyntax expression from being generated  
immediately, and postpone it instead to the gimplify phase,
when we know for sure that the getter is being used (or not).

Anyway, this patch does it all; 4 new testcases are included and  
everything works with the patch.

Ok to commit to trunk ?

Thanks
diff mbox

Patch

Index: c-family/c-objc.h
===================================================================
--- c-family/c-objc.h   (revision 168293)
+++ c-family/c-objc.h   (working copy)
@@ -54,7 +54,7 @@  extern void objc_declare_alias (tree, tr
  extern void objc_declare_class (tree);
  extern void objc_declare_protocols (tree, tree);
  extern tree objc_build_message_expr (tree);
-extern tree objc_finish_message_expr (tree, tree, tree);
+extern tree objc_finish_message_expr (tree, tree, tree, tree*);
  extern tree objc_build_selector_expr (location_t, tree);
  extern tree objc_build_protocol_expr (tree);
  extern tree objc_build_encode_expr (tree);
Index: c-family/ChangeLog
===================================================================
--- c-family/ChangeLog  (revision 168293)
+++ c-family/ChangeLog  (working copy)
@@ -1,3 +1,9 @@ 
+2010-12-28  Nicola Pero  <nicola@nicola.brainstorm.co.uk>
+
+       PR objc/47075
+       * c-objc.h (objc_finish_message_expr): Added argument to
+       prototype.
+
  2010-12-22  Nathan Froyd  <froydnj@codesourcery.com>

         * c-common.c (handle_nonnull_attribute,  
handle_sentinel_attribute):
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c     (revision 168294)
+++ objc/objc-act.c     (working copy)
@@ -1468,7 +1468,7 @@  maybe_make_artificial_property_decl (tre
        DECL_SOURCE_LOCATION (property_decl) = input_location;
        TREE_DEPRECATED (property_decl) = 0;
        DECL_ARTIFICIAL (property_decl) = 1;
-
+
        /* Add property-specific information.  Note that one of
          PROPERTY_GETTER_NAME or PROPERTY_SETTER_NAME may refer to a
          non-existing method; this will generate an error when the
@@ -1743,6 +1743,7 @@  objc_maybe_build_component_ref (tree obj
      {
        tree expression;
        tree getter_call;
+      tree deprecated_method_prototype = NULL_TREE;

        /* We have an additional nasty problem here; if this
          PROPERTY_REF needs to become a 'getter', then the conversion
@@ -1770,14 +1771,16 @@  objc_maybe_build_component_ref (tree obj
        if (PROPERTY_HAS_NO_GETTER (x))
         getter_call = NULL_TREE;
        else
-       getter_call = objc_finish_message_expr (object,
-                                               PROPERTY_GETTER_NAME  
(x),
-                                               NULL_TREE);
-
-      if (TREE_DEPRECATED (x))
-       warn_deprecated_use (x, NULL_TREE);
+       getter_call = objc_finish_message_expr
+         (object, PROPERTY_GETTER_NAME (x), NULL_TREE,
+          /* Disable the immediate deprecation warning if the getter
+             is deprecated, but record the fact that the getter is
+             deprecated by setting PROPERTY_REF_DEPRECATED_GETTER to
+             the method prototype.  */
+          &deprecated_method_prototype);

-      expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x,  
getter_call);
+      expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x,  
getter_call,
+                          deprecated_method_prototype);
        SET_EXPR_LOCATION (expression, input_location);
        TREE_SIDE_EFFECTS (expression) = 1;

@@ -1839,17 +1842,17 @@  objc_build_class_component_ref (tree cla
      {
        tree expression;
        tree getter_call;
+      tree deprecated_method_prototype = NULL_TREE;

        if (PROPERTY_HAS_NO_GETTER (x))
         getter_call = NULL_TREE;
        else
-       getter_call = objc_finish_message_expr (object,
-                                               PROPERTY_GETTER_NAME  
(x),
-                                               NULL_TREE);
-      if (TREE_DEPRECATED (x))
-       warn_deprecated_use (x, NULL_TREE);
+       getter_call = objc_finish_message_expr
+         (object, PROPERTY_GETTER_NAME (x), NULL_TREE,
+          &deprecated_method_prototype);

-      expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x,  
getter_call);
+      expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x,  
getter_call,
+                          deprecated_method_prototype);
        SET_EXPR_LOCATION (expression, input_location);
        TREE_SIDE_EFFECTS (expression) = 1;

@@ -1906,7 +1909,7 @@  objc_build_setter_call (tree lhs, tree r
        /* TODO: Decay arguments in C.  */
        setter = objc_finish_message_expr (object_expr,
                                          PROPERTY_SETTER_NAME  
(property_decl),
-                                        setter_argument);
+                                        setter_argument, NULL);
        return setter;
      }
  @@ -8023,7 +8026,7 @@ objc_build_message_expr (tree mess)
                          method_params);
  #endif

-  return objc_finish_message_expr (receiver, sel_name, method_params);
+  return objc_finish_message_expr (receiver, sel_name, method_params,  
NULL);
  }

  /* Look up method SEL_NAME that would be suitable for receiver
@@ -8052,10 +8055,20 @@  lookup_method_in_hash_lists (tree sel_na
  /* The 'objc_finish_message_expr' routine is called from within
     'objc_build_message_expr' for non-template functions.  In the  
case of
     C++ template functions, it is called from 'build_expr_from_tree'
-   (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.   
*/
+   (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.

+   If the DEPRECATED_METHOD_PROTOTYPE argument is NULL, then we warn
+   if the method being used is deprecated.  If it is not NULL, instead
+   of deprecating, we set *DEPRECATED_METHOD_PROTOTYPE to the method
+   prototype that was used and is deprecated.  This is useful for
+   getter calls that are always generated when compiling dot-syntax
+   expressions, even if they may not be used.  In that case, we don't
+   want the warning immediately; we produce it (if needed) at gimplify
+   stage when we are sure that the deprecated getter is being
+   used.  */
  tree
-objc_finish_message_expr (tree receiver, tree sel_name, tree  
method_params)
+objc_finish_message_expr (tree receiver, tree sel_name, tree  
method_params,
+                         tree *deprecated_method_prototype)
  {
    tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
    tree selector, retval, class_tree;

@@ -8272,7 +8285,12 @@  objc_finish_message_expr (tree receiver,
          is often used precisely to turn off warnings associated with
          the object being of a particular class.  */
        if (TREE_DEPRECATED (method_prototype)  &&  rtype != NULL_TREE)
-       warn_deprecated_use (method_prototype, NULL_TREE);
+       {
+         if (deprecated_method_prototype)
+           *deprecated_method_prototype = method_prototype;
+         else
+           warn_deprecated_use (method_prototype, NULL_TREE);
+       }
      }


@@ -10733,6 +10751,7 @@  finish_class (tree klass)
                   objc_add_method (objc_interface_context,  
getter_decl, false, true);
                 else
                   objc_add_method (objc_interface_context,  
getter_decl, false, false);
+               TREE_DEPRECATED (getter_decl) = TREE_DEPRECATED (x);
                 METHOD_PROPERTY_CONTEXT (getter_decl) = x;
               }

@@ -10776,6 +10795,7 @@  finish_class (tree klass)
                       objc_add_method (objc_interface_context,  
setter_decl, false, true);
                     else
                       objc_add_method (objc_interface_context,  
setter_decl, false, false);
+                   TREE_DEPRECATED (setter_decl) = TREE_DEPRECATED (x);
                     METHOD_PROPERTY_CONTEXT (setter_decl) = x;
                   }
               }
@@ -13100,6 +13120,14 @@  objc_gimplify_property_ref (tree *expr_p
        return;
      }

+  if (PROPERTY_REF_DEPRECATED_GETTER (*expr_p))
+    {
+      /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype
+        that is deprecated.  */
+      warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p),
+                          NULL_TREE);
+    }
+
    call_exp = getter;
  #ifdef OBJCPLUS
    /* In C++, a getter which returns an aggregate value results in a
@@ -13493,7 +13521,7 @@  objc_finish_foreach_loop (location_t loc
                                  tree_cons   /* __objc_foreach_items   
*/
                                  (NULL_TREE, objc_foreach_items_decl,
                                   tree_cons  /* 16 */
-                                 (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))));
+                                 (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))), NULL);
  #else
    /* In C, we need to decay the __objc_foreach_items array that we  
are passing.  */
    {
@@ -13506,7 +13534,7 @@  objc_finish_foreach_loop (location_t loc
                                    tree_cons   /*  
__objc_foreach_items  */
                                    (NULL_TREE,  
default_function_array_conversion (location, array).value,
                                     tree_cons  /* 16 */
-                                   (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))));
+                                   (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))), NULL);
    }
  #endif
    t = build2 (MODIFY_EXPR, void_type_node,  
objc_foreach_batchsize_decl,
@@ -13667,7 +13695,7 @@  objc_finish_foreach_loop (location_t loc
                                  tree_cons   /* __objc_foreach_items   
*/
                                  (NULL_TREE, objc_foreach_items_decl,
                                   tree_cons  /* 16 */
-                                 (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))));
+                                 (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))), NULL);
  #else
    /* In C, we need to decay the __objc_foreach_items array that we  
are passing.  */
    {
@@ -13680,7 +13708,7 @@  objc_finish_foreach_loop (location_t loc
                                    tree_cons   /*  
__objc_foreach_items  */
                                    (NULL_TREE,  
default_function_array_conversion (location, array).value,
                                     tree_cons  /* 16 */
-                                   (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))));
+                                   (NULL_TREE, build_int_cst  
(NULL_TREE, 16), NULL_TREE))), NULL);
    }
  #endif
    t = build2 (MODIFY_EXPR, void_type_node,  
objc_foreach_batchsize_decl,
Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog      (revision 168294)
+++ objc/ChangeLog      (working copy)
@@ -1,5 +1,27 @@ 
  2010-12-28  Nicola Pero  <nicola.pero@meta-innovation.com>

+       PR objc/47075
+       * objc-act.h (PROPERTY_REF_DEPRECATED_GETTER): New.
+       * objc-tree.def (PROPERTY_REF): Increased the number of operands
+       from 3 to 4.
+       * objc-act.c (objc_finish_message_expr): Added optional argument
+       allowing to return the deprecated method prototype for  
deprecated
+       methods, instead of immediately emitting the deprecation  
warning.
+       (objc_maybe_build_component_ref): Do not warn for a deprecated
+       property.  When building the getter call, get the deprecated
+       method prototype from objc_finish_message_expr() and put it into
+       the PROPERTY_REF.
+       (objc_build_class_component_ref): Same change.
+       (finish_class): Mark the getter and setter as deprecated if they
+       are generated from a deprecated property.
+       (objc_gimplify_property_ref): If the getter is deprecated,  
emit a
+       deprecation warning.
+       (objc_build_setter_call, objc_build_message_expr,
+       objc_finish_foreach_loop): Updated call to
+       objc_finish_message_expr.
+
+2010-12-28  Nicola Pero  <nicola.pero@meta-innovation.com>
+
         * objc-act.c (objc_start_category_interface): Produce an  
error if
         a class extension is found after the class @implementation.

Index: objc/objc-tree.def
===================================================================
--- objc/objc-tree.def  (revision 168293)
+++ objc/objc-tree.def  (working copy)
@@ -46,7 +46,10 @@  DEFTREECODE (CLASS_REFERENCE_EXPR, "clas
     representing the expression), and Operand 1 is the property (the
     PROPERTY_DECL).  Operand 2 is the 'getter' call, ready to be used;
     we pregenerate it because it is hard to generate it properly later
-   on.  A PROPERTY_REF tree needs to be transformed into 'setter' and
+   on.  Operand 3 records whether using the 'getter' call should
+   generate a deprecation warning or not.
+
+   A PROPERTY_REF tree needs to be transformed into 'setter' and
     'getter' calls at some point; at the moment this happens in two
     places:

@@ -58,13 +61,14 @@  DEFTREECODE (CLASS_REFERENCE_EXPR, "clas
        gimplification; at that point, we convert each PROPERTY_REF into
        a 'getter' call during ObjC/ObjC++ gimplify.  At that point, it
        is quite hard to build a 'getter' call, but we have already  
built
-      it and we just need to swap Operand 2 in.
+      it and we just need to swap Operand 2 in, and emit the  
deprecation
+      warnings from Operand 3 if needed.

    Please note that when the Objective-C 2.0 "dot-syntax"  
'object.component'
    is encountered, where 'component' is not a property but there are  
valid
    setter/getter methods for it, an artificial PROPERTY_DECL is  
generated
    and used in the PROPERTY_REF.  */
-DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 3)
+DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 4)

  /*
  Local variables:
Index: objc/objc-act.h
===================================================================
--- objc/objc-act.h     (revision 168293)
+++ objc/objc-act.h     (working copy)
@@ -144,6 +144,11 @@  typedef enum objc_property_assign_semant
     use it.  */
  #define PROPERTY_REF_GETTER_CALL(NODE) TREE_OPERAND  
(PROPERTY_REF_CHECK (NODE), 2)

+/* PROPERTY_REF_DEPRECATED_GETTER is normally set to NULL_TREE.  If
+   the property getter is deprecated, it is set to the method
+   prototype for it, which is used to generate the deprecation warning
+   when the getter is used.  */
+#define PROPERTY_REF_DEPRECATED_GETTER(NODE) TREE_OPERAND  
(PROPERTY_REF_CHECK (NODE), 3)

  /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
     CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog (revision 168294)
+++ testsuite/ChangeLog (working copy)
@@ -1,5 +1,15 @@ 
  2010-12-28  Nicola Pero  <nicola.pero@meta-innovation.com>

+       PR objc/47075
+       * objc.dg/property/property-deprecated-1.m: Updated.
+       * objc.dg/property/property-deprecated-2.m: New.
+       * objc.dg/property/dotsyntax-deprecated-1.m: New.
+       * obj-c++.dg/property/property-deprecated-1.mm: Updated.
+       * obj-c++.dg/property/property-deprecated-2.mm: New.
+       * obj-c++.dg/property/dotsyntax-deprecated-1.mm: New.
+
+2010-12-28  Nicola Pero  <nicola.pero@meta-innovation.com>
+
         * objc.dg/class-extension-4.m: New.
         * obj-c++.dg/class-extension-4.mm: New.

Index: testsuite/objc.dg/property/dotsyntax-deprecated-1.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-deprecated-1.m (revision 0)
+++ testsuite/objc.dg/property/dotsyntax-deprecated-1.m (revision 0)
@@ -0,0 +1,41 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>,  
October 2010.  */
+/* { dg-do compile } */
+
+/* Test the 'dot syntax' with deprecated methods.  */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+}
++ (int) classCount __attribute__ ((deprecated));
++ (void) setClassCount: (int)value __attribute__ ((deprecated));
+
+- (int) count __attribute__ ((deprecated));
+- (void) setCount: (int)value __attribute__ ((deprecated));
+
+- (int) classCount2;
+- (void) setClassCount2: (int)value;
+
+- (int) count2;
+- (void) setCount2: (int)value;
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+
+  if (object.count > 0)  /* { dg-warning "is deprecated" } */
+    object.count = 20;  /* { dg-warning "is deprecated" } */
+
+  if (MyClass.classCount < -7)   /* { dg-warning "is deprecated" } */
+    MyClass.classCount = 11;  /* { dg-warning "is deprecated" } */
+
+  if (object.classCount2 > 0)
+    object.classCount2 = 19;
+
+  if (object.count2 < -7)
+    object.count2 = 74;
+}
Index: testsuite/objc.dg/property/at-property-deprecated-1.m
===================================================================
--- testsuite/objc.dg/property/at-property-deprecated-1.m        
(revision 168293)
+++ testsuite/objc.dg/property/at-property-deprecated-1.m        
(working copy)
@@ -29,8 +29,8 @@  int main (void)
  {
    MyRootClass *object = [[MyRootClass alloc] init];

-  object.a = 40;      /* { dg-warning ".a. is deprecated .declared at  
" } */
-  if (object.a != 40) /* { dg-warning ".a. is deprecated .declared at  
" } */
+  object.a = 40;      /* { dg-warning "is deprecated" } */
+  if (object.a != 40) /* { dg-warning "is deprecated" } */
      abort ();

    return 0;
Index: testsuite/objc.dg/property/at-property-deprecated-2.m
===================================================================
--- testsuite/objc.dg/property/at-property-deprecated-2.m        
(revision 0)
+++ testsuite/objc.dg/property/at-property-deprecated-2.m        
(revision 0)
@@ -0,0 +1,25 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>,  
October 2010.  */
+/* { dg-do compile } */
+
+/* Test that deprecation warnings are produced when a setter/getter of
+   a @property is used directly.  */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+  int variable;
+}
+@property (assign, nonatomic) int property __attribute__  
((deprecated));
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+  if ([object property] > 0)  /* { dg-warning "is deprecated" } */
+    {
+      [object setProperty: 43]; /* { dg-warning "is deprecated" } */
+    }
+}
Index: testsuite/obj-c++.dg/property/dotsyntax-deprecated-1.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-deprecated-1.mm      
(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-deprecated-1.mm      
(revision 0)
@@ -0,0 +1,41 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>,  
October 2010.  */
+/* { dg-do compile } */
+
+/* Test the 'dot syntax' with deprecated methods.  */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+}
++ (int) classCount __attribute__ ((deprecated));
++ (void) setClassCount: (int)value __attribute__ ((deprecated));
+
+- (int) count __attribute__ ((deprecated));
+- (void) setCount: (int)value __attribute__ ((deprecated));
+
+- (int) classCount2;
+- (void) setClassCount2: (int)value;
+
+- (int) count2;
+- (void) setCount2: (int)value;
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+
+  if (object.count > 0)  /* { dg-warning "is deprecated" } */
+    object.count = 20;  /* { dg-warning "is deprecated" } */
+
+  if (MyClass.classCount < -7)   /* { dg-warning "is deprecated" } */
+    MyClass.classCount = 11;  /* { dg-warning "is deprecated" } */
+
+  if (object.classCount2 > 0)
+    object.classCount2 = 19;
+
+  if (object.count2 < -7)
+    object.count2 = 74;
+}
Index: testsuite/obj-c++.dg/property/at-property-deprecated-2.mm
===================================================================
--- testsuite/obj-c++.dg/property/at-property-deprecated-2.mm    
(revision 0)
+++ testsuite/obj-c++.dg/property/at-property-deprecated-2.mm    
(revision 0)
@@ -0,0 +1,25 @@ 
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>,  
October 2010.  */
+/* { dg-do compile } */
+
+/* Test that deprecation warnings are produced when a setter/getter of
+   a @property is used directly.  */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+  int variable;
+}
+@property (assign, nonatomic) int property __attribute__  
((deprecated));
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+  if ([object property] > 0)  /* { dg-warning "is deprecated" } */
+    {
+      [object setProperty: 43]; /* { dg-warning "is deprecated" } */
+    }
+}
Index: testsuite/obj-c++.dg/property/at-property-deprecated-1.mm
===================================================================
--- testsuite/obj-c++.dg/property/at-property-deprecated-1.mm    
(revision 168293)
+++ testsuite/obj-c++.dg/property/at-property-deprecated-1.mm    
(working copy)
@@ -29,8 +29,8 @@  int main (void)
  {
    MyRootClass *object = [[MyRootClass alloc] init];

-  object.a = 40;      /* { dg-warning ".a. is deprecated .declared at  
" } */
-  if (object.a != 40) /* { dg-warning ".a. is deprecated .declared at  
" } */
+  object.a = 40;      /* { dg-warning "is deprecated" } */
+  if (object.a != 40) /* { dg-warning "is deprecated" } */
      abort ();

    return (0);
Index: objcp/ChangeLog
===================================================================
--- objcp/ChangeLog     (revision 168293)
+++ objcp/ChangeLog     (working copy)
@@ -1,3 +1,8 @@ 
+2010-12-28  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objcp-lang.c (objcp_tsubst_copy_and_build): Update call to
+       objc_finish_message_expr.
+
  2010-12-26  Nicola Pero  <nicola.pero@meta-innovation.com>

         * config-lang.in (gtfiles): Added c-family/c-cppbuiltin.c.
Index: objcp/objcp-lang.c
===================================================================
--- objcp/objcp-lang.c  (revision 168293)
+++ objcp/objcp-lang.c  (working copy)
@@ -76,7 +76,7 @@  objcp_tsubst_copy_and_build (tree t, tre
        return objc_finish_message_expr
         (RECURSE (TREE_OPERAND (t, 0)),
          TREE_OPERAND (t, 1),  /* No need to expand the selector.  */
-        RECURSE (TREE_OPERAND (t, 2)));
+        RECURSE (TREE_OPERAND (t, 2)), NULL);

      case CLASS_REFERENCE_EXPR:
        return objc_get_class_reference