2929
3030typedef void (* ctest_void_func )(void );
3131
32+ /* Query a pointer to string constants.
33+ *
34+ * Define a function that returns a pointer to the value of the constant to test.
35+ * This will later be called on the Rust side via FFI.
36+ */
3237{%- for const_cstr in ctx .const_cstr_tests + %}
3338
3439static char * ctest_const_ {{ const_cstr .id }}_val_static = {{ const_cstr .c_val }};
3540
36- // Define a function that returns a pointer to the value of the constant to test.
37- // This will later be called on the Rust side via FFI.
3841CTEST_EXTERN char * ctest_const_cstr__ {{ const_cstr .id }}(void ) {
3942 return ctest_const_ {{ const_cstr .id }}_val_static ;
4043}
4144{%- endfor + %}
4245
46+
47+ /* Query a pointer to non-string constants.
48+ *
49+ * Define a function that returns a pointer to the value of the constant to test.
50+ * This will later be called on the Rust side via FFI.
51+ */
4352{%- for constant in ctx .const_tests + %}
4453
4554static {{ constant .c_ty }} ctest_const_ {{ constant .id }}_val_static = {{ constant .c_val }};
4655
47- // Define a function that returns a pointer to the value of the constant to test.
48- // This will later be called on the Rust side via FFI.
4956CTEST_EXTERN {{ constant .c_ty }} * ctest_const__ {{ constant .id }}(void ) {
5057 return & ctest_const_ {{ constant .id }}_val_static ;
5158}
5259{%- endfor + %}
5360
61+
62+ /* Query the size and alignment of all types */
5463{%- for item in ctx .size_align_tests + %}
5564
56- // Return the size of a type.
5765CTEST_EXTERN uint64_t ctest_size_of__ {{ item .id }}(void ) { return sizeof ({{ item .c_ty }}); }
58-
59- // Return the alignment of a type.
6066CTEST_EXTERN uint64_t ctest_align_of__ {{ item .id }}(void ) { return CTEST_ALIGNOF ({{ item .c_ty }}); }
6167{%- endfor + %}
6268
69+
70+ /* Query the signedness of a type.
71+ *
72+ * Return `1` if the type is signed, otherwise return `0`.
73+ * Casting -1 to the aliased type if signed evaluates to `-1 < 0`, if unsigned to `MAX_VALUE < 0`
74+ */
6375{%- for alias in ctx .signededness_tests + %}
6476
65- // Return `1` if the type is signed, otherwise return `0`.
66- // Casting -1 to the aliased type if signed evaluates to `-1 < 0`, if unsigned to `MAX_VALUE < 0`
6777CTEST_EXTERN uint32_t ctest_signededness_of__ {{ alias .id }}(void ) {
6878 {{ alias .c_ty }} all_ones = ({{ alias .c_ty }}) - 1 ;
6979 return all_ones < 0 ;
7080}
7181{%- endfor + %}
7282
83+
84+ /* Query the offsets of fields and their sizes. */
7385{%- for item in ctx .field_size_offset_tests + %}
7486
75- // Return the offset of a struct/union field.
7687CTEST_EXTERN uint64_t ctest_offset_of__ {{ item .id }}__ {{ item .field .ident () }}(void ) {
7788 return offsetof({{ item .c_ty }}, {{ item .c_field }});
7889}
7990
80- // Return the size of a struct/union field.
8191CTEST_EXTERN uint64_t ctest_size_of__ {{ item .id }}__ {{ item .field .ident () }}(void ) {
8292 return sizeof ((({{ item .c_ty }}){}).{{ item .c_field }});
8393}
8494{%- endfor + %}
8595
96+
97+ /* Query a pointer to a field given a pointer to its struct */
8698{%- for item in ctx .field_ptr_tests + %}
8799
88- // Return a pointer to a struct/union field.
89- // This field can have a normal data type, or it could be a function pointer or an array, which
90- // have different syntax. A typedef is used for convenience, but the syntax must be precomputed.
100+ {#
101+ // This field can have a normal data type, or it could be a function pointer or an array, which
102+ // have different syntax. A typedef is used for convenience, but the syntax must be precomputed.
103+ #}
91104typedef {{ item .volatile_keyword }}{{ item .field_return_type }};
92105CTEST_EXTERN ctest_field_ty__ {{ item .id }}__ {{ item .field .ident () }}
93106ctest_field_ptr__ {{ item .id }}__ {{ item .field .ident () }}({{ item .c_ty }} * b ) {
@@ -107,28 +120,38 @@ ctest_field_ptr__{{ item.id }}__{{ item.field.ident() }}({{ item.c_ty }} *b) {
107120 #pragma GCC diagnostic ignored "-Wignored-qualifiers"
108121#endif
109122
123+
124+ /* Write a nonrepeating bitpattern to a data type
125+ *
126+ * Tests whether the struct/union/alias `x` when passed by value to C and back to Rust
127+ * remains unchanged.
128+ * It checks if the size is the same as well as if the padding bytes are all in the correct place.
129+ */
110130{%- for item in ctx .roundtrip_tests + %}
111131
112- // Tests whether the struct/union/alias `x` when passed by value to C and back to Rust
113- // remains unchanged.
114- // It checks if the size is the same as well as if the padding bytes are all in the correct place.
115132CTEST_EXTERN {{ item .c_ty }} ctest_roundtrip__ {{ item .id }}(
116133 {{ item .c_ty }} value ,
117134 const uint8_t is_padding_byte [sizeof ({{ item .c_ty }})],
118135 uint8_t value_bytes [sizeof ({{ item .c_ty }})]
119136) {
120137 int size = (int )sizeof ({{ item .c_ty }});
121- // Mark `p` as volatile so that the C compiler does not optimize away the pattern we create.
122- // Otherwise the Rust side would not be able to see it.
138+ {#
139+ // Mark `p` as volatile so that the C compiler does not optimize away the pattern we create.
140+ // Otherwise the Rust side would not be able to see it.
141+ #}
123142 volatile uint8_t * p = (volatile uint8_t * )& value ;
124143 int i = 0 ;
125144 for (i = 0 ; i < size ; ++ i ) {
126- // We skip padding bytes in both Rust and C because writing to it is undefined.
127- // Instead we just make sure the the placement of the padding bytes remains the same.
145+ {#
146+ // We skip padding bytes in both Rust and C because writing to it is undefined.
147+ // Instead we just make sure the the placement of the padding bytes remains the same.
148+ #}
128149 if (is_padding_byte [i ]) { continue ; }
129150 value_bytes [i ] = p [i ];
130- // After we check that the pattern remained unchanged from Rust to C, we invert the pattern
131- // and send it back to Rust to make sure that it remains unchanged from C to Rust.
151+ {#
152+ // After we check that the pattern remained unchanged from Rust to C, we invert the pattern
153+ // and send it back to Rust to make sure that it remains unchanged from C to Rust.
154+ #}
132155 uint8_t d = (uint8_t )(255 ) - (uint8_t )(i % 256 );
133156 d = d == 0 ? 42 : d ;
134157 p [i ] = d ;
@@ -154,9 +177,9 @@ CTEST_EXTERN {{ item.c_ty }} ctest_roundtrip__{{ item.id }}(
154177 #pragma warning(disable:4191)
155178#endif
156179
180+ /* Query a function's pointer */
157181{%- for item in ctx .foreign_fn_tests + %}
158182
159- // Return a function pointer.
160183CTEST_EXTERN ctest_void_func ctest_foreign_fn__ {{ item .id }}(void ) {
161184 return (ctest_void_func ){{ item .c_val }};
162185}
@@ -167,11 +190,14 @@ CTEST_EXTERN ctest_void_func ctest_foreign_fn__{{ item.id }}(void) {
167190 #pragma warning(default:4191)
168191#endif
169192
193+
194+ /* Query pointers to statics */
170195{%- for static_ in ctx .foreign_static_tests + %}
171196
172- // Return a pointer to the static variable content.
173197CTEST_EXTERN void * ctest_static__ {{ static_ .id }}(void ) {
174- // FIXME(ctest): Not correct due to casting the function to a data pointer.
198+ {#
199+ // FIXME(ctest): Not correct due to casting the function to a data pointer.
200+ #}
175201 return (void * )& {{ static_ .c_val }};
176202}
177203{%- endfor + %}
0 commit comments