Fix multidimensional array member indexing master
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 4 Oct 2026 18:15:11 +0000 (19:15 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 4 Oct 2026 18:15:11 +0000 (19:15 +0100)
amd64.c
i386.c
parse.c
parse.h

diff --git a/amd64.c b/amd64.c
index 8a8af564b3de09a300e609d0ef363731da021008..3d6483f44ac19f854d95fc23cf9b8ef52815407c 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -14752,11 +14752,14 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
             const char *member_caret;
             
             unsigned long member_line;
-            
             int offset = 0;
+            
             int size = DATA_INT & 0x1f;
             int elem_size = DATA_INT & 0x1f;
+            
+            int array_dimensions = 0;
             int pointer_depth = 0;
+            
             int is_array = 0;
             int is_floating = 0;
             int is_unsigned = 0;
@@ -14787,6 +14790,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
             }
             
             is_unsigned = last_found_member_is_unsigned;
+            array_dimensions = last_found_member_array_dimensions;
             
             {
             
@@ -14890,9 +14894,11 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
                     
                     }
                 
+                } else if (array_dimensions > 1) {
+                    emit_parse_postfix_subscripts_to_reg_dims_now (reg, subscript_elem_size, pointer_depth, elem_size, array_dimensions, is_unsigned, &subscript_elem_size);
                 } else {
                     emit_parse_postfix_subscript_scaled_address_to_reg_now (reg, subscript_elem_size);
-                }
+                 }
                 
                 if (tok.kind == TOK_ARROW && subscript_elem_size <= (DATA_PTR & 0x1f)) {
                 
@@ -15040,7 +15046,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
                     postfix_member_pointer_depth--;
                 }
                 
-                if (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f)) {
+                if (array_dimensions <= 1 && (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f))) {
                     emit_load_deref_reg_ex_now (reg, subscript_elem_size, is_unsigned);
                 }
                 
diff --git a/i386.c b/i386.c
index 936c1ae6b9ea60b6745467961de8232ece8af412..3607d51643e66e7c9c52c5616be0984b0bb6d8bf 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -13686,11 +13686,14 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
             const char *member_caret;
             
             unsigned long member_line;
-            
             int offset = 0;
+            
             int size = DATA_INT & 0x1f;
             int elem_size = DATA_INT & 0x1f;
+            
+            int array_dimensions = 0;
             int pointer_depth = 0;
+            
             int is_array = 0;
             int is_floating = 0;
             int is_unsigned = 0;
@@ -13721,6 +13724,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
             }
             
             is_unsigned = last_found_member_is_unsigned;
+            array_dimensions = last_found_member_array_dimensions;
             
             {
             
@@ -13807,9 +13811,11 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
                     
                     }
                 
+                } else if (array_dimensions > 1) {
+                    emit_parse_postfix_subscripts_to_reg_dims_now (reg, subscript_elem_size, pointer_depth, elem_size, array_dimensions, is_unsigned, &subscript_elem_size);
                 } else {
                     emit_parse_postfix_subscript_scaled_address_to_reg_now (reg, subscript_elem_size);
-                }
+                 }
                 
                 if (tok.kind == TOK_ARROW && subscript_elem_size <= (DATA_PTR & 0x1f)) {
                 
@@ -13957,7 +13963,7 @@ static void emit_apply_postfix_member_access_to_reg_now (const char *reg) {
                     postfix_member_pointer_depth--;
                 }
                 
-                if (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f)) {
+                if (array_dimensions <= 1 && (postfix_member_pointer_depth != 0 || postfix_member_size <= (DATA_PTR & 0x1f))) {
                     emit_load_deref_reg_ex_now (reg, subscript_elem_size, is_unsigned);
                 }
                 
diff --git a/parse.c b/parse.c
index 3d730893c899b6e2dbcacc0919e9c5f71a8bc18c..e71f143f9f8ffae5f85479cea5d335a4152471d6 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -91,10 +91,11 @@ int parsed_field_count = 0;
 struct member_info_entry member_infos[MAX_MEMBER_INFOS];
 int member_info_count = 0;
 
-const char *last_found_member_tag_name = 0;
+int last_found_member_array_dimensions = 0;
 int last_found_member_is_unsigned = 0;
 
 struct pending_param pending_params[MAX_PENDING_PARAMS];
+const char *last_found_member_tag_name = 0;
 
 int pending_param_count;
 int preserve_pending_params;
@@ -1467,6 +1468,7 @@ int find_member_info_ex_bounded (const char *name, int max_size, const char *own
     
     last_found_member_tag_name = 0;
     last_found_member_is_unsigned = 0;
+    last_found_member_array_dimensions = 0;
     last_found_member_calling_convention = TOK_EOF;
     
     if (!name) {
@@ -1532,6 +1534,7 @@ int find_member_info_ex_bounded (const char *name, int max_size, const char *own
     
         last_found_member_tag_name = member_infos[best].tag_name;
         last_found_member_is_unsigned = member_infos[best].is_unsigned ? 1 : 0;
+        last_found_member_array_dimensions = member_infos[best].array_dimensions;
         last_found_member_calling_convention = member_infos[best].calling_convention;
         
         if (offset) {
@@ -2686,6 +2689,7 @@ int find_member_info_ex (const char *name, int *offset, int *size, int *elem_siz
     
     last_found_member_tag_name = 0;
     last_found_member_is_unsigned = 0;
+    last_found_member_array_dimensions = 0;
     last_found_member_calling_convention = TOK_EOF;
     
     if (!name) {
@@ -2711,6 +2715,7 @@ int find_member_info_ex (const char *name, int *offset, int *size, int *elem_siz
     
     last_found_member_tag_name = member_infos[best].tag_name;
     last_found_member_is_unsigned = member_infos[best].is_unsigned ? 1 : 0;
+    last_found_member_array_dimensions = member_infos[best].array_dimensions;
     last_found_member_calling_convention = member_infos[best].calling_convention;
 
     if (offset) {
@@ -2831,6 +2836,7 @@ static void remember_member_info_ex (const char *name, int offset, int size, int
     member_infos[member_info_count].size = size;
     member_infos[member_info_count].elem_size = elem_size > 0 ? elem_size : size;
     member_infos[member_info_count].pointer_depth = pointer_depth;
+    member_infos[member_info_count].array_dimensions = is_array ? declarator_array_dimensions : 0;
     member_infos[member_info_count].is_array = is_array;
     member_infos[member_info_count].is_floating = is_floating ? 1 : 0;
     member_infos[member_info_count].is_unsigned = parsed_type_is_unsigned ? 1 : 0;
@@ -2877,6 +2883,7 @@ static void promote_anonymous_aggregate_members (const char *owner_tag_name, int
         dst->size = src->size;
         dst->elem_size = src->elem_size;
         dst->pointer_depth = src->pointer_depth;
+        dst->array_dimensions = src->array_dimensions;
         dst->is_array = src->is_array;
         dst->is_floating = src->is_floating;
         dst->is_unsigned = src->is_unsigned;
@@ -3550,11 +3557,27 @@ void parse_type_spec (void) {
                         
                         if (declarator_has_array && declarator_is_pointer) {
                             member_info_elem_size = DATA_PTR;
+                        } else if (declarator_has_array && declarator_first_array_count > 0) {
+                        
+                            /*
+                             * One subscript of a multidimensional array member
+                             * selects the complete object after the first
+                             * dimension.  member_size already contains the
+                             * storage for every dimension, so divide by the
+                             * first dimension rather than recording the scalar
+                             * base type.
+                             *
+                             *     char segment[32][4];
+                             *
+                             * segment[i] therefore has a four-byte stride.
+                             */
+                            member_info_elem_size = member_size / declarator_first_array_count;
+                        
                         } else {
                         
                             member_info_elem_size = declarator_is_pointer ?
                                 (parsed_type_is_aggregate ? parsed_type_size : (parsed_type_size & 0x1f)) :
-                                    (declarator_has_array ? member_type_size : member_size);
+                                    member_size;
                         
                         }
                         
diff --git a/parse.h b/parse.h
index bf38cd64f9b00817464654f1a69d529c4a704dc1..87f47103aa97e3af785c3b1c387835d34efe805c 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -141,6 +141,8 @@ struct member_info_entry {
     int offset;
     int size;
     int elem_size;
+    
+    int array_dimensions;
     int pointer_depth;
     
     int is_array;
@@ -198,7 +200,9 @@ struct local_symbol {
 };
 
 extern const char *last_found_member_tag_name;
+
 extern int last_found_member_is_unsigned;
+extern int last_found_member_array_dimensions;
 
 struct aggregate_tag_entry {