Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog      (revision 170370)
+++ objc/ChangeLog      (working copy)
@@ -1,10 +1,19 @@
 2011-02-20  Nicola Pero  <nicola.pero@meta-innovation.com>
 
-       * objc-gnu-runtime-abi-01.c (TARGET_64BIT): Removed.  Removed
-       usage of padding fields.  Do not include tm.h.
-       * objc-act.c (objc_write_global_declaration): Set input_location
-       to BUILTINS_LOCATION while generating runtime metadata.
+       PR objc/47832
+       * objc-act.c (flexible_array_type_p): New.
+       (add_instance_variable): Produce an error if an instance variable
+       is of flexible array type.
+       (encode_array): Do not emit an error if encoding a flexible array
+       type while generating instance variables.
 
+2011-02-20  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-gnu-runtime-abi-01.c (TARGET_64BIT): Removed.  Removed
+       usage of padding fields.  Do not include tm.h.
+       * objc-act.c (objc_write_global_declaration): Set input_location
+       to BUILTINS_LOCATION while generating runtime metadata.
+
 2011-01-20  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        PR objc/47784
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c     (revision 170370)
+++ objc/objc-act.c     (working copy)
@@ -5925,6 +5925,49 @@ add_category (tree klass, tree category)
     }
 }
 
+/* TODO: The check for flexible array members in instance variables is
+   implemented only for ObjC, and it is implemented by using this
+   flexible_array_type_p() function, which is basically lifted from
+   c-decl.c.  Is this the best way of doing the check ?  */
+
+/* flexible_array_type_p() seems to crash the compiler when used in
+   ObjC++, so we disable the check in ObjC++.  */
+#ifndef OBJCPLUS
+/* Determine whether TYPE is a structure with a flexible array member,
+   or a union containing such a structure (possibly recursively).  These
+   are invalid as instance variable.  */
+
+static bool
+flexible_array_type_p (tree type)
+{
+  tree x;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      x = TYPE_FIELDS (type);
+      if (x == NULL_TREE)
+       return false;
+      while (DECL_CHAIN (x) != NULL_TREE)
+       x = DECL_CHAIN (x);
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+       return true;
+      return false;
+    case UNION_TYPE:
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+       {
+         if (flexible_array_type_p (TREE_TYPE (x)))
+           return true;
+       }
+      return false;
+    default:
+    return false;
+  }
+}
+#endif
+
 /* Called after parsing each instance variable declaration. Necessary to
    preserve typedefs and implement public/private...
 
@@ -5958,6 +6001,27 @@ add_instance_variable (tree klass, objc_ivar_visib
       return klass;
     }
 
+  /* Also, reject a struct with a flexible array member.  Ie,
+
+       struct A { int x; int[] y; };
+
+       @interface X
+       {
+         struct A instance_variable;
+       }
+       @end
+
+       is not valid as 'struct A' doesn't have a known size.  */
+#ifndef OBJCPLUS
+  /* TODO: Implemented this check for ObjC++ too.  */
+  if (flexible_array_type_p (field_type))
+    {
+      error ("instance variable %qs has unknown size", ivar_name);
+      /* Return class as is without adding this ivar.  */
+      return klass;      
+    }
+#endif
+
 #ifdef OBJCPLUS
   /* Check if the ivar being added has a non-POD C++ type.   If so, we will
      need to either (1) warn the user about it or (2) generate suitable
@@ -9926,27 +9990,23 @@ encode_array (tree type, int curtype, int format)
   if (an_int_cst == NULL)
     {
       /* We are trying to encode an incomplete array.  An incomplete
-        array is forbidden as part of an instance variable.  */
-      if (generating_instance_variables)
-       {
-         /* TODO: Detect this error earlier.  */
-         error ("instance variable has unknown size");
-         return;
-       }
+        array is forbidden as part of an instance variable; but it
+        may occur if the instance variable is a pointer to such an
+        array.  */
 
-      /* So the only case in which an incomplete array could occur is
-        if we are encoding the arguments or return value of a method.
-        In that case, an incomplete array argument or return value
-        (eg, -(void)display: (char[])string) is treated like a
-        pointer because that is how the compiler does the function
-        call.  A special, more complicated case, is when the
-        incomplete array is the last member of a struct (eg, if we
-        are encoding "struct { unsigned long int a;double b[];}"),
-        which is again part of a method argument/return value.  In
-        that case, we really need to communicate to the runtime that
-        there is an incomplete array (not a pointer!) there.  So, we
-        detect that special case and encode it as a zero-length
-        array.
+      /* So the only case in which an incomplete array could occur
+        (without being pointed to) is if we are encoding the
+        arguments or return value of a method.  In that case, an
+        incomplete array argument or return value (eg,
+        -(void)display: (char[])string) is treated like a pointer
+        because that is how the compiler does the function call.  A
+        special, more complicated case, is when the incomplete array
+        is the last member of a struct (eg, if we are encoding
+        "struct { unsigned long int a;double b[];}"), which is again
+        part of a method argument/return value.  In that case, we
+        really need to communicate to the runtime that there is an
+        incomplete array (not a pointer!) there.  So, we detect that
+        special case and encode it as a zero-length array.
 
         Try to detect that we are part of a struct.  We do this by
         searching for '=' in the type encoding for the current type.
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog (revision 170370)
+++ testsuite/ChangeLog (working copy)
@@ -1,3 +1,8 @@
+2011-02-21  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       PR objc/47832
+       * objc.dg/type-size-4.m: New test.
+
 2011-02-21  Jeff Law <law@redhat.com>
 
        PR rtl-optimization/46178
Index: testsuite/objc.dg/type-size-3.m
===================================================================
--- testsuite/objc.dg/type-size-3.m     (revision 170370)
+++ testsuite/objc.dg/type-size-3.m     (working copy)
@@ -10,11 +10,9 @@ typedef struct
 
 @interface Test
 {
-  test_type c;
+  test_type c; /* { dg-error "instance variable .c. has unknown size" } */
 }
 @end
 
 @implementation Test
 @end
-
-/* { dg-error "instance variable has unknown size" "" { target *-*-* } 0 } */
Index: testsuite/objc.dg/type-size-4.m
===================================================================
--- testsuite/objc.dg/type-size-4.m     (revision 0)
+++ testsuite/objc.dg/type-size-4.m     (revision 0)
@@ -0,0 +1,20 @@
+/* Allow ivars that are pointers to structs with an unknown size.  */
+/* Contributed by Nicola Pero  <nicola.pero@meta-innovation.com> */
+/* PR objc/47832 */
+/* { dg-do compile } */
+
+typedef struct
+{
+  unsigned long int a;
+  double b[];
+} test_type;
+
+@interface Test
+{
+  /* This is fine.  */
+  test_type *c;
+}
+@end
+
+@implementation Test
+@end
