]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libobjc/selector.c
Fix boostrap failure in tree-ssa-loop-ch.cc
[thirdparty/gcc.git] / libobjc / selector.c
index 699e52ee966ea48fbb0a0237de0c068a8295bf4a..57be2141d85173e0ccbdf7e602abb262c9b767b0 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU Objective C Runtime selector related functions
-   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1993-2023 Free Software Foundation, Inc.
    Contributed by Kresten Krab Thorup
 
 This file is part of GCC.
@@ -31,6 +31,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "objc-private/runtime.h"
 #include "objc-private/sarray.h"
 #include "objc-private/selector.h"
+#include <stdlib.h>                    /* For malloc.  */
 
 /* Initial selector hash table size. Value doesn't matter much.  */
 #define SELECTOR_HASH_SIZE 128
@@ -225,7 +226,7 @@ sel_isEqual (SEL s1, SEL s2)
 
 /* Return YES iff t1 and t2 have same method types.  Ignore the
    argframe layout.  */
-BOOL
+static BOOL
 sel_types_match (const char *t1, const char *t2)
 {
   if (! t1 || ! t2)
@@ -252,7 +253,7 @@ sel_types_match (const char *t1, const char *t2)
 
 /* Return selector representing name.  */
 SEL
-sel_get_typed_uid (const char *name, const char *types)
+sel_get_any_uid (const char *name)
 {
   struct objc_list *l;
   sidx i;
@@ -260,91 +261,139 @@ sel_get_typed_uid (const char *name, const char *types)
   objc_mutex_lock (__objc_runtime_mutex);
 
   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
-  if (i == 0)
+  if (soffset_decode (i) == 0)
     {
       objc_mutex_unlock (__objc_runtime_mutex);
       return 0;
     }
 
-  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
-       l; l = l->tail)
-    {
-      SEL s = (SEL) l->head;
-      if (types == 0 || s->sel_types == 0)
-       {
-         if (s->sel_types == types)
-           {
-             objc_mutex_unlock (__objc_runtime_mutex);
-             return s;
-           }
-       }
-      else if (sel_types_match (s->sel_types, types))
-       {
-         objc_mutex_unlock (__objc_runtime_mutex);
-         return s;
-       }
-    }
-
+  l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
   objc_mutex_unlock (__objc_runtime_mutex);
-  return 0;
+
+  if (l == 0)
+    return 0;
+
+  return (SEL) l->head;
 }
 
-/* Return selector representing name; prefer a selector with non-NULL
-   type.  */
 SEL
-sel_get_any_typed_uid (const char *name)
+sel_getTypedSelector (const char *name)
 {
-  struct objc_list *l;
   sidx i;
-  SEL s = NULL;
 
+  if (name == NULL)
+    return NULL;
+  
   objc_mutex_lock (__objc_runtime_mutex);
-
+  
+  /* Look for a typed selector.  */
   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
-  if (i == 0)
+  if (i != 0)
     {
-      objc_mutex_unlock (__objc_runtime_mutex);
-      return 0;
-    }
+      struct objc_list *l;
+      SEL returnValue = NULL;
 
-  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
-       l; l = l->tail)
-    {
-      s = (SEL) l->head;
-      if (s->sel_types)
+      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+          l; l = l->tail)
+       {
+         SEL s = (SEL) l->head;
+         if (s->sel_types)
+           {
+             if (returnValue == NULL)
+               {
+                 /* First typed selector that we find.  Keep it in
+                    returnValue, but keep checking as we want to
+                    detect conflicts.  */
+                 returnValue = s;
+               }
+             else
+               {
+                 /* We had already found a typed selectors, so we
+                    have multiple ones.  Double-check that they have
+                    different types, just in case for some reason we
+                    got duplicates with the same types.  If so, it's
+                    OK, we'll ignore the duplicate.  */
+                 if (returnValue->sel_types == s->sel_types)
+                   continue;
+                 else if (sel_types_match (returnValue->sel_types, s->sel_types))
+                   continue;
+                 else
+                   {
+                     /* The types of the two selectors are different;
+                        it's a conflict.  Too bad.  Return NULL.  */
+                     objc_mutex_unlock (__objc_runtime_mutex);
+                     return NULL;
+                   }
+               }
+           }
+       }
+
+      if (returnValue != NULL)
        {
          objc_mutex_unlock (__objc_runtime_mutex);
-         return s;
+         return returnValue;
        }
     }
 
