Update copyright years in libobjc/
[gcc.git] / libobjc / ivars.c
index 827243a6c716bc0b965b0ce6c0e6e87361db2c88..f666a96ec01836d4bf1fc1a601248a476ac373b6 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU Objective C Runtime ivar related functions.
-   Copyright (C) 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010-2014 Free Software Foundation, Inc.
    Contributed by Nicola Pero
 
 This file is part of GCC.
@@ -27,14 +27,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "objc-private/module-abi-8.h" /* For runtime structures  */
 #include "objc/thr.h"
 #include "objc-private/runtime.h"      /* the kitchen sink */
-#include <string.h>                    /* For strcmp */
+#include <string.h>                    /* For strcmp.  */
+#include <stdlib.h>                    /* For malloc.  */
 
 struct objc_ivar *
 class_getInstanceVariable (Class class_, const char *name)
 {
-  if (class_ != Nil  &&  name != NULL)
+  if (class_ != Nil  &&  name != NULL  &&  ! CLS_IS_IN_CONSTRUCTION (class_))
     {
-      objc_mutex_lock (__objc_runtime_mutex);
       while (class_ != Nil)
        {
          struct objc_ivar_list *ivars = class_->ivars;
@@ -47,15 +47,11 @@ class_getInstanceVariable (Class class_, const char *name)
                  struct objc_ivar *ivar = &(ivars->ivar_list[i]);
                  
                  if (!strcmp (ivar->ivar_name, name))
-                   {
-                     objc_mutex_unlock (__objc_runtime_mutex);
-                     return ivar;
-                   }
+                   return ivar;
                }
            }
-         class_ = class_->super_class;
+         class_ = class_getSuperclass (class_);
        }
-      objc_mutex_unlock (__objc_runtime_mutex);
     }
   return NULL;
 }
@@ -85,10 +81,8 @@ object_getIndexedIvars (id object)
   if (object == nil)
     return NULL;
   else
-    {
-      return (void *)(((char *)object) 
-                     + object->class_pointer->instance_size);
-    }
+    return (void *)(((char *)object) 
+                   + object->class_pointer->instance_size);
 }
 
 struct objc_ivar *
@@ -185,22 +179,13 @@ struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfRetu
   struct objc_ivar **returnValue = NULL;
   struct objc_ivar_list* ivar_list;
 
-  if (class_ == Nil)
+  if (class_ == Nil  ||  CLS_IS_IN_CONSTRUCTION (class_))
     {
       if (numberOfReturnedIvars)
        *numberOfReturnedIvars = 0;
       return NULL;
     }
-
-  /* TODO: We do not need to lock the runtime mutex if the class has
-     been registered with the runtime, since the instance variable
-     list can not change after the class is registered.  The only case
-     where the lock may be useful if the class is still being created
-     using objc_allocateClassPair(), but has not been registered using
-     objc_registerClassPair() yet.  I'm not even sure that is
-     allowed.  */
-  objc_mutex_lock (__objc_runtime_mutex);
-
+    
   /* Count how many ivars we have.  */
   ivar_list = class_->ivars;
   count = ivar_list->ivar_count;
@@ -214,21 +199,103 @@ struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfRetu
       
       /* Copy the ivars.  */
       for (i = 0; i < count; i++)
-       {
-         returnValue[i] = &(ivar_list->ivar_list[i]);
-       }
+       returnValue[i] = &(ivar_list->ivar_list[i]);
       
       returnValue[i] = NULL;
     }
   
-  objc_mutex_unlock (__objc_runtime_mutex);
-
   if (numberOfReturnedIvars)
     *numberOfReturnedIvars = count;
 
   return returnValue;
 }
 
+BOOL
+class_addIvar (Class class_, const char * ivar_name, size_t size,
+              unsigned char log_2_of_alignment, const char *type)
+{
+  struct objc_ivar_list *ivars;
+
+  if (class_ == Nil
+      || (! CLS_IS_IN_CONSTRUCTION (class_))  
+      || ivar_name == NULL  
+      || (strcmp (ivar_name, "") == 0)
+      || size == 0
+      || type == NULL)
+    return NO;
+
+  /* Check if the class has an instance variable with that name
+     already.  */
+  ivars = class_->ivars;
+
+  if (ivars != NULL)
+    {
+      int i;
+      
+      for (i = 0; i < ivars->ivar_count; i++)
+       {
+         struct objc_ivar *ivar = &(ivars->ivar_list[i]);
+         
+         if (strcmp (ivar->ivar_name, ivar_name) == 0)
+           return NO;
+       }
+    }
+
+  /* Ok, no direct ivars.  Check superclasses.  */
+  if (class_getInstanceVariable (objc_getClass ((char *)(class_->super_class)),
+                                ivar_name))
+    return NO;
+
+  /* Good.  Create space for the new instance variable.  */
+  if (ivars)
+    {
+      int ivar_count = ivars->ivar_count + 1;
+      int new_size = sizeof (struct objc_ivar_list) 
+       + (ivar_count - 1) * sizeof (struct objc_ivar);
+      
+      ivars = (struct objc_ivar_list*) objc_realloc (ivars, new_size);
+      ivars->ivar_count = ivar_count;
+      class_->ivars = ivars;
+    }
+  else
+    {
+      int new_size = sizeof (struct objc_ivar_list);
+      
+      ivars = (struct objc_ivar_list*) objc_malloc (new_size);
+      ivars->ivar_count = 1;
+      class_->ivars = ivars;
+    }
+    
+  /* Now ivars is set to a list of instance variables of the right
+     size. */
+  {
+    struct objc_ivar *ivar = &(ivars->ivar_list[ivars->ivar_count - 1]);
+    unsigned int alignment = 1 << log_2_of_alignment;
+    int misalignment;
+    
+    ivar->ivar_name = objc_malloc (strlen (ivar_name) + 1);
+    strcpy ((char *)ivar->ivar_name, ivar_name);
+
+    ivar->ivar_type = objc_malloc (strlen (type) + 1);
+    strcpy ((char *)ivar->ivar_type, type);
+
+    /* The new instance variable is placed at the end of the existing
+       instance_size, at the first byte that is aligned with
+       alignment.  */
+    misalignment = class_->instance_size % alignment;
+    
+    if (misalignment == 0)
+      ivar->ivar_offset = class_->instance_size;
+    else
+      ivar->ivar_offset = class_->instance_size - misalignment + alignment;
+    
+    class_->instance_size = ivar->ivar_offset + size;
+  }
+  
+  return YES;
+}
+
+
 const char *
 property_getName (struct objc_property * property __attribute__ ((__unused__)))
 {