rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

layout tests fail for max_align_t on debian sid.i386

Open plugwash opened this issue 1 year ago • 3 comments

While working on updating the rust-bindgen package in debian sid, I ran into a bindgen layout error with leptonica-sys. After some experimentation this failure seems to be caused by building bindings for stddef.h.

As a reduced testcase the following commands

echo '#include <stddef.h>' > wrapper.h
bindgen wrapper.h

resulted in

/* automatically generated by rust-bindgen 0.70.1 */

pub type wchar_t = ::std::os::raw::c_int;
#[repr(C)]
#[repr(align(8))]
#[derive(Debug, Copy, Clone)]
pub struct max_align_t {
    pub __clang_max_align_nonce1: ::std::os::raw::c_longlong,
    pub __clang_max_align_nonce2: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of max_align_t"][::std::mem::size_of::<max_align_t>() - 24usize];
    ["Alignment of max_align_t"][::std::mem::align_of::<max_align_t>() - 8usize];
    ["Offset of field: max_align_t::__clang_max_align_nonce1"]
        [::std::mem::offset_of!(max_align_t, __clang_max_align_nonce1) - 0usize];
    ["Offset of field: max_align_t::__clang_max_align_nonce2"]
        [::std::mem::offset_of!(max_align_t, __clang_max_align_nonce2) - 8usize];
};

I wrote a small c test program to see what size the c compilers thought max_align_t should have, worryingly gcc and clang gave different results with gcc giving a result of 48 and clang a result of only 24.

max_align_t does not seem to be defined in any system headers, so I presume there is some built-in magic going on in gcc and clang.

plugwash avatar Nov 26 '24 02:11 plugwash

max_align_t comes from /usr/lib/clang/18/include/__stddef_max_align_t.h on my system:

/*===---- __stddef_max_align_t.h - Definition of max_align_t ---------------===
 *
 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 * See https://llvm.org/LICENSE.txt for license information.
 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 *
 *===-----------------------------------------------------------------------===
 */

#ifndef __CLANG_MAX_ALIGN_T_DEFINED
#define __CLANG_MAX_ALIGN_T_DEFINED

#if defined(_MSC_VER)
typedef double max_align_t;
#elif defined(__APPLE__)
typedef long double max_align_t;
#else
// Define 'max_align_t' to match the GCC definition.
typedef struct {
  long long __clang_max_align_nonce1
      __attribute__((__aligned__(__alignof__(long long))));
  long double __clang_max_align_nonce2
      __attribute__((__aligned__(__alignof__(long double))));
} max_align_t;
#endif

#endif

so it seems clang is trying to match gcc's definition of it. In either case, I think part of the issue here is that long double is not being translated properly by bindgen or something. So definitely a bug in our side.

pvdrz avatar Nov 26 '24 20:11 pvdrz

@pvdrz #2403 fixes this, but it has been waiting for review for over two years. It blocks the generation of function bindings taking or returning long double by value, as they cannot be represented in Rust, and then uses a struct __BindgenLongDouble with the correct size and alignment to represent long double. Would you be able to have a look?

GKFX avatar Mar 09 '25 10:03 GKFX