+  /* No typed selector found.  Return NULL.  */
   objc_mutex_unlock (__objc_runtime_mutex);
-  return s;
+  return 0;
 }
 
-/* Return selector representing name.  */
-SEL
-sel_get_any_uid (const char *name)
+SEL *
+sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
 {
-  struct objc_list *l;
+  unsigned int count = 0;
+  SEL *returnValue = NULL;
   sidx i;
+  
+  if (name == NULL)
+    {
+      if (numberOfReturnedSelectors)
+       *numberOfReturnedSelectors = 0;
+      return NULL;
+    }
 
   objc_mutex_lock (__objc_runtime_mutex);
 
+  /* Count how many selectors we have.  */
   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
-  if (soffset_decode (i) == 0)
+  if (i != 0)
     {
-      objc_mutex_unlock (__objc_runtime_mutex);
-      return 0;
-    }
+      struct objc_list *selector_list = NULL;
+      selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
 
-  l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
-  objc_mutex_unlock (__objc_runtime_mutex);
+      /* Count how many selectors we have.  */
+      {
+       struct objc_list *l;
+       for (l = selector_list; l; l = l->tail)
+         count++;
+      }
 
-  if (l == 0)
-    return 0;
+      if (count != 0)
+       {
+         /* Allocate enough memory to hold them.  */
+         returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
+         
+         /* Copy the selectors.  */
+         {
+           unsigned int j;
+           for (j = 0; j < count; j++)
+             {
+               returnValue[j] = (SEL)(selector_list->head);
+               selector_list = selector_list->tail;
+             }
+           returnValue[j] = NULL;
+         }
+       }
+    }      
 
-  return (SEL) l->head;
+  objc_mutex_unlock (__objc_runtime_mutex);
+  
+  if (numberOfReturnedSelectors)
+    *numberOfReturnedSelectors = count;
+  
+  return returnValue;
 }
 
 /* Get the name of a selector.  If the selector is unknown, the empty
@@ -366,15 +415,6 @@ const char *sel_getName (SEL selector)
   return ret;
 }
 
-/* Traditional GNU Objective-C Runtime API.  */
-const char *sel_get_name (SEL selector)
-{
-  if (selector == NULL)
-    return 0;
-
-  return sel_getName (selector);
-}
-
 BOOL
 sel_is_mapped (SEL selector)
 {
@@ -382,7 +422,7 @@ sel_is_mapped (SEL selector)
   return ((idx > 0) && (idx <= __objc_selector_max_index));
 }
 
-const char *sel_getType (SEL selector)
+const char *sel_getTypeEncoding (SEL selector)
 {
   if (selector)
     return selector->sel_types;
@@ -390,12 +430,6 @@ const char *sel_getType (SEL selector)
     return 0;
 }
 
-/* Traditional GNU Objective-C Runtime API.  */
-const char *sel_get_type (SEL selector)
-{
-  return sel_getType (selector);
-}
-
 /* The uninstalled dispatch table.  */
 extern struct sarray *__objc_uninstalled_dtable;
 
