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

Name for anonymous enumeration and typedef collide when their layout is different #2761

Open
therealfrauholle opened this issue Feb 15, 2024 · 0 comments

Comments

@therealfrauholle
Copy link

Bindgen version 0.69.4 infers name for anonymous enumeration from its typedef, even if the typedef and enumerations are different.

Input C/C++ Header

typedef enum {
    A,
    B
} TypeExport __attribute__((mode(__word__)));

Bindgen Invocation

$ bindgen --default-enum-style rust input.h -o bindings.rs

Actual Results

/* automatically generated by rust-bindgen 0.69.4 */

#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum TypeExport {
    A = 0,
    B = 1,
}
pub type TypeExport = ::std::os::raw::c_ulong;

Expected Results

/* automatically generated by rust-bindgen 0.69.4 */

#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum _bindgen_ty_1 {
    A = 0,
    B = 1,
}
pub type TypeExport = ::std::os::raw::c_ulong;

Additional information

I was very confused at first but this makes sense in the end - take this with a grain of salt, my knowledge about C is very limited. It is important to note that

typedef enum Anonymous {
    A,
    B
} TypeExport __attribute__((mode(__word__)));

and

typedef enum Anonymous {
    A,
    B
} __attribute__((mode(__word__))) TypeExport;

appear to be different: In the first case the attribute (__attribute__((mode(__word__))) means "size of the type is a machine word") only applies to the typedef TypeExport, while in the second case the attribute applies directly to enum Anonymous and then transitively to TypeExport. I confirmed that by looking at LLVM output from two different clang versions (windows and ubuntu). See the following example output.

Ubuntu LLVM output
bash $ clang --version
Ubuntu clang version 14.0.0-1ubuntu1.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
bash $ cat old.c
typedef enum Anonymous {
    A,
    B
} TypeExport __attribute__((mode(__word__)));

void some_function(enum Anonymous anonymous_input, TypeExport typed) {}
bash $ clang -S -emit-llvm old.c && cat old.ll
; ModuleID = 'old.c'
source_filename = "old.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @some_function(i32 noundef %0, i64 noundef %1) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i64, align 8
  store i32 %0, i32* %3, align 4
  store i64 %1, i64* %4, align 8
  ret void
}

attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"}
bash $ cat new.c
typedef enum Anonymous {
    A,
    B
} __attribute__((mode(__word__))) TypeExport;

void some_function(enum Anonymous anonymous_input, TypeExport typed) {}
bash $ clang -S -emit-llvm new.c && cat new.ll
; ModuleID = 'new.c'
source_filename = "new.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @some_function(i64 noundef %0, i64 noundef %1) #0 {
  %3 = alloca i64, align 8
  %4 = alloca i64, align 8
  store i64 %0, i64* %3, align 8
  store i64 %1, i64* %4, align 8
  ret void
}

attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"}
bash $ 

I would wish that annotating an attribute on the typedef would be forbidded in C and users would have to apply attributes to the enumeration itself, but this appears to be legal so bindgen should be able to handle that correctly.

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

1 participant