Bug 563469 – Arrays not treated correctly in struct offset calculation
authorColin Walters <walters@src.gnome.org>
Mon, 2 Feb 2009 16:31:02 +0000 (16:31 +0000)
committerColin Walters <walters@src.gnome.org>
Mon, 2 Feb 2009 16:31:02 +0000 (16:31 +0000)
Arrays are currently not handled specially, and hence treated as pointers in
giroffsets.c:get_field_size_alignment(), which is (obviously) wrong.

svn path=/trunk/; revision=1078

ChangeLog
girepository/giroffsets.c
tests/offsets/gen-gitestoffsets
tests/offsets/offsets.h

index e3a418c..8f1b793 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,23 @@
-2009-01-28  Johan Bilien  <jobi@via.ecp.fr>
+2009-02-02  Andreas Rottmann  <a.rottmann@gmx.at>
+
+       Bug 563469 – Arrays not treated correctly in struct offset calculation
+
+       * tests/offsets/offsets.h (OffsetsArray): New struct, containing a
+       bunch of arrays.
+
+       * tests/offsets/gen-gitestoffsets (FIELD_RE): Handle arrays.
+
+       * girepository/giroffsets.c (get_interface_size_alignment):
+       Refactored to make it more general, now takes a GIrNodeType*
+       instead of a GIrNodeField*, plus an additional 'who' parameter
+       that denotes what the size/alignment is calculated for.
+       (get_type_size_alignment): New function, refactored version of
+       get_field_size_alignment().
+       (get_field_size_alignment): Implemented in terms of
+       get_type_size_alignment().
+       (get_type_size_alignment): Handle array types correctly.
+
+  2009-01-28  Johan Bilien  <jobi@via.ecp.fr>
 
        * tests/scanner/annotation-1.0-expected.gir: add missing
        with_voidp
index 46cdbd9..f224e69 100644 (file)
@@ -144,21 +144,19 @@ get_enum_size_alignment (GIrNodeEnum *enum_node,
 }
 
 static gboolean
