Skip to content

Commit

Permalink
Two test cases where Rust calls C using enums by value
Browse files Browse the repository at this point in the history
One calls into C functions passing non-c-like enumerations by
value. The other calls into C expecting non-C-like enumerations as
returns.

These test cases are based on the tests provided by @bitwalker on
issue rust-lang#68190. The original tests were provided at:
https://github.com/bitwalker/rust_non_c_like_enums_issue/tree/2688d5c672bd4e289085fcdf1c6110e99e7e8ab1
  • Loading branch information
sw17ch authored and eddyb committed Feb 8, 2020
1 parent 26bb0f1 commit 3b23b98
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-include ../tools.mk

all:
$(CC) -c test.c -o $(call STATICLIB,test) $(EXTRACFLAGS) $(EXTRACXXFLAGS)
$(RUSTC) nonclike.rs -L$(TMPDIR) -ltest
$(call RUN,nonclike)
24 changes: 24 additions & 0 deletions src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/nonclike.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![crate_type = "bin"]
#![crate_name = "nonclike"]

#[repr(C, u8)]
pub enum TT {
AA(u64, u64),
BB,
}

#[repr(C,u8)]
pub enum T {
A(u64),
B,
}

extern "C" {
pub fn t_add(a: T, b: T) -> u64;
pub fn tt_add(a: TT, b: TT) -> u64;
}

fn main() {
assert_eq!(33, unsafe { tt_add(TT::AA(1,2), TT::AA(10,20)) });
assert_eq!(11, unsafe { t_add(T::A(1), T::A(10)) });
}
85 changes: 85 additions & 0 deletions src/test/run-make-fulldeps/pass-non-c-like-enum-to-c/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <stdint.h>

/* This is the code generated by cbindgen 0.12.1 for the `enum TT`
* type in nonclike.rs . */
enum TT_Tag {
AA,
BB,
};
typedef uint8_t TT_Tag;

typedef struct {
uint64_t _0;
uint64_t _1;
} AA_Body;

typedef struct {
TT_Tag tag;
union {
AA_Body aa;
};
} TT;

/* This is the code generated by cbindgen 0.12.1 for the `enum T` type
* in nonclike.rs . */
enum T_Tag {
A,
B,
};
typedef uint8_t T_Tag;

typedef struct {
uint64_t _0;
} A_Body;

typedef struct {
T_Tag tag;
union {
A_Body a;
};
} T;

uint64_t tt_add(TT a, TT b) {
if (a.tag == AA && b.tag == AA) {
return a.aa._0 + a.aa._1 + b.aa._0 + b.aa._1;
} else if (a.tag == AA) {
return a.aa._0 + a.aa._1;
} else if (b.tag == BB) {
return b.aa._0 + b.aa._1;
} else {
return 0;
}
}

uint64_t t_add(T a, T b) {
if (a.tag == A && b.tag == A) {
return a.a._0 + b.a._0;
} else if (a.tag == AA) {
return a.a._0;
} else if (b.tag == BB) {
return b.a._0;
} else {
return 0;
}
}

TT tt_new(uint64_t a, uint64_t b) {
TT tt = {
.tag = AA,
.aa = {
._0 = a,
._1 = b,
},
};
return tt;
}

T t_new(uint64_t a) {
T t = {
.tag = A,
.a = {
._0 = a,
},
};
return t;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-include ../tools.mk

all:
$(CC) -c test.c -o $(call STATICLIB,test) $(EXTRACFLAGS) $(EXTRACXXFLAGS)
$(RUSTC) nonclike.rs -L$(TMPDIR) -ltest
$(call RUN,nonclike)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#![crate_type = "bin"]
#![crate_name = "nonclike"]

#[repr(C, u8)]
pub enum TT {
AA(u64, u64),
BB,
}

#[repr(C,u8)]
pub enum T {
A(u64),
B,
}

extern "C" {
pub fn t_new(a: u64) -> T;
pub fn tt_new(a: u64, b: u64) -> TT;
}

fn main() {
if let TT::AA(a, b) = unsafe { tt_new(10, 11) } {
assert_eq!(10, a);
assert_eq!(11, b);
} else {
panic!("expected TT::AA");
}

if let T::A(a) = unsafe { t_new(10) } {
assert_eq!(10, a);
} else {
panic!("expected T::A");
}
}
61 changes: 61 additions & 0 deletions src/test/run-make-fulldeps/return-non-c-like-enum-from-c/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <stdint.h>

/* This is the code generated by cbindgen 0.12.1 for the `enum TT`
* type in nonclike.rs . */
enum TT_Tag {
AA,
BB,
};
typedef uint8_t TT_Tag;

typedef struct {
uint64_t _0;
uint64_t _1;
} AA_Body;

typedef struct {
TT_Tag tag;
union {
AA_Body aa;
};
} TT;

/* This is the code generated by cbindgen 0.12.1 for the `enum T` type
* in nonclike.rs . */
enum T_Tag {
A,
B,
};
typedef uint8_t T_Tag;

typedef struct {
uint64_t _0;
} A_Body;

typedef struct {
T_Tag tag;
union {
A_Body a;
};
} T;

TT tt_new(uint64_t a, uint64_t b) {
TT tt = {
.tag = AA,
.aa = {
._0 = a,
._1 = b,
},
};
return tt;
}

T t_new(uint64_t a) {
T t = {
.tag = A,
.a = {
._0 = a,
},
};
return t;
}

0 comments on commit 3b23b98

Please sign in to comment.