rust-lang / rust-lang/rust-bindgen

bindgen fails to generate __bindgen_padding in some situations on AVR

Open
#2,175 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

This bug report has an example repo to aid in reproduction of the problem:
https://github.com/mutantbob/bindgen-malfunction
It does not seem to malfunction when generating in the native environment, but instead malfunctions when cross-compiling for AVR.

headers

base.h:

#ifndef Base_h_
#define Base_h_


class Base
{
private:
    int maple;
 public:
    Base() : maple(7) {}
    virtual int f() =0;
};

#endif Base_h_

alpha.h:

#include "base.h"

class Alpha: Base
{
#ifdef MALFUNCTION
    int bar;
#else
    short bar;
    short bacon;
#endif
 public:
    int f() { return bar; }
};
Bindgen Invocation
use std::env;
use std::path::PathBuf;
use bindgen;
use bindgen::Builder;

pub trait BlocklistFileMulti {
    fn blocklist_file_multi<T: AsRef<str>, I: IntoIterator<Item = T>>(self, iter: I) -> Self;
}

impl BlocklistFileMulti for bindgen::Builder {
    fn blocklist_file_multi<T: AsRef<str>, I: IntoIterator<Item = T>>(self, iter: I) -> Self {
        let mut builder = self;
        for file in iter {
            println!("# blocking file {}", file.as_ref());
            builder = builder.blocklist_file(file)
        }
        builder
    }
}

fn generate_bindings_generic<T: AsRef<str>, I: IntoIterator<Item = T>>(header: &str, out_basename: &str, excludes: I, malfunction:bool) {
    println!("cargo:rerun-if-changed={}", header);
    let bindings = make_builder_for(header)
        .blocklist_file_multi(excludes)
        .clang_args(if malfunction {
            vec!["-DMALFUNCTION=1"]
        } else {
            vec![]
        })
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    let bindings_out_file = out_path.join(out_basename);
    bindings
        .write_to_file(bindings_out_file)
        .expect("Couldn't write bindings!");
}

fn make_builder_for(header: &str) -> Builder {
    bindgen::Builder::default()
        .header(header)
        .clang_args(&[
            "-x",
            "c++",
        ])
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .ctypes_prefix("cty")
        .rustfmt_bindings(true)
}

fn main()
{
    let blank : [&str;0] = [];
    generate_bindings_generic("src-cpp/mixed.h", "mixed.rs", &blank, false);
    generate_bindings_generic("src-cpp/alpha.h", "alpha.rs", &blank, false);
    generate_bindings_generic("src-cpp/alpha.h", "alpha-minus.rs", vec!["src-cpp/base.h"], false);
    generate_bindings_generic("src-cpp/alpha.h", "alpha-wrong.rs", vec!["src-cpp/base.h"], true);
}
Actual Results
#[repr(C)]
pub struct Alpha__bindgen_vtable(cty::c_void);
#[repr(C, packed)]
pub struct Alpha {
    pub vtable_: *const Alpha__bindgen_vtable,
    pub bar: cty::c_int,
}
Expected Results

#[repr(C)]
pub struct Alpha__bindgen_vtable(cty::c_void);
#[repr(C)]
pub struct Alpha {
    pub vtable_: *const Alpha__bindgen_vtable,
    pub __bindgen_padding_0: u16,
    pub bar: cty::c_int,
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue using the linked bindgen-malfunction repository, starting with src-cpp/base.h and src-cpp/alpha.h and the shown Builder invocation. Compare alpha-wrong.rs with the expected Alpha layout, then trace padding generation for the AVR cross-compilation case; done means the generated struct uses repr(C) and includes the required __bindgen_padding_0 field.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
embedded-iot, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.