-get_interface_size_alignment (GIrNodeField *field,
-                             GIrNode      *parent_node,
-                             GIrModule    *module,
-                             GList        *modules,
-                             gint         *size,
-                             gint         *alignment)
+get_interface_size_alignment (GIrNodeType *type,
+                              GIrModule   *module,
+                             GList       *modules,
+                             gint        *size,
+                             gint        *alignment,
+                              const char  *who)
 {
-  GIrNodeType *type = field->type;
   GIrNode *iface;
   GIrModule *iface_module;
 
   if (!g_ir_find_node (module, modules, type->interface, &iface, &iface_module))
     {
-      g_warning ("Can't resolve type '%s' for field %s.%s.%s",
-                type->interface, module->name, parent_node->name, ((GIrNode *)field)->name);
+      g_warning ("Can't resolve type '%s' for %s", type->interface, who);
       *size = -1;
       *alignment = -1;
       return FALSE;
@@ -212,8 +210,8 @@ get_interface_size_alignment (GIrNodeField *field,
       }
     default:
       {
-       g_warning ("Field %s.%s.%s has is not a pointer and is of type %s",
-                  module->name, parent_node->name, ((GIrNode *)field)->name,
+       g_warning ("%s has is not a pointer and is of type %s",
+                   who,
                   g_ir_node_type_to_string (iface->type));
        *size = -1;
        *alignment = -1;
@@ -225,17 +223,34 @@ get_interface_size_alignment (GIrNodeField *field,
 }
 
 static gboolean
-get_field_size_alignment (GIrNodeField *field,
-                         GIrNode      *parent_node,
-                         GIrModule    *module,
-                         GList        *modules,
-                         gint         *size,
-                         gint         *alignment)
+get_type_size_alignment (GIrNodeType *type,
+                         GIrModule   *module,
+                         GList       *modules,
+                         gint        *size,
+                         gint        *alignment,
+                         const char  *who)
 {
-  GIrNodeType *type = field->type;
   ffi_type *type_ffi;
 
-  if (type->is_pointer)
+  if (type->tag == GI_TYPE_TAG_ARRAY)
+    {
+      gint elt_size, elt_alignment;
+          
+      if (!type->has_size
+          || !get_type_size_alignment(type->parameter_type1, module, modules,
+                                      &elt_size, &elt_alignment, who))
+        {
+          *size = -1;
+          *alignment = -1;
+          return FALSE;
+        }
+          
+      *size = type->size * elt_size;
+      *alignment = elt_alignment;
+          
+      return TRUE;
+    }
+  else if (type->is_pointer)
     {
       type_ffi = &ffi_type_pointer;
     }
@@ -243,9 +258,7 @@ get_field_size_alignment (GIrNodeField *field,
     {
       if (type->tag == GI_TYPE_TAG_INTERFACE)
        {
-         return get_interface_size_alignment (field, parent_node,
-                                              module, modules,
-                                              size, alignment);
+         return get_interface_size_alignment (type, module, modules, size, alignment, who);
        }
       else
        {
@@ -253,16 +266,15 @@ get_field_size_alignment (GIrNodeField *field,
 
          if (type_ffi == &ffi_type_void)
            {
-             g_warning ("Field %s.%s.%s has void type",
-                        module->name, parent_node->name, ((GIrNode *)field)->name);
+             g_warning ("%s has void type", who);
              *size = -1;
              *alignment = -1;
              return FALSE;
            }
          else if (type_ffi == &ffi_type_pointer)
            {
-             g_warning ("Field %s.%s.%s has is not a pointer and is of type %s",
-                        module->name, parent_node->name, ((GIrNode *)field)->name,
+             g_warning ("%s has is not a pointer and is of type %s",
+                         who,
                         g_type_tag_to_string (type->tag));
              *size = -1;
              *alignment = -1;
@@ -278,6 +290,25 @@ get_field_size_alignment (GIrNodeField *field,
   return TRUE;
 }
 
+static gboolean
+get_field_size_alignment (GIrNodeField *field,
+                         GIrNode      *parent_node,
+                         GIrModule    *module,
+                         GList        *modules,
+                         gint         *size,
+                         gint         *alignment)
+{
+  gchar *who;
+  gboolean success;
+  
+  who = g_strdup_printf ("field %s.%s.%s", module->name, parent_node->name, ((GIrNode *)field)->name);
+
+  success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
+  g_free (who);
+
+  return success;
+}
+
 #define ALIGN(n, align) (((n) + (align) - 1) & ~((align) - 1))
 
 static gboolean
index ce4a977..58139fc 100755 (executable)
@@ -61,7 +61,7 @@ STRUCT_DEF_RE = compile_re("struct\s+_(TOKEN)\s*{([^}]*)}")
 
 # This certainly can't handle all type declarations, but it only
 # needs to handle the ones we use in the test cases
-FIELD_RE = compile_re("^(?:const\s+)?TOKEN(?:[\s*]+)(TOKEN)\s*;$");
+FIELD_RE = compile_re(r"^(?:const\s+)?TOKEN(?:[\s*]+)(TOKEN)\s*(?:\[([0-9]*)\])?\s*;$")
 
 
 input_f = open(sys.argv[1])
index c0edfe0..9c29a98 100644 (file)
@@ -104,4 +104,18 @@ struct _OffsetsNested {
   char dummy3;
 };
 
+/* Test array offsets
+ */
+
+typedef struct _OffsetsArray OffsetsArray;
+
+struct _OffsetsArray
+{ 
+  gint some_ints[2];
+  gint8 some_int8s[3];
+  gdouble some_doubles[4];
+  Enum1 some_enum[2];
+  gpointer some_ptrs[5];
+};
+
 #endif /* __OFFSETS_H__ */