@@ -451,106 +485,125 @@ __sel_register_typed_name (const char *name, const char *types,
   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (soffset_decode (i) != 0)
     {
-      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+      /* There are already selectors with that name.  Examine them to
+        see if the one we're registering already exists.  */
+      for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
           l; l = l->tail)
        {
-         SEL s = (SEL) l->head;
+         SEL s = (SEL)l->head;
          if (types == 0 || s->sel_types == 0)
            {
              if (s->sel_types == types)
                {
                  if (orig)
                    {
-                     orig->sel_id = (void *) i;
+                     orig->sel_id = (void *)i;
                      return orig;
                    }
                  else
                    return s;
                }
            }
-         else if (! strcmp (s->sel_types, types))
+         else if (sel_types_match (s->sel_types, types))
            {
              if (orig)
                {
-                 orig->sel_id = (void *) i;
+                 orig->sel_id = (void *)i;
                  return orig;
                }
              else
                return s;
            }
        }
+      /* A selector with this specific name/type combination does not
+        exist yet.  We need to register it.  */
       if (orig)
        j = orig;
       else
        j = pool_alloc_selector ();
       
-      j->sel_id = (void *) i;
-      /* Can we use the pointer or must copy types?  Don't copy if
+      j->sel_id = (void *)i;
+      /* Can we use the pointer or must we copy types ?  Don't copy if
         NULL.  */
       if ((is_const) || (types == 0))
-       j->sel_types = (const char *) types;
+       j->sel_types = types;
       else
        {
-         j->sel_types = (char *) objc_malloc (strlen (types) + 1);
-         strcpy ((char *) j->sel_types, types);
+         j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+         strcpy ((char *)j->sel_types, types);
        }
-      l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+      l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
     }
   else
     {
+      /* There are no other selectors with this name registered in the
+        runtime tables.  */
+      const char *new_name;
+
+      /* Determine i.  */
       __objc_selector_max_index += 1;
       i = soffset_encode (__objc_selector_max_index);
+
+      /* Prepare the selector.  */
       if (orig)
        j = orig;
       else
        j = pool_alloc_selector ();
       
-      j->sel_id = (void *) i;
-      /* Can we use the pointer or must copy types?  Don't copy if
+      j->sel_id = (void *)i;
+      /* Can we use the pointer or must we copy types ?  Don't copy if
         NULL.  */
-      if ((is_const) || (types == 0))
-       j->sel_types = (const char *) types;
+      if (is_const || (types == 0))
+       j->sel_types = types;
       else
        {
-         j->sel_types = (char *) objc_malloc (strlen (types) + 1);
-         strcpy ((char *) j->sel_types, types);
+         j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+         strcpy ((char *)j->sel_types, types);
        }
+
+      /* Since this is the first selector with this name, we need to
+        register the correspondence between 'i' (the sel_id) and
+        'name' (the actual string) in __objc_selector_names and
+        __objc_selector_hash.  */
+      
+      /* Can we use the pointer or must we copy name ?  Don't copy if
+        NULL.  (FIXME: Can the name really be NULL here ?)  */
+      if (is_const || (name == 0))
+       new_name = name;
+      else
+       {
+         new_name = (char *)objc_malloc (strlen (name) + 1);
+         strcpy ((char *)new_name, name);
+       }
+      
+      /* This maps the sel_id to the name.  */
+      sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
+
+      /* This maps the name to the sel_id.  */
+      objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
+
       l = 0;
     }
 
   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
-               (long) soffset_decode (i));
-  
-  {
-    int is_new = (l == 0);
-    const char *new_name;
-
-    /* Can we use the pointer or must copy name?  Don't copy if
-       NULL.  */
-    if ((is_const) || (name == 0))
-      new_name = name;
-    else
-      {
-       new_name = (char *) objc_malloc (strlen (name) + 1);
-       strcpy ((char *) new_name, name);
-      }
-    
-    l = list_cons ((void *) j, l);
-    sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
-    sarray_at_put_safe (__objc_selector_array, i, (void *) l);
-    if (is_new)
-      objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
-  }
-  
+               (long)soffset_decode (i));
+
+  /* Now add the selector to the list of selectors with that id.  */
+  l = list_cons ((void *)j, l);
+  sarray_at_put_safe (__objc_selector_array, i, (void *)l);
+
   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
   
-  return (SEL) j;
+  return (SEL)j;
 }
 
 SEL
 sel_registerName (const char *name)
 {
   SEL ret;
+
+  if (name == NULL)
+    return NULL;
     
   objc_mutex_lock (__objc_runtime_mutex);
   /* Assume that name is not constant static memory and needs to be
@@ -561,18 +614,14 @@ sel_registerName (const char *name)
   return ret;
 }
 
-/* Traditional GNU Objective-C Runtime API.  */
-SEL
-sel_register_name (const char *name)
-{
-  return sel_registerName (name);
-}
-
 SEL
 sel_registerTypedName (const char *name, const char *type)
 {
   SEL ret;
 
+  if (name == NULL)
+    return NULL;
+
   objc_mutex_lock (__objc_runtime_mutex);
   /* Assume that name and type are not constant static memory and need
      to be copied before put into a runtime structure.  is_const ==
@@ -583,22 +632,9 @@ sel_registerTypedName (const char *name, const char *type)
   return ret;
 }
 
-SEL
-sel_register_typed_name (const char *name, const char *type)
-{
-  return sel_registerTypedName (name, type);
-}
-
 /* Return the selector representing name.  */
 SEL
 sel_getUid (const char *name)
 {
   return sel_registerTypedName (name, 0);
 }
-
-/* Traditional GNU Objective-C Runtime API.  */
-SEL
-sel_get_uid (const char *name)
-{
-  return sel_getUid (name);
-}