Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wrap-static-fns generates too many consts #2973

Open
alistair23 opened this issue Nov 5, 2024 · 3 comments
Open

wrap-static-fns generates too many consts #2973

alistair23 opened this issue Nov 5, 2024 · 3 comments

Comments

@alistair23
Copy link

When running bindgen --experimental --wrap-static-fns ... on the following function

static inline int arch_within_stack_frames(const void * const stack,
					   const void * const stackend,
					   const void *obj, unsigned long len)
{
	return 0;
}

bindgen 0.69.5 generates the following C code in extern.c

int arch_within_stack_frames__extern(const const void *const stack, const const void *const stackend, const void *obj, unsigned long len) { return arch_within_stack_frames(stack, stackend, obj, len); }

Which then fails to build with the following error

rust/extern.c:1036:44: error: duplicate ‘const’ declaration specifier [-Werror=duplicate-decl-specifier]
 1036 | int arch_within_stack_frames__extern(const const void *const stack, const const void *const stackend, const void *obj, unsigned long len) { return arch_within_stack_frames(stack, stackend, obj, len); }
      |                                            ^~~~~
rust/extern.c:1036:75: error: duplicate ‘const’ declaration specifier [-Werror=duplicate-decl-specifier]
 1036 | int arch_within_stack_frames__extern(const const void *const stack, const const void *const stackend, const void *obj, unsigned long len) { return arch_within_stack_frames(stack, stackend, obj, len); }
      |                                                                           ^~~~~
cc1: all warnings being treated as errors

@hi-glenn
Copy link

hi-glenn commented Nov 7, 2024

@alistair23

Make a try to use main branch.

https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md#unreleased

The --wrap-static-fns related options no longer require the experimental feature or flag

@pvdrz
Copy link
Contributor

pvdrz commented Nov 7, 2024

@alistair23

Make a try to use main branch.

https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md#unreleased

The --wrap-static-fns related options no longer require the experimental feature or flag

I think that has nothing to do with the issue

@pvdrz
Copy link
Contributor

pvdrz commented Nov 11, 2024

I suspect the code at fault is here:

impl<'a> CSerialize<'a> for Type {
type Extra = &'a Item;
fn serialize<W: Write>(
&self,
ctx: &BindgenContext,
item: Self::Extra,
stack: &mut Vec<String>,
writer: &mut W,
) -> Result<(), CodegenError> {
match self.kind() {
TypeKind::Void => {
if self.is_const() {
write!(writer, "const ")?;
}
write!(writer, "void")?
}
TypeKind::NullPtr => {
if self.is_const() {
write!(writer, "const ")?;
}
write!(writer, "nullptr_t")?
}
TypeKind::Int(int_kind) => {
if self.is_const() {
write!(writer, "const ")?;
}
match int_kind {
IntKind::Bool => write!(writer, "bool")?,
IntKind::SChar => write!(writer, "signed char")?,
IntKind::UChar => write!(writer, "unsigned char")?,
IntKind::WChar => write!(writer, "wchar_t")?,
IntKind::Short => write!(writer, "short")?,
IntKind::UShort => write!(writer, "unsigned short")?,
IntKind::Int => write!(writer, "int")?,
IntKind::UInt => write!(writer, "unsigned int")?,
IntKind::Long => write!(writer, "long")?,
IntKind::ULong => write!(writer, "unsigned long")?,
IntKind::LongLong => write!(writer, "long long")?,
IntKind::ULongLong => write!(writer, "unsigned long long")?,
IntKind::Char { .. } => write!(writer, "char")?,
int_kind => {
return Err(CodegenError::Serialize {
msg: format!(
"Cannot serialize integer kind {:?}",
int_kind
),
loc: get_loc(item),
})
}
}
}
TypeKind::Float(float_kind) => {
if self.is_const() {
write!(writer, "const ")?;
}
match float_kind {
FloatKind::Float16 => write!(writer, "_Float16")?,
FloatKind::Float => write!(writer, "float")?,
FloatKind::Double => write!(writer, "double")?,
FloatKind::LongDouble => write!(writer, "long double")?,
FloatKind::Float128 => write!(writer, "__float128")?,
}
}
TypeKind::Complex(float_kind) => {
if self.is_const() {
write!(writer, "const ")?;
}
match float_kind {
FloatKind::Float16 => write!(writer, "_Float16 complex")?,
FloatKind::Float => write!(writer, "float complex")?,
FloatKind::Double => write!(writer, "double complex")?,
FloatKind::LongDouble => {
write!(writer, "long double complex")?
}
FloatKind::Float128 => write!(writer, "__complex128")?,
}
}
TypeKind::Alias(type_id) => {
if let Some(name) = self.name() {
if self.is_const() {
write!(writer, "const {}", name)?;
} else {
write!(writer, "{}", name)?;
}
} else {
type_id.serialize(ctx, (), stack, writer)?;
}
}
TypeKind::Array(type_id, length) => {
type_id.serialize(ctx, (), stack, writer)?;
write!(writer, " [{}]", length)?
}
TypeKind::Function(signature) => {
if self.is_const() {
stack.push("const ".to_string());
}
signature.return_type().serialize(
ctx,
(),
&mut vec![],
writer,
)?;
write!(writer, " (")?;
while let Some(item) = stack.pop() {
write!(writer, "{}", item)?;
}
write!(writer, ")")?;
let args = signature.argument_types();
if args.is_empty() {
write!(writer, " (void)")?;
} else {
write!(writer, " (")?;
serialize_sep(
", ",
args.iter(),
ctx,
writer,
|(name, type_id), ctx, buf| {
let mut stack = vec![];
if let Some(name) = name {
stack.push(name.clone());
}
type_id.serialize(ctx, (), &mut stack, buf)
},
)?;
write!(writer, ")")?
}
}
TypeKind::ResolvedTypeRef(type_id) => {
if self.is_const() {
write!(writer, "const ")?;
}
type_id.serialize(ctx, (), stack, writer)?
}
TypeKind::Pointer(type_id) => {
if self.is_const() {
stack.push("*const ".to_owned());
} else {
stack.push("*".to_owned());
}
type_id.serialize(ctx, (), stack, writer)?
}
TypeKind::Comp(comp_info) => {
if self.is_const() {
write!(writer, "const ")?;
}
let name = item.canonical_name(ctx);
match comp_info.kind() {
CompKind::Struct => write!(writer, "struct {}", name)?,
CompKind::Union => write!(writer, "union {}", name)?,
};
}
TypeKind::Enum(_enum_ty) => {
if self.is_const() {
write!(writer, "const ")?;
}
let name = item.canonical_name(ctx);
write!(writer, "enum {}", name)?;
}
ty => {
return Err(CodegenError::Serialize {
msg: format!("Cannot serialize type kind {:?}", ty),
loc: get_loc(item),
})
}
};
if !stack.is_empty() {
write!(writer, " ")?;
while let Some(item) = stack.pop() {
write!(writer, "{}", item)?;
}
}
Ok(())
}
}

Sometimes we do weird things when following references to types and we might be adding an extra const unnecessarily in the process.

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

No branches or pull requests

3 participants