Fixed address-of dereferenced member expressions
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 14 Sep 2026 10:15:33 +0000 (11:15 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 14 Sep 2026 10:15:33 +0000 (11:15 +0100)
amd64.c
i386.c

diff --git a/amd64.c b/amd64.c
index ec6e95e0c7b127a905c814e0977ee7e61c297a18..a97afa6494af911de58d3dd032e2fa51fe5b0a92 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -15821,9 +15821,10 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     enum token_kind member_op;
     struct local_symbol *src;
     
+    const char *current_object_tag_name = 0;
     int global_index;
     
-    const char *current_object_tag_name = 0;
+    int parenthesis_consumed = 0;
     int current_object_size = 0;
     
     if (tok.kind != TOK_LPAREN) {
@@ -15845,6 +15846,76 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     }
     
+    if (tok.kind == TOK_STAR) {
+    
+        struct aggregate_tag_entry *entry;
+        get_token ();
+        
+        if (tok.kind != TOK_IDENT) {
+        
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected identifier after '&(*'");
+            
+            expect (TOK_RPAREN, ")");
+            return 1;
+        
+        }
+        
+        name = xstrdup (tok.ident);
+        get_token ();
+        
+        src = find_local_symbol (name);
+        global_index = find_global_symbol (name);
+        
+        if (src && src->pointer_depth > 0) {
+        
+            current_object_tag_name = src->pointed_tag_name;
+            current_object_size = src->pointed_size;
+            
+            if (src->is_static && src->static_label) {
+               emit_load_global_to_reg (reg, src->static_label, DATA_PTR);
+            } else {
+                emit_load_local_to_reg (reg, src->offset, DATA_PTR);
+            }
+            
+            emit_load_deref_reg_now (reg, DATA_PTR & 0x1f);
+        
+        } else if (global_index >= 0 && get_global_symbol_pointer_depth (name) > 0) {
+        
+            current_object_tag_name = get_global_symbol_tag_name (name);
+            current_object_size = get_global_symbol_pointed_size (name);
+            
+            emit_load_global_to_reg (reg, name, DATA_PTR);
+            emit_load_deref_reg_now (reg, DATA_PTR & 0x1f);
+        
+        } else {
+        
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "cannot dereference '%s'", name);
+            free (name);
+            
+            expect (TOK_RPAREN, ")");
+            return 1;
+        
+        }
+        
+        if (current_object_tag_name) {
+        
+            entry = find_aggregate_tag (current_object_tag_name, 0);
+            
+            if (entry) {
+                current_object_size = entry->size;
+            }
+        
+        }
+        
+        free (name);
+        
+        expect (TOK_RPAREN, ")");
+        parenthesis_consumed = 1;
+        
+        goto parenthesized_address_members;
+    
+    }
+    
     if (tok.kind != TOK_IDENT) {
     
         report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected identifier after '&('");
@@ -15987,6 +16058,8 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     free (name);
     
+parenthesized_address_members:
+    
     while (tok.kind == TOK_ARROW || tok.kind == TOK_DOT) {
     
         char *member;
@@ -16084,7 +16157,10 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     }
     
-    expect (TOK_RPAREN, ")");
+    if (!parenthesis_consumed) {
+        expect (TOK_RPAREN, ")");
+    }
+    
     return 1;
 
 }
diff --git a/i386.c b/i386.c
index d9543462a776014e5039994303b99bc6a705c5f8..e7cf72e68ddbdd1eed703f609f1daaebeb0fcb48 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -14669,10 +14669,11 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     enum token_kind member_op;
     struct local_symbol *src;
     
+    const char *current_object_tag_name = 0;
     int global_index;
     
-    const char *current_object_tag_name = 0;
     int current_object_size = 0;
+    int parenthesis_consumed = 0;
     
     if (tok.kind != TOK_LPAREN) {
         return 0;
@@ -14693,6 +14694,76 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     }
     
+    if (tok.kind == TOK_STAR) {
+    
+        struct aggregate_tag_entry *entry;
+        get_token ();
+        
+        if (tok.kind != TOK_IDENT) {
+        
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected identifier after '&(*'");
+            
+            expect (TOK_RPAREN, ")");
+            return 1;
+        
+        }
+        
+        name = xstrdup (tok.ident);
+        get_token ();
+        
+        src = find_local_symbol (name);
+        global_index = find_global_symbol (name);
+        
+        if (src && src->pointer_depth > 0) {
+        
+            current_object_tag_name = src->pointed_tag_name;
+            current_object_size = src->pointed_size;
+            
+            if (src->is_static && src->static_label) {
+                emit_load_global_to_reg (reg, src->static_label, DATA_PTR);
+            } else {
+                emit_load_local_to_reg (reg, src->offset, DATA_PTR);
+            }
+            
+            emit_load_deref_reg_now (reg, DATA_PTR & 0x1f);
+        
+       } else if (global_index >= 0 && get_global_symbol_pointer_depth (name) > 0) {
+        
+            current_object_tag_name = get_global_symbol_tag_name (name);
+            current_object_size = get_global_symbol_pointed_size (name);
+            
+            emit_load_global_to_reg (reg, name, DATA_PTR);
+            emit_load_deref_reg_now (reg, DATA_PTR & 0x1f);
+        
+        } else {
+        
+            report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "cannot dereference '%s'", name);
+            free (name);
+            
+            expect (TOK_RPAREN, ")");
+            return 1;
+        
+        }
+        
+        if (current_object_tag_name) {
+        
+            entry = find_aggregate_tag (current_object_tag_name, 0);
+            
+            if (entry) {
+                current_object_size = entry->size;
+            }
+        
+        }
+        
+        free (name);
+        
+        expect (TOK_RPAREN, ")");
+        parenthesis_consumed = 1;
+        
+        goto parenthesized_address_members;
+    
+    }
+    
     if (tok.kind != TOK_IDENT) {
     
         report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected identifier after '&('");
@@ -14835,6 +14906,8 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     free (name);
     
+parenthesized_address_members:
+    
     while (tok.kind == TOK_ARROW || tok.kind == TOK_DOT) {
     
         char *member;
@@ -14932,7 +15005,10 @@ static int emit_load_address_of_parenthesized_postfix_to_reg_now (const char *re
     
     }
     
-    expect (TOK_RPAREN, ")");
+    if (!parenthesis_consumed) {
+        expect (TOK_RPAREN, ")");
+    }
+    
     return 1;
 
 }