Skip to content

--wrap-static-fns generates invalid C for pointer-to-array parameters and returns #3403

Description

@lwz23

Input C/C++ Header

static inline int (*phase8_array_identity(int (*value)[4]))[4] {
    return value;
}

Bindgen Invocation

$ bindgen input.h \
    --wrap-static-fns \
    --wrap-static-fns-path wrapper \
    --rust-target 1.75 \
    --no-layout-tests \
    --no-rustfmt-bindings \
    --output bindings.rs

Actual Results

The Rust declaration has the expected pointer-to-array type:

extern "C" {
    #[link_name = "phase8_array_identity__extern"]
    pub fn phase8_array_identity(
        value: *mut [::std::os::raw::c_int; 4usize],
    ) -> *mut [::std::os::raw::c_int; 4usize];
}

The generated wrapper.c does not preserve the C declarator:

int * [4] phase8_array_identity__extern(int *value [4]) {
    return phase8_array_identity(value);
}

Clang rejects it:

error: brackets are not allowed here
error: function cannot return array type 'int *[4]'
error: incompatible pointer types passing 'int **' to parameter of type 'int (*)[4]'

The parameter is wrong as well as the return type. In a parameter list,
int *value[4] is adjusted to int **; it is not int (*)[4].

Expected Results

The generated wrapper needs parentheses around the pointer declarators:

int (*phase8_array_identity__extern(int (*value)[4]))[4] {
    return phase8_array_identity(value);
}

I compiled that wrapper and linked it to a Rust caller using the generated
bindings.rs without edits. The direct C caller and the Rust caller both
printed:

identity=1 sum=10 first=1 last=4

Environment

bindgen current main: 9d26c6eddeff9192ddedb563192abe3128fc5aae
bindgen release:      0.72.1
clang:                15.0.7
rustc:                1.75.0
target:               x86_64-unknown-linux-gnu

The same generated C compile failure occurs with current main and 0.72.1,
at both O0 and O2.

Additional notes

This looks like a declarator serialization problem. The array serializer
appends [length], while the pointer serializer pushes * onto the type
string. That is not enough to represent cases where the * must be
parenthesized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions