Skip to content

cgen: fix pointer reference in for-in fixed-array iteration with & [fj4WqyCCw3C5ShR1RfB7MoBPTpkRrBFYP1uT35g3MvT] - #28166

Open
waterWang wants to merge 5 commits into
vlang:masterfrom
waterWang:fix-for_in-fixed-array-ref-ptr
Open

cgen: fix pointer reference in for-in fixed-array iteration with & [fj4WqyCCw3C5ShR1RfB7MoBPTpkRrBFYP1uT35g3MvT]#28166
waterWang wants to merge 5 commits into
vlang:masterfrom
waterWang:fix-for_in-fixed-array-ref-ptr

Conversation

@waterWang

Copy link
Copy Markdown
Contributor

Fix for i in &fixed_array producing invalid C when the array element is a struct

Description

When iterating over a fixed array by reference (for i in &t.buf where t.buf is a fixed array of structs), the cgen generates main__Item* i = (*tmp)[idx] — assigning a struct value to a pointer type.

Root Cause

In vlib/v/gen/c/for.v, the .array_fixed branch computes the address prefix as:

addr := if node.val_is_mut { '&' } else { '' }

This only checks val_is_mut, but not val_is_ref. When val_is_ref is true (the user wrote for i in &expr), the loop variable is a pointer type (&Item), but the generated C code assigns the element's value instead of its address.

Fix

Change the condition to also check val_is_ref:

addr := if node.val_is_mut || node.val_is_ref { '&' } else { '' }

Reproduction

module main

struct Item {
    a [100000]f32
}

@[heap]
struct Test {
    buf [10]Item
}

fn main() {
    t := Test{}
    for i in &t.buf {
        println(i.a[0])
    }
}

Before: error: initializing 'main__Item *' with an expression of incompatible type 'main__Item'
After: compiles correctly.

Closes #28128
[fj4WqyCCw3C5ShR1RfB7MoBPTpkRrBFYP1uT35g3MvT]

@medvednikov

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 874a934146

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vlib/v/gen/c/for.v
}
if !is_fixed_array {
addr := if node.val_is_mut { '&' } else { '' }
addr := if node.val_is_mut || node.val_is_ref { '&' } else { '' }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve pointer elements during reference iteration

When the fixed array's element type is already a pointer, such as mut items := [2]&Item{} followed by for item in &items, for_in_val_type deliberately leaves the loop variable as &Item rather than creating &&Item. This unconditional & now emits an initializer equivalent to Item *item = &items[idx], whose right side is Item **, so previously valid reference iteration over fixed arrays of pointers fails C compilation. Only take the element address when reference iteration actually added a pointer level.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cgen: for i in &fixed_array_of_structs binds the loop pointer to a value (take the address with &)

2 participants