├── .gitignore ├── test ├── cases │ ├── translate │ │ ├── empty declaration.c │ │ ├── ptr_macro.c │ │ ├── string_prefix.c │ │ ├── #define_a_char_literal.c │ │ ├── #define_string.c │ │ ├── Macro_matching.c │ │ ├── multibyte_character_literals.c │ │ ├── null_statements.c │ │ ├── const_ptr_initializer.c │ │ ├── constant_size_array.c │ │ ├── noreturn attribute.c │ │ ├── string_array_initializer.c │ │ ├── l_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── u_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── undefined_array_global.c │ │ ├── #define_an_unsigned_integer_literal.c │ │ ├── lu_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── string_concatenation_in_macros-_three_strings.c │ │ ├── ul_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── ll_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── llu_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── ull_integer_suffix_after_0_(zero)_in_macro_definition.c │ │ ├── bitwise_not_on_u-suffixed_0_(zero)_in_macro_definition.c │ │ ├── macro_with_left_shift.c │ │ ├── return_void.c │ │ ├── #define_hex_literal_with_capital_X.c │ │ ├── Undefined_macro_identifier.c │ │ ├── extern_array_of_unknown_length.c │ │ ├── function_with_no_prototype.c │ │ ├── macro_with_parens_around_negative_number.c │ │ ├── typedef_void.c │ │ ├── comments.c │ │ ├── empty_for_loop.c │ │ ├── __extension___cast.c │ │ ├── macro_keyword_define.c │ │ ├── restrict_to_noalias.c │ │ ├── macro_line_continuation.c │ │ ├── null_pointer_implicit_cast.c │ │ ├── simple_function_definition.c │ │ ├── string_literal.c │ │ ├── Macro_redefines_builtin.c │ │ ├── __cdecl_doesn't_mess_up_function_pointers.c │ │ ├── Only_consider_public_decls_in_`isBuiltinDefined`.c │ │ ├── simple function prototypes.c │ │ ├── #define_referencing_another_#define.c │ │ ├── always_inline_attribute.c │ │ ├── macro_conditional_operator.c │ │ ├── string_concatenation_in_macros-_two_strings.c │ │ ├── strlit_as_bool.c │ │ ├── comment_after_integer_literal.c │ │ ├── struct_in_macro_not_defined.c │ │ ├── l_integer_suffix_after_hex_literal.c │ │ ├── macro_using_argument_as_struct_name_is_not_translated.c │ │ ├── simple_union.c │ │ ├── u_integer_suffix_after_hex_literal.c │ │ ├── ll_integer_suffix_after_hex_literal.c │ │ ├── lu_integer_suffix_after_hex_literal.c │ │ ├── simple_struct.c │ │ ├── ul_integer_suffix_after_hex_literal.c │ │ ├── assert_with_strlit.c │ │ ├── llu_integer_suffix_after_hex_literal.c │ │ ├── ull_integer_suffix_after_hex_literal.c │ │ ├── Macro_without_a_value.c │ │ ├── void_cast.c │ │ ├── Calling_convention_aarch64.c │ │ ├── anonymous_enum.c │ │ ├── bin_not.c │ │ ├── macro_calling_convention.c │ │ ├── Parameterless_function_pointers.c │ │ ├── demote_un-implemented_builtins.c │ │ ├── duplicate_typedef.c │ │ ├── macro_call.c │ │ ├── macro_call_with_no_args.c │ │ ├── normal_deref.c │ │ ├── bitshift.c │ │ ├── break_statement.c │ │ ├── variables.c │ │ ├── variadic_function_demoted_to_extern.c │ │ ├── continue_statement.c │ │ ├── atomic types.c │ │ ├── macro_pointer_cast.c │ │ ├── zig_keywords_in_c_code.c │ │ ├── Forward-declared_enum.c │ │ ├── bitshift_with_bitcast.c │ │ ├── Use_@_syntax_for_bare_underscore_identifier_in_macro_or_public_symbol.c │ │ ├── binary_conditional_operator_result_unused.c │ │ ├── do_while_as_expr.c │ │ ├── macro_function_string_concat.c │ │ ├── simple_function.c │ │ ├── string_concatenation_in_macros-_two_defines.c │ │ ├── string_concatenation_in_macros.c │ │ ├── for_loop.c │ │ ├── macro_integer_literal_casts.c │ │ ├── pointer_casting.c │ │ ├── function prototype with parenthesis.c │ │ ├── implicit_cast_to_void_ptr.c │ │ ├── variable_declarations.c │ │ ├── packed_union_simple.c │ │ ├── macro_defines_string_literal_with_hex.c │ │ ├── macro_with_right_shift.c │ │ ├── casting_pointer_to_pointer.c │ │ ├── macro_defines_string_literal_with_octal.c │ │ ├── comma_operator.c │ │ ├── Don't_make_const_parameters_mutable.c │ │ ├── early_return.c │ │ ├── arg_name_aliasing_decl_which_comes_after.c │ │ ├── don't_export_inline_functions.c │ │ ├── leading_zeroes.c │ │ ├── self_referential_struct_with_function_pointer.c │ │ ├── unsigned_array_index_skips_cast.c │ │ ├── call_builtin_popcount.c │ │ ├── enums.c │ │ ├── static_incomplete_array_inside_function.c │ │ ├── Simple_array_access_of_pointer_with_non-negative_integer_constant.c │ │ ├── address_of_operator.c │ │ ├── arg_name_aliasing_macro_which_comes_after.c │ │ ├── assign.c │ │ ├── pointer_to_struct_demoted_opaque_due_to_bit_fields.c │ │ ├── conditional_operator_cast_to_void.c │ │ ├── enums msvc.c │ │ ├── Calling_convention_arm.c │ │ ├── bitwise_binary_operators,_simpler_parens.c │ │ ├── bool_array_index.c │ │ ├── cast_signed_array_index_to_unsigned.c │ │ ├── for_loop_with_simple_init_expression.c │ │ ├── typedeffed_bool_expression.c │ │ ├── long_long_array_index_cast_to_usize.c │ │ ├── floats.c │ │ ├── struct prototype used in func.c │ │ ├── macro_with_nontrivial_cast.c │ │ ├── statement_expression.c │ │ ├── Demote_function_that_dereferences_opaque_type.c │ │ ├── function_call.c │ │ ├── global_struct_whose_default_name_conflicts_with_global_is_mangled.c │ │ ├── correct_semicolon_after_infixop.c │ │ ├── use_cast_param_as_macro_fn_return_type.c │ │ ├── unnamed_typedef_referencing_itself.c │ │ ├── circular_struct_definitions.c │ │ ├── complex_switch.c │ │ ├── nested_loops_without_blocks.c │ │ ├── Function_prototype_declared_within_function.c │ │ ├── macro_pointer_type_argument.c │ │ ├── Assign_expression_from_bool_to_int.c │ │ ├── conditional_operator.c │ │ ├── global_assembly.c │ │ ├── struct_initializer_-_packed.c │ │ ├── empty union initializer list.c │ │ ├── missing_return_stmt.c │ │ ├── shadowing_primitive_types.c │ │ ├── worst-case_assign.c │ │ ├── unnamed_child_types_of_typedef_receive_typedef's_name.c │ │ ├── ==,_!=.c │ │ ├── pointer_to_opaque_demoted_struct.c │ │ ├── void_pointer_subtraction.c │ │ ├── worst-case_assign_from_mangle_prefix.c │ │ ├── worst-case_assign_to_mangle_prefix.c │ │ ├── member_with_const_qualifier.c │ │ ├── c_booleans_are_just_ints.c │ │ ├── ignore_result,_explicit_function_arguments.c │ │ ├── linksection()_attribute.c │ │ ├── shift_right_assign.c │ │ ├── worst-case_compound_assign_to_mangle_prefix.c │ │ ├── alignof.c │ │ ├── chaining_assign.c │ │ ├── large_packed_struct.c │ │ ├── typedef_of_function_in_struct_field.c │ │ ├── worst-case_compound_assign_from_mangle_prefix.c │ │ ├── Make_sure_casts_are_grouped.c │ │ ├── Pointer_subtraction_with_typedef_linux.c │ │ ├── macro_defines_hexadecimal_float.c │ │ ├── cast_array_to_pointer.c │ │ ├── double_define_struct.c │ │ ├── if_as_while_stmt_has_semicolon.c │ │ ├── widening_and_truncating_integer_casting_to_different_signedness.c │ │ ├── Pointer_subtraction_with_typedef_windows.c │ │ ├── align() attribute.c │ │ ├── if_statements.c │ │ ├── macro_comparisons.c │ │ ├── nameless_struct_fields_linux.c │ │ ├── shift_right_assign_with_a_fixed_size_type.c │ │ ├── discard_unused_local_variables_and_function_parameters.c │ │ ├── struct_with_atomic_field.c │ │ ├── logical_and,_logical_or.c │ │ ├── field_access_is_grouped_if_necessary.c │ │ ├── simple_data_types.c │ │ ├── unsupport_declare_statement_at_the_last_of_a_compound_statement_which_belongs_to_a_statement_expr.c │ │ ├── Parameterless_function_prototypes.c │ │ ├── macro_with_cast_to_unsigned_short,_long,_and_long_long.c │ │ ├── Demote_function_that_initializes_opaque_struct.c │ │ ├── union_initializer.c │ │ ├── array_initializer_with_typedef.c │ │ ├── macro_cast.c │ │ ├── _Static_assert.c │ │ ├── macro_referencing_var.c │ │ ├── static_variable_in_block_scope.c │ │ ├── struct_in_struct_init_to_zero.c │ │ ├── type_referenced_struct.c │ │ ├── simple_if_statement.c │ │ ├── array_access.c │ │ ├── worst-case_precrement_mangle_prefix.c │ │ ├── Demote_function_that_dereference_types_that_contain_opaque_type.c │ │ ├── basic_macro_function.c │ │ ├── macro_add.c │ │ ├── nested_assignment.c │ │ ├── static empty struct.c │ │ ├── sizeof.c │ │ ├── for_on_non-bool.c │ │ ├── c_style_cast.c │ │ ├── variables_check_for_opaque_demotion.c │ │ ├── while_on_non-bool.c │ │ ├── zero_width_field_alignment_.c │ │ ├── static_local_variable_zero-initialized_if_no_initializer.c │ │ ├── worst-case_postcrement_mangle_prefix.c │ │ ├── nameless_struct_fields_MSVC.c │ │ ├── packed_union_nested_unpacked.c │ │ ├── simple_ptrCast_for_casts_between_opaque_types.c │ │ ├── unnamed_fields_have_predictable_names.c │ │ ├── handling_of__Bool_type.c │ │ ├── qualified_struct_and_enum.c │ │ ├── for_loops.c │ │ ├── casting_away_const_and_volatile.c │ │ ├── qualified_struct_and_enum_msvc.c │ │ ├── bool_not.c │ │ ├── extern_local_used_in_nested_block.c │ │ ├── post_increment.c │ │ ├── union_struct_forward_decl.c │ │ ├── Calling_convention_x86.c │ │ ├── function_prototype_translated_as_optional.c │ │ ├── zero_width_field_alignment_msvc.c │ │ ├── binary_conditional_operator_where_condition_is_the_mangle_prefix.c │ │ ├── binary_conditional_operator_where_false_expr_is_the_mangle_prefix.c │ │ ├── predefined_expressions.c │ │ ├── deref_function_pointer.c │ │ ├── anonymous_struct_&_unions.c │ │ ├── variable_aliasing.c │ │ ├── macro_comma_operator.c │ │ ├── struct_with_flexible_array.c │ │ ├── casting_pointers_to_ints_and_ints_to_pointers.c │ │ ├── struct_with_aligned_fields.c │ │ ├── member_access_in_struct_with_union_as_const_arg.c │ │ ├── array_access_with_enum.c │ │ ├── do_loop.c │ │ ├── self_referential_init.c │ │ ├── if_on_non-bool.c │ │ ├── field_access_expression.c │ │ ├── generate_inline_func_for_#define_global_extern_fn.c │ │ ├── casting_to_and_from_bool.c │ │ ├── simple_var_decls.c │ │ ├── while_loops.c │ │ ├── comparison_operators_(no_if).c │ │ ├── escape_sequences.c │ │ ├── pre_increment_and_decrement.c │ │ ├── do_while_with_breaks.c │ │ ├── float_suffixes.c │ │ ├── scoped_typedef.c │ │ ├── struct_with_invalid_field_alignment.c │ │ ├── scoped_record.c │ │ ├── integer_literal_promotion.c │ │ ├── add,_sub,_mul,_div,_rem.c │ │ ├── macros_with_field_targets.c │ │ ├── post_increment_and_decrement.c │ │ ├── macro_expressions_respect_C_operator_precedence.c │ │ ├── enums_linux.c │ │ ├── enums_MSVC.c │ │ └── float_types.c │ └── run │ │ ├── float_from_bool_expr_cast.c │ │ ├── parenthesized_string_literal.c │ │ ├── K&R-style_static_function_prototype_for_unused_function.c │ │ ├── variable_shadowing_type_type.c │ │ ├── forward_declaration_of_variable.c │ │ ├── explicit_cast_bool_from_float.c │ │ ├── NDEBUG_disables_assert.c │ │ ├── assignment_as_expression.c │ │ ├── Typedef'ed_void_used_as_return_type.c │ │ ├── case_boolean_and_lt.c │ │ ├── dereference address of.c │ │ ├── Variadic_function_call.c │ │ ├── Nested_comma_operator_in_macro.c │ │ ├── Render_array_LHS_as_grouped_node_if_necessary.c │ │ ├── Zero-initialization_of_global_union.c │ │ ├── Use_correct_break_label_for_statement_expression_in_nested_scope.c │ │ ├── cast_signed_array_index_to_unsigned.c │ │ ├── forward_declarations.c │ │ ├── hello_world.c │ │ ├── Closure_over_local_in_typeof.c │ │ ├── cast_long_long_array_index_to_unsigned.c │ │ ├── case_boolean_expression_converted_to_int.c │ │ ├── enum_used_as_boolean_expression.c │ │ ├── enum_with_value_that_fits_in_c_uint_but_not_c_int.c │ │ ├── function_macro_that_uses_builtin.c │ │ ├── handle_assert.h.c │ │ ├── case_boolean_expression_on_left_converted_to_int.c │ │ ├── static_K&R-style_no_prototype_function_declaration_(empty_parameter_list).c │ │ ├── case_boolean_and_plus_converts_bool_to_int.c │ │ ├── multi-character_character_constant.c │ │ ├── scoped_typedef.c │ │ ├── static_variable_in_block_scope.c │ │ ├── Underscore_identifiers.c │ │ ├── case_boolean_and_asterisk.c │ │ ├── anon_struct_init.c │ │ ├── failed_macros_are_only_declared_once.c │ │ ├── K&R-style_static_function_prototype_+_separate_definition.c │ │ ├── typedef_with_multiple_names.c │ │ ├── assign_enum_to_int.c │ │ ├── Boolean_expression_coerced_to_int.c │ │ ├── scoped_for_loops_with_shadowing.c │ │ ├── assign_bool_result_to_int_or_char.c │ │ ├── assign_enum_to_uint,_no_explicit_cast.c │ │ ├── division_of_floating_literals.c │ │ ├── Cast_to_enum_from_larger_integral_type.c │ │ ├── Comma_operator_should_create_new_scope.c │ │ ├── Remainder_operator_with_negative_integers.c │ │ ├── cast_enum_to_smaller_uint.c │ │ ├── Enum_constant_matches_enum_name,_multiple_enumerations_with_same_value.c │ │ ├── cast_enum_to_smaller_signed_int.c │ │ ├── casting_away_const_and_volatile.c │ │ ├── use_global_scope_for_record_enum_typedef_type_translation_if_needed.c │ │ ├── cast_builtin_call_result_to_opaque_struct_pointer.c │ │ ├── cast_negative_enum_to_smaller_signed_int.c │ │ ├── array_initializer.c │ │ ├── struct_without_global_declaration_does_not_conflict_with_local_variable_name.c │ │ ├── use_of_unimplemented_builtin_in_unused_function_does_not_prevent_compilation.c │ │ ├── array_cast_int_to_uint.c │ │ ├── cast_negative_enum_to_smaller_unsigned_int.c │ │ ├── sizeof.c │ │ ├── struct_without_global_declaration_does_not_conflict_with_global_variable_name.c │ │ ├── array_value_type_casts_properly.c │ │ ├── array_to_pointer_decay.c │ │ ├── __builtin_choose_expr_(unchosen_expression_is_not_evaluated).c │ │ ├── implicit_enum_cast_in_boolean_expression.c │ │ ├── block-scope_static_variable_shadows_function_parameter.c │ │ ├── struct_initializer_-_packed.c │ │ ├── Compound_literals.c │ │ ├── compound_assignments_with_implicit_casts.c │ │ ├── pointer_difference-_array_of_function_pointers.c │ │ ├── ensure_array_casts_outside_addeq.c │ │ ├── ternary_operator.c │ │ ├── typedef_and_function_pointer.c │ │ ├── Scoped_enums.c │ │ ├── dollar_sign_in_identifiers.c │ │ ├── compound_assignments_with_pointer_arithmetic.c │ │ ├── array_value_type_casts_properly_use_addeq.c │ │ ├── __builtin_convertvector_float_to_int.c │ │ ├── anonymous_struct_&_unions.c │ │ ├── Cast_boolean_expression_result_to_int.c │ │ ├── Ensure_side-effects_only_evaluated_once_for_signed_array_indices.c │ │ ├── Function_to_integral.c │ │ ├── Ensure_while_loop_under_an_if_doesn't_steal_the_else.c │ │ ├── pointer_difference-_unary_operators.c │ │ ├── convert_single-statement_bodies_into_blocks_for_if,else,for,while.c │ │ ├── extern_typedef_variables_in_functions.c │ │ ├── Enum_constants_are_assigned_correct_type.c │ │ ├── boolean_values_and_expressions.c │ │ ├── Wide,_UTF-16,_and_UTF-32_character_literals.c │ │ ├── switch_case.c │ │ ├── Flexible_array_with_typedefed_flexible_item.c │ │ ├── Cast-to-union.c │ │ ├── nested_same-name_static_locals.c │ │ ├── Allow_non-const_char_ptr_string_literals.c │ │ ├── typeof_operator.c │ │ ├── __cleanup___attribute.c │ │ ├── __builtin_convertvector.c │ │ ├── Address_of_function_is_no-op.c │ │ ├── pointer_difference-_struct_array_with_padding.c │ │ ├── pointer_difference-_scalar_array_with_size_truncation_or_negative_result.c │ │ ├── out-ofscope_function_declaration.c │ │ ├── basic_vector_expressions.c │ │ ├── vector_casting.c │ │ ├── Wide,_UTF-16,_and_UTF-32_string_literals.c │ │ ├── signed_array_subscript.c │ │ ├── pointer_difference-_C_standard_edge_case.c │ │ ├── Flexible_arrays.c │ │ ├── Obscure_ways_of_calling_functions.c │ │ ├── Generic_selections.c │ │ ├── cast_RHS_of_compound_assignment_if_necessary,_unused_result.c │ │ ├── Return_boolean_expression_as_int.c │ │ ├── pointer_arithmetic_with_signed_operand.c │ │ ├── break_from_switch_statement.c │ │ ├── cast_RHS_of_compound_assignment_if_necessary,_used_result.c │ │ ├── offsetof.c │ │ └── NAN_and_INFINITY.c └── macros_not_utf8.h ├── examples ├── use_static_lib │ ├── libfoo │ │ ├── add.c │ │ ├── add.h │ │ ├── print.h │ │ └── print.c │ ├── main.zig │ └── build.zig.zon ├── import_header │ ├── header.h │ ├── main.zig │ └── build.zig.zon ├── compile_c │ ├── main.c │ └── build.zig.zon ├── build.zig.zon └── build.zig ├── .gitattributes └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .zig-cache/ 2 | zig-out/ 3 | -------------------------------------------------------------------------------- /test/cases/translate/empty declaration.c: -------------------------------------------------------------------------------- 1 | ; 2 | 3 | //translate 4 | // -------------------------------------------------------------------------------- /examples/use_static_lib/libfoo/add.c: -------------------------------------------------------------------------------- 1 | int foo_add(int x, int y) { 2 | return x + y; 3 | } 4 | -------------------------------------------------------------------------------- /test/macros_not_utf8.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziglang/translate-c/main/test/macros_not_utf8.h -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.zig text eol=lf 2 | *.zon text eol=lf 3 | *.txt text eol=lf 4 | *.c text eol=lf 5 | *.h text eol=lf 6 | -------------------------------------------------------------------------------- /test/cases/translate/ptr_macro.c: -------------------------------------------------------------------------------- 1 | #define PTR void* 2 | 3 | // translate 4 | // 5 | // pub const PTR = ?*anyopaque; 6 | -------------------------------------------------------------------------------- /test/cases/translate/string_prefix.c: -------------------------------------------------------------------------------- 1 | #define foo L"hello" 2 | 3 | // translate 4 | // 5 | // pub const foo = "hello"; 6 | -------------------------------------------------------------------------------- /test/cases/translate/#define_a_char_literal.c: -------------------------------------------------------------------------------- 1 | #define A_CHAR 'a' 2 | 3 | // translate 4 | // 5 | // pub const A_CHAR = 'a'; 6 | -------------------------------------------------------------------------------- /test/cases/translate/#define_string.c: -------------------------------------------------------------------------------- 1 | #define foo "a string" 2 | 3 | // translate 4 | // 5 | // pub const foo = "a string"; 6 | -------------------------------------------------------------------------------- /test/cases/run/float_from_bool_expr_cast.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | float f = (float)(10.0f > 1.0f); 3 | return 0; 4 | } 5 | 6 | // run 7 | -------------------------------------------------------------------------------- /test/cases/translate/Macro_matching.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) (X ## U) 2 | 3 | // translate 4 | // 5 | // pub const FOO = __helpers.U_SUFFIX; 6 | -------------------------------------------------------------------------------- /test/cases/translate/multibyte_character_literals.c: -------------------------------------------------------------------------------- 1 | #define FOO 'abcd' 2 | 3 | // translate 4 | // 5 | // pub const FOO = 0x61626364; 6 | -------------------------------------------------------------------------------- /examples/import_header/header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MY_MACRO 12 4 | 5 | int my_add(int a, int b) { 6 | return a + b; 7 | } 8 | -------------------------------------------------------------------------------- /test/cases/run/parenthesized_string_literal.c: -------------------------------------------------------------------------------- 1 | void foo(const char *s) {} 2 | int main(void) { 3 | foo(("bar")); 4 | } 5 | 6 | // run 7 | -------------------------------------------------------------------------------- /test/cases/translate/null_statements.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | ;;;;; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() void {} 8 | -------------------------------------------------------------------------------- /test/cases/run/K&R-style_static_function_prototype_for_unused_function.c: -------------------------------------------------------------------------------- 1 | static int foo(); 2 | int main() { 3 | return 0; 4 | } 5 | 6 | // run 7 | -------------------------------------------------------------------------------- /test/cases/translate/const_ptr_initializer.c: -------------------------------------------------------------------------------- 1 | static const char *v0 = "0.0.0"; 2 | 3 | // translate 4 | // 5 | // pub var v0: [*c]const u8 = "0.0.0"; 6 | -------------------------------------------------------------------------------- /test/cases/translate/constant_size_array.c: -------------------------------------------------------------------------------- 1 | void func(int array[20]); 2 | 3 | // translate 4 | // 5 | // pub extern fn func(array: [*c]c_int) void; 6 | -------------------------------------------------------------------------------- /test/cases/translate/noreturn attribute.c: -------------------------------------------------------------------------------- 1 | void foo(void) __attribute__((noreturn)); 2 | 3 | // translate 4 | // 5 | // pub extern fn foo() noreturn; 6 | -------------------------------------------------------------------------------- /test/cases/translate/string_array_initializer.c: -------------------------------------------------------------------------------- 1 | static const char foo[] = {"bar"}; 2 | 3 | // translate 4 | // 5 | // pub const foo: [3:0]u8 = "bar".*; 6 | -------------------------------------------------------------------------------- /test/cases/run/variable_shadowing_type_type.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int type = 1; 4 | if (type != 1) abort(); 5 | } 6 | 7 | // run 8 | -------------------------------------------------------------------------------- /test/cases/translate/l_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0L 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_long, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/u_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0U 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_uint, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/undefined_array_global.c: -------------------------------------------------------------------------------- 1 | int array[100] = {}; 2 | 3 | // translate 4 | // 5 | // pub export var array: [100]c_int = [1]c_int{0} ** 100; 6 | -------------------------------------------------------------------------------- /test/cases/translate/#define_an_unsigned_integer_literal.c: -------------------------------------------------------------------------------- 1 | #define CHANNEL_COUNT 24 2 | 3 | // translate 4 | // 5 | // pub const CHANNEL_COUNT = @as(c_int, 24); 6 | -------------------------------------------------------------------------------- /test/cases/translate/lu_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0LU 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_ulong, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/string_concatenation_in_macros-_three_strings.c: -------------------------------------------------------------------------------- 1 | #define FOO "a" "b" "c" 2 | 3 | // translate 4 | // 5 | // pub const FOO = "a" ++ "b" ++ "c"; 6 | -------------------------------------------------------------------------------- /test/cases/translate/ul_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0UL 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_ulong, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/ll_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0LL 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_longlong, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/llu_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0LLU 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_ulonglong, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/ull_integer_suffix_after_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define ZERO 0ULL 2 | 3 | // translate 4 | // 5 | // pub const ZERO = @as(c_ulonglong, 0); 6 | -------------------------------------------------------------------------------- /examples/use_static_lib/libfoo/add.h: -------------------------------------------------------------------------------- 1 | #ifndef FOO_ADD_H 2 | #define FOO_ADD_H 3 | 4 | // Add `x` to `y`, and return the result. 5 | int foo_add(int x, int y); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /test/cases/translate/bitwise_not_on_u-suffixed_0_(zero)_in_macro_definition.c: -------------------------------------------------------------------------------- 1 | #define NOT_ZERO (~0U) 2 | 3 | // translate 4 | // 5 | // pub const NOT_ZERO = ~@as(c_uint, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/macro_with_left_shift.c: -------------------------------------------------------------------------------- 1 | #define REDISMODULE_READ (1<<0) 2 | 3 | // translate 4 | // 5 | // pub const REDISMODULE_READ = @as(c_int, 1) << @as(c_int, 0); 6 | -------------------------------------------------------------------------------- /test/cases/translate/return_void.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | return; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() void { 8 | // return; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/run/forward_declaration_of_variable.c: -------------------------------------------------------------------------------- 1 | extern int a; 2 | int a; 3 | int a = 1; 4 | int a; 5 | extern int a; 6 | 7 | // translate 8 | // 9 | // pub export var a: c_int = 1; -------------------------------------------------------------------------------- /test/cases/translate/#define_hex_literal_with_capital_X.c: -------------------------------------------------------------------------------- 1 | #define VAL 0XF00D 2 | 3 | // translate 4 | // 5 | // pub const VAL = __helpers.promoteIntLiteral(c_int, 0xF00D, .hex); 6 | -------------------------------------------------------------------------------- /examples/use_static_lib/libfoo/print.h: -------------------------------------------------------------------------------- 1 | #ifndef FOO_PRINT_H 2 | #define FOO_PRINT_H 3 | 4 | // Simple `printf` wrapper. 5 | void foo_print(const char *format, ...); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /examples/use_static_lib/main.zig: -------------------------------------------------------------------------------- 1 | const foo = @import("foo"); 2 | pub fn main() void { 3 | const result = foo.foo_add(1, 2); 4 | foo.foo_print("1 + 2 = %d\n", result); 5 | } 6 | -------------------------------------------------------------------------------- /test/cases/run/explicit_cast_bool_from_float.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | float f = 2.0f; 5 | bool b = (bool) f; 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/NDEBUG_disables_assert.c: -------------------------------------------------------------------------------- 1 | #define NDEBUG 2 | #include 3 | int main() { 4 | assert(0); 5 | assert(NULL); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/assignment_as_expression.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int a, b, c, d = 5; 4 | int e = a = b = c = d; 5 | if (e != 5) abort(); 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/translate/Undefined_macro_identifier.c: -------------------------------------------------------------------------------- 1 | #define FOO BAR 2 | 3 | // translate 4 | // 5 | // pub const FOO = @compileError("unable to translate macro: undefined identifier `BAR`"); 6 | -------------------------------------------------------------------------------- /test/cases/translate/extern_array_of_unknown_length.c: -------------------------------------------------------------------------------- 1 | extern int foo[]; 2 | 3 | // translate 4 | // 5 | // const foo: [*c]c_int = @extern([*c]c_int, .{ 6 | // .name = "foo", 7 | // }); 8 | -------------------------------------------------------------------------------- /test/cases/translate/function_with_no_prototype.c: -------------------------------------------------------------------------------- 1 | int foo() { 2 | return 5; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() c_int { 8 | // return 5; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/macro_with_parens_around_negative_number.c: -------------------------------------------------------------------------------- 1 | #define LUA_GLOBALSINDEX (-10002) 2 | 3 | // translate 4 | // 5 | // pub const LUA_GLOBALSINDEX = -@as(c_int, 10002); 6 | -------------------------------------------------------------------------------- /test/cases/translate/typedef_void.c: -------------------------------------------------------------------------------- 1 | typedef void Foo; 2 | Foo fun(Foo *a); 3 | 4 | // translate 5 | // 6 | // pub const Foo = anyopaque; 7 | // 8 | // pub extern fn fun(a: ?*Foo) void; 9 | -------------------------------------------------------------------------------- /test/cases/run/Typedef'ed_void_used_as_return_type.c: -------------------------------------------------------------------------------- 1 | typedef void V; 2 | V foo(V *f) {} 3 | int main(void) { 4 | int x = 0; 5 | foo(&x); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/comments.c: -------------------------------------------------------------------------------- 1 | #define foo 1 //foo 2 | #define bar /* bar */ 2 3 | 4 | // translate 5 | // 6 | // pub const foo = @as(c_int, 1); 7 | // 8 | // pub const bar = @as(c_int, 2); 9 | -------------------------------------------------------------------------------- /test/cases/translate/empty_for_loop.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | for (;;) { } 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() void { 8 | // while (true) {} 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/run/case_boolean_and_lt.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int value = (8 == 9) < 3; 4 | if (value == 0) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/run/dereference address of.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int i = 0; 4 | *&i = 42; 5 | if (i != 42) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/__extension___cast.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | return __extension__ 1; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() c_int { 8 | // return 1; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/macro_keyword_define.c: -------------------------------------------------------------------------------- 1 | #define foo 1 2 | #define inline 2 3 | 4 | // translate 5 | // 6 | // pub const foo = @as(c_int, 1); 7 | // 8 | // pub const @"inline" = @as(c_int, 2); 9 | -------------------------------------------------------------------------------- /test/cases/translate/restrict_to_noalias.c: -------------------------------------------------------------------------------- 1 | void foo(void *restrict bar, void *restrict); 2 | 3 | // translate 4 | // 5 | // pub extern fn foo(noalias bar: ?*anyopaque, noalias ?*anyopaque) void; 6 | -------------------------------------------------------------------------------- /test/cases/translate/macro_line_continuation.c: -------------------------------------------------------------------------------- 1 | int BAR = 0; 2 | #define FOO -\ 3 | BAR 4 | 5 | // translate 6 | // 7 | // pub inline fn FOO() @TypeOf(-BAR) { 8 | // return -BAR; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/null_pointer_implicit_cast.c: -------------------------------------------------------------------------------- 1 | int* foo(void) { 2 | return 0; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() [*c]c_int { 8 | // return null; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/simple_function_definition.c: -------------------------------------------------------------------------------- 1 | void foo(void) {} 2 | static void bar(void) {} 3 | 4 | // translate 5 | // 6 | // pub export fn foo() void {} 7 | // pub fn bar() callconv(.c) void {} 8 | -------------------------------------------------------------------------------- /test/cases/translate/string_literal.c: -------------------------------------------------------------------------------- 1 | const char *foo(void) { 2 | return "bar"; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() [*c]const u8 { 8 | // return "bar"; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/Macro_redefines_builtin.c: -------------------------------------------------------------------------------- 1 | #define FOO __builtin_popcount 2 | 3 | // translate 4 | // 5 | // pub const __builtin = @import("c_builtins"); 6 | // 7 | // pub const FOO = __builtin.popcount; 8 | -------------------------------------------------------------------------------- /test/cases/translate/__cdecl_doesn't_mess_up_function_pointers.c: -------------------------------------------------------------------------------- 1 | void foo(void (__cdecl *fn_ptr)(void)); 2 | 3 | // translate 4 | // 5 | // pub extern fn foo(fn_ptr: ?*const fn () callconv(.c) void) void; 6 | -------------------------------------------------------------------------------- /test/cases/run/Variadic_function_call.c: -------------------------------------------------------------------------------- 1 | #define _NO_CRT_STDIO_INLINE 1 2 | #include 3 | int main(void) { 4 | printf("%d %d", 1, 2); 5 | return 0; 6 | } 7 | 8 | // run 9 | // 10 | // 1 2 11 | -------------------------------------------------------------------------------- /test/cases/translate/Only_consider_public_decls_in_`isBuiltinDefined`.c: -------------------------------------------------------------------------------- 1 | #define FOO std 2 | 3 | // translate 4 | // 5 | // pub const FOO = @compileError("unable to translate macro: undefined identifier `std`"); 6 | -------------------------------------------------------------------------------- /test/cases/translate/simple function prototypes.c: -------------------------------------------------------------------------------- 1 | void __attribute__((noreturn)) foo(void); 2 | int bar(void); 3 | 4 | // translate 5 | // 6 | // pub extern fn foo() noreturn; 7 | // pub extern fn bar() c_int; 8 | -------------------------------------------------------------------------------- /test/cases/run/Nested_comma_operator_in_macro.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define FOO (1, (2, 3)) 3 | int main(void) { 4 | int x = FOO; 5 | if (x != 3) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/#define_referencing_another_#define.c: -------------------------------------------------------------------------------- 1 | #define THING2 THING1 2 | #define THING1 1234 3 | 4 | // translate 5 | // 6 | // pub const THING1 = @as(c_int, 1234); 7 | // 8 | // pub const THING2 = THING1; 9 | -------------------------------------------------------------------------------- /test/cases/translate/always_inline_attribute.c: -------------------------------------------------------------------------------- 1 | __attribute__((always_inline)) int foo() { 2 | return 5; 3 | } 4 | 5 | // translate 6 | // 7 | // pub inline fn foo() c_int { 8 | // return 5; 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/macro_conditional_operator.c: -------------------------------------------------------------------------------- 1 | int a, b, c; 2 | #define FOO a ? b : c 3 | 4 | // translate 5 | // 6 | // pub inline fn FOO() @TypeOf(if (a) b else c) { 7 | // return if (a) b else c; 8 | // } 9 | -------------------------------------------------------------------------------- /test/cases/translate/string_concatenation_in_macros-_two_strings.c: -------------------------------------------------------------------------------- 1 | #define FOO "a" "b" 2 | #define BAR FOO "c" 3 | 4 | // translate 5 | // 6 | // pub const FOO = "a" ++ "b"; 7 | // 8 | // pub const BAR = FOO ++ "c"; 9 | -------------------------------------------------------------------------------- /test/cases/translate/strlit_as_bool.c: -------------------------------------------------------------------------------- 1 | void foo() { if(0 && "error message") {} } 2 | 3 | // translate 4 | // 5 | // pub export fn foo() void { 6 | // if (false and (@intFromPtr("error message") != 0)) {} 7 | // } 8 | -------------------------------------------------------------------------------- /test/cases/run/Render_array_LHS_as_grouped_node_if_necessary.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int arr[] = {40, 41, 42, 43}; 4 | if ((arr + 1)[1] != 42) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/run/Zero-initialization_of_global_union.c: -------------------------------------------------------------------------------- 1 | #include 2 | union U { int x; double y; }; 3 | union U u; 4 | int main(void) { 5 | if (u.x != 0) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/comment_after_integer_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_int, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/translate/struct_in_macro_not_defined.c: -------------------------------------------------------------------------------- 1 | #define FOO(x) x 2 | #define BAR(x) struct FOO(x) 3 | 4 | // translate 5 | // 6 | // pub const BAR = @compileError("unable to translate C expr: 'struct_FOO' not found"); 7 | -------------------------------------------------------------------------------- /test/cases/run/Use_correct_break_label_for_statement_expression_in_nested_scope.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int x = ({1, ({2; 3;});}); 4 | if (x != 3) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/run/cast_signed_array_index_to_unsigned.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int a[10], i = 0; 4 | a[i] = 0; 5 | if (a[i] != 0) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/l_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_long, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/translate/macro_using_argument_as_struct_name_is_not_translated.c: -------------------------------------------------------------------------------- 1 | #define FOO(x) struct x 2 | 3 | // translate 4 | // 5 | // pub const FOO = @compileError("unable to translate macro: untranslatable usage of arg `x`"); 6 | -------------------------------------------------------------------------------- /test/cases/translate/simple_union.c: -------------------------------------------------------------------------------- 1 | union Foo { 2 | int x; 3 | }; 4 | 5 | // translate 6 | // 7 | // pub const union_Foo = extern union { 8 | // x: c_int, 9 | // }; 10 | // 11 | // pub const Foo = union_Foo; 12 | -------------------------------------------------------------------------------- /test/cases/translate/u_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_uint, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/run/forward_declarations.c: -------------------------------------------------------------------------------- 1 | #include 2 | int foo(int); 3 | int foo(int x) { return x + 1; } 4 | int main(int argc, char **argv) { 5 | if (foo(2) != 3) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/hello_world.c: -------------------------------------------------------------------------------- 1 | #define _NO_CRT_STDIO_INLINE 1 2 | #include 3 | int main(int argc, char **argv) { 4 | printf("hello, world!"); 5 | return 0; 6 | } 7 | 8 | // run 9 | // 10 | // hello, world! 11 | -------------------------------------------------------------------------------- /test/cases/translate/ll_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_longlong, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/translate/lu_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/translate/simple_struct.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int x; 3 | }; 4 | 5 | // translate 6 | // 7 | // const struct_Foo = extern struct { 8 | // x: c_int = 0, 9 | // }; 10 | // 11 | // pub const Foo = struct_Foo; 12 | -------------------------------------------------------------------------------- /test/cases/translate/ul_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020); 6 | -------------------------------------------------------------------------------- /examples/use_static_lib/libfoo/print.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void foo_print(const char *format, ...) { 4 | va_list ap; 5 | va_start(ap, format); 6 | (void)vprintf(format, ap); 7 | va_end(ap); 8 | } 9 | -------------------------------------------------------------------------------- /test/cases/run/Closure_over_local_in_typeof.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int x = 123; 4 | union { typeof(x) val; } u = { x }; 5 | if (u.val != 123) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/cast_long_long_array_index_to_unsigned.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | long long a[10], i = 0; 4 | a[i] = 0; 5 | if (a[i] != 0) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/assert_with_strlit.c: -------------------------------------------------------------------------------- 1 | 2 | void assert(int x) {} 3 | #define FOO assert(0 && "error message") 4 | 5 | // translate 6 | // 7 | // pub const FOO = assert((@as(c_int, 0) != 0) and (@intFromPtr("error message") != 0)); 8 | -------------------------------------------------------------------------------- /test/cases/translate/llu_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/translate/ull_integer_suffix_after_hex_literal.c: -------------------------------------------------------------------------------- 1 | #define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 2 | 3 | // translate 4 | // 5 | // pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020); 6 | -------------------------------------------------------------------------------- /test/cases/run/case_boolean_expression_converted_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int value = 1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9; 4 | if (value != 4224) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/run/enum_used_as_boolean_expression.c: -------------------------------------------------------------------------------- 1 | #include 2 | enum FOO {BAR, BAZ}; 3 | int main(void) { 4 | enum FOO x = BAR; 5 | if (x) abort(); 6 | if (!BAZ) abort(); 7 | return 0; 8 | } 9 | 10 | // run 11 | -------------------------------------------------------------------------------- /test/cases/run/enum_with_value_that_fits_in_c_uint_but_not_c_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | enum my_enum { 3 | FORCE_UINT = 0xffffffff 4 | }; 5 | int main(void) { 6 | if(FORCE_UINT != 0xffffffff) abort(); 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/function_macro_that_uses_builtin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define FOO(x, y) (__builtin_popcount((x)) + __builtin_strlen((y))) 3 | int main() { 4 | if (FOO(7, "hello!") != 9) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/translate/Macro_without_a_value.c: -------------------------------------------------------------------------------- 1 | #define FOO 2 | #define BAR(x) 3 | 4 | // translate 5 | // 6 | // pub const FOO = ""; 7 | // 8 | // pub inline fn BAR(x: anytype) void { 9 | // _ = &x; 10 | // return; 11 | // } 12 | -------------------------------------------------------------------------------- /test/cases/translate/void_cast.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int a; 3 | (void) a; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var a: c_int = undefined; 10 | // _ = &a; 11 | // _ = &a; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/run/handle_assert.h.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int x = 1; 4 | int *xp = &x; 5 | assert(1); 6 | assert(x != 0); 7 | assert(xp); 8 | assert(*xp); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/Calling_convention_aarch64.c: -------------------------------------------------------------------------------- 1 | void __attribute__((aarch64_vector_pcs)) foo1(float *a); 2 | 3 | // translate 4 | // target=aarch64-linux-none 5 | // 6 | // pub extern fn foo1(a: [*c]f32) callconv(.{ .aarch64_vfabi = .{} }) void; 7 | -------------------------------------------------------------------------------- /test/cases/translate/anonymous_enum.c: -------------------------------------------------------------------------------- 1 | enum { 2 | One, 3 | Two, 4 | }; 5 | 6 | // translate 7 | // target=native-linux 8 | // 9 | // pub const One: c_int = 0; 10 | // pub const Two: c_int = 1; 11 | // const enum_unnamed_1 = c_uint; 12 | -------------------------------------------------------------------------------- /test/cases/translate/bin_not.c: -------------------------------------------------------------------------------- 1 | int foo() { 2 | int x; 3 | return ~x; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() c_int { 9 | // var x: c_int = undefined; 10 | // _ = &x; 11 | // return ~x; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/macro_calling_convention.c: -------------------------------------------------------------------------------- 1 | #define SYSV_ABI __attribute__((sysv_abi)) 2 | void SYSV_ABI foo(void); 3 | 4 | 5 | // translate 6 | // target=x86_64-windows 7 | // 8 | // pub extern fn foo() callconv(.{ .x86_64_sysv = .{} }) void; 9 | -------------------------------------------------------------------------------- /examples/import_header/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const header = @import("header"); 4 | 5 | test "using my_add from Zig" { 6 | const res = header.my_add(30, header.MY_MACRO); 7 | try std.testing.expectEqual(42, res); 8 | } 9 | -------------------------------------------------------------------------------- /test/cases/run/case_boolean_expression_on_left_converted_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int value = 8 == 9 | 1 + 2 * 3 + 4 * 5 + 6 << 7; 4 | if (value != 4224) abort(); 5 | return 0; 6 | } 7 | 8 | // run 9 | -------------------------------------------------------------------------------- /test/cases/translate/Parameterless_function_pointers.c: -------------------------------------------------------------------------------- 1 | typedef void (*fn0)(); 2 | typedef void (*fn1)(char); 3 | 4 | // translate 5 | // 6 | // pub const fn0 = ?*const fn (...) callconv(.c) void; 7 | // pub const fn1 = ?*const fn (u8) callconv(.c) void; 8 | -------------------------------------------------------------------------------- /test/cases/translate/demote_un-implemented_builtins.c: -------------------------------------------------------------------------------- 1 | #define FOO(X) __builtin_alloca_with_align((X), 8) 2 | 3 | // translate 4 | // 5 | // pub const FOO = @compileError("unable to translate macro: undefined identifier `__builtin_alloca_with_align`"); 6 | -------------------------------------------------------------------------------- /test/cases/translate/duplicate_typedef.c: -------------------------------------------------------------------------------- 1 | typedef long foo; 2 | typedef int bar; 3 | typedef long foo; 4 | typedef int baz; 5 | 6 | // translate 7 | // 8 | // pub const foo = c_long; 9 | // pub const bar = c_int; 10 | // pub const baz = c_int; 11 | -------------------------------------------------------------------------------- /test/cases/translate/macro_call.c: -------------------------------------------------------------------------------- 1 | #define CALL(arg) bar(arg) 2 | int bar(int x) { return x; } 3 | 4 | // translate 5 | // 6 | // pub inline fn CALL(arg: anytype) @TypeOf(bar(arg)) { 7 | // _ = &arg; 8 | // return bar(arg); 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/macro_call_with_no_args.c: -------------------------------------------------------------------------------- 1 | #define CALL(arg) bar() 2 | int bar(void) { return 0; } 3 | 4 | // translate 5 | // 6 | // pub inline fn CALL(arg: anytype) @TypeOf(bar()) { 7 | // _ = &arg; 8 | // return bar(); 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/normal_deref.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int *x; 3 | *x = 1; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var x: [*c]c_int = undefined; 10 | // _ = &x; 11 | // x.* = 1; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/bitshift.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | return (1 << 2) >> 1; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() c_int { 8 | // return (@as(c_int, 1) << @intCast(@as(c_int, 2))) >> @intCast(@as(c_int, 1)); 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/break_statement.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | for (;;) { 3 | break; 4 | } 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // while (true) { 11 | // break; 12 | // } 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/variables.c: -------------------------------------------------------------------------------- 1 | extern int extern_var; 2 | static const int int_var = 13; 3 | int foo; 4 | 5 | // translate 6 | // 7 | // pub extern var extern_var: c_int; 8 | // pub const int_var: c_int = 13; 9 | // pub export var foo: c_int = 0; 10 | -------------------------------------------------------------------------------- /test/cases/run/static_K&R-style_no_prototype_function_declaration_(empty_parameter_list).c: -------------------------------------------------------------------------------- 1 | #include 2 | static int foo() { 3 | return 42; 4 | } 5 | int main() { 6 | if (foo() != 42) abort(); 7 | return 0; 8 | } 9 | 10 | // run 11 | -------------------------------------------------------------------------------- /test/cases/translate/variadic_function_demoted_to_extern.c: -------------------------------------------------------------------------------- 1 | int foo(int bar, ...) { 2 | return 1; 3 | } 4 | 5 | // translate 6 | // 7 | // warning: TODO unable to translate variadic function, demoted to extern 8 | // pub extern fn foo(bar: c_int, ...) c_int; 9 | -------------------------------------------------------------------------------- /test/cases/run/case_boolean_and_plus_converts_bool_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int value = (8 == 9) + 3; 4 | int value2 = 3 + (8 == 9); 5 | if (value != value2) abort(); 6 | return 0; 7 | } 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/run/multi-character_character_constant.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int foo = 'abcd'; 4 | switch (foo) { 5 | case 'abcd': break; 6 | default: abort(); 7 | } 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/scoped_typedef.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char **argv) { 2 | typedef int Foo; 3 | typedef Foo Bar; 4 | typedef void (*func)(int); 5 | typedef int uint32_t; 6 | uint32_t a; 7 | Foo i; 8 | Bar j; 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/run/static_variable_in_block_scope.c: -------------------------------------------------------------------------------- 1 | #include 2 | int foo() { 3 | static int bar; 4 | bar += 1; 5 | return bar; 6 | } 7 | int main() { 8 | foo(); 9 | foo(); 10 | if (foo() != 3) abort(); 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/translate/continue_statement.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | for (;;) { 3 | continue; 4 | } 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // while (true) { 11 | // continue; 12 | // } 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/run/Underscore_identifiers.c: -------------------------------------------------------------------------------- 1 | #include 2 | int _ = 10; 3 | typedef struct { int _; } S; 4 | int main(void) { 5 | if (_ != 10) abort(); 6 | S foo = { ._ = _ }; 7 | if (foo._ != _) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/case_boolean_and_asterisk.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int value = (8 == 9) * 3; 4 | int value2 = 3 * (9 == 9); 5 | if (value != 0) abort(); 6 | if (value2 == 0) abort(); 7 | return 0; 8 | } 9 | 10 | // run 11 | -------------------------------------------------------------------------------- /test/cases/translate/atomic types.c: -------------------------------------------------------------------------------- 1 | typedef _Atomic(int) AtomicInt; 2 | 3 | // translate 4 | // target=x86_64-linux 5 | // 6 | // tmp.c:1:22: warning: TODO support atomic type: '_Atomic(int)' 7 | // pub const AtomicInt = @compileError("unable to resolve typedef child type"); 8 | -------------------------------------------------------------------------------- /test/cases/translate/macro_pointer_cast.c: -------------------------------------------------------------------------------- 1 | #define NRF_GPIO_BASE 0 2 | typedef struct { int dummy; } NRF_GPIO_Type; 3 | #define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) 4 | 5 | // translate 6 | // 7 | // pub const NRF_GPIO = __helpers.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE); 8 | -------------------------------------------------------------------------------- /test/cases/translate/zig_keywords_in_c_code.c: -------------------------------------------------------------------------------- 1 | struct comptime { 2 | int defer; 3 | }; 4 | 5 | // translate 6 | // 7 | // pub const struct_comptime = extern struct { 8 | // @"defer": c_int = 0, 9 | // }; 10 | // 11 | // pub const @"comptime" = struct_comptime; 12 | -------------------------------------------------------------------------------- /test/cases/run/anon_struct_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | struct {int a; int b;} x = {1, 2}; 3 | int main(int argc, char **argv) { 4 | x.a += 2; 5 | x.b += 1; 6 | if (x.a != 3) abort(); 7 | if (x.b != 3) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/failed_macros_are_only_declared_once.c: -------------------------------------------------------------------------------- 1 | #define FOO = 2 | #define FOO = 3 | #define PtrToPtr64(p) ((void *POINTER_64) p) 4 | #define STRUC_ALIGNED_STACK_COPY(t,s) ((CONST t *)(s)) 5 | #define bar = 0x 6 | #define baz = 0b 7 | int main(void) {} 8 | 9 | // run 10 | -------------------------------------------------------------------------------- /test/cases/translate/Forward-declared_enum.c: -------------------------------------------------------------------------------- 1 | extern enum enum_ty my_enum; 2 | enum enum_ty { FOO }; 3 | 4 | // translate 5 | // target=native-linux 6 | // 7 | // pub const FOO: c_int = 0; 8 | // pub const enum_enum_ty = c_uint; 9 | // pub extern var my_enum: enum_enum_ty; 10 | -------------------------------------------------------------------------------- /test/cases/translate/bitshift_with_bitcast.c: -------------------------------------------------------------------------------- 1 | unsigned int bit31() { 2 | return 1u << (31); 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn bit31() c_uint { 8 | // return @as(c_uint, 1) << @intCast(@as(c_uint, @bitCast(@as(c_int, @as(c_int, 31))))); 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/run/K&R-style_static_function_prototype_+_separate_definition.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int foo(); 3 | static int foo(int a, int b) { 4 | return a + b; 5 | } 6 | int main() { 7 | if (foo(40, 2) != 42) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/typedef_with_multiple_names.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef struct { 3 | char field; 4 | } a_t, b_t; 5 | 6 | int main(void) { 7 | a_t a = { .field = 42 }; 8 | b_t b = a; 9 | if (b.field != 42) abort(); 10 | return 0; 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/translate/Use_@_syntax_for_bare_underscore_identifier_in_macro_or_public_symbol.c: -------------------------------------------------------------------------------- 1 | #define FOO _ 2 | int _ = 42; 3 | 4 | // translate 5 | // 6 | // pub inline fn FOO() @TypeOf(@"_") { 7 | // return @"_"; 8 | // } 9 | // 10 | // pub export var @"_": c_int = 42; 11 | -------------------------------------------------------------------------------- /test/cases/translate/binary_conditional_operator_result_unused.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int c = 1; 3 | c ?: foo(); 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var c: c_int = 1; 10 | // _ = &c; 11 | // if (c != 0) foo(); 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/do_while_as_expr.c: -------------------------------------------------------------------------------- 1 | static void foo(void) { 2 | if (1) 3 | do {} while (0); 4 | } 5 | 6 | // translate 7 | // 8 | // pub fn foo() callconv(.c) void { 9 | // if (true) while (true) { 10 | // if (!false) break; 11 | // }; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/macro_function_string_concat.c: -------------------------------------------------------------------------------- 1 | #define bar() "" 2 | #define FOO bar() "," bar() 3 | 4 | // translate 5 | // target=x86_64-linux 6 | // 7 | // pub inline fn bar() @TypeOf("") { 8 | // return ""; 9 | // } 10 | // pub const FOO = bar() ++ "," ++ bar(); 11 | -------------------------------------------------------------------------------- /test/cases/translate/simple_function.c: -------------------------------------------------------------------------------- 1 | int abs(int a) { 2 | return a < 0 ? -a : a; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn abs(arg_a: c_int) c_int { 8 | // var a = arg_a; 9 | // _ = &a; 10 | // return if (a < @as(c_int, 0)) -a else a; 11 | // } 12 | -------------------------------------------------------------------------------- /test/cases/run/assign_enum_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef enum { 3 | ENUM_0 = 0, 4 | ENUM_1 = 1, 5 | } my_enum_t; 6 | 7 | int main() { 8 | my_enum_t val = ENUM_1; 9 | int x = val; 10 | if (x != 1) abort(); 11 | return 0; 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/translate/string_concatenation_in_macros-_two_defines.c: -------------------------------------------------------------------------------- 1 | #define FOO "hello" 2 | #define BAZ " world" 3 | #define BAR FOO BAZ 4 | 5 | // translate 6 | // 7 | // pub const FOO = "hello"; 8 | // 9 | // pub const BAZ = " world"; 10 | // 11 | // pub const BAR = FOO ++ BAZ; 12 | -------------------------------------------------------------------------------- /test/cases/translate/string_concatenation_in_macros.c: -------------------------------------------------------------------------------- 1 | #define FOO "hello" 2 | #define BAR FOO " world" 3 | #define BAZ "oh, " FOO 4 | 5 | // translate 6 | // 7 | // pub const FOO = "hello"; 8 | // 9 | // pub const BAR = FOO ++ " world"; 10 | // 11 | // pub const BAZ = "oh, " ++ FOO; 12 | -------------------------------------------------------------------------------- /examples/compile_c/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __TRANSLATE_C__ 4 | # define LANGUAGE "Zig" 5 | #else 6 | # define LANGUAGE "C" 7 | #endif 8 | 9 | int main(int argc, const char *argv[]) { 10 | printf("Hello from my %s program!\n", LANGUAGE); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/cases/run/Boolean_expression_coerced_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | int sign(int v) { 3 | return -(v < 0); 4 | } 5 | int main(void) { 6 | if (sign(-5) != -1) abort(); 7 | if (sign(5) != 0) abort(); 8 | if (sign(0) != 0) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/run/scoped_for_loops_with_shadowing.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int count = 0; 4 | for (int x = 0; x < 2; x++) 5 | for (int x = 0; x < 2; x++) 6 | count++; 7 | 8 | if (count != 4) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/for_loop.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | for (int i = 0; i; i++) { } 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() void { 8 | // { 9 | // var i: c_int = 0; 10 | // _ = &i; 11 | // while (i != 0) : (i += 1) {} 12 | // } 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/macro_integer_literal_casts.c: -------------------------------------------------------------------------------- 1 | #define NULL ((void*)0) 2 | #define FOO ((int)0x8000) 3 | 4 | // translate 5 | // 6 | // pub const NULL = __helpers.cast(?*anyopaque, @as(c_int, 0)); 7 | // 8 | // pub const FOO = __helpers.cast(c_int, __helpers.promoteIntLiteral(c_int, 0x8000, .hex)); 9 | -------------------------------------------------------------------------------- /test/cases/translate/pointer_casting.c: -------------------------------------------------------------------------------- 1 | float *ptrcast() { 2 | int *a; 3 | return (float *)a; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn ptrcast() [*c]f32 { 9 | // var a: [*c]c_int = undefined; 10 | // _ = &a; 11 | // return @ptrCast(@alignCast(a)); 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/run/assign_bool_result_to_int_or_char.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | bool foo() { return true; } 4 | int main() { 5 | int x = foo(); 6 | if (x != 1) abort(); 7 | signed char c = foo(); 8 | if (c != 1) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/function prototype with parenthesis.c: -------------------------------------------------------------------------------- 1 | void (f0) (void *L); 2 | void ((f1)) (void *L); 3 | void (((f2))) (void *L); 4 | 5 | // translate 6 | // 7 | // pub extern fn f0(L: ?*anyopaque) void; 8 | // pub extern fn f1(L: ?*anyopaque) void; 9 | // pub extern fn f2(L: ?*anyopaque) void; 10 | -------------------------------------------------------------------------------- /test/cases/translate/implicit_cast_to_void_ptr.c: -------------------------------------------------------------------------------- 1 | void *foo() { 2 | unsigned short *x; 3 | return x; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() ?*anyopaque { 9 | // var x: [*c]c_ushort = undefined; 10 | // _ = &x; 11 | // return @ptrCast(@alignCast(x)); 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/variable_declarations.c: -------------------------------------------------------------------------------- 1 | extern char arr0[] = "hello"; 2 | static char arr1[] = "hello"; 3 | char arr2[] = "hello"; 4 | 5 | // translate 6 | // 7 | // pub export var arr0: [5:0]u8 = "hello".*; 8 | // pub var arr1: [5:0]u8 = "hello".*; 9 | // pub export var arr2: [5:0]u8 = "hello".*; 10 | -------------------------------------------------------------------------------- /test/cases/run/assign_enum_to_uint,_no_explicit_cast.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef enum { 3 | ENUM_0 = 0, 4 | ENUM_1 = 1, 5 | } my_enum_t; 6 | 7 | int main() { 8 | my_enum_t val = ENUM_1; 9 | unsigned int x = val; 10 | if (x != 1) abort(); 11 | return 0; 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/translate/packed_union_simple.c: -------------------------------------------------------------------------------- 1 | union Foo { 2 | short x; 3 | double y; 4 | } __attribute__((packed)); 5 | 6 | // translate 7 | // 8 | // pub const union_Foo = extern union { 9 | // x: c_short align(1), 10 | // y: f64 align(1), 11 | // }; 12 | // 13 | // pub const Foo = union_Foo; 14 | -------------------------------------------------------------------------------- /test/cases/run/division_of_floating_literals.c: -------------------------------------------------------------------------------- 1 | #define _NO_CRT_STDIO_INLINE 1 2 | #include 3 | #define PI 3.14159265358979323846f 4 | #define DEG2RAD (PI/180.0f) 5 | int main(void) { 6 | printf("DEG2RAD is: %f", DEG2RAD); 7 | return 0; 8 | } 9 | 10 | // run 11 | // 12 | // DEG2RAD is: 0.017453 13 | -------------------------------------------------------------------------------- /test/cases/translate/macro_defines_string_literal_with_hex.c: -------------------------------------------------------------------------------- 1 | #define FOO "aoeu\xab derp" 2 | #define FOO2 "aoeu\x0007a derp" 3 | #define FOO_CHAR '\xfF' 4 | 5 | // translate 6 | // 7 | // pub const FOO = "aoeu\xab derp"; 8 | // 9 | // pub const FOO2 = "aoeu\x7a derp"; 10 | // 11 | // pub const FOO_CHAR = '\xff'; 12 | -------------------------------------------------------------------------------- /test/cases/translate/macro_with_right_shift.c: -------------------------------------------------------------------------------- 1 | #define FLASH_SIZE 0x200000UL /* 2 MB */ 2 | #define FLASH_BANK_SIZE (FLASH_SIZE >> 1) /* 1 MB */ 3 | 4 | // translate 5 | // 6 | // pub const FLASH_SIZE = @as(c_ulong, 0x200000); 7 | // 8 | // pub const FLASH_BANK_SIZE = FLASH_SIZE >> @as(c_int, 1); 9 | -------------------------------------------------------------------------------- /test/cases/translate/casting_pointer_to_pointer.c: -------------------------------------------------------------------------------- 1 | float **ptrptrcast() { 2 | int **a; 3 | return (float **)a; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn ptrptrcast() [*c][*c]f32 { 9 | // var a: [*c][*c]c_int = undefined; 10 | // _ = &a; 11 | // return @ptrCast(@alignCast(a)); 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/macro_defines_string_literal_with_octal.c: -------------------------------------------------------------------------------- 1 | #define FOO "aoeu\023 derp" 2 | #define FOO2 "aoeu\0234 derp" 3 | #define FOO_CHAR '\077' 4 | 5 | // translate 6 | // 7 | // pub const FOO = "aoeu\x13 derp"; 8 | // 9 | // pub const FOO2 = "aoeu\x134 derp"; 10 | // 11 | // pub const FOO_CHAR = '\x3f'; 12 | -------------------------------------------------------------------------------- /test/cases/translate/comma_operator.c: -------------------------------------------------------------------------------- 1 | int foo() { 2 | 2, 4; 3 | return 2, 4, 6; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() c_int { 9 | // _ = 2; 10 | // _ = 4; 11 | // return blk: { 12 | // _ = 2; 13 | // _ = 4; 14 | // break :blk 6; 15 | // }; 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/run/Cast_to_enum_from_larger_integral_type.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | enum Foo { A, B, C }; 4 | static inline enum Foo do_stuff(void) { 5 | int64_t i = 1; 6 | return (enum Foo)i; 7 | } 8 | int main(void) { 9 | if (do_stuff() != B) abort(); 10 | return 0; 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/run/Comma_operator_should_create_new_scope.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(void) { 4 | if (1 || (abort(), 1)) {} 5 | if (0 && (1, printf("do not print\n"))) {} 6 | int x = 0; 7 | x = (x = 3, 4, x + 1); 8 | if (x != 4) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/Don't_make_const_parameters_mutable.c: -------------------------------------------------------------------------------- 1 | int max(const int x, int y) { 2 | return (x > y) ? x : y; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn max(x: c_int, arg_y: c_int) c_int { 8 | // _ = &x; 9 | // var y = arg_y; 10 | // _ = &y; 11 | // return if (x > y) x else y; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/translate/early_return.c: -------------------------------------------------------------------------------- 1 | static unsigned long early_return(void) { 2 | return 8 * 1024 * 1024; 3 | return 2 * 1024 * 1024; 4 | } 5 | 6 | // translate 7 | // 8 | // pub fn early_return() callconv(.c) c_ulong { 9 | // return @bitCast(@as(c_long, (@as(c_int, 8) * @as(c_int, 1024)) * @as(c_int, 1024))); 10 | // } 11 | -------------------------------------------------------------------------------- /test/cases/translate/arg_name_aliasing_decl_which_comes_after.c: -------------------------------------------------------------------------------- 1 | void foo(int bar) { 2 | bar = 2; 3 | } 4 | int bar = 4; 5 | 6 | // translate 7 | // 8 | // pub export fn foo(arg_bar_1: c_int) void { 9 | // var bar_1 = arg_bar_1; 10 | // _ = &bar_1; 11 | // bar_1 = 2; 12 | // } 13 | // pub export var bar: c_int = 4; 14 | -------------------------------------------------------------------------------- /test/cases/translate/don't_export_inline_functions.c: -------------------------------------------------------------------------------- 1 | inline void a(void) {} 2 | static void b(void) {} 3 | void c(void) {} 4 | static void foo() {} 5 | 6 | // translate 7 | // 8 | // pub fn a() callconv(.c) void {} 9 | // pub fn b() callconv(.c) void {} 10 | // pub export fn c() void {} 11 | // pub fn foo() callconv(.c) void {} 12 | -------------------------------------------------------------------------------- /test/cases/translate/leading_zeroes.c: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 00 2 | #define HELLO 000 3 | #define ZERO 0 4 | #define WORLD 00000123 5 | 6 | // translate 7 | // 8 | // pub const O_RDONLY = @as(c_int, 0o0); 9 | // pub const HELLO = @as(c_int, 0o00); 10 | // pub const ZERO = @as(c_int, 0); 11 | // pub const WORLD = @as(c_int, 0o0000123); 12 | -------------------------------------------------------------------------------- /test/cases/translate/self_referential_struct_with_function_pointer.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | void (*derp)(struct Foo *foo); 3 | }; 4 | 5 | // translate 6 | // 7 | // pub const struct_Foo = extern struct { 8 | // derp: ?*const fn (foo: [*c]struct_Foo) callconv(.c) void = null, 9 | // }; 10 | // 11 | // pub const Foo = struct_Foo; 12 | -------------------------------------------------------------------------------- /test/cases/translate/unsigned_array_index_skips_cast.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | unsigned int a[10], i = 0; 3 | a[i] = 0; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var a: [10]c_uint = undefined; 10 | // _ = &a; 11 | // var i: c_uint = 0; 12 | // _ = &i; 13 | // a[i] = 0; 14 | // } 15 | -------------------------------------------------------------------------------- /test/cases/translate/call_builtin_popcount.c: -------------------------------------------------------------------------------- 1 | int max(int a) { 2 | return __builtin_popcount(1); 3 | } 4 | 5 | // translate 6 | // 7 | // pub const __builtin = @import("c_builtins"); 8 | // 9 | // pub export fn max(arg_a: c_int) c_int { 10 | // var a = arg_a; 11 | // _ = &a; 12 | // return __builtin.popcount(1); 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/enums.c: -------------------------------------------------------------------------------- 1 | enum Foo { 2 | FooA = 2, 3 | FooB = 5, 4 | Foo1, 5 | }; 6 | 7 | // translate 8 | // target=x86_64-linux 9 | // 10 | // pub const FooA: c_int = 2; 11 | // pub const FooB: c_int = 5; 12 | // pub const Foo1: c_int = 6; 13 | // pub const enum_Foo = c_uint; 14 | // 15 | // pub const Foo = enum_Foo; 16 | -------------------------------------------------------------------------------- /test/cases/translate/static_incomplete_array_inside_function.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | static const char v2[] = "2.2.2"; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo() void { 8 | // const static_local_v2 = struct { 9 | // const v2: [5:0]u8 = "2.2.2".*; 10 | // }; 11 | // _ = &static_local_v2; 12 | // } 13 | -------------------------------------------------------------------------------- /test/cases/run/Remainder_operator_with_negative_integers.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int denominator = -2; 4 | int numerator = 5; 5 | if (numerator % denominator != 1) abort(); 6 | numerator = -5; denominator = 2; 7 | if (numerator % denominator != -1) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/cast_enum_to_smaller_uint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef enum { 4 | ENUM_0 = 0, 5 | ENUM_257 = 257, 6 | } my_enum_t; 7 | 8 | int main() { 9 | my_enum_t val = ENUM_257; 10 | uint8_t x = (uint8_t)val; 11 | if (x != (uint8_t)257) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/Simple_array_access_of_pointer_with_non-negative_integer_constant.c: -------------------------------------------------------------------------------- 1 | void foo(int *p) { 2 | p[0]; 3 | p[1]; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo(arg_p: [*c]c_int) void { 9 | // var p = arg_p; 10 | // _ = &p; 11 | // _ = p[@as(c_int, 0)]; 12 | // _ = p[@as(c_int, 1)]; 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/address_of_operator.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | int x = 1234; 3 | int *ptr = &x; 4 | return *ptr; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() c_int { 10 | // var x: c_int = 1234; 11 | // _ = &x; 12 | // var ptr: [*c]c_int = &x; 13 | // _ = &ptr; 14 | // return ptr.*; 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/arg_name_aliasing_macro_which_comes_after.c: -------------------------------------------------------------------------------- 1 | void foo(int bar) { 2 | bar = 2; 3 | } 4 | #define bar 4 5 | 6 | // translate 7 | // 8 | // pub export fn foo(arg_bar_1: c_int) void { 9 | // var bar_1 = arg_bar_1; 10 | // _ = &bar_1; 11 | // bar_1 = 2; 12 | // } 13 | // 14 | // pub const bar = @as(c_int, 4); 15 | -------------------------------------------------------------------------------- /test/cases/translate/assign.c: -------------------------------------------------------------------------------- 1 | void max(int a) { 2 | int tmp; 3 | tmp = a; 4 | a = tmp; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn max(arg_a: c_int) void { 10 | // var a = arg_a; 11 | // _ = &a; 12 | // var tmp: c_int = undefined; 13 | // _ = &tmp; 14 | // tmp = a; 15 | // a = tmp; 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/translate/pointer_to_struct_demoted_opaque_due_to_bit_fields.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | unsigned int: 1; 3 | }; 4 | struct Bar { 5 | struct Foo *foo; 6 | }; 7 | 8 | // translate 9 | // 10 | // pub const struct_Foo = opaque {}; 11 | // 12 | // pub const struct_Bar = extern struct { 13 | // foo: ?*struct_Foo = null, 14 | // }; 15 | -------------------------------------------------------------------------------- /test/cases/run/Enum_constant_matches_enum_name,_multiple_enumerations_with_same_value.c: -------------------------------------------------------------------------------- 1 | #include 2 | enum FOO { 3 | FOO = 1, 4 | BAR = 2, 5 | BAZ = 1, 6 | }; 7 | int main(void) { 8 | enum FOO x = BAZ; 9 | if (x != 1) abort(); 10 | if (x != BAZ) abort(); 11 | if (x != FOO) abort(); 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/run/cast_enum_to_smaller_signed_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef enum { 4 | ENUM_0 = 0, 5 | ENUM_384 = 384, 6 | } my_enum_t; 7 | 8 | int main() { 9 | my_enum_t val = ENUM_384; 10 | int8_t x = (int8_t)val; 11 | if (x != (int8_t)384) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/conditional_operator_cast_to_void.c: -------------------------------------------------------------------------------- 1 | int bar(); 2 | void foo() { 3 | int a; 4 | a ? a = 2 : bar(); 5 | } 6 | 7 | // translate 8 | // 9 | // pub extern fn bar(...) c_int; 10 | // pub export fn foo() void { 11 | // var a: c_int = undefined; 12 | // _ = &a; 13 | // if (a != 0) a = 2 else _ = bar(); 14 | // } 15 | -------------------------------------------------------------------------------- /test/cases/translate/enums msvc.c: -------------------------------------------------------------------------------- 1 | enum Foo { 2 | FooA = 2, 3 | FooB = 5, 4 | Foo1, 5 | }; 6 | 7 | // translate 8 | // target=x86_64-windows-msvc 9 | // 10 | // pub const FooA: c_int = 2; 11 | // pub const FooB: c_int = 5; 12 | // pub const Foo1: c_int = 6; 13 | // pub const enum_Foo = c_int; 14 | // 15 | // pub const Foo = enum_Foo; 16 | -------------------------------------------------------------------------------- /test/cases/run/casting_away_const_and_volatile.c: -------------------------------------------------------------------------------- 1 | void foo(int *a) {} 2 | void bar(const int *a) { 3 | foo((int *)a); 4 | } 5 | void baz(volatile int *a) { 6 | foo((int *)a); 7 | } 8 | int main(int argc, char **argv) { 9 | int a = 0; 10 | bar((const int *)&a); 11 | baz((volatile int *)&a); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/run/use_global_scope_for_record_enum_typedef_type_translation_if_needed.c: -------------------------------------------------------------------------------- 1 | void bar(void); 2 | void baz(void); 3 | struct foo { int x; }; 4 | void bar() { 5 | struct foo tmp; 6 | } 7 | 8 | void baz() { 9 | struct foo tmp; 10 | } 11 | 12 | int main(void) { 13 | bar(); 14 | baz(); 15 | return 0; 16 | } 17 | 18 | // run 19 | -------------------------------------------------------------------------------- /examples/compile_c/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .compile_c, 3 | .version = "0.0.0", 4 | .fingerprint = 0x29391e092030566f, 5 | .paths = .{""}, 6 | 7 | .dependencies = .{ 8 | // Install by running `zig fetch --save git+https://github.com/ziglang/translate-c`. 9 | .translate_c = .{ .path = "../../" }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /test/cases/run/cast_builtin_call_result_to_opaque_struct_pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | struct foo* make_foo(void) 3 | { 4 | return (struct foo*)__builtin_strlen("0123456789ABCDEF"); 5 | } 6 | int main(void) { 7 | struct foo *foo_pointer = make_foo(); 8 | if (foo_pointer != (struct foo*)16) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/run/cast_negative_enum_to_smaller_signed_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef enum { 4 | ENUM_MINUS_1 = -1, 5 | ENUM_384 = 384, 6 | } my_enum_t; 7 | 8 | int main() { 9 | my_enum_t val = ENUM_MINUS_1; 10 | int8_t x = (int8_t)val; 11 | if (x != -1) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/Calling_convention_arm.c: -------------------------------------------------------------------------------- 1 | void __attribute__((pcs("aapcs"))) foo1(float *a); 2 | void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); 3 | 4 | // translate 5 | // target=arm-linux-none 6 | // 7 | // pub extern fn foo1(a: [*c]f32) callconv(.{ .arm_aapcs = .{} }) void; 8 | // pub extern fn foo2(a: [*c]f32) callconv(.{ .arm_aapcs_vfp = .{} }) void; 9 | -------------------------------------------------------------------------------- /test/cases/translate/bitwise_binary_operators,_simpler_parens.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | return (a & b) ^ (a | b); 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn max(arg_a: c_int, arg_b: c_int) c_int { 8 | // var a = arg_a; 9 | // _ = &a; 10 | // var b = arg_b; 11 | // _ = &b; 12 | // return (a & b) ^ (a | b); 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/bool_array_index.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | unsigned int a[10]; 3 | _Bool i = 0; 4 | a[i] = 0; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // var a: [10]c_uint = undefined; 11 | // _ = &a; 12 | // var i: bool = @as(c_int, 0) != 0; 13 | // _ = &i; 14 | // a[@intFromBool(i)] = 0; 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/cast_signed_array_index_to_unsigned.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int a[10], i = 0; 3 | a[i] = 0; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var a: [10]c_int = undefined; 10 | // _ = &a; 11 | // var i: c_int = 0; 12 | // _ = &i; 13 | // a[@bitCast(@as(isize, @intCast(i)))] = 0; 14 | // } 15 | -------------------------------------------------------------------------------- /test/cases/translate/for_loop_with_simple_init_expression.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int i; 3 | for (i = 3; i; i--) { } 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var i: c_int = undefined; 10 | // _ = &i; 11 | // { 12 | // i = 3; 13 | // while (i != 0) : (i -= 1) {} 14 | // } 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/typedeffed_bool_expression.c: -------------------------------------------------------------------------------- 1 | typedef char* yes; 2 | void foo(void) { 3 | yes a; 4 | if (a) 2; 5 | } 6 | 7 | // translate 8 | // 9 | // pub const yes = [*c]u8; 10 | // pub export fn foo() void { 11 | // var a: yes = undefined; 12 | // _ = &a; 13 | // if (a != null) { 14 | // _ = 2; 15 | // } 16 | // } 17 | -------------------------------------------------------------------------------- /examples/import_header/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .import_header, 3 | .version = "0.0.0", 4 | .fingerprint = 0x124312d94ed7032c, 5 | .paths = .{""}, 6 | 7 | .dependencies = .{ 8 | // Install by running `zig fetch --save git+https://github.com/ziglang/translate-c`. 9 | .translate_c = .{ .path = "../../" }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /test/cases/run/array_initializer.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | int a0[4] = {1}; 4 | int a1[4] = {1,2,3,4}; 5 | int s0 = 0, s1 = 0; 6 | for (int i = 0; i < 4; i++) { 7 | s0 += a0[i]; 8 | s1 += a1[i]; 9 | } 10 | if (s0 != 1) abort(); 11 | if (s1 != 10) abort(); 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/run/struct_without_global_declaration_does_not_conflict_with_local_variable_name.c: -------------------------------------------------------------------------------- 1 | #include 2 | static void foo(struct foobar *unused) {} 3 | int main(void) { 4 | int struct_foobar = 123; 5 | if (struct_foobar != 123) abort(); 6 | int foobar = 456; 7 | if (foobar != 456) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/run/use_of_unimplemented_builtin_in_unused_function_does_not_prevent_compilation.c: -------------------------------------------------------------------------------- 1 | // See __builtin_alloca_with_align comment in lib/c_builtins.zig 2 | #include 3 | void unused() { 4 | __builtin_alloca_with_align(1, 8); 5 | } 6 | int main(void) { 7 | if (__builtin_sqrt(1.0) != 1.0) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/translate/long_long_array_index_cast_to_usize.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | unsigned long long a[10], i = 0; 3 | a[i] = 0; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var a: [10]c_ulonglong = undefined; 10 | // _ = &a; 11 | // var i: c_ulonglong = 0; 12 | // _ = &i; 13 | // a[@intCast(i)] = 0; 14 | // } 15 | -------------------------------------------------------------------------------- /examples/use_static_lib/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .use_static_lib, 3 | .version = "0.0.0", 4 | .fingerprint = 0x63e0d025a416d0df, 5 | .paths = .{""}, 6 | 7 | .dependencies = .{ 8 | // Install by running `zig fetch --save git+https://github.com/ziglang/translate-c`. 9 | .translate_c = .{ .path = "../../" }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /test/cases/run/array_cast_int_to_uint.c: -------------------------------------------------------------------------------- 1 | #include 2 | static unsigned int hash_binary(int k) 3 | { 4 | int choose[3] = {-1, -2, 3}; 5 | unsigned int sum = 2; 6 | sum += choose[k]; 7 | return sum; 8 | } 9 | 10 | int main() { 11 | unsigned int x = hash_binary(1); 12 | if (x != 0) abort(); 13 | return 0; 14 | } 15 | 16 | // run 17 | -------------------------------------------------------------------------------- /test/cases/run/cast_negative_enum_to_smaller_unsigned_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef enum { 4 | ENUM_MINUS_1 = -1, 5 | ENUM_384 = 384, 6 | } my_enum_t; 7 | 8 | int main() { 9 | my_enum_t val = ENUM_MINUS_1; 10 | uint8_t x = (uint8_t)val; 11 | if (x != (uint8_t)-1) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/run/sizeof.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | char a[]="a"; 4 | char b[3]="a"; 5 | int c[10]; 6 | if (sizeof("a")!=2) abort(); 7 | if (sizeof(a)!=2) abort(); 8 | if (sizeof(b)!=3) abort(); 9 | if (sizeof(c)!=sizeof(int)*10) abort(); 10 | if (__alignof("a")!=1) abort(); 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/run/struct_without_global_declaration_does_not_conflict_with_global_variable_name.c: -------------------------------------------------------------------------------- 1 | #include 2 | static void foo(struct foobar *unused) {} 3 | static int struct_foobar = 123; 4 | static int foobar = 456; 5 | int main(void) { 6 | if (struct_foobar != 123) abort(); 7 | if (foobar != 456) abort(); 8 | return 0; 9 | } 10 | 11 | // run 12 | -------------------------------------------------------------------------------- /test/cases/translate/floats.c: -------------------------------------------------------------------------------- 1 | float a = 3.1415; 2 | double b = 3.1415; 3 | int c = 3.1415; 4 | double d = 3; 5 | 6 | // translate 7 | // 8 | // pub export var a: f32 = @floatCast(@as(f64, 3.1415)); 9 | // pub export var b: f64 = 3.1415; 10 | // pub export var c: c_int = @intFromFloat(@as(f64, 3.1415)); 11 | // pub export var d: f64 = @floatFromInt(@as(c_int, 3)); 12 | -------------------------------------------------------------------------------- /test/cases/translate/struct prototype used in func.c: -------------------------------------------------------------------------------- 1 | struct Foo; 2 | struct Foo *some_func(struct Foo *foo, int x); 3 | 4 | // translate 5 | // 6 | // pub const struct_Foo = opaque { 7 | // pub const some_func = __root.some_func; 8 | // pub const func = __root.some_func; 9 | // }; 10 | // pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo; 11 | -------------------------------------------------------------------------------- /test/cases/run/array_value_type_casts_properly.c: -------------------------------------------------------------------------------- 1 | #include 2 | unsigned int choose[53][10]; 3 | static int hash_binary(int k) 4 | { 5 | choose[0][k] = 3; 6 | int sum = 0; 7 | sum += choose[0][k]; 8 | return sum; 9 | } 10 | 11 | int main() { 12 | int s = hash_binary(4); 13 | if (s != 3) abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/run/array_to_pointer_decay.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) { 3 | char data[3] = {'a','b','c'}; 4 | if (2[data] != data[2]) abort(); 5 | if ("abc"[1] != data[1]) abort(); 6 | char *as_ptr = data; 7 | if (2[as_ptr] != as_ptr[2]) abort(); 8 | if ("abc"[1] != as_ptr[1]) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/macro_with_nontrivial_cast.c: -------------------------------------------------------------------------------- 1 | #define MAP_FAILED ((void *) -1) 2 | typedef long long LONG_PTR; 3 | #define INVALID_HANDLE_VALUE ((void *)(LONG_PTR)-1) 4 | 5 | // translate 6 | // 7 | // pub const MAP_FAILED = __helpers.cast(?*anyopaque, -@as(c_int, 1)); 8 | // pub const INVALID_HANDLE_VALUE = __helpers.cast(?*anyopaque, __helpers.cast(LONG_PTR, -@as(c_int, 1))); 9 | -------------------------------------------------------------------------------- /test/cases/translate/statement_expression.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | return ({ 3 | int a = 1; 4 | a; 5 | a; 6 | }); 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo() c_int { 12 | // return blk: { 13 | // var a: c_int = 1; 14 | // _ = &a; 15 | // _ = &a; 16 | // break :blk a; 17 | // }; 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/run/__builtin_choose_expr_(unchosen_expression_is_not_evaluated).c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int x = 0.0; 4 | int y = 0.0; 5 | int res; 6 | res = __builtin_choose_expr(1, 1, x / y); 7 | if (res != 1) abort(); 8 | res = __builtin_choose_expr(0, x / y, 2); 9 | if (res != 2) abort(); 10 | return 0; 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/run/implicit_enum_cast_in_boolean_expression.c: -------------------------------------------------------------------------------- 1 | #include 2 | enum Foo { 3 | FooA, 4 | FooB, 5 | FooC, 6 | }; 7 | int main() { 8 | int a = 0; 9 | float b = 0; 10 | void *c = 0; 11 | enum Foo d = FooA; 12 | if (a || d) abort(); 13 | if (d && b) abort(); 14 | if (c || d) abort(); 15 | return 0; 16 | } 17 | 18 | // run 19 | -------------------------------------------------------------------------------- /test/cases/translate/Demote_function_that_dereferences_opaque_type.c: -------------------------------------------------------------------------------- 1 | struct my_struct { 2 | unsigned a: 1; 3 | }; 4 | void deref(struct my_struct *s) { 5 | *s; 6 | } 7 | 8 | // translate 9 | // 10 | // warning: cannot dereference opaque type 11 | // 12 | // warning: unable to translate function, demoted to extern 13 | // pub extern fn deref(arg_s: ?*struct_my_struct) void; 14 | -------------------------------------------------------------------------------- /test/cases/run/block-scope_static_variable_shadows_function_parameter.c: -------------------------------------------------------------------------------- 1 | #include 2 | int func1(int foo) { return foo + 1; } 3 | int func2(void) { 4 | static int foo = 5; 5 | return foo++; 6 | } 7 | int main(void) { 8 | if (func1(42) != 43) abort(); 9 | if (func2() != 5) abort(); 10 | if (func2() != 6) abort(); 11 | return 0; 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/run/struct_initializer_-_packed.c: -------------------------------------------------------------------------------- 1 | #define _NO_CRT_STDIO_INLINE 1 2 | #include 3 | #include 4 | struct s {uint8_t x,y; 5 | uint32_t z;} __attribute__((packed)) s0 = {1, 2}; 6 | int main() { 7 | /* sizeof nor offsetof currently supported */ 8 | if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/function_call.c: -------------------------------------------------------------------------------- 1 | static void bar(void) { } 2 | void foo(int *(baz)(void)) { 3 | bar(); 4 | baz(); 5 | } 6 | 7 | // translate 8 | // 9 | // pub fn bar() callconv(.c) void {} 10 | // pub export fn foo(arg_baz: ?*const fn () callconv(.c) [*c]c_int) void { 11 | // var baz = arg_baz; 12 | // _ = &baz; 13 | // bar(); 14 | // _ = baz.?(); 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/run/Compound_literals.c: -------------------------------------------------------------------------------- 1 | #include 2 | struct Foo { 3 | int a; 4 | char b[2]; 5 | float c; 6 | }; 7 | int main() { 8 | struct Foo foo; 9 | int x = 1, y = 2; 10 | foo = (struct Foo) {x + y, {'a', 'b'}, 42.0f}; 11 | if (foo.a != x + y || foo.b[0] != 'a' || foo.b[1] != 'b' || foo.c != 42.0f) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/run/compound_assignments_with_implicit_casts.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int i = 2; 3 | float f = 3.2f; 4 | 5 | i += 1.7; 6 | if (i != 3) return 1; 7 | i += f; 8 | if (i != 6) return 2; 9 | 10 | 11 | f += 2UL; 12 | if (f <= 5.1999 || f >= 5.2001) return 3; 13 | f += i; 14 | if (f <= 11.1999 || f >= 11.2001) return 4; 15 | 16 | return 0; 17 | } 18 | 19 | // run 20 | -------------------------------------------------------------------------------- /test/cases/translate/global_struct_whose_default_name_conflicts_with_global_is_mangled.c: -------------------------------------------------------------------------------- 1 | struct foo { 2 | int x; 3 | }; 4 | const char *struct_foo = "hello world"; 5 | 6 | // translate 7 | // 8 | // pub const struct_foo_1 = extern struct { 9 | // x: c_int = 0, 10 | // }; 11 | // pub export var struct_foo: [*c]const u8 = "hello world"; 12 | // 13 | // pub const foo = struct_foo_1; 14 | -------------------------------------------------------------------------------- /test/cases/translate/correct_semicolon_after_infixop.c: -------------------------------------------------------------------------------- 1 | #define _IO_ERR_SEEN 0 2 | #define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0) 3 | 4 | // translate 5 | // 6 | // pub inline fn __ferror_unlocked_body(_fp: anytype) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0)) { 7 | // _ = &_fp; 8 | // return (_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0); 9 | // } 10 | -------------------------------------------------------------------------------- /test/cases/translate/use_cast_param_as_macro_fn_return_type.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define SYS_BASE_CACHED 0 3 | #define MEM_PHYSICAL_TO_K0(x) (void*)((uint32_t)(x) + SYS_BASE_CACHED) 4 | 5 | // translate 6 | // 7 | // pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*anyopaque { 8 | // _ = &x; 9 | // return __helpers.cast(?*anyopaque, __helpers.cast(u32, x) + SYS_BASE_CACHED); 10 | // } 11 | -------------------------------------------------------------------------------- /test/cases/run/pointer_difference-_array_of_function_pointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | int a(void) { return 1;} 3 | int b(void) { return 2;} 4 | int c(void) { return 3;} 5 | typedef int (*myfunc)(void); 6 | int main() { 7 | myfunc arr[] = {a, b, c, a, b, c}; 8 | myfunc *f1 = &arr[1]; 9 | myfunc *f4 = &arr[4]; 10 | if (f4 - f1 != 3) abort(); 11 | return 0; 12 | } 13 | 14 | // run 15 | -------------------------------------------------------------------------------- /test/cases/translate/unnamed_typedef_referencing_itself.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | struct TypeB* b_member; 3 | } TypeA; 4 | 5 | struct TypeB { 6 | TypeA* a_member; 7 | }; 8 | 9 | // translate 10 | // 11 | // pub const struct_TypeB = extern struct { 12 | // a_member: [*c]TypeA = null, 13 | // }; 14 | // pub const TypeA = extern struct { 15 | // b_member: [*c]struct_TypeB = null, 16 | // }; 17 | -------------------------------------------------------------------------------- /test/cases/run/ensure_array_casts_outside_addeq.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int hash_binary(int k) 3 | { 4 | unsigned int choose[3] = {1, 2, 3}; 5 | int sum = -2; 6 | int prev = sum + choose[k]; 7 | if (prev != 0) abort(); 8 | return sum + prev; 9 | } 10 | 11 | int main() { 12 | int x = hash_binary(1); 13 | if (x != -2) abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/run/ternary_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int cnt = 0; 3 | int foo() { cnt++; return 42; } 4 | int main(int argc, char **argv) { 5 | short q = 3; 6 | signed char z0 = q?:1; 7 | if (z0 != 3) abort(); 8 | int z1 = 3?:1; 9 | if (z1 != 3) abort(); 10 | int z2 = foo()?:-1; 11 | if (z2 != 42) abort(); 12 | if (cnt != 1) abort(); 13 | return 0; 14 | } 15 | 16 | // run 17 | -------------------------------------------------------------------------------- /test/cases/run/typedef_and_function_pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef struct _Foo Foo; 3 | typedef int Ret; 4 | typedef int Param; 5 | struct _Foo { Ret (*func)(Param p); }; 6 | static Ret add1(Param p) { 7 | return p + 1; 8 | } 9 | int main(int argc, char **argv) { 10 | Foo strct = { .func = add1 }; 11 | if (strct.func(16) != 17) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/run/Scoped_enums.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | enum Foo { A, B, C }; 4 | enum Foo a = B; 5 | if (a != B) abort(); 6 | if (a != 1) abort(); 7 | { 8 | enum Foo { A = 5, B = 6, C = 7 }; 9 | enum Foo a = B; 10 | if (a != B) abort(); 11 | if (a != 6) abort(); 12 | } 13 | if (a != B) abort(); 14 | if (a != 1) abort(); 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/run/dollar_sign_in_identifiers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define $FOO 2 3 | #define $foo bar$ 4 | #define $baz($x) ($x + $FOO) 5 | int $$$(int $x$) { return $x$ + $FOO; } 6 | int main() { 7 | int bar$ = 42; 8 | if ($foo != 42) abort(); 9 | if (bar$ != 42) abort(); 10 | if ($baz(bar$) != 44) abort(); 11 | if ($$$(bar$) != 44) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/circular_struct_definitions.c: -------------------------------------------------------------------------------- 1 | struct Bar; 2 | 3 | struct Foo { 4 | struct Bar *next; 5 | }; 6 | 7 | struct Bar { 8 | struct Foo *next; 9 | }; 10 | 11 | // translate 12 | // 13 | // pub const struct_Bar = extern struct { 14 | // next: [*c]struct_Foo = null, 15 | // }; 16 | // 17 | // pub const struct_Foo = extern struct { 18 | // next: [*c]struct_Bar = null, 19 | // }; 20 | -------------------------------------------------------------------------------- /test/cases/translate/complex_switch.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int i = 2; 3 | switch (i) { 4 | case 0: { 5 | case 2:{ 6 | i += 2;} 7 | i += 1; 8 | } 9 | } 10 | } 11 | 12 | // translate 13 | // 14 | // :5:13: warning: TODO complex switch 15 | // 16 | // :1:5: warning: unable to translate function, demoted to extern 17 | // pub extern fn main() c_int; 18 | -------------------------------------------------------------------------------- /test/cases/translate/nested_loops_without_blocks.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | while (0) while (0) {} 3 | for (;;) while (0); 4 | for (;;) do {} while (0); 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // while (false) while (false) {}; 11 | // while (true) while (false) {}; 12 | // while (true) while (true) { 13 | // if (!false) break; 14 | // }; 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/Function_prototype_declared_within_function.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | extern int bar(int, int); 3 | return bar(1, 2); 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() c_int { 9 | // const extern_local_bar = struct { 10 | // extern fn bar(c_int, c_int) c_int; 11 | // }; 12 | // _ = &extern_local_bar; 13 | // return extern_local_bar.bar(1, 2); 14 | // } 15 | -------------------------------------------------------------------------------- /test/cases/translate/macro_pointer_type_argument.c: -------------------------------------------------------------------------------- 1 | typedef int Foo; 2 | 3 | #define CAST(type, expr) ((type)(expr)) 4 | #define FOO_CAST(op) CAST(Foo*, (op)) 5 | 6 | // translate 7 | // 8 | // pub const Foo = c_int; 9 | // 10 | // pub const CAST = __helpers.CAST_OR_CALL; 11 | // pub inline fn FOO_CAST(op: anytype) @TypeOf(CAST([*c]Foo, op)) { 12 | // _ = &op; 13 | // return CAST([*c]Foo, op); 14 | // } 15 | -------------------------------------------------------------------------------- /examples/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .examples, 3 | .version = "0.0.0", 4 | .fingerprint = 0x7bd0ad45e4b4e146, 5 | .minimum_zig_version = "0.15.0-dev.460+f4e9846bc", 6 | .paths = .{""}, 7 | .dependencies = .{ 8 | .compile_c = .{ .path = "compile_c" }, 9 | .import_header = .{ .path = "import_header" }, 10 | .use_static_lib = .{ .path = "use_static_lib" }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /test/cases/run/compound_assignments_with_pointer_arithmetic.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | const char *s = "forgreatjustice"; 3 | unsigned int add = 1; 4 | 5 | s += add; 6 | if (*s != 'o') return 1; 7 | 8 | s += 1UL; 9 | if (*s != 'r') return 2; 10 | 11 | const char *s2 = (s += add); 12 | if (*s2 != 'g') return 3; 13 | 14 | s2 -= add; 15 | if (*s2 != 'r') return 4; 16 | 17 | return 0; 18 | } 19 | 20 | // run 21 | -------------------------------------------------------------------------------- /test/cases/translate/Assign_expression_from_bool_to_int.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a; 3 | if (a = 1 > 0) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var a: c_int = undefined; 10 | // _ = &a; 11 | // if ((blk: { 12 | // const tmp = @intFromBool(@as(c_int, 1) > @as(c_int, 0)); 13 | // a = tmp; 14 | // break :blk tmp; 15 | // }) != 0) {} 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/translate/conditional_operator.c: -------------------------------------------------------------------------------- 1 | int bar(void) { 2 | if (2 ? 5 : 5 ? 4 : 6) 2; 3 | return 2 ? 5 : 5 ? 4 : 6; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn bar() c_int { 9 | // if ((if (true) @as(c_int, 5) else if (true) @as(c_int, 4) else @as(c_int, 6)) != 0) { 10 | // _ = 2; 11 | // } 12 | // return if (true) @as(c_int, 5) else if (true) @as(c_int, 4) else @as(c_int, 6); 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/global_assembly.c: -------------------------------------------------------------------------------- 1 | __asm__(".globl func\n\t" 2 | ".type func, @function\n\t" 3 | "func:\n\t" 4 | ".cfi_startproc\n\t" 5 | "movl $42, %eax\n\t" 6 | "ret\n\t" 7 | ".cfi_endproc"); 8 | 9 | // translate 10 | // 11 | // comptime { 12 | // asm (".globl func\n\t.type func, @function\n\tfunc:\n\t.cfi_startproc\n\tmovl $42, %eax\n\tret\n\t.cfi_endproc"); 13 | // } 14 | -------------------------------------------------------------------------------- /test/cases/translate/struct_initializer_-_packed.c: -------------------------------------------------------------------------------- 1 | struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2}; 2 | 3 | // translate 4 | // 5 | // const struct_unnamed_1 = extern struct { 6 | // x: c_int align(1) = 0, 7 | // y: c_int align(1) = 0, 8 | // z: c_int align(1) = 0, 9 | // }; 10 | // pub export var s0: struct_unnamed_1 = struct_unnamed_1{ 11 | // .x = 1, 12 | // .y = 2, 13 | // .z = 0, 14 | // }; 15 | -------------------------------------------------------------------------------- /test/cases/run/array_value_type_casts_properly_use_addeq.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int hash_binary(int k) 3 | { 4 | unsigned int choose[1][1] = {{3}}; 5 | int sum = -1; 6 | int prev = 0; 7 | prev = sum += choose[0][0]; 8 | if (sum != 2) abort(); 9 | return sum + prev; 10 | } 11 | 12 | int main() { 13 | int x = hash_binary(4); 14 | if (x != 4) abort(); 15 | return 0; 16 | } 17 | 18 | // run 19 | -------------------------------------------------------------------------------- /test/cases/translate/empty union initializer list.c: -------------------------------------------------------------------------------- 1 | union U { 2 | int x; 3 | long y; 4 | }; 5 | 6 | void foo(void) { 7 | union U u = {}; 8 | } 9 | // translate 10 | // target=x86_64-linux 11 | // 12 | // pub const union_U = extern union { 13 | // x: c_int, 14 | // y: c_long, 15 | // }; 16 | // pub export fn foo() void { 17 | // var u: union_U = @import("std").mem.zeroes(union_U); 18 | // _ = &u; 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/translate/missing_return_stmt.c: -------------------------------------------------------------------------------- 1 | int foo() {} 2 | int bar() { 3 | int a = 2; 4 | } 5 | int baz() { 6 | return 0; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo() c_int { 12 | // return undefined; 13 | // } 14 | // pub export fn bar() c_int { 15 | // var a: c_int = 2; 16 | // _ = &a; 17 | // return undefined; 18 | // } 19 | // pub export fn baz() c_int { 20 | // return 0; 21 | // } 22 | -------------------------------------------------------------------------------- /test/cases/translate/shadowing_primitive_types.c: -------------------------------------------------------------------------------- 1 | unsigned anyerror = 2; 2 | #define noreturn _Noreturn 3 | typedef enum { 4 | f32, 5 | u32, 6 | } BadEnum; 7 | 8 | // translate 9 | // 10 | // pub export var @"anyerror": c_uint = 2; 11 | // 12 | // pub const @"noreturn" = @compileError("unable to translate C expr: unexpected token '_Noreturn'"); 13 | // 14 | // pub const @"f32": c_int = 0; 15 | // pub const @"u32": c_int = 1; 16 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_assign.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int a; 3 | int b; 4 | a = b = 2; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // var a: c_int = undefined; 11 | // _ = &a; 12 | // var b: c_int = undefined; 13 | // _ = &b; 14 | // a = blk: { 15 | // const tmp = @as(c_int, 2); 16 | // b = tmp; 17 | // break :blk tmp; 18 | // }; 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/run/__builtin_convertvector_float_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef int i32x2 __attribute__((__vector_size__(8))); 3 | typedef float f32x2 __attribute__((__vector_size__(8))); 4 | int main(int argc, char *argv[]) { 5 | f32x2 x = { 1.4, 2.4 }; 6 | i32x2 a = __builtin_convertvector((f32x2){ x[0], x[1] }, i32x2); 7 | if (a[0] != 1) abort(); 8 | if (a[1] != 2) abort(); 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/run/anonymous_struct_&_unions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | static struct { struct { uint16_t x, y; }; } x = { 1 }; 4 | static struct { union { uint32_t x; uint8_t y; }; } y = { 0x55AA55AA }; 5 | int main(int argc, char **argv) { 6 | if (x.x != 1) abort(); 7 | if (x.y != 0) abort(); 8 | if (y.x != 0x55AA55AA) abort(); 9 | if (y.y != 0xAA) abort(); 10 | return 0; 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/translate/unnamed_child_types_of_typedef_receive_typedef's_name.c: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | FooA, 3 | FooB, 4 | } Foo; 5 | typedef struct { 6 | int a, b; 7 | } Bar; 8 | 9 | // translate 10 | // target=native-linux 11 | // 12 | // pub const FooA: c_int = 0; 13 | // pub const FooB: c_int = 1; 14 | // pub const Foo = c_uint; 15 | // pub const Bar = extern struct { 16 | // a: c_int = 0, 17 | // b: c_int = 0, 18 | // }; 19 | -------------------------------------------------------------------------------- /test/cases/run/Cast_boolean_expression_result_to_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | char foo(char c) { return c; } 3 | int bar(int i) { return i; } 4 | long baz(long l) { return l; } 5 | int main() { 6 | if (foo(1 == 2)) abort(); 7 | if (!foo(1 == 1)) abort(); 8 | if (bar(1 == 2)) abort(); 9 | if (!bar(1 == 1)) abort(); 10 | if (baz(1 == 2)) abort(); 11 | if (!baz(1 == 1)) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/==,_!=.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | if (a == b) 3 | return a; 4 | if (a != b) 5 | return b; 6 | return a; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn max(arg_a: c_int, arg_b: c_int) c_int { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // var b = arg_b; 15 | // _ = &b; 16 | // if (a == b) return a; 17 | // if (a != b) return b; 18 | // return a; 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/translate/pointer_to_opaque_demoted_struct.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | _Atomic int foo; 3 | } Foo; 4 | 5 | typedef struct { 6 | Foo *bar; 7 | } Bar; 8 | 9 | // translate 10 | // 11 | // :2:17: warning: struct demoted to opaque type - unable to translate type of field foo 12 | // pub const Foo = opaque {}; 13 | // 14 | // warning: struct demoted to opaque type - unable to translate type of field foo 15 | // pub const Foo = opaque {}; 16 | -------------------------------------------------------------------------------- /test/cases/translate/void_pointer_subtraction.c: -------------------------------------------------------------------------------- 1 | #include 2 | ptrdiff_t sub_ptr(void *a, void *b) { 3 | return a - b; 4 | } 5 | 6 | // translate 7 | // target=x86_64-linux 8 | // 9 | // pub export fn sub_ptr(arg_a: ?*anyopaque, arg_b: ?*anyopaque) ptrdiff_t { 10 | // var a = arg_a; 11 | // _ = &a; 12 | // var b = arg_b; 13 | // _ = &b; 14 | // return @as(c_long, @bitCast(@intFromPtr(a) -% @intFromPtr(b))); 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_assign_from_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int n, tmp = 1; 3 | if (n = tmp) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var n: c_int = undefined; 10 | // _ = &n; 11 | // var tmp: c_int = 1; 12 | // _ = &tmp; 13 | // if ((blk: { 14 | // const tmp_1 = tmp; 15 | // n = tmp_1; 16 | // break :blk tmp_1; 17 | // }) != 0) {} 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_assign_to_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int tmp, n = 1; 3 | if (tmp = n) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var tmp: c_int = undefined; 10 | // _ = &tmp; 11 | // var n: c_int = 1; 12 | // _ = &n; 13 | // if ((blk: { 14 | // const tmp_1 = n; 15 | // tmp = tmp_1; 16 | // break :blk tmp_1; 17 | // }) != 0) {} 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/run/Ensure_side-effects_only_evaluated_once_for_signed_array_indices.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int foo[] = {1, 2, 3, 4}; 4 | int *p = foo; 5 | int idx = 1; 6 | if ((++p)[--idx] != 2) abort(); 7 | if (p != foo + 1) abort(); 8 | if (idx != 0) abort(); 9 | if ((p++)[idx++] != 2) abort(); 10 | if (p != foo + 2) abort(); 11 | if (idx != 1) abort(); 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/run/Function_to_integral.c: -------------------------------------------------------------------------------- 1 | // The C standard does not require function pointers to be convertible to any integer type. 2 | // However, POSIX requires that function pointers have the same representation as `void *` 3 | // so that dlsym() can work 4 | #include 5 | int main(void) { 6 | #if defined(__UINTPTR_MAX__) && __has_include() 7 | uintptr_t x = (uintptr_t)main; 8 | #endif 9 | return 0; 10 | } 11 | 12 | // run 13 | -------------------------------------------------------------------------------- /test/cases/translate/member_with_const_qualifier.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int a; 3 | }; 4 | extern int foo(const struct Foo *); 5 | extern int bar(struct Foo *); 6 | 7 | // translate 8 | // 9 | // pub const struct_Foo = extern struct { 10 | // a: c_int = 0, 11 | // pub const foo = __root.foo; 12 | // pub const bar = __root.bar; 13 | // }; 14 | // pub extern fn foo([*c]const struct_Foo) c_int; 15 | // pub extern fn bar([*c]struct_Foo) c_int; 16 | -------------------------------------------------------------------------------- /test/cases/run/Ensure_while_loop_under_an_if_doesn't_steal_the_else.c: -------------------------------------------------------------------------------- 1 | #include 2 | void doWork(int id) { } 3 | int reallyDelete(int id) { printf("deleted %d\n", id); return 1; } 4 | int process(int id, int n, int delete) { 5 | if(!delete) 6 | while(n-- > 0) doWork(id); 7 | else 8 | return reallyDelete(id); 9 | return 0; 10 | } 11 | int main(void) { 12 | process(99, 3, 0); 13 | return 0; 14 | } 15 | 16 | // run 17 | -------------------------------------------------------------------------------- /test/cases/run/pointer_difference-_unary_operators.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int foo[10]; 4 | int *x = &foo[1]; 5 | const int *y = &foo[5]; 6 | if (y - x++ != 4) abort(); 7 | if (y - x != 3) abort(); 8 | if (y - ++x != 2) abort(); 9 | if (y - x-- != 2) abort(); 10 | if (y - x != 3) abort(); 11 | if (y - --x != 4) abort(); 12 | if (y - &foo[0] != 5) abort(); 13 | return 0; 14 | } 15 | 16 | // run 17 | -------------------------------------------------------------------------------- /test/cases/translate/c_booleans_are_just_ints.c: -------------------------------------------------------------------------------- 1 | #define FOO(x) ((x >= 0) + (x >= 0)) 2 | #define BAR 1 && 2 > 4 3 | 4 | // translate 5 | // 6 | // pub inline fn FOO(x: anytype) @TypeOf(@intFromBool(x >= @as(c_int, 0)) + @intFromBool(x >= @as(c_int, 0))) { 7 | // _ = &x; 8 | // return @intFromBool(x >= @as(c_int, 0)) + @intFromBool(x >= @as(c_int, 0)); 9 | // } 10 | // 11 | // pub const BAR = (@as(c_int, 1) != 0) and (@as(c_int, 2) > @as(c_int, 4)); 12 | -------------------------------------------------------------------------------- /test/cases/translate/ignore_result,_explicit_function_arguments.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a; 3 | 1; 4 | "hey"; 5 | 1 + 1; 6 | 1 - 1; 7 | a = 1; 8 | } 9 | 10 | // translate 11 | // 12 | // pub export fn foo() void { 13 | // var a: c_int = undefined; 14 | // _ = &a; 15 | // _ = 1; 16 | // _ = "hey"; 17 | // _ = @as(c_int, 1) + @as(c_int, 1); 18 | // _ = @as(c_int, 1) - @as(c_int, 1); 19 | // a = 1; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/linksection()_attribute.c: -------------------------------------------------------------------------------- 1 | // Use the "segment,section" format to make this test pass when 2 | // targeting the mach-o binary format 3 | __attribute__ ((__section__("NEAR,.data"))) 4 | extern char my_array[16]; 5 | __attribute__ ((__section__("NEAR,.data"))) 6 | void my_fn(void) { } 7 | 8 | // translate 9 | // 10 | // pub extern var my_array: [16]u8 linksection("NEAR,.data"); 11 | // pub export fn my_fn() linksection("NEAR,.data") void {} 12 | -------------------------------------------------------------------------------- /test/cases/translate/shift_right_assign.c: -------------------------------------------------------------------------------- 1 | int log2(unsigned a) { 2 | int i = 0; 3 | while (a > 0) { 4 | a >>= 1; 5 | } 6 | return i; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn log2(arg_a: c_uint) c_int { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // var i: c_int = 0; 15 | // _ = &i; 16 | // while (a > @as(c_uint, 0)) { 17 | // a >>= @intCast(1); 18 | // } 19 | // return i; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_compound_assign_to_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int ref, n = 1; 3 | if (ref += n) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var ref: c_int = undefined; 10 | // _ = &ref; 11 | // var n: c_int = 1; 12 | // _ = &n; 13 | // if ((blk: { 14 | // const ref_1 = &ref; 15 | // ref_1.* += n; 16 | // break :blk ref_1.*; 17 | // }) != 0) {} 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/run/convert_single-statement_bodies_into_blocks_for_if,else,for,while.c: -------------------------------------------------------------------------------- 1 | #include 2 | int foo() { return 1; } 3 | int main(void) { 4 | int i = 0; 5 | if (i == 0) if (i == 0) if (i != 0) i = 1; 6 | if (i != 0) i = 1; else if (i == 0) if (i == 0) i += 1; 7 | for (; i < 10;) for (; i < 10;) i++; 8 | while (i == 100) while (i == 100) foo(); 9 | if (0) do do "string"; while(1); while(1); 10 | return 0; 11 | } 12 | 13 | // run 14 | -------------------------------------------------------------------------------- /test/cases/translate/alignof.c: -------------------------------------------------------------------------------- 1 | void main() { 2 | int a = _Alignof(int); 3 | } 4 | void foo() { 5 | int a = _Alignof 1; 6 | } 7 | 8 | // translate 9 | // 10 | // pub export fn main() void { 11 | // var a: c_int = @bitCast(@as(c_uint, @truncate(@alignOf(c_int)))); 12 | // _ = &a; 13 | // } 14 | // 15 | // pub export fn foo() void { 16 | // var a: c_int = @bitCast(@as(c_uint, @truncate(@alignOf(@TypeOf(@as(c_int, 1)))))); 17 | // _ = &a; 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/translate/chaining_assign.c: -------------------------------------------------------------------------------- 1 | void max(int a) { 2 | int b, c; 3 | c = b = a; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn max(arg_a: c_int) void { 9 | // var a = arg_a; 10 | // _ = &a; 11 | // var b: c_int = undefined; 12 | // _ = &b; 13 | // var c: c_int = undefined; 14 | // _ = &c; 15 | // c = blk: { 16 | // const tmp = a; 17 | // b = tmp; 18 | // break :blk tmp; 19 | // }; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/large_packed_struct.c: -------------------------------------------------------------------------------- 1 | struct __attribute__((packed)) bar { 2 | short a; 3 | float b; 4 | double c; 5 | short x; 6 | float y; 7 | double z; 8 | }; 9 | 10 | // translate 11 | // 12 | // pub const struct_bar = extern struct { 13 | // a: c_short align(1) = 0, 14 | // b: f32 align(1) = 0, 15 | // c: f64 align(1) = 0, 16 | // x: c_short align(1) = 0, 17 | // y: f32 align(1) = 0, 18 | // z: f64 align(1) = 0, 19 | // }; 20 | -------------------------------------------------------------------------------- /test/cases/translate/typedef_of_function_in_struct_field.c: -------------------------------------------------------------------------------- 1 | typedef void lws_callback_function(void); 2 | struct Foo { 3 | void (*func)(void); 4 | lws_callback_function *callback_http; 5 | }; 6 | 7 | // translate 8 | // 9 | // pub const lws_callback_function = fn () callconv(.c) void; 10 | // pub const struct_Foo = extern struct { 11 | // func: ?*const fn () callconv(.c) void = null, 12 | // callback_http: ?*const lws_callback_function = null, 13 | // }; 14 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_compound_assign_from_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int n, ref = 1; 3 | if (n += ref) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var n: c_int = undefined; 10 | // _ = &n; 11 | // var ref: c_int = 1; 12 | // _ = &ref; 13 | // if ((blk: { 14 | // const ref_1 = &n; 15 | // ref_1.* += ref; 16 | // break :blk ref_1.*; 17 | // }) != 0) {} 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/run/extern_typedef_variables_in_functions.c: -------------------------------------------------------------------------------- 1 | const int ev = 40; 2 | 3 | static int func(void) 4 | { 5 | typedef int test_type_t; 6 | extern const test_type_t ev; 7 | // Ensure mangled name is also being used for conditions and loops, see #20828 8 | if (ev == 0); 9 | while (ev == 0); 10 | do; while (ev == 0); 11 | return ev + 2; 12 | } 13 | 14 | int main() 15 | { 16 | if (func() != 42) 17 | return 1; 18 | return 0; 19 | } 20 | 21 | // run 22 | -------------------------------------------------------------------------------- /test/cases/translate/Make_sure_casts_are_grouped.c: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | int i; 4 | } 5 | *_XPrivDisplay; 6 | typedef struct _XDisplay Display; 7 | #define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) 8 | 9 | 10 | // translate 11 | // 12 | // pub inline fn DefaultScreen(dpy: anytype) @TypeOf(__helpers.cast(_XPrivDisplay, dpy).*.default_screen) { 13 | // _ = &dpy; 14 | // return __helpers.cast(_XPrivDisplay, dpy).*.default_screen; 15 | // } 16 | -------------------------------------------------------------------------------- /test/cases/translate/Pointer_subtraction_with_typedef_linux.c: -------------------------------------------------------------------------------- 1 | typedef char* S; 2 | void foo() { 3 | S a, b; 4 | long c = a - b; 5 | } 6 | 7 | // translate 8 | // target=native-linux 9 | // 10 | // pub export fn foo() void { 11 | // var a: S = undefined; 12 | // _ = &a; 13 | // var b: S = undefined; 14 | // _ = &b; 15 | // var c: c_long = @divExact(@as(c_long, @bitCast(@intFromPtr(a) -% @intFromPtr(b))), @sizeOf(u8)); 16 | // _ = &c; 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/run/Enum_constants_are_assigned_correct_type.c: -------------------------------------------------------------------------------- 1 | enum A { A0, A1=0xFFFFFFFF }; 2 | enum B { B0=-1, B1=0xFFFFFFFF }; 3 | enum C { C0=-1, C1=0 }; 4 | enum D { D0, D1=0xFFFFFFFFFFL }; 5 | enum E { E0=-1, E1=0xFFFFFFFFFFL }; 6 | int main(void) { 7 | signed char a0 = A0, a1 = A1; 8 | signed char b0 = B0, b1 = B1; 9 | signed char c0 = C0, c1 = C1; 10 | signed char d0 = D0, d1 = D1; 11 | signed char e0 = E0, e1 = E1; 12 | return 0; 13 | } 14 | 15 | // run 16 | -------------------------------------------------------------------------------- /test/cases/translate/macro_defines_hexadecimal_float.c: -------------------------------------------------------------------------------- 1 | #define FOO 0xf7p38 2 | #define BAR -0X8F.BP5F 3 | #define FOOBAR 0X0P+0 4 | #define BAZ -0x.0a5dp+12 5 | #define FOOBAZ 0xfE.P-1l 6 | 7 | // translate 8 | // 9 | // pub const FOO = @as(f64, 0xf7p38); 10 | // 11 | // pub const BAR = -@as(f32, 0x8F.BP5); 12 | // 13 | // pub const FOOBAR = @as(f64, 0x0P+0); 14 | // 15 | // pub const BAZ = -@as(f64, 0x0.0a5dp+12); 16 | // 17 | // pub const FOOBAZ = @as(c_longdouble, 0xfE.P-1); 18 | -------------------------------------------------------------------------------- /test/cases/run/boolean_values_and_expressions.c: -------------------------------------------------------------------------------- 1 | #include 2 | static const _Bool false_val = 0; 3 | static const _Bool true_val = 1; 4 | void foo(int x, int y) { 5 | _Bool r = x < y; 6 | if (!r) abort(); 7 | _Bool self = foo; 8 | if (self == false_val) abort(); 9 | if (((r) ? 'a' : 'b') != 'a') abort(); 10 | } 11 | int main(int argc, char **argv) { 12 | foo(2, 5); 13 | if (false_val == true_val) abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/run/Wide,_UTF-16,_and_UTF-32_character_literals.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() { 4 | wchar_t wc = L'™'; 5 | int utf16_char = u'™'; 6 | int utf32_char = U'💯'; 7 | if (wc != 8482) abort(); 8 | if (utf16_char != 8482) abort(); 9 | if (utf32_char != 128175) abort(); 10 | unsigned char c = wc; 11 | if (c != 0x22) abort(); 12 | c = utf32_char; 13 | if (c != 0xaf) abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/run/switch_case.c: -------------------------------------------------------------------------------- 1 | #include 2 | int lottery(unsigned int x) { 3 | switch (x) { 4 | case 3: return 0; 5 | case -1: return 3; 6 | case 8 ... 10: return x; 7 | default: return -1; 8 | } 9 | } 10 | int main(int argc, char **argv) { 11 | if (lottery(2) != -1) abort(); 12 | if (lottery(3) != 0) abort(); 13 | if (lottery(-1) != 3) abort(); 14 | if (lottery(9) != 9) abort(); 15 | return 0; 16 | } 17 | 18 | // run 19 | -------------------------------------------------------------------------------- /test/cases/translate/cast_array_to_pointer.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a[10]; 3 | int* x = a; 4 | 5 | char b[6]; 6 | char* y = b; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo() void { 12 | // var a: [10]c_int = undefined; 13 | // _ = &a; 14 | // var x: [*c]c_int = @ptrCast(@alignCast(&a)); 15 | // _ = &x; 16 | // var b: [6]u8 = undefined; 17 | // _ = &b; 18 | // var y: [*c]u8 = @ptrCast(@alignCast(&b)); 19 | // _ = &y; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/double_define_struct.c: -------------------------------------------------------------------------------- 1 | typedef struct Bar Bar; 2 | typedef struct Foo Foo; 3 | 4 | struct Foo { 5 | Foo *a; 6 | }; 7 | 8 | struct Bar { 9 | Foo *a; 10 | }; 11 | 12 | // translate 13 | // 14 | // pub const struct_Foo = extern struct { 15 | // a: [*c]Foo = null, 16 | // }; 17 | // 18 | // pub const Foo = struct_Foo; 19 | // 20 | // pub const struct_Bar = extern struct { 21 | // a: [*c]Foo = null, 22 | // }; 23 | // 24 | // pub const Bar = struct_Bar; 25 | -------------------------------------------------------------------------------- /test/cases/translate/if_as_while_stmt_has_semicolon.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | while (1) if (1) { 3 | int a = 1; 4 | } else { 5 | int b = 2; 6 | } 7 | if (1) if (1) {} 8 | } 9 | 10 | // translate 11 | // 12 | // pub export fn foo() void { 13 | // while (true) if (true) { 14 | // var a: c_int = 1; 15 | // _ = &a; 16 | // } else { 17 | // var b: c_int = 2; 18 | // _ = &b; 19 | // }; 20 | // if (true) if (true) {}; 21 | // } 22 | -------------------------------------------------------------------------------- /test/cases/translate/widening_and_truncating_integer_casting_to_different_signedness.c: -------------------------------------------------------------------------------- 1 | unsigned long foo(void) { 2 | return -1; 3 | } 4 | unsigned short bar(long x) { 5 | return x; 6 | } 7 | 8 | // translate 9 | // 10 | // pub export fn foo() c_ulong { 11 | // return @bitCast(@as(c_long, -@as(c_int, 1))); 12 | // } 13 | // pub export fn bar(arg_x: c_long) c_ushort { 14 | // var x = arg_x; 15 | // _ = &x; 16 | // return @bitCast(@as(c_short, @truncate(x))); 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/translate/Pointer_subtraction_with_typedef_windows.c: -------------------------------------------------------------------------------- 1 | typedef char* S; 2 | void foo() { 3 | S a, b; 4 | long long c = a - b; 5 | } 6 | 7 | // translate 8 | // target=native-windows-msvc 9 | // 10 | // pub export fn foo() void { 11 | // var a: S = undefined; 12 | // _ = &a; 13 | // var b: S = undefined; 14 | // _ = &b; 15 | // var c: c_longlong = @divExact(@as(c_longlong, @bitCast(@intFromPtr(a) -% @intFromPtr(b))), @sizeOf(u8)); 16 | // _ = &c; 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/translate/align() attribute.c: -------------------------------------------------------------------------------- 1 | __attribute__ ((aligned(128))) 2 | extern char my_array[16]; 3 | __attribute__ ((aligned(128))) 4 | void my_fn(void) { } 5 | void other_fn(void) { 6 | char ARR[16] __attribute__ ((aligned (16))); 7 | } 8 | 9 | // translate 10 | // 11 | // pub extern var my_array: [16]u8 align(128); 12 | // pub export fn my_fn() align(128) void {} 13 | // pub export fn other_fn() void { 14 | // var ARR: [16]u8 align(16) = undefined; 15 | // _ = &ARR; 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/translate/if_statements.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | if (2) { 3 | int a = 2; 4 | } 5 | if (2, 5) { 6 | int a = 2; 7 | } 8 | } 9 | 10 | // translate 11 | // 12 | // pub export fn foo() void { 13 | // if (true) { 14 | // var a: c_int = 2; 15 | // _ = &a; 16 | // } 17 | // if ((blk: { 18 | // _ = 2; 19 | // break :blk 5; 20 | // }) != 0) { 21 | // var a: c_int = 2; 22 | // _ = &a; 23 | // } 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/macro_comparisons.c: -------------------------------------------------------------------------------- 1 | #define MIN(a, b) ((b) < (a) ? (b) : (a)) 2 | #define MAX(a, b) ((b) > (a) ? (b) : (a)) 3 | 4 | // translate 5 | // 6 | // pub inline fn MIN(a: anytype, b: anytype) @TypeOf(if (b < a) b else a) { 7 | // _ = &a; 8 | // _ = &b; 9 | // return if (b < a) b else a; 10 | // } 11 | // 12 | // pub inline fn MAX(a: anytype, b: anytype) @TypeOf(if (b > a) b else a) { 13 | // _ = &a; 14 | // _ = &b; 15 | // return if (b > a) b else a; 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/translate/nameless_struct_fields_linux.c: -------------------------------------------------------------------------------- 1 | typedef struct NAMED 2 | { 3 | long name; 4 | } NAMED; 5 | 6 | typedef struct ONENAMEWITHSTRUCT 7 | { 8 | NAMED; 9 | long b; 10 | } ONENAMEWITHSTRUCT; 11 | 12 | // translate 13 | // target=native-linux 14 | // 15 | // pub const struct_NAMED = extern struct { 16 | // name: c_long = 0, 17 | // }; 18 | // pub const NAMED = struct_NAMED; 19 | // pub const struct_ONENAMEWITHSTRUCT = extern struct { 20 | // b: c_long = 0, 21 | // }; 22 | -------------------------------------------------------------------------------- /test/cases/translate/shift_right_assign_with_a_fixed_size_type.c: -------------------------------------------------------------------------------- 1 | #include 2 | int log2(uint32_t a) { 3 | int i = 0; 4 | while (a > 0) { 5 | a >>= 1; 6 | } 7 | return i; 8 | } 9 | 10 | // translate 11 | // 12 | // pub export fn log2(arg_a: u32) c_int { 13 | // var a = arg_a; 14 | // _ = &a; 15 | // var i: c_int = 0; 16 | // _ = &i; 17 | // while (a > @as(u32, 0)) { 18 | // a >>= @intCast(1); 19 | // } 20 | // return i; 21 | // } 22 | -------------------------------------------------------------------------------- /test/cases/run/Flexible_array_with_typedefed_flexible_item.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef int MARKER[0]; 4 | typedef struct { int x; MARKER y; } Flexible; 5 | #define SIZE 10 6 | int main(void) { 7 | Flexible *flex = malloc(sizeof(Flexible) + SIZE * sizeof(int)); 8 | for (int i = 0; i < SIZE; i++) { 9 | flex->y[i] = i; 10 | } 11 | for (int i = 0; i < SIZE; i++) { 12 | assert(flex->y[i] == i); 13 | } 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/translate/discard_unused_local_variables_and_function_parameters.c: -------------------------------------------------------------------------------- 1 | #define FOO(A, B) (A) 2 | int bar(int x, int y) { 3 | return x; 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn bar(arg_x: c_int, arg_y: c_int) c_int { 9 | // var x = arg_x; 10 | // _ = &x; 11 | // var y = arg_y; 12 | // _ = &y; 13 | // return x; 14 | // } 15 | // 16 | // pub inline fn FOO(A: anytype, B: anytype) @TypeOf(A) { 17 | // _ = &A; 18 | // _ = &B; 19 | // return A; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/struct_with_atomic_field.c: -------------------------------------------------------------------------------- 1 | struct arcan_shmif_cont { 2 | struct arcan_shmif_page* addr; 3 | }; 4 | struct arcan_shmif_page { 5 | volatile _Atomic int abufused[12]; 6 | }; 7 | 8 | // translate 9 | // 10 | // warning: struct demoted to opaque type - unable to translate type of field abufused 11 | // pub const struct_arcan_shmif_page = opaque {}; 12 | // pub const struct_arcan_shmif_cont = extern struct { 13 | // addr: ?*struct_arcan_shmif_page = null, 14 | // }; 15 | -------------------------------------------------------------------------------- /test/cases/translate/logical_and,_logical_or.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | if (a < b || a == b) 3 | return b; 4 | if (a >= b && a == b) 5 | return a; 6 | return a; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn max(arg_a: c_int, arg_b: c_int) c_int { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // var b = arg_b; 15 | // _ = &b; 16 | // if ((a < b) or (a == b)) return b; 17 | // if ((a >= b) and (a == b)) return a; 18 | // return a; 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/translate/field_access_is_grouped_if_necessary.c: -------------------------------------------------------------------------------- 1 | unsigned long foo(unsigned long x) { 2 | return ((union{unsigned long _x}){x})._x; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo(arg_x: c_ulong) c_ulong { 8 | // var x = arg_x; 9 | // _ = &x; 10 | // const union_unnamed_1 = extern union { 11 | // _x: c_ulong, 12 | // }; 13 | // _ = &union_unnamed_1; 14 | // return @as(union_unnamed_1, union_unnamed_1{ 15 | // ._x = x, 16 | // })._x; 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/translate/simple_data_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | int foo(char a, unsigned char b, signed char c); 3 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype 4 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); 5 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); 6 | 7 | // translate 8 | // 9 | // pub extern fn foo(a: u8, b: u8, c: i8) c_int; 10 | // pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void; 11 | // pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void; 12 | -------------------------------------------------------------------------------- /test/cases/translate/unsupport_declare_statement_at_the_last_of_a_compound_statement_which_belongs_to_a_statement_expr.c: -------------------------------------------------------------------------------- 1 | void somefunc(void) { 2 | int y; 3 | (void)({y=1; _Static_assert(1);}); 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn somefunc() void { 9 | // var y: c_int = undefined; 10 | // _ = &y; 11 | // { 12 | // y = 1; 13 | // comptime { 14 | // if (!(@as(c_int, 1) != 0)) @compileError("static assertion failed"); 15 | // } 16 | // } 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/translate/Parameterless_function_prototypes.c: -------------------------------------------------------------------------------- 1 | void a() {} 2 | void b(void) {} 3 | void c(); 4 | void d(void); 5 | static void e() {} 6 | static void f(void) {} 7 | static void g(); 8 | static void h(void); 9 | 10 | // translate 11 | // 12 | // pub export fn a() void {} 13 | // pub export fn b() void {} 14 | // pub extern fn c(...) void; 15 | // pub extern fn d() void; 16 | // pub fn e() callconv(.c) void {} 17 | // pub fn f() callconv(.c) void {} 18 | // pub extern fn g(...) void; 19 | // pub extern fn h() void; 20 | -------------------------------------------------------------------------------- /test/cases/translate/macro_with_cast_to_unsigned_short,_long,_and_long_long.c: -------------------------------------------------------------------------------- 1 | #define CURLAUTH_BASIC_BUT_USHORT ((unsigned short) 1) 2 | #define CURLAUTH_BASIC ((unsigned long) 1) 3 | #define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1) 4 | 5 | // translate 6 | // 7 | // pub const CURLAUTH_BASIC_BUT_USHORT = __helpers.cast(c_ushort, @as(c_int, 1)); 8 | // pub const CURLAUTH_BASIC = __helpers.cast(c_ulong, @as(c_int, 1)); 9 | // pub const CURLAUTH_BASIC_BUT_ULONGLONG = __helpers.cast(c_ulonglong, @as(c_int, 1)); 10 | -------------------------------------------------------------------------------- /test/cases/run/Cast-to-union.c: -------------------------------------------------------------------------------- 1 | #include 2 | struct S { int x; }; 3 | union U { 4 | long l; 5 | double d; 6 | struct S s; 7 | }; 8 | union U bar(union U u) { return u; } 9 | int main(void) { 10 | union U u = (union U) 42L; 11 | if (u.l != 42L) abort(); 12 | u = (union U) 2.0; 13 | if (u.d != 2.0) abort(); 14 | u = bar((union U)4.0); 15 | if (u.d != 4.0) abort(); 16 | u = (union U)(struct S){ .x = 5 }; 17 | if (u.s.x != 5) abort(); 18 | return 0; 19 | } 20 | 21 | // run 22 | -------------------------------------------------------------------------------- /test/cases/translate/Demote_function_that_initializes_opaque_struct.c: -------------------------------------------------------------------------------- 1 | struct my_struct { 2 | unsigned a: 15; 3 | unsigned: 2; 4 | unsigned b: 15; 5 | }; 6 | void initialize(void) { 7 | struct my_struct S = {.a = 1, .b = 2}; 8 | } 9 | 10 | // translate 11 | // 12 | // warning: struct demoted to opaque type - has bitfield 13 | // pub const struct_my_struct = opaque {}; 14 | // pub export fn initialize() void { 15 | // const S = if (true) @compileError("local variable has opaque type"); 16 | // _ = &S; 17 | // } 18 | -------------------------------------------------------------------------------- /test/cases/translate/union_initializer.c: -------------------------------------------------------------------------------- 1 | union { int x; char c[4]; } 2 | ua = {1}, 3 | ub = {.c={'a','b','b','a'}}; 4 | 5 | // translate 6 | // 7 | // const union_unnamed_1 = extern union { 8 | // x: c_int, 9 | // c: [4]u8, 10 | // }; 11 | // pub export var ua: union_unnamed_1 = union_unnamed_1{ 12 | // .x = 1, 13 | // }; 14 | // pub export var ub: union_unnamed_1 = union_unnamed_1{ 15 | // .c = [4]u8{ 16 | // 'a', 17 | // 'b', 18 | // 'b', 19 | // 'a', 20 | // }, 21 | // }; 22 | -------------------------------------------------------------------------------- /test/cases/run/nested_same-name_static_locals.c: -------------------------------------------------------------------------------- 1 | #include 2 | int func(int val) { 3 | static int foo; 4 | if (foo != val) abort(); 5 | { 6 | foo += 1; 7 | static int foo = 2; 8 | if (foo != val + 2) abort(); 9 | foo += 1; 10 | } 11 | return foo; 12 | } 13 | int main(void) { 14 | int foo = 1; 15 | if (func(0) != 1) abort(); 16 | if (func(1) != 2) abort(); 17 | if (func(2) != 3) abort(); 18 | if (foo != 1) abort(); 19 | return 0; 20 | } 21 | 22 | // run 23 | -------------------------------------------------------------------------------- /test/cases/translate/array_initializer_with_typedef.c: -------------------------------------------------------------------------------- 1 | typedef unsigned char uuid_t[16]; 2 | static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 3 | 4 | // translate 5 | // 6 | // pub const uuid_t = [16]u8; 7 | // pub const UUID_NULL: uuid_t = [16]u8{ 8 | // 0, 9 | // 0, 10 | // 0, 11 | // 0, 12 | // 0, 13 | // 0, 14 | // 0, 15 | // 0, 16 | // 0, 17 | // 0, 18 | // 0, 19 | // 0, 20 | // 0, 21 | // 0, 22 | // 0, 23 | // 0, 24 | // }; 25 | -------------------------------------------------------------------------------- /test/cases/translate/macro_cast.c: -------------------------------------------------------------------------------- 1 | #include 2 | int baz(void *arg) { return 0; } 3 | #define FOO(bar) baz((void *)(baz)) 4 | #define BAR (void*) a 5 | #define BAZ (uint32_t)(2) 6 | #define a 2 7 | 8 | // translate 9 | // 10 | // pub inline fn FOO(bar: anytype) @TypeOf(baz(__helpers.cast(?*anyopaque, baz))) { 11 | // _ = &bar; 12 | // return baz(__helpers.cast(?*anyopaque, baz)); 13 | // } 14 | // 15 | // pub const BAR = __helpers.cast(?*anyopaque, a); 16 | // 17 | // pub const BAZ = __helpers.cast(u32, @as(c_int, 2)); 18 | -------------------------------------------------------------------------------- /test/cases/translate/_Static_assert.c: -------------------------------------------------------------------------------- 1 | _Static_assert(1 == 1, ""); 2 | 3 | void my_function() { 4 | _Static_assert(2 + 2 * 2 == 6, "Math is hard"); 5 | } 6 | 7 | // translate 8 | // 9 | // comptime { 10 | // if (!(@as(c_int, 1) == @as(c_int, 1))) @compileError("static assertion failed \"\""); 11 | // } 12 | // pub export fn my_function() void { 13 | // comptime { 14 | // if (!((@as(c_int, 2) + (@as(c_int, 2) * @as(c_int, 2))) == @as(c_int, 6))) @compileError("static assertion failed \"Math is hard\""); 15 | // } 16 | // } 17 | -------------------------------------------------------------------------------- /test/cases/translate/macro_referencing_var.c: -------------------------------------------------------------------------------- 1 | extern float foo; 2 | #define FOO_TWICE foo * 2.0f 3 | #define FOO_NEGATIVE -foo 4 | 5 | #define BAR 10.0f 6 | #define BAR_TWICE BAR * 2.0f 7 | 8 | // translate 9 | // 10 | // pub extern var foo: f32; 11 | // 12 | // pub inline fn FOO_TWICE() @TypeOf(foo * @as(f32, 2.0)) { 13 | // return foo * @as(f32, 2.0); 14 | // } 15 | // 16 | // pub inline fn FOO_NEGATIVE() @TypeOf(-foo) { 17 | // return -foo; 18 | // } 19 | // pub const BAR = @as(f32, 10.0); 20 | // pub const BAR_TWICE = BAR * @as(f32, 2.0); 21 | -------------------------------------------------------------------------------- /test/cases/translate/static_variable_in_block_scope.c: -------------------------------------------------------------------------------- 1 | float static_local_bar; 2 | float bar; 3 | int foo() { 4 | _Thread_local static int bar = 2; 5 | (void)bar; 6 | } 7 | 8 | // translate 9 | // 10 | // pub export var static_local_bar: f32 = 0; 11 | // pub export var bar: f32 = 0; 12 | // pub export fn foo() c_int { 13 | // const static_local_bar_1 = struct { 14 | // threadlocal var bar: c_int = 2; 15 | // }; 16 | // _ = &static_local_bar_1; 17 | // _ = static_local_bar_1.bar; 18 | // return undefined; 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/translate/struct_in_struct_init_to_zero.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int a; 3 | struct Bar { 4 | int a; 5 | } b; 6 | } a = {}; 7 | 8 | // translate 9 | // 10 | // pub const struct_Bar_1 = extern struct { 11 | // a: c_int = 0, 12 | // }; 13 | // pub const struct_Foo = extern struct { 14 | // a: c_int = 0, 15 | // b: struct_Bar_1 = @import("std").mem.zeroes(struct_Bar_1), 16 | // }; 17 | // pub export var a: struct_Foo = struct_Foo{ 18 | // .a = 0, 19 | // .b = @import("std").mem.zeroes(struct_Bar_1), 20 | // }; 21 | -------------------------------------------------------------------------------- /test/cases/translate/type_referenced_struct.c: -------------------------------------------------------------------------------- 1 | // When clang uses the -windows-none, triple it behaves as MSVC and 2 | // interprets the inner `struct Bar` as an anonymous structure 3 | struct Foo { 4 | struct Bar{ 5 | int b; 6 | }; 7 | struct Bar c; 8 | }; 9 | 10 | // translate 11 | // target=x86_64-linux-gnu 12 | // 13 | // pub const struct_Bar_1 = extern struct { 14 | // b: c_int = 0, 15 | // }; 16 | // pub const struct_Foo = extern struct { 17 | // c: struct_Bar_1 = @import("std").mem.zeroes(struct_Bar_1), 18 | // }; 19 | -------------------------------------------------------------------------------- /test/cases/run/Allow_non-const_char_ptr_string_literals.c: -------------------------------------------------------------------------------- 1 | #include 2 | int func(char *x) { return x[0]; } 3 | struct S { char *member; }; 4 | struct S global_struct = { .member = "global" }; 5 | char *g = "global"; 6 | int main(void) { 7 | if (g[0] != 'g') abort(); 8 | if (global_struct.member[0] != 'g') abort(); 9 | char *string = "hello"; 10 | if (string[0] != 'h') abort(); 11 | struct S s = {.member = "hello"}; 12 | if (s.member[0] != 'h') abort(); 13 | if (func("foo") != 'f') abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/translate/simple_if_statement.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | if (a < b) 3 | return b; 4 | 5 | if (a < b) 6 | return b; 7 | else 8 | return a; 9 | 10 | if (a < b) ; else ; 11 | } 12 | 13 | // translate 14 | // 15 | // pub export fn max(arg_a: c_int, arg_b: c_int) c_int { 16 | // var a = arg_a; 17 | // _ = &a; 18 | // var b = arg_b; 19 | // _ = &b; 20 | // if (a < b) return b; 21 | // if (a < b) return b else return a; 22 | // if (a < b) {} else {} 23 | // return undefined; 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/run/typeof_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int FOO = 42; 3 | typedef typeof(FOO) foo_type; 4 | typeof(foo_type) myfunc(typeof(FOO) x) { return (typeof(FOO)) x; } 5 | int main(void) { 6 | int x = FOO; 7 | typeof(x) y = x; 8 | foo_type z = y; 9 | if (x != y) abort(); 10 | if (myfunc(z) != x) abort(); 11 | 12 | const char *my_string = "bar"; 13 | typeof (typeof (my_string)[4]) string_arr = {"a","b","c","d"}; 14 | if (string_arr[0][0] != 'a' || string_arr[3][0] != 'd') abort(); 15 | return 0; 16 | } 17 | 18 | // run 19 | -------------------------------------------------------------------------------- /test/cases/translate/array_access.c: -------------------------------------------------------------------------------- 1 | #define ACCESS array[2] 2 | int array[100] = {}; 3 | int foo(int index) { 4 | return array[index]; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export var array: [100]c_int = [1]c_int{0} ** 100; 10 | // pub export fn foo(arg_index: c_int) c_int { 11 | // var index = arg_index; 12 | // _ = &index; 13 | // return array[@bitCast(@as(isize, @intCast(index)))]; 14 | // } 15 | // 16 | // pub inline fn ACCESS() @TypeOf(array[@as(usize, @intCast(@as(c_int, 2)))]) { 17 | // return array[@as(usize, @intCast(@as(c_int, 2)))]; 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_precrement_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int n, ref = 1; 3 | if (n = ++ref) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var n: c_int = undefined; 10 | // _ = &n; 11 | // var ref: c_int = 1; 12 | // _ = &ref; 13 | // if ((blk: { 14 | // const tmp = blk_1: { 15 | // const ref_2 = &ref; 16 | // ref_2.* += 1; 17 | // break :blk_1 ref_2.*; 18 | // }; 19 | // n = tmp; 20 | // break :blk tmp; 21 | // }) != 0) {} 22 | // } 23 | -------------------------------------------------------------------------------- /test/cases/translate/Demote_function_that_dereference_types_that_contain_opaque_type.c: -------------------------------------------------------------------------------- 1 | struct inner { 2 | _Atomic int a; 3 | }; 4 | struct outer { 5 | int thing; 6 | struct inner sub_struct; 7 | }; 8 | void deref(struct outer *s) { 9 | *s; 10 | } 11 | 12 | // translate 13 | // 14 | // pub const struct_inner = opaque {}; 15 | // 16 | // warning: struct demoted to opaque type - has opaque field 17 | // pub const struct_outer = opaque {}; 18 | // 19 | // warning: unable to translate function, demoted to extern 20 | // 21 | // pub extern fn deref(arg_s: ?*struct_outer) void; 22 | -------------------------------------------------------------------------------- /test/cases/translate/basic_macro_function.c: -------------------------------------------------------------------------------- 1 | extern int c; 2 | #define BASIC(c) (c*2) 3 | #define FOO(L,b) (L + b) 4 | #define BAR() (c*c) 5 | 6 | // translate 7 | // 8 | // pub extern var c: c_int; 9 | // 10 | // pub inline fn BASIC(c_1: anytype) @TypeOf(c_1 * @as(c_int, 2)) { 11 | // _ = &c_1; 12 | // return c_1 * @as(c_int, 2); 13 | // } 14 | // 15 | // pub inline fn FOO(L: anytype, b: anytype) @TypeOf(L + b) { 16 | // _ = &L; 17 | // _ = &b; 18 | // return L + b; 19 | // } 20 | // 21 | // pub inline fn BAR() @TypeOf(c * c) { 22 | // return c * c; 23 | // } 24 | -------------------------------------------------------------------------------- /test/cases/translate/macro_add.c: -------------------------------------------------------------------------------- 1 | #define D3_AHB1PERIPH_BASE 0 2 | #define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ 3 | #define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) 4 | #define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) 5 | 6 | // translate 7 | // 8 | // pub const PERIPH_BASE = @as(c_ulong, 0x40000000); 9 | // 10 | // pub const D3_APB1PERIPH_BASE = PERIPH_BASE + @as(c_ulong, 0x18000000); 11 | // 12 | // pub const RCC_BASE = D3_AHB1PERIPH_BASE + @as(c_ulong, 0x4400); 13 | -------------------------------------------------------------------------------- /test/cases/run/__cleanup___attribute.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int cleanup_count = 0; 3 | void clean_up(int *final_value) { 4 | if (*final_value != cleanup_count++) abort(); 5 | } 6 | void doit(void) { 7 | int a __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 2; 8 | int b __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 1; 9 | int c __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 0; 10 | } 11 | int main(void) { 12 | doit(); 13 | if (cleanup_count != 3) abort(); 14 | return 0; 15 | } 16 | 17 | // run 18 | -------------------------------------------------------------------------------- /test/cases/translate/nested_assignment.c: -------------------------------------------------------------------------------- 1 | int foo(int *p, int x) { 2 | return *p++ = x; 3 | } 4 | 5 | // translate 6 | // 7 | // pub export fn foo(arg_p: [*c]c_int, arg_x: c_int) c_int { 8 | // var p = arg_p; 9 | // _ = &p; 10 | // var x = arg_x; 11 | // _ = &x; 12 | // return blk: { 13 | // const tmp = x; 14 | // (blk_1: { 15 | // const ref = &p; 16 | // const tmp_2 = ref.*; 17 | // ref.* += 1; 18 | // break :blk_1 tmp_2; 19 | // }).* = tmp; 20 | // break :blk tmp; 21 | // }; 22 | // } 23 | -------------------------------------------------------------------------------- /test/cases/run/__builtin_convertvector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef int16_t __v8hi __attribute__((__vector_size__(16))); 4 | typedef uint16_t __v8hu __attribute__((__vector_size__(16))); 5 | int main(int argc, char**argv) { 6 | __v8hi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4}; 7 | __v8hu unsigned_vector = __builtin_convertvector(signed_vector, __v8hu); 8 | 9 | for (int i = 0; i < 8; i++) { 10 | if (unsigned_vector[i] != (uint16_t)signed_vector[i]) abort(); 11 | } 12 | return 0; 13 | } 14 | 15 | // run 16 | // skip_vector_index=true 17 | -------------------------------------------------------------------------------- /test/cases/translate/static empty struct.c: -------------------------------------------------------------------------------- 1 | struct empty_struct {}; 2 | 3 | static inline void foo() { 4 | static struct empty_struct bar = {}; 5 | (void)bar; 6 | } 7 | 8 | // translate 9 | // target=x86_64-linux 10 | // 11 | // pub const struct_empty_struct = extern struct {}; 12 | // pub fn foo() callconv(.c) void { 13 | // const static_local_bar = struct { 14 | // var bar: struct_empty_struct = struct_empty_struct{}; 15 | // }; 16 | // _ = &static_local_bar; 17 | // _ = static_local_bar.bar; 18 | // } 19 | // 20 | // pub const empty_struct = struct_empty_struct; 21 | -------------------------------------------------------------------------------- /test/cases/translate/sizeof.c: -------------------------------------------------------------------------------- 1 | #include 2 | size_t size_of(void) { 3 | return sizeof(int); 4 | } 5 | size_t size_of_expr(void) { 6 | return sizeof 1; 7 | } 8 | #define sizeof_macro(x) sizeof(x) 9 | 10 | // translate 11 | // 12 | // pub export fn size_of() usize { 13 | // return @sizeOf(c_int); 14 | // } 15 | // 16 | // pub export fn size_of_expr() usize { 17 | // return @sizeOf(@TypeOf(@as(c_int, 1))); 18 | // } 19 | // 20 | // pub inline fn sizeof_macro(x: anytype) @TypeOf(__helpers.sizeof(x)) { 21 | // _ = &x; 22 | // return __helpers.sizeof(x); 23 | // } 24 | -------------------------------------------------------------------------------- /test/cases/run/Address_of_function_is_no-op.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef int (*myfunc)(int); 4 | int a(int arg) { return arg + 1;} 5 | int b(int arg) { return arg + 2;} 6 | int caller(myfunc fn, int arg) { 7 | return fn(arg); 8 | } 9 | int main() { 10 | myfunc arr[3] = {&a, &b, a}; 11 | myfunc foo = a; 12 | myfunc bar = &(a); 13 | if (foo != bar) abort(); 14 | if (arr[0] == arr[1]) abort(); 15 | if (arr[0] != arr[2]) abort(); 16 | if (caller(b, 40) != 42) abort(); 17 | if (caller(&b, 40) != 42) abort(); 18 | return 0; 19 | } 20 | 21 | // run 22 | -------------------------------------------------------------------------------- /test/cases/translate/for_on_non-bool.c: -------------------------------------------------------------------------------- 1 | int for_none_bool() { 2 | int a; 3 | float b; 4 | void *c; 5 | for (;a;) return 0; 6 | for (;b;) return 1; 7 | for (;c;) return 2; 8 | return 3; 9 | } 10 | 11 | // translate 12 | // 13 | // pub export fn for_none_bool() c_int { 14 | // var a: c_int = undefined; 15 | // _ = &a; 16 | // var b: f32 = undefined; 17 | // _ = &b; 18 | // var c: ?*anyopaque = undefined; 19 | // _ = &c; 20 | // while (a != 0) return 0; 21 | // while (b != 0) return 1; 22 | // while (c != null) return 2; 23 | // return 3; 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/c_style_cast.c: -------------------------------------------------------------------------------- 1 | int int_from_float(float a) { 2 | return (int)a; 3 | } 4 | 5 | int add_int_from_float(float a, float b) { 6 | return (int)a + (int) b; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn int_from_float(arg_a: f32) c_int { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // return @intFromFloat(a); 15 | // } 16 | // pub export fn add_int_from_float(arg_a: f32, arg_b: f32) c_int { 17 | // var a = arg_a; 18 | // _ = &a; 19 | // var b = arg_b; 20 | // _ = &b; 21 | // return @as(c_int, @intFromFloat(a)) + @as(c_int, @intFromFloat(b)); 22 | // } 23 | -------------------------------------------------------------------------------- /test/cases/translate/variables_check_for_opaque_demotion.c: -------------------------------------------------------------------------------- 1 | struct A { 2 | _Atomic int a; 3 | } a; 4 | int main(void) { 5 | struct A b; 6 | } 7 | 8 | // translate 9 | // 10 | // warning: TODO support atomic type: '_Atomic(int)' 11 | // 12 | // warning: struct demoted to opaque type - unable to translate type of field a 13 | // pub const struct_A = opaque {}; 14 | // pub const a = @compileError("non-extern variable has opaque type"); 15 | // 16 | // pub export fn main() c_int { 17 | // const b = if (true) @compileError("local variable has opaque type"); 18 | // _ = &b; 19 | // return 0; 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/while_on_non-bool.c: -------------------------------------------------------------------------------- 1 | int while_none_bool() { 2 | int a; 3 | float b; 4 | void *c; 5 | while (a) return 0; 6 | while (b) return 1; 7 | while (c) return 2; 8 | return 3; 9 | } 10 | 11 | // translate 12 | // 13 | // pub export fn while_none_bool() c_int { 14 | // var a: c_int = undefined; 15 | // _ = &a; 16 | // var b: f32 = undefined; 17 | // _ = &b; 18 | // var c: ?*anyopaque = undefined; 19 | // _ = &c; 20 | // while (a != 0) return 0; 21 | // while (b != 0) return 1; 22 | // while (c != null) return 2; 23 | // return 3; 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/zero_width_field_alignment_.c: -------------------------------------------------------------------------------- 1 | struct __attribute__((packed)) foo { 2 | int x; 3 | struct {}; 4 | float y; 5 | union {}; 6 | }; 7 | 8 | // translate 9 | // target=native-linux 10 | // 11 | // const struct_unnamed_1 = extern struct {}; 12 | // const union_unnamed_2 = extern union {}; 13 | // pub const struct_foo = extern struct { 14 | // x: c_int align(1) = 0, 15 | // unnamed_0: struct_unnamed_1 align(1) = @import("std").mem.zeroes(struct_unnamed_1), 16 | // y: f32 align(1) = 0, 17 | // unnamed_1: union_unnamed_2 align(1) = @import("std").mem.zeroes(union_unnamed_2), 18 | // }; 19 | -------------------------------------------------------------------------------- /test/cases/run/pointer_difference-_struct_array_with_padding.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define SIZE 10 4 | typedef struct my_struct { 5 | int x; 6 | char c; 7 | int y; 8 | } my_struct_t; 9 | int main() { 10 | my_struct_t foo[SIZE]; 11 | my_struct_t *start = &foo[0]; 12 | my_struct_t *one_past_end = start + SIZE; 13 | ptrdiff_t diff = one_past_end - start; 14 | int diff_int = one_past_end - start; 15 | if (diff != SIZE || diff_int != SIZE) abort(); 16 | diff = start - one_past_end; 17 | if (diff != -SIZE) abort(); 18 | return 0; 19 | } 20 | 21 | // run 22 | -------------------------------------------------------------------------------- /test/cases/translate/static_local_variable_zero-initialized_if_no_initializer.c: -------------------------------------------------------------------------------- 1 | struct FOO {int x; int y;}; 2 | int bar(void) { 3 | static struct FOO foo; 4 | return foo.x; 5 | } 6 | 7 | // translate 8 | // 9 | // pub const struct_FOO = extern struct { 10 | // x: c_int = 0, 11 | // y: c_int = 0, 12 | // }; 13 | // pub export fn bar() c_int { 14 | // const static_local_foo = struct { 15 | // var foo: struct_FOO = @import("std").mem.zeroes(struct_FOO); 16 | // }; 17 | // _ = &static_local_foo; 18 | // return static_local_foo.foo.x; 19 | // } 20 | // 21 | // pub const FOO = struct_FOO; 22 | -------------------------------------------------------------------------------- /test/cases/translate/worst-case_postcrement_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int n, ref = 1; 3 | if (n = ref++) {} 4 | } 5 | 6 | // translate 7 | // 8 | // pub export fn foo() void { 9 | // var n: c_int = undefined; 10 | // _ = &n; 11 | // var ref: c_int = 1; 12 | // _ = &ref; 13 | // if ((blk: { 14 | // const tmp = blk_1: { 15 | // const ref_2 = &ref; 16 | // const tmp_3 = ref_2.*; 17 | // ref_2.* += 1; 18 | // break :blk_1 tmp_3; 19 | // }; 20 | // n = tmp; 21 | // break :blk tmp; 22 | // }) != 0) {} 23 | // } 24 | -------------------------------------------------------------------------------- /test/cases/translate/nameless_struct_fields_MSVC.c: -------------------------------------------------------------------------------- 1 | typedef struct NAMED 2 | { 3 | long name; 4 | } NAMED; 5 | 6 | typedef struct ONENAMEWITHSTRUCT 7 | { 8 | NAMED; 9 | long b; 10 | } ONENAMEWITHSTRUCT; 11 | 12 | // translate 13 | // target=native-windows-msvc 14 | // 15 | // pub const struct_NAMED = extern struct { 16 | // name: c_long = 0, 17 | // }; 18 | // pub const NAMED = struct_NAMED; 19 | // pub const struct_ONENAMEWITHSTRUCT = extern struct { 20 | // unnamed_0: NAMED = @import("std").mem.zeroes(NAMED), 21 | // b: c_long = 0, 22 | // }; 23 | // pub const ONENAMEWITHSTRUCT = struct_ONENAMEWITHSTRUCT; 24 | -------------------------------------------------------------------------------- /test/cases/translate/packed_union_nested_unpacked.c: -------------------------------------------------------------------------------- 1 | // NOTE: The nested struct is *not* packed/aligned, 2 | // even though the parent struct is 3 | // this is consistent with GCC docs 4 | union Foo{ 5 | short x; 6 | double y; 7 | struct { 8 | int b; 9 | } z; 10 | } __attribute__((packed)); 11 | 12 | // translate 13 | // 14 | // const struct_unnamed_1 = extern struct { 15 | // b: c_int = 0, 16 | // }; 17 | // 18 | // pub const union_Foo = extern union { 19 | // x: c_short align(1), 20 | // y: f64 align(1), 21 | // z: struct_unnamed_1 align(1), 22 | // }; 23 | // 24 | // pub const Foo = union_Foo; 25 | -------------------------------------------------------------------------------- /test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c: -------------------------------------------------------------------------------- 1 | struct opaque; 2 | struct opaque_2; 3 | void function(struct opaque *opaque) { 4 | struct opaque_2 *cast = (struct opaque_2 *)opaque; 5 | } 6 | 7 | // translate 8 | // 9 | // pub const struct_opaque = opaque { 10 | // pub const function = __root.function; 11 | // }; 12 | // pub const struct_opaque_2 = opaque {}; 13 | // pub export fn function(arg_opaque_1: ?*struct_opaque) void { 14 | // var opaque_1 = arg_opaque_1; 15 | // _ = &opaque_1; 16 | // var cast: ?*struct_opaque_2 = @ptrCast(@alignCast(opaque_1)); 17 | // _ = &cast; 18 | // } 19 | -------------------------------------------------------------------------------- /test/cases/translate/unnamed_fields_have_predictable_names.c: -------------------------------------------------------------------------------- 1 | struct a { 2 | struct { int x; }; 3 | }; 4 | struct b { 5 | struct { int y; }; 6 | }; 7 | 8 | // translate 9 | // 10 | // const struct_unnamed_1 = extern struct { 11 | // x: c_int = 0, 12 | // }; 13 | // pub const struct_a = extern struct { 14 | // unnamed_0: struct_unnamed_1 = @import("std").mem.zeroes(struct_unnamed_1), 15 | // }; 16 | // const struct_unnamed_2 = extern struct { 17 | // y: c_int = 0, 18 | // }; 19 | // pub const struct_b = extern struct { 20 | // unnamed_0: struct_unnamed_2 = @import("std").mem.zeroes(struct_unnamed_2), 21 | // }; 22 | -------------------------------------------------------------------------------- /test/cases/translate/handling_of__Bool_type.c: -------------------------------------------------------------------------------- 1 | _Bool foo(_Bool x) { 2 | _Bool a = x != 1; 3 | _Bool b = a != 0; 4 | _Bool c = foo; 5 | return foo(c != b); 6 | } 7 | 8 | // translate 9 | // 10 | // pub export fn foo(arg_x: bool) bool { 11 | // var x = arg_x; 12 | // _ = &x; 13 | // var a: bool = @as(c_int, @intFromBool(x)) != @as(c_int, 1); 14 | // _ = &a; 15 | // var b: bool = @as(c_int, @intFromBool(a)) != @as(c_int, 0); 16 | // _ = &b; 17 | // var c: bool = @intFromPtr(&foo) != 0; 18 | // _ = &c; 19 | // return foo(@as(c_int, @intFromBool(c)) != @as(c_int, @intFromBool(b))); 20 | // } 21 | -------------------------------------------------------------------------------- /test/cases/translate/qualified_struct_and_enum.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int x; 3 | int y; 4 | }; 5 | enum Bar { 6 | BarA, 7 | BarB, 8 | }; 9 | void func(struct Foo *a, enum Bar **b); 10 | 11 | // translate 12 | // target=x86_64-linux 13 | // 14 | // pub const struct_Foo = extern struct { 15 | // x: c_int = 0, 16 | // y: c_int = 0, 17 | // pub const func = __root.func; 18 | // }; 19 | // pub const BarA: c_int = 0; 20 | // pub const BarB: c_int = 1; 21 | // pub const enum_Bar = c_uint; 22 | // pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; 23 | // 24 | // pub const Foo = struct_Foo; 25 | // pub const Bar = enum_Bar; 26 | -------------------------------------------------------------------------------- /test/cases/translate/for_loops.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | for (int i = 2, b = 4; i + 2; i = 2) { 3 | int a = 2; 4 | a = 6, 5, 7; 5 | } 6 | char i = 2; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo() void { 12 | // { 13 | // var i: c_int = 2; 14 | // _ = &i; 15 | // var b: c_int = 4; 16 | // _ = &b; 17 | // while ((i + @as(c_int, 2)) != 0) : (i = 2) { 18 | // var a: c_int = 2; 19 | // _ = &a; 20 | // a = 6; 21 | // _ = 5; 22 | // _ = 7; 23 | // } 24 | // } 25 | // var i: u8 = 2; 26 | // _ = &i; 27 | // } 28 | -------------------------------------------------------------------------------- /test/cases/translate/casting_away_const_and_volatile.c: -------------------------------------------------------------------------------- 1 | void foo(int *a) {} 2 | void bar(const int *a) { 3 | foo((int *)a); 4 | } 5 | void baz(volatile int *a) { 6 | foo((int *)a); 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo(arg_a: [*c]c_int) void { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // } 15 | // pub export fn bar(arg_a: [*c]const c_int) void { 16 | // var a = arg_a; 17 | // _ = &a; 18 | // foo(@ptrCast(@alignCast(@constCast(a)))); 19 | // } 20 | // pub export fn baz(arg_a: [*c]volatile c_int) void { 21 | // var a = arg_a; 22 | // _ = &a; 23 | // foo(@ptrCast(@alignCast(@volatileCast(a)))); 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/qualified_struct_and_enum_msvc.c: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | int x; 3 | int y; 4 | }; 5 | enum Bar { 6 | BarA, 7 | BarB, 8 | }; 9 | void func(struct Foo *a, enum Bar **b); 10 | 11 | // translate 12 | // target=x86_64-windows-msvc 13 | // 14 | // pub const struct_Foo = extern struct { 15 | // x: c_int = 0, 16 | // y: c_int = 0, 17 | // pub const func = __root.func; 18 | // }; 19 | // pub const BarA: c_int = 0; 20 | // pub const BarB: c_int = 1; 21 | // pub const enum_Bar = c_int; 22 | // pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; 23 | // 24 | // pub const Foo = struct_Foo; 25 | // pub const Bar = enum_Bar; 26 | -------------------------------------------------------------------------------- /test/cases/translate/bool_not.c: -------------------------------------------------------------------------------- 1 | int foo() { 2 | int a; 3 | float b; 4 | void *c; 5 | if (1) return !(a == 0); 6 | if (1) return !a; 7 | if (1) return !b; 8 | return !c; 9 | } 10 | 11 | // translate 12 | // 13 | // pub export fn foo() c_int { 14 | // var a: c_int = undefined; 15 | // _ = &a; 16 | // var b: f32 = undefined; 17 | // _ = &b; 18 | // var c: ?*anyopaque = undefined; 19 | // _ = &c; 20 | // if (true) return @intFromBool(!(a == @as(c_int, 0))); 21 | // if (true) return @intFromBool(!(a != 0)); 22 | // if (true) return @intFromBool(!(b != 0)); 23 | // return @intFromBool(!(c != null)); 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/run/pointer_difference-_scalar_array_with_size_truncation_or_negative_result.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define SIZE 10 4 | int main() { 5 | int foo[SIZE]; 6 | int *start = &foo[0]; 7 | int *one_past_end = start + SIZE; 8 | ptrdiff_t diff = one_past_end - start; 9 | char diff_char = one_past_end - start; 10 | if (diff != SIZE || diff_char != SIZE) abort(); 11 | diff = start - one_past_end; 12 | if (diff != -SIZE) abort(); 13 | if (one_past_end - foo != SIZE) abort(); 14 | if ((one_past_end - 1) - foo != SIZE - 1) abort(); 15 | if ((start + 1) - foo != 1) abort(); 16 | return 0; 17 | } 18 | 19 | // run 20 | -------------------------------------------------------------------------------- /test/cases/run/out-ofscope_function_declaration.c: -------------------------------------------------------------------------------- 1 | int bar(int a) { 2 | extern int abs(int); 3 | return abs(a); 4 | } 5 | int foo() { 6 | return abs(-1); 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn bar(arg_a: c_int) c_int { 12 | // var a = arg_a; 13 | // _ = &a; 14 | // const extern_local_abs = struct { 15 | // extern fn abs(c_int) c_int; 16 | // }; 17 | // _ = &extern_local_abs; 18 | // return extern_local_abs.abs(a); 19 | // } 20 | // pub export fn foo() c_int { 21 | // const extern_local_abs = struct { 22 | // extern fn abs(c_int) c_int; 23 | // }; 24 | // _ = &extern_local_abs; 25 | // return abs(-@as(c_int, 1)); 26 | // } -------------------------------------------------------------------------------- /test/cases/translate/extern_local_used_in_nested_block.c: -------------------------------------------------------------------------------- 1 | int foo(int bar) { 2 | extern int arr[]; 3 | if (bar) { 4 | return *(arr + 2); 5 | } 6 | return 0; 7 | } 8 | 9 | // translate 10 | // 11 | // pub export fn foo(arg_bar: c_int) c_int { 12 | // var bar = arg_bar; 13 | // _ = &bar; 14 | // const extern_local_arr = struct { 15 | // const arr: [*c]c_int = @extern([*c]c_int, .{ 16 | // .name = "arr", 17 | // }); 18 | // }; 19 | // _ = &extern_local_arr; 20 | // if (bar != 0) { 21 | // return (extern_local_arr.arr + @as(usize, @bitCast(@as(isize, @intCast(@as(c_int, 2)))))).*; 22 | // } 23 | // return 0; 24 | // } -------------------------------------------------------------------------------- /test/cases/translate/post_increment.c: -------------------------------------------------------------------------------- 1 | unsigned foo1(unsigned a) { 2 | a++; 3 | return a; 4 | } 5 | int foo2(int a) { 6 | a++; 7 | return a; 8 | } 9 | int *foo3(int *a) { 10 | a++; 11 | return a; 12 | } 13 | 14 | // translate 15 | // 16 | // pub export fn foo1(arg_a: c_uint) c_uint { 17 | // var a = arg_a; 18 | // _ = &a; 19 | // a +%= 1; 20 | // return a; 21 | // } 22 | // pub export fn foo2(arg_a: c_int) c_int { 23 | // var a = arg_a; 24 | // _ = &a; 25 | // a += 1; 26 | // return a; 27 | // } 28 | // pub export fn foo3(arg_a: [*c]c_int) [*c]c_int { 29 | // var a = arg_a; 30 | // _ = &a; 31 | // a += 1; 32 | // return a; 33 | // } 34 | -------------------------------------------------------------------------------- /test/cases/translate/union_struct_forward_decl.c: -------------------------------------------------------------------------------- 1 | struct A; 2 | union B; 3 | enum C; 4 | 5 | struct A { 6 | short x; 7 | double y; 8 | }; 9 | 10 | union B { 11 | short x; 12 | double y; 13 | }; 14 | 15 | struct Foo { 16 | struct A a; 17 | union B b; 18 | }; 19 | 20 | 21 | // translate 22 | // 23 | // pub const struct_A = extern struct { 24 | // x: c_short = 0, 25 | // y: f64 = 0, 26 | // }; 27 | // 28 | // pub const union_B = extern union { 29 | // x: c_short, 30 | // y: f64, 31 | // }; 32 | // 33 | // pub const struct_Foo = extern struct { 34 | // a: struct_A = @import("std").mem.zeroes(struct_A), 35 | // b: union_B = @import("std").mem.zeroes(union_B), 36 | // }; 37 | -------------------------------------------------------------------------------- /test/cases/translate/Calling_convention_x86.c: -------------------------------------------------------------------------------- 1 | void __attribute__((fastcall)) foo1(float *a); 2 | void __attribute__((stdcall)) foo2(float *a); 3 | void __attribute__((vectorcall)) foo3(float *a); 4 | void __attribute__((cdecl)) foo4(float *a); 5 | void __attribute__((thiscall)) foo5(float *a); 6 | 7 | // translate 8 | // target=x86-linux-none 9 | // 10 | // pub extern fn foo1(a: [*c]f32) callconv(.{ .x86_fastcall = .{} }) void; 11 | // pub extern fn foo2(a: [*c]f32) callconv(.{ .x86_stdcall = .{} }) void; 12 | // pub extern fn foo3(a: [*c]f32) callconv(.{ .x86_vectorcall = .{} }) void; 13 | // pub extern fn foo4(a: [*c]f32) void; 14 | // pub extern fn foo5(a: [*c]f32) callconv(.{ .x86_thiscall = .{} }) void; 15 | -------------------------------------------------------------------------------- /test/cases/translate/function_prototype_translated_as_optional.c: -------------------------------------------------------------------------------- 1 | typedef void (*fnptr_ty)(void); 2 | typedef __attribute__((cdecl)) void (*fnptr_attr_ty)(void); 3 | struct foo { 4 | __attribute__((cdecl)) void (*foo)(void); 5 | void (*bar)(void); 6 | fnptr_ty baz; 7 | fnptr_attr_ty qux; 8 | }; 9 | 10 | // translate 11 | // 12 | // pub const fnptr_ty = ?*const fn () callconv(.c) void; 13 | // pub const fnptr_attr_ty = ?*const fn () callconv(.c) void; 14 | // pub const struct_foo = extern struct { 15 | // foo: ?*const fn () callconv(.c) void = null, 16 | // bar: ?*const fn () callconv(.c) void = null, 17 | // baz: fnptr_ty = null, 18 | // qux: fnptr_attr_ty = null, 19 | // }; 20 | -------------------------------------------------------------------------------- /test/cases/translate/zero_width_field_alignment_msvc.c: -------------------------------------------------------------------------------- 1 | struct __attribute__((packed)) foo { 2 | int x; 3 | struct {}; 4 | float y; 5 | union {}; 6 | }; 7 | 8 | // translate 9 | // target=native-windows-msvc 10 | // 11 | // const struct_unnamed_1 = extern struct { 12 | // _padding: u32 align(1) = 0, 13 | // }; 14 | // const union_unnamed_2 = extern union { 15 | // _padding: u32 align(1), 16 | // }; 17 | // pub const struct_foo = extern struct { 18 | // x: c_int align(1) = 0, 19 | // unnamed_0: struct_unnamed_1 = @import("std").mem.zeroes(struct_unnamed_1), 20 | // y: f32 align(1) = 0, 21 | // unnamed_1: union_unnamed_2 = @import("std").mem.zeroes(union_unnamed_2), 22 | // }; 23 | -------------------------------------------------------------------------------- /test/cases/run/basic_vector_expressions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef int16_t __v8hi __attribute__((__vector_size__(16))); 4 | int main(int argc, char**argv) { 5 | __v8hi uninitialized; 6 | __v8hi empty_init = {}; 7 | for (int i = 0; i < 8; i++) { 8 | if (empty_init[i] != 0) abort(); 9 | } 10 | __v8hi partial_init = {0, 1, 2, 3}; 11 | 12 | __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7}; 13 | __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800}; 14 | 15 | __v8hi sum = a + b; 16 | for (int i = 0; i < 8; i++) { 17 | if (sum[i] != a[i] + b[i]) abort(); 18 | } 19 | return 0; 20 | } 21 | 22 | // run 23 | // skip_vector_index=true 24 | -------------------------------------------------------------------------------- /test/cases/translate/binary_conditional_operator_where_condition_is_the_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int f = 1; 3 | int n, cond_temp = 1; 4 | if (n = (cond_temp)?:(f)) {} 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // var f: c_int = 1; 11 | // _ = &f; 12 | // var n: c_int = undefined; 13 | // _ = &n; 14 | // var cond_temp: c_int = 1; 15 | // _ = &cond_temp; 16 | // if ((blk: { 17 | // const tmp = blk_1: { 18 | // const cond_temp_2 = cond_temp; 19 | // break :blk_1 if (cond_temp_2 != 0) cond_temp_2 else f; 20 | // }; 21 | // n = tmp; 22 | // break :blk tmp; 23 | // }) != 0) {} 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/binary_conditional_operator_where_false_expr_is_the_mangle_prefix.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | int cond_temp = 1; 3 | int n, f = 1; 4 | if (n = (f)?:(cond_temp)) {} 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // var cond_temp: c_int = 1; 11 | // _ = &cond_temp; 12 | // var n: c_int = undefined; 13 | // _ = &n; 14 | // var f: c_int = 1; 15 | // _ = &f; 16 | // if ((blk: { 17 | // const tmp = blk_1: { 18 | // const cond_temp_2 = f; 19 | // break :blk_1 if (cond_temp_2 != 0) cond_temp_2 else cond_temp; 20 | // }; 21 | // n = tmp; 22 | // break :blk tmp; 23 | // }) != 0) {} 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/predefined_expressions.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | __func__; 3 | __FUNCTION__; 4 | __PRETTY_FUNCTION__; 5 | } 6 | 7 | // translate 8 | // 9 | // pub export fn foo() void { 10 | // const static_local___PRETTY_FUNCTION__ = struct { 11 | // const __PRETTY_FUNCTION__: [14:0]u8 = "void foo(void)".*; 12 | // }; 13 | // _ = &static_local___PRETTY_FUNCTION__; 14 | // const static_local___func__ = struct { 15 | // const __func__: [3:0]u8 = "foo".*; 16 | // }; 17 | // _ = &static_local___func__; 18 | // _ = static_local___func__.__func__; 19 | // _ = static_local___func__.__func__; 20 | // _ = static_local___PRETTY_FUNCTION__.__PRETTY_FUNCTION__; 21 | // } 22 | -------------------------------------------------------------------------------- /test/cases/translate/deref_function_pointer.c: -------------------------------------------------------------------------------- 1 | void foo(void) {} 2 | int baz(void) { return 0; } 3 | void bar(void) { 4 | void(*f)(void) = foo; 5 | int(*b)(void) = baz; 6 | f(); 7 | (*(f))(); 8 | foo(); 9 | b(); 10 | (*(b))(); 11 | baz(); 12 | } 13 | 14 | // translate 15 | // 16 | // pub export fn foo() void {} 17 | // pub export fn baz() c_int { 18 | // return 0; 19 | // } 20 | // pub export fn bar() void { 21 | // var f: ?*const fn () callconv(.c) void = foo; 22 | // _ = &f; 23 | // var b: ?*const fn () callconv(.c) c_int = baz; 24 | // _ = &b; 25 | // f.?(); 26 | // f.?(); 27 | // foo(); 28 | // _ = b.?(); 29 | // _ = b.?(); 30 | // _ = baz(); 31 | // } 32 | -------------------------------------------------------------------------------- /test/cases/run/vector_casting.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef int8_t __v8qi __attribute__((__vector_size__(8))); 4 | typedef uint8_t __v8qu __attribute__((__vector_size__(8))); 5 | int main(int argc, char**argv) { 6 | __v8qi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4}; 7 | 8 | uint64_t big_int = (uint64_t) signed_vector; 9 | if (big_int != 0x01020304FFFEFDFCULL && big_int != 0xFCFDFEFF04030201ULL) abort(); 10 | __v8qu unsigned_vector = (__v8qu) big_int; 11 | for (int i = 0; i < 8; i++) { 12 | if (unsigned_vector[i] != (uint8_t)signed_vector[i] && unsigned_vector[i] != (uint8_t)signed_vector[7 - i]) abort(); 13 | } 14 | return 0; 15 | } 16 | 17 | // run 18 | // skip_vector_index=true 19 | -------------------------------------------------------------------------------- /test/cases/translate/anonymous_struct_&_unions.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | union { 3 | char x; 4 | struct { int y; }; 5 | }; 6 | } outer; 7 | void foo(outer *x) { x->y = x->x; } 8 | 9 | // translate 10 | // 11 | // const struct_unnamed_2 = extern struct { 12 | // y: c_int = 0, 13 | // }; 14 | // const union_unnamed_1 = extern union { 15 | // x: u8, 16 | // unnamed_0: struct_unnamed_2, 17 | // }; 18 | // pub const outer = extern struct { 19 | // unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1), 20 | // pub const foo = __root.foo; 21 | // }; 22 | // pub export fn foo(arg_x: [*c]outer) void { 23 | // var x = arg_x; 24 | // _ = &x; 25 | // x.*.unnamed_0.unnamed_0.y = x.*.unnamed_0.x; 26 | // } 27 | -------------------------------------------------------------------------------- /examples/build.zig: -------------------------------------------------------------------------------- 1 | pub fn build(b: *std.Build) void { 2 | const target = b.standardTargetOptions(.{}); 3 | const optimize = b.standardOptimizeOption(.{}); 4 | 5 | const all_step = b.step("all", "Run all examples"); 6 | b.default_step = all_step; 7 | 8 | for (b.available_deps) |available_dep| { 9 | const example_name, _ = available_dep; 10 | const run_example = b.dependency(example_name, .{ 11 | .target = target, 12 | .optimize = optimize, 13 | }).builder.default_step; 14 | const example_step = b.step(example_name, b.fmt("Run the '{s}' example", .{example_name})); 15 | example_step.dependOn(run_example); 16 | all_step.dependOn(example_step); 17 | } 18 | } 19 | const std = @import("std"); 20 | -------------------------------------------------------------------------------- /test/cases/translate/variable_aliasing.c: -------------------------------------------------------------------------------- 1 | static long a = 2; 2 | static long b = 2; 3 | static int c = 4; 4 | void foo(char c) { 5 | int a; 6 | char b = 123; 7 | b = (char) a; 8 | { 9 | int d = 5; 10 | } 11 | unsigned d = 440; 12 | } 13 | 14 | // translate 15 | // 16 | // pub var a: c_long = 2; 17 | // pub var b: c_long = 2; 18 | // pub var c: c_int = 4; 19 | // pub export fn foo(arg_c_1: u8) void { 20 | // var c_1 = arg_c_1; 21 | // _ = &c_1; 22 | // var a_2: c_int = undefined; 23 | // _ = &a_2; 24 | // var b_3: u8 = 123; 25 | // _ = &b_3; 26 | // b_3 = @bitCast(@as(i8, @truncate(a_2))); 27 | // { 28 | // var d: c_int = 5; 29 | // _ = &d; 30 | // } 31 | // var d: c_uint = 440; 32 | // _ = &d; 33 | // } 34 | -------------------------------------------------------------------------------- /test/cases/translate/macro_comma_operator.c: -------------------------------------------------------------------------------- 1 | #define foo (foo, bar) 2 | int baz(int x, int y) { return 0; } 3 | #define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2)) 4 | 5 | // translate 6 | // 7 | // pub const foo = blk_1: { 8 | // _ = &foo; 9 | // break :blk_1 bar; 10 | // }; 11 | // 12 | // pub inline fn bar(x: anytype) @TypeOf(baz(@as(c_int, 1), @as(c_int, 2))) { 13 | // _ = &x; 14 | // return blk_1: { 15 | // _ = &x; 16 | // _ = @as(c_int, 3); 17 | // _ = @as(c_int, 4) == @as(c_int, 4); 18 | // _ = @as(c_int, 5) * @as(c_int, 6); 19 | // _ = baz(@as(c_int, 1), @as(c_int, 2)); 20 | // _ = __helpers.rem(@as(c_int, 2), @as(c_int, 2)); 21 | // break :blk_1 baz(@as(c_int, 1), @as(c_int, 2)); 22 | // }; 23 | // } 24 | -------------------------------------------------------------------------------- /test/cases/translate/struct_with_flexible_array.c: -------------------------------------------------------------------------------- 1 | struct foo { int x; int y[]; }; 2 | struct bar { int x; int y[0]; }; 3 | 4 | // translate 5 | // 6 | // pub const struct_foo = extern struct { 7 | // x: c_int = 0, 8 | // _y: [0]c_int = @import("std").mem.zeroes([0]c_int), 9 | // pub fn y(self: anytype) __helpers.FlexibleArrayType(@TypeOf(self), @typeInfo(@TypeOf(self.*._y)).array.child) { 10 | // return @ptrCast(@alignCast(&self.*._y)); 11 | // } 12 | // }; 13 | // pub const struct_bar = extern struct { 14 | // x: c_int = 0, 15 | // _y: [0]c_int = @import("std").mem.zeroes([0]c_int), 16 | // pub fn y(self: anytype) __helpers.FlexibleArrayType(@TypeOf(self), @typeInfo(@TypeOf(self.*._y)).array.child) { 17 | // return @ptrCast(@alignCast(&self.*._y)); 18 | // } 19 | // }; 20 | -------------------------------------------------------------------------------- /test/cases/translate/casting_pointers_to_ints_and_ints_to_pointers.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int x = 23; 3 | int y = (int*)x; 4 | } 5 | void bar(void) { 6 | void *func_ptr = foo; 7 | void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr; 8 | } 9 | 10 | // translate 11 | // 12 | // pub export fn foo() void { 13 | // var x: c_int = 23; 14 | // _ = &x; 15 | // var y: c_int = @intCast(@intFromPtr(@as([*c]c_int, @ptrFromInt(@as(usize, @intCast(x)))))); 16 | // _ = &y; 17 | // } 18 | // pub export fn bar() void { 19 | // var func_ptr: ?*anyopaque = @ptrCast(@alignCast(@constCast(&foo))); 20 | // _ = &func_ptr; 21 | // var typed_func_ptr: ?*const fn () callconv(.c) void = @ptrFromInt(@as(c_ulong, @intCast(@intFromPtr(func_ptr)))); 22 | // _ = &typed_func_ptr; 23 | // } 24 | -------------------------------------------------------------------------------- /test/cases/translate/struct_with_aligned_fields.c: -------------------------------------------------------------------------------- 1 | struct foo { 2 | __attribute__((aligned(4))) short bar; 3 | }; 4 | 5 | struct over_aligned_array_head { 6 | __attribute__((aligned(16))) float bar[4]; 7 | }; 8 | 9 | struct over_aligned_array_padding { 10 | float a; 11 | short b; 12 | __attribute__((aligned(16))) float bar[4]; 13 | }; 14 | 15 | // translate 16 | // 17 | // pub const struct_foo = extern struct { 18 | // bar: c_short align(4) = 0, 19 | // }; 20 | // 21 | // pub const struct_over_aligned_array_head = extern struct { 22 | // bar: [4]f32 align(16) = @import("std").mem.zeroes([4]f32), 23 | // }; 24 | // 25 | // pub const struct_over_aligned_array_padding = extern struct { 26 | // a: f32 align(16) = 0, 27 | // b: c_short = 0, 28 | // bar: [4]f32 align(16) = @import("std").mem.zeroes([4]f32), 29 | // }; 30 | -------------------------------------------------------------------------------- /test/cases/run/Wide,_UTF-16,_and_UTF-32_string_literals.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main(void) { 5 | const wchar_t *wide_str = L"wide"; 6 | const wchar_t wide_hello[] = L"hello"; 7 | if (wcslen(wide_str) != 4) abort(); 8 | if (wcslen(L"literal") != 7) abort(); 9 | if (wcscmp(wide_hello, L"hello") != 0) abort(); 10 | 11 | const uint16_t *u16_str = u"wide"; 12 | const uint16_t u16_hello[] = u"hello"; 13 | if (u16_str[3] != u'e' || u16_str[4] != 0) abort(); 14 | if (u16_hello[4] != u'o' || u16_hello[5] != 0) abort(); 15 | 16 | const uint32_t *u32_str = U"wide"; 17 | const uint32_t u32_hello[] = U"hello"; 18 | if (u32_str[3] != U'e' || u32_str[4] != 0) abort(); 19 | if (u32_hello[4] != U'o' || u32_hello[5] != 0) abort(); 20 | return 0; 21 | } 22 | 23 | // run 24 | -------------------------------------------------------------------------------- /test/cases/run/signed_array_subscript.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define TEST_NEGATIVE(type) { type x = -1; if (ptr[x] != 42) abort(); } 4 | #define TEST_UNSIGNED(type) { type x = 2; if (arr[x] != 42) abort(); } 5 | int main(void) { 6 | int arr[] = {40, 41, 42, 43}; 7 | int *ptr = arr + 3; 8 | if (ptr[-1] != 42) abort(); 9 | TEST_NEGATIVE(int); 10 | TEST_NEGATIVE(long); 11 | TEST_NEGATIVE(long long); 12 | TEST_NEGATIVE(int64_t); 13 | #ifdef __SIZEOF_INT128__ 14 | TEST_NEGATIVE(__int128); 15 | #endif 16 | TEST_UNSIGNED(unsigned); 17 | TEST_UNSIGNED(unsigned long); 18 | TEST_UNSIGNED(unsigned long long); 19 | TEST_UNSIGNED(uint64_t); 20 | TEST_UNSIGNED(size_t); 21 | #ifdef __SIZEOF_INT128__ 22 | TEST_UNSIGNED(unsigned __int128); 23 | #endif 24 | return 0; 25 | } 26 | 27 | // run 28 | -------------------------------------------------------------------------------- /test/cases/translate/member_access_in_struct_with_union_as_const_arg.c: -------------------------------------------------------------------------------- 1 | #define SUFFIXED(x) x##_suffix 2 | 3 | struct my_struct { 4 | union { 5 | int SUFFIXED(internal); 6 | double d; 7 | }; 8 | }; 9 | 10 | int my_func(const struct my_struct* s) { 11 | return s->SUFFIXED(internal); 12 | } 13 | 14 | // translate 15 | // 16 | // const union_unnamed_1 = extern union { 17 | // internal_suffix: c_int, 18 | // d: f64, 19 | // }; 20 | // pub const struct_my_struct = extern struct { 21 | // unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1), 22 | // pub const my_func = __root.my_func; 23 | // pub const func = __root.my_func; 24 | // }; 25 | // pub export fn my_func(arg_s: [*c]const struct_my_struct) c_int { 26 | // var s = arg_s; 27 | // _ = &s; 28 | // return s.*.unnamed_0.internal_suffix; 29 | // } 30 | -------------------------------------------------------------------------------- /test/cases/translate/array_access_with_enum.c: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | one = 1, 3 | two = 2, 4 | } EnumValues; 5 | 6 | static inline int dynamic_array_access(EnumValues idx) { 7 | static const int values[] = {0, 1, 2}; 8 | return values[idx - 1]; 9 | } 10 | 11 | // translate 12 | // target=native-linux 13 | // 14 | // pub const one: c_int = 1; 15 | // pub const two: c_int = 2; 16 | // pub const EnumValues = c_uint; 17 | // pub fn dynamic_array_access(arg_idx: EnumValues) callconv(.c) c_int { 18 | // var idx = arg_idx; 19 | // _ = &idx; 20 | // const static_local_values = struct { 21 | // const values: [3]c_int = [3]c_int{ 22 | // 0, 23 | // 1, 24 | // 2, 25 | // }; 26 | // }; 27 | // _ = &static_local_values; 28 | // return static_local_values.values[idx -% @as(EnumValues, 1)]; 29 | // } 30 | -------------------------------------------------------------------------------- /test/cases/translate/do_loop.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a = 2; 3 | do { 4 | a = a - 1; 5 | } while (a); 6 | 7 | int b = 2; 8 | do 9 | b = b -1; 10 | while (b); 11 | do { 12 | __builtin_unreachable(); 13 | } while (0); 14 | do { 15 | continue; 16 | } while (1); 17 | } 18 | 19 | // translate 20 | // 21 | // pub export fn foo() void { 22 | // var a: c_int = 2; 23 | // _ = &a; 24 | // while (true) { 25 | // a = a - @as(c_int, 1); 26 | // if (!(a != 0)) break; 27 | // } 28 | // var b: c_int = 2; 29 | // _ = &b; 30 | // while (true) { 31 | // b = b - @as(c_int, 1); 32 | // if (!(b != 0)) break; 33 | // } 34 | // while (true) { 35 | // unreachable; 36 | // } 37 | // while (true) { 38 | // continue; 39 | // } 40 | // } 41 | -------------------------------------------------------------------------------- /test/cases/translate/self_referential_init.c: -------------------------------------------------------------------------------- 1 | int *a = (int*)(&a + 1); // TODO result missing casts 2 | 3 | extern void *alloc(unsigned long long); 4 | void foo(void) { 5 | int b = b + 1; 6 | int *c = alloc(sizeof(*c)); 7 | const double *d = alloc(sizeof(*d)); 8 | } 9 | 10 | // translate 11 | // 12 | // pub export var a: [*c]c_int = @ptrCast(@alignCast((&a) + @as(usize, @bitCast(@as(isize, @intCast(@as(c_int, 1))))))); 13 | // pub extern fn alloc(c_ulonglong) ?*anyopaque; 14 | // pub export fn foo() void { 15 | // var b: c_int = undefined; 16 | // b = b + @as(c_int, 1); 17 | // _ = &b; 18 | // var c: [*c]c_int = undefined; 19 | // c = @ptrCast(@alignCast(alloc(@sizeOf(@TypeOf(c.*))))); 20 | // _ = &c; 21 | // var d: [*c]const f64 = undefined; 22 | // d = @ptrCast(@alignCast(alloc(@sizeOf(@TypeOf(d.*))))); 23 | // _ = &d; 24 | // } 25 | -------------------------------------------------------------------------------- /test/cases/translate/if_on_non-bool.c: -------------------------------------------------------------------------------- 1 | enum SomeEnum { A, B, C }; 2 | int if_none_bool(int a, float b, void *c, enum SomeEnum d) { 3 | if (a) return 0; 4 | if (b) return 1; 5 | if (c) return 2; 6 | if (d) return 3; 7 | return 4; 8 | } 9 | 10 | // translate 11 | // target=native-linux 12 | // 13 | // pub const A: c_int = 0; 14 | // pub const B: c_int = 1; 15 | // pub const C: c_int = 2; 16 | // pub const enum_SomeEnum = c_uint; 17 | // pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*anyopaque, arg_d: enum_SomeEnum) c_int { 18 | // var a = arg_a; 19 | // _ = &a; 20 | // var b = arg_b; 21 | // _ = &b; 22 | // var c = arg_c; 23 | // _ = &c; 24 | // var d = arg_d; 25 | // _ = &d; 26 | // if (a != 0) return 0; 27 | // if (b != 0) return 1; 28 | // if (c != null) return 2; 29 | // if (d != 0) return 3; 30 | // return 4; 31 | // } 32 | -------------------------------------------------------------------------------- /test/cases/run/pointer_difference-_C_standard_edge_case.c: -------------------------------------------------------------------------------- 1 | // C standard: if the expression P points either to an element of an array object or one 2 | // past the last element of an array object, and the expression Q points to the last 3 | // element of the same array object, the expression ((Q)+1)-(P) has the same value as 4 | // ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points 5 | // one past the last element of the array object, even though the expression (Q)+1 6 | // does not point to an element of the array object 7 | #include 8 | #include 9 | #define SIZE 10 10 | int main() { 11 | int foo[SIZE]; 12 | int *start = &foo[0]; 13 | int *P = start + SIZE; 14 | int *Q = &foo[SIZE - 1]; 15 | if ((Q + 1) - P != 0) abort(); 16 | if ((Q + 1) - P != (Q - P) + 1) abort(); 17 | if ((Q + 1) - P != -(P - (Q + 1))) abort(); 18 | return 0; 19 | } 20 | 21 | // run 22 | -------------------------------------------------------------------------------- /test/cases/translate/field_access_expression.c: -------------------------------------------------------------------------------- 1 | #define ARROW a->b 2 | #define DOT a.b 3 | extern struct Foo { 4 | int b; 5 | }a; 6 | float b = 2.0f; 7 | void foo(void) { 8 | struct Foo *c; 9 | a.b; 10 | c->b; 11 | } 12 | #define invalid(a, name) (a.name) 13 | 14 | // translate 15 | // 16 | // pub const struct_Foo = extern struct { 17 | // b: c_int = 0, 18 | // }; 19 | // pub extern var a: struct_Foo; 20 | // pub export var b: f32 = 2; 21 | // pub export fn foo() void { 22 | // var c: [*c]struct_Foo = undefined; 23 | // _ = &c; 24 | // _ = a.b; 25 | // _ = c.*.b; 26 | // } 27 | // 28 | // pub const Foo = struct_Foo; 29 | // 30 | // pub inline fn ARROW() @TypeOf(a.*.b) { 31 | // return a.*.b; 32 | // } 33 | // 34 | // pub inline fn DOT() @TypeOf(a.b) { 35 | // return a.b; 36 | // } 37 | // 38 | // pub const invalid = @compileError("unable to translate C expr: field access using macro parameter"); 39 | -------------------------------------------------------------------------------- /test/cases/translate/generate_inline_func_for_#define_global_extern_fn.c: -------------------------------------------------------------------------------- 1 | extern void (*fn_ptr)(void); 2 | #define foo fn_ptr 3 | 4 | extern char (*fn_ptr2)(int, float); 5 | #define bar fn_ptr2 6 | 7 | extern double y0(double); 8 | void (*epoxy_glDrawTextureNV)(float y0); 9 | #define glDrawTextureNV epoxy_glDrawTextureNV 10 | 11 | // translate 12 | // 13 | // pub extern var fn_ptr: ?*const fn () callconv(.c) void; 14 | // 15 | // pub inline fn foo() void { 16 | // return fn_ptr.?(); 17 | // } 18 | // 19 | // pub extern var fn_ptr2: ?*const fn (c_int, f32) callconv(.c) u8; 20 | // 21 | // pub inline fn bar(arg: c_int, arg_1: f32) u8 { 22 | // return fn_ptr2.?(arg, arg_1); 23 | // } 24 | // 25 | // pub extern fn y0(f64) f64; 26 | // pub export var epoxy_glDrawTextureNV: ?*const fn (y0: f32) callconv(.c) void = null; 27 | // 28 | // pub inline fn glDrawTextureNV(y0_1: f32) void { 29 | // return epoxy_glDrawTextureNV.?(y0_1); 30 | // } 31 | -------------------------------------------------------------------------------- /test/cases/translate/casting_to_and_from_bool.c: -------------------------------------------------------------------------------- 1 | int foo(void) { 2 | int v1; 3 | _Bool b1 = v1; 4 | double v2; 5 | _Bool b2 = v2; 6 | void* v3; 7 | _Bool b3 = v3; 8 | 9 | int v4 = b1; 10 | double v5 = b2; 11 | void* v6 = b3; 12 | } 13 | 14 | // translate 15 | // 16 | // pub export fn foo() c_int { 17 | // var v1: c_int = undefined; 18 | // _ = &v1; 19 | // var b1: bool = v1 != 0; 20 | // _ = &b1; 21 | // var v2: f64 = undefined; 22 | // _ = &v2; 23 | // var b2: bool = v2 != 0; 24 | // _ = &b2; 25 | // var v3: ?*anyopaque = undefined; 26 | // _ = &v3; 27 | // var b3: bool = v3 != null; 28 | // _ = &b3; 29 | // var v4: c_int = @intFromBool(b1); 30 | // _ = &v4; 31 | // var v5: f64 = @floatFromInt(@intFromBool(b2)); 32 | // _ = &v5; 33 | // var v6: ?*anyopaque = @ptrFromInt(@intFromBool(b3)); 34 | // _ = &v6; 35 | // return undefined; 36 | // } 37 | -------------------------------------------------------------------------------- /test/cases/run/Flexible_arrays.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef struct { char foo; int bar; } ITEM; 4 | typedef struct { size_t count; ITEM items[]; } ITEM_LIST; 5 | typedef struct { unsigned char count; int items[]; } INT_LIST; 6 | #define SIZE 10 7 | int main(void) { 8 | ITEM_LIST *list = malloc(sizeof(ITEM_LIST) + SIZE * sizeof(ITEM)); 9 | for (int i = 0; i < SIZE; i++) list->items[i] = (ITEM) {.foo = i, .bar = i + 1}; 10 | const ITEM_LIST *const c_list = list; 11 | for (int i = 0; i < SIZE; i++) if (c_list->items[i].foo != i || c_list->items[i].bar != i + 1) abort(); 12 | INT_LIST *int_list = malloc(sizeof(INT_LIST) + SIZE * sizeof(int)); 13 | for (int i = 0; i < SIZE; i++) int_list->items[i] = i; 14 | const INT_LIST *const c_int_list = int_list; 15 | const int *const ints = int_list->items; 16 | for (int i = 0; i < SIZE; i++) if (ints[i] != i) abort(); 17 | return 0; 18 | } 19 | 20 | // run 21 | -------------------------------------------------------------------------------- /test/cases/translate/simple_var_decls.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int a; 3 | char b = 123; 4 | const int c; 5 | const unsigned d = 440; 6 | int e = 10; 7 | unsigned int f = 10u; 8 | short g = e; 9 | unsigned short h = e; 10 | const unsigned i = 4294967297; 11 | } 12 | 13 | // translate 14 | // target=x86_64-linux 15 | // 16 | // pub export fn foo() void { 17 | // var a: c_int = undefined; 18 | // _ = &a; 19 | // var b: u8 = 123; 20 | // _ = &b; 21 | // const c: c_int = undefined; 22 | // _ = &c; 23 | // const d: c_uint = 440; 24 | // _ = &d; 25 | // var e: c_int = 10; 26 | // _ = &e; 27 | // var f: c_uint = 10; 28 | // _ = &f; 29 | // var g: c_short = @truncate(e); 30 | // _ = &g; 31 | // var h: c_ushort = @bitCast(@as(c_short, @truncate(e))); 32 | // _ = &h; 33 | // const i: c_uint = @bitCast(@as(c_int, @truncate(@as(c_long, 4294967297)))); 34 | // _ = &i; 35 | // } 36 | -------------------------------------------------------------------------------- /test/cases/translate/while_loops.c: -------------------------------------------------------------------------------- 1 | int foo() { 2 | int a = 5; 3 | while (2) 4 | a = 2; 5 | while (4) { 6 | int a = 4; 7 | a = 9; 8 | return 6, a; 9 | } 10 | do { 11 | int a = 2; 12 | a = 12; 13 | } while (4); 14 | do 15 | a = 7; 16 | while (4); 17 | } 18 | 19 | // translate 20 | // 21 | // pub export fn foo() c_int { 22 | // var a: c_int = 5; 23 | // _ = &a; 24 | // while (true) { 25 | // a = 2; 26 | // } 27 | // while (true) { 28 | // var a_1: c_int = 4; 29 | // _ = &a_1; 30 | // a_1 = 9; 31 | // return blk: { 32 | // _ = 6; 33 | // break :blk a_1; 34 | // }; 35 | // } 36 | // while (true) { 37 | // var a_1: c_int = 2; 38 | // _ = &a_1; 39 | // a_1 = 12; 40 | // } 41 | // while (true) { 42 | // a = 7; 43 | // } 44 | // return undefined; 45 | // } 46 | -------------------------------------------------------------------------------- /test/cases/translate/comparison_operators_(no_if).c: -------------------------------------------------------------------------------- 1 | int test_comparisons(int a, int b) { 2 | int c = (a < b); 3 | int d = (a > b); 4 | int e = (a <= b); 5 | int f = (a >= b); 6 | int g = (c < d); 7 | int h = (e < f); 8 | int i = (g < h); 9 | return i; 10 | } 11 | 12 | // translate 13 | // 14 | // pub export fn test_comparisons(arg_a: c_int, arg_b: c_int) c_int { 15 | // var a = arg_a; 16 | // _ = &a; 17 | // var b = arg_b; 18 | // _ = &b; 19 | // var c: c_int = @intFromBool(a < b); 20 | // _ = &c; 21 | // var d: c_int = @intFromBool(a > b); 22 | // _ = &d; 23 | // var e: c_int = @intFromBool(a <= b); 24 | // _ = &e; 25 | // var f: c_int = @intFromBool(a >= b); 26 | // _ = &f; 27 | // var g: c_int = @intFromBool(c < d); 28 | // _ = &g; 29 | // var h: c_int = @intFromBool(e < f); 30 | // _ = &h; 31 | // var i: c_int = @intFromBool(g < h); 32 | // _ = &i; 33 | // return i; 34 | // } 35 | -------------------------------------------------------------------------------- /test/cases/translate/escape_sequences.c: -------------------------------------------------------------------------------- 1 | const char *escapes() { 2 | char a = '\'', 3 | b = '\\', 4 | c = '\a', 5 | d = '\b', 6 | e = '\f', 7 | f = '\n', 8 | g = '\r', 9 | h = '\t', 10 | i = '\v', 11 | j = '\0', 12 | k = '\"'; 13 | return "\'\\\a\b\f\n\r\t\v\0\""; 14 | } 15 | 16 | 17 | // translate 18 | // 19 | // pub export fn escapes() [*c]const u8 { 20 | // var a: u8 = '\''; 21 | // _ = &a; 22 | // var b: u8 = '\\'; 23 | // _ = &b; 24 | // var c: u8 = '\x07'; 25 | // _ = &c; 26 | // var d: u8 = '\x08'; 27 | // _ = &d; 28 | // var e: u8 = '\x0c'; 29 | // _ = &e; 30 | // var f: u8 = '\n'; 31 | // _ = &f; 32 | // var g: u8 = '\r'; 33 | // _ = &g; 34 | // var h: u8 = '\t'; 35 | // _ = &h; 36 | // var i: u8 = '\x0b'; 37 | // _ = &i; 38 | // var j: u8 = '\x00'; 39 | // _ = &j; 40 | // var k: u8 = '"'; 41 | // _ = &k; 42 | // return "'\\\x07\x08\x0c\n\r\t\x0b\x00\""; 43 | // } 44 | -------------------------------------------------------------------------------- /test/cases/run/Obscure_ways_of_calling_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | static int add(int a, int b) { 3 | return a + b; 4 | } 5 | typedef int (*adder)(int, int); 6 | typedef void (*funcptr)(void); 7 | int main() { 8 | if ((add)(1, 2) != 3) abort(); 9 | if ((&add)(1, 2) != 3) abort(); 10 | if (add(3, 1) != 4) abort(); 11 | if ((*add)(2, 3) != 5) abort(); 12 | if ((**add)(7, -1) != 6) abort(); 13 | if ((***add)(-2, 9) != 7) abort(); 14 | 15 | int (*ptr)(int a, int b); 16 | ptr = add; 17 | 18 | if (ptr(1, 2) != 3) abort(); 19 | if ((*ptr)(3, 1) != 4) abort(); 20 | if ((**ptr)(2, 3) != 5) abort(); 21 | if ((***ptr)(7, -1) != 6) abort(); 22 | if ((****ptr)(-2, 9) != 7) abort(); 23 | 24 | funcptr addr1 = (funcptr)(add); 25 | funcptr addr2 = (funcptr)(&add); 26 | 27 | if (addr1 != addr2) abort(); 28 | if (((int(*)(int, int))addr1)(1, 2) != 3) abort(); 29 | if (((adder)addr2)(1, 2) != 3) abort(); 30 | return 0; 31 | } 32 | 33 | // run 34 | -------------------------------------------------------------------------------- /test/cases/translate/pre_increment_and_decrement.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int i = 0; 3 | unsigned u = 0; 4 | ++i; 5 | --i; 6 | ++u; 7 | --u; 8 | i = ++i; 9 | i = --i; 10 | u = ++u; 11 | u = --u; 12 | } 13 | 14 | // translate 15 | // 16 | // pub export fn foo() void { 17 | // var i: c_int = 0; 18 | // _ = &i; 19 | // var u: c_uint = 0; 20 | // _ = &u; 21 | // i += 1; 22 | // i -= 1; 23 | // u +%= 1; 24 | // u -%= 1; 25 | // i = blk: { 26 | // const ref = &i; 27 | // ref.* += 1; 28 | // break :blk ref.*; 29 | // }; 30 | // i = blk: { 31 | // const ref = &i; 32 | // ref.* -= 1; 33 | // break :blk ref.*; 34 | // }; 35 | // u = blk: { 36 | // const ref = &u; 37 | // ref.* +%= 1; 38 | // break :blk ref.*; 39 | // }; 40 | // u = blk: { 41 | // const ref = &u; 42 | // ref.* -%= 1; 43 | // break :blk ref.*; 44 | // }; 45 | // } 46 | -------------------------------------------------------------------------------- /test/cases/translate/do_while_with_breaks.c: -------------------------------------------------------------------------------- 1 | void foo(int a) { 2 | do { 3 | if (a) break; 4 | } while (4); 5 | do { 6 | if (a) break; 7 | } while (0); 8 | do { 9 | if (a) break; 10 | } while (a); 11 | do { 12 | break; 13 | } while (3); 14 | do { 15 | break; 16 | } while (0); 17 | do { 18 | break; 19 | } while (a); 20 | } 21 | 22 | // translate 23 | // 24 | // pub export fn foo(arg_a: c_int) void { 25 | // var a = arg_a; 26 | // _ = &a; 27 | // while (true) { 28 | // if (a != 0) break; 29 | // } 30 | // while (true) { 31 | // if (a != 0) break; 32 | // if (!false) break; 33 | // } 34 | // while (true) { 35 | // if (a != 0) break; 36 | // if (!(a != 0)) break; 37 | // } 38 | // while (true) { 39 | // break; 40 | // } 41 | // while (true) { 42 | // break; 43 | // } 44 | // while (true) { 45 | // break; 46 | // } 47 | // } 48 | -------------------------------------------------------------------------------- /test/cases/run/Generic_selections.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define my_generic_fn(X) _Generic((X), \ 5 | int: abs, \ 6 | char *: strlen, \ 7 | size_t: malloc, \ 8 | default: free \ 9 | )(X) 10 | #define my_generic_val(X) _Generic((X), \ 11 | int: 1, \ 12 | const char *: "bar" \ 13 | ) 14 | int main(void) { 15 | if (my_generic_val(100) != 1) abort(); 16 | 17 | const char *foo = "foo"; 18 | const char *bar = my_generic_val(foo); 19 | if (strcmp(bar, "bar") != 0) abort(); 20 | 21 | if (my_generic_fn(-42) != 42) abort(); 22 | if (my_generic_fn("hello") != 5) abort(); 23 | 24 | size_t size = 8192; 25 | uint8_t *mem = my_generic_fn(size); 26 | memset(mem, 42, size); 27 | if (mem[size - 1] != 42) abort(); 28 | my_generic_fn(mem); 29 | 30 | return 0; 31 | } 32 | 33 | // run 34 | -------------------------------------------------------------------------------- /test/cases/translate/float_suffixes.c: -------------------------------------------------------------------------------- 1 | #define foo 3.14f 2 | #define bar 16.e-2l 3 | #define FOO 0.12345 4 | #define BAR .12345 5 | #define baz 1e1 6 | #define BAZ 42e-3f 7 | #define foobar -73.L 8 | extern const float my_float = 1.0f; 9 | extern const double my_double = 1.0; 10 | extern const long double my_longdouble = 1.0l; 11 | extern const long double my_extended_precision_longdouble = 1.0000000000000003l; 12 | 13 | // translate 14 | // 15 | // pub const foo = @as(f32, 3.14); 16 | // 17 | // pub const bar = @as(c_longdouble, 16.e-2); 18 | // 19 | // pub const FOO = @as(f64, 0.12345); 20 | // 21 | // pub const BAR = @as(f64, 0.12345); 22 | // 23 | // pub const baz = @as(f64, 1e1); 24 | // 25 | // pub const BAZ = @as(f32, 42e-3); 26 | // 27 | // pub const foobar = -@as(c_longdouble, 73); 28 | // 29 | // pub export const my_float: f32 = 1; 30 | // 31 | // pub export const my_double: f64 = 1; 32 | // 33 | // pub export const my_longdouble: c_longdouble = 1; 34 | // 35 | // pub export const my_extended_precision_longdouble: c_longdouble = 1.0000000000000002; 36 | -------------------------------------------------------------------------------- /test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_unused_result.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int int1 = 1; 4 | int int2 = 2; 5 | int int100000000 = 100000000; 6 | signed short val = -1; 7 | val += int1; if (val != 0) abort(); 8 | val -= int1; if (val != -1) abort(); 9 | val *= int2; if (val != -2) abort(); 10 | val /= int2; if (val != -1) abort(); 11 | val %= int2; if (val != -1) abort(); 12 | val <<= int1; if (val != -2) abort(); 13 | val >>= int1; if (val != -1) abort(); 14 | val += int100000000; // compile error if @truncate() not inserted 15 | unsigned short uval = 1; 16 | uval += int1; if (uval != 2) abort(); 17 | uval -= int1; if (uval != 1) abort(); 18 | uval *= int2; if (uval != 2) abort(); 19 | uval /= int2; if (uval != 1) abort(); 20 | uval %= int2; if (uval != 1) abort(); 21 | uval <<= int1; if (uval != 2) abort(); 22 | uval >>= int1; if (uval != 1) abort(); 23 | uval += int100000000; // compile error if @truncate() not inserted 24 | } 25 | 26 | // run 27 | -------------------------------------------------------------------------------- /test/cases/translate/scoped_typedef.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | typedef union { 3 | int A; 4 | int B; 5 | int C; 6 | } Foo; 7 | Foo a = {0}; 8 | { 9 | typedef union { 10 | int A; 11 | int B; 12 | int C; 13 | } Foo; 14 | Foo a = {0}; 15 | } 16 | } 17 | 18 | // translate 19 | // 20 | // pub export fn foo() void { 21 | // const union_unnamed_1 = extern union { 22 | // A: c_int, 23 | // B: c_int, 24 | // C: c_int, 25 | // }; 26 | // _ = &union_unnamed_1; 27 | // const Foo = union_unnamed_1; 28 | // _ = &Foo; 29 | // var a: Foo = Foo{ 30 | // .A = 0, 31 | // }; 32 | // _ = &a; 33 | // { 34 | // const union_unnamed_2 = extern union { 35 | // A: c_int, 36 | // B: c_int, 37 | // C: c_int, 38 | // }; 39 | // _ = &union_unnamed_2; 40 | // const Foo_1 = union_unnamed_2; 41 | // _ = &Foo_1; 42 | // var a_2: Foo_1 = Foo_1{ 43 | // .A = 0, 44 | // }; 45 | // _ = &a_2; 46 | // } 47 | // } 48 | -------------------------------------------------------------------------------- /test/cases/translate/struct_with_invalid_field_alignment.c: -------------------------------------------------------------------------------- 1 | // The aligned attribute cannot decrease the alignment of a field. The packed attribute is required 2 | // for decreasing the alignment. gcc and clang will compile these structs without error 3 | // (and possibly without warning), but checking the alignment will reveal a different value than 4 | // what was requested. This is consistent with the gcc documentation on type attributes. 5 | // 6 | // This test is currently broken for the clang frontend. See issue #19307. 7 | 8 | struct foo { 9 | __attribute__((aligned(1)))int x; 10 | }; 11 | 12 | struct bar { 13 | __attribute__((aligned(2)))float y; 14 | }; 15 | 16 | struct baz { 17 | __attribute__((aligned(4)))double z; 18 | }; 19 | 20 | // translate 21 | // target=x86_64-linux 22 | // 23 | // pub const struct_foo = extern struct { 24 | // x: c_int = 0, 25 | // }; 26 | // 27 | // pub const struct_bar = extern struct { 28 | // y: f32 = 0, 29 | // }; 30 | // 31 | // pub const struct_baz = extern struct { 32 | // z: f64 = 0, 33 | // }; 34 | // 35 | -------------------------------------------------------------------------------- /test/cases/translate/scoped_record.c: -------------------------------------------------------------------------------- 1 | void foo() { 2 | struct Foo { 3 | int A; 4 | int B; 5 | int C; 6 | }; 7 | struct Foo a = {0}; 8 | { 9 | struct Foo { 10 | int A; 11 | int B; 12 | int C; 13 | }; 14 | struct Foo a = {0}; 15 | } 16 | } 17 | 18 | // translate 19 | // 20 | // pub export fn foo() void { 21 | // const struct_Foo = extern struct { 22 | // A: c_int = 0, 23 | // B: c_int = 0, 24 | // C: c_int = 0, 25 | // }; 26 | // _ = &struct_Foo; 27 | // var a: struct_Foo = struct_Foo{ 28 | // .A = 0, 29 | // .B = 0, 30 | // .C = 0, 31 | // }; 32 | // _ = &a; 33 | // { 34 | // const struct_Foo_1 = extern struct { 35 | // A: c_int = 0, 36 | // B: c_int = 0, 37 | // C: c_int = 0, 38 | // }; 39 | // _ = &struct_Foo_1; 40 | // var a_2: struct_Foo_1 = struct_Foo_1{ 41 | // .A = 0, 42 | // .B = 0, 43 | // .C = 0, 44 | // }; 45 | // _ = &a_2; 46 | // } 47 | // } 48 | -------------------------------------------------------------------------------- /test/cases/translate/integer_literal_promotion.c: -------------------------------------------------------------------------------- 1 | #define GUARANTEED_TO_FIT_1 1024 2 | #define GUARANTEED_TO_FIT_2 10241024L 3 | #define GUARANTEED_TO_FIT_3 20482048LU 4 | #define MAY_NEED_PROMOTION_1 10241024 5 | #define MAY_NEED_PROMOTION_2 307230723072L 6 | #define MAY_NEED_PROMOTION_3 819281928192LU 7 | #define MAY_NEED_PROMOTION_HEX 0x80000000 8 | #define MAY_NEED_PROMOTION_OCT 020000000000 9 | 10 | // translate 11 | // 12 | // pub const GUARANTEED_TO_FIT_1 = @as(c_int, 1024); 13 | // pub const GUARANTEED_TO_FIT_2 = @as(c_long, 10241024); 14 | // pub const GUARANTEED_TO_FIT_3 = @as(c_ulong, 20482048); 15 | // pub const MAY_NEED_PROMOTION_1 = __helpers.promoteIntLiteral(c_int, 10241024, .decimal); 16 | // pub const MAY_NEED_PROMOTION_2 = __helpers.promoteIntLiteral(c_long, 307230723072, .decimal); 17 | // pub const MAY_NEED_PROMOTION_3 = __helpers.promoteIntLiteral(c_ulong, 819281928192, .decimal); 18 | // pub const MAY_NEED_PROMOTION_HEX = __helpers.promoteIntLiteral(c_int, 0x80000000, .hex); 19 | // pub const MAY_NEED_PROMOTION_OCT = __helpers.promoteIntLiteral(c_int, 0o20000000000, .octal); 20 | -------------------------------------------------------------------------------- /test/cases/run/Return_boolean_expression_as_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | bool actual_bool(void) { return 4 - 1 < 4;} 4 | char char_bool_ret(void) { return 0 || 1; } 5 | short short_bool_ret(void) { return 0 < 1; } 6 | int int_bool_ret(void) { return 1 && 1; } 7 | long long_bool_ret(void) { return !(0 > 1); } 8 | static int GLOBAL = 1; 9 | int nested_scopes(int a, int b) { 10 | if (a == 1) { 11 | int target = 1; 12 | return b == target; 13 | } else { 14 | int target = 2; 15 | if (b == target) { 16 | return GLOBAL == 1; 17 | } 18 | return target == 2; 19 | } 20 | } 21 | int main(void) { 22 | if (!actual_bool()) abort(); 23 | if (!char_bool_ret()) abort(); 24 | if (!short_bool_ret()) abort(); 25 | if (!int_bool_ret()) abort(); 26 | if (!long_bool_ret()) abort(); 27 | if (!nested_scopes(1, 1)) abort(); 28 | if (nested_scopes(1, 2)) abort(); 29 | if (!nested_scopes(0, 2)) abort(); 30 | if (!nested_scopes(0, 3)) abort(); 31 | return 1 != 1; 32 | } 33 | 34 | // run 35 | -------------------------------------------------------------------------------- /test/cases/run/pointer_arithmetic_with_signed_operand.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int array[10]; 4 | int *x = &array[5]; 5 | int *y; 6 | int idx = 0; 7 | y = x + ++idx; 8 | if (y != x + 1 || y != &array[6]) abort(); 9 | y = idx + x; 10 | if (y != x + 1 || y != &array[6]) abort(); 11 | y = x - idx; 12 | if (y != x - 1 || y != &array[4]) abort(); 13 | 14 | idx = 0; 15 | y = --idx + x; 16 | if (y != x - 1 || y != &array[4]) abort(); 17 | y = idx + x; 18 | if (y != x - 1 || y != &array[4]) abort(); 19 | y = x - idx; 20 | if (y != x + 1 || y != &array[6]) abort(); 21 | 22 | idx = 1; 23 | x += idx; 24 | if (x != &array[6]) abort(); 25 | x -= idx; 26 | if (x != &array[5]) abort(); 27 | y = (x += idx); 28 | if (y != x || y != &array[6]) abort(); 29 | y = (x -= idx); 30 | if (y != x || y != &array[5]) abort(); 31 | 32 | if (array + idx != &array[1] || array + 1 != &array[1]) abort(); 33 | idx = -1; 34 | if (array - idx != &array[1]) abort(); 35 | 36 | return 0; 37 | } 38 | 39 | // run 40 | -------------------------------------------------------------------------------- /test/cases/translate/add,_sub,_mul,_div,_rem.c: -------------------------------------------------------------------------------- 1 | int s() { 2 | int a, b, c; 3 | c = a + b; 4 | c = a - b; 5 | c = a * b; 6 | c = a / b; 7 | c = a % b; 8 | } 9 | unsigned u() { 10 | unsigned a, b, c; 11 | c = a + b; 12 | c = a - b; 13 | c = a * b; 14 | c = a / b; 15 | c = a % b; 16 | } 17 | 18 | // translate 19 | // 20 | // pub export fn s() c_int { 21 | // var a: c_int = undefined; 22 | // _ = &a; 23 | // var b: c_int = undefined; 24 | // _ = &b; 25 | // var c: c_int = undefined; 26 | // _ = &c; 27 | // c = a + b; 28 | // c = a - b; 29 | // c = a * b; 30 | // c = @divTrunc(a, b); 31 | // c = __helpers.signedRemainder(a, b); 32 | // return undefined; 33 | // } 34 | // pub export fn u() c_uint { 35 | // var a: c_uint = undefined; 36 | // _ = &a; 37 | // var b: c_uint = undefined; 38 | // _ = &b; 39 | // var c: c_uint = undefined; 40 | // _ = &c; 41 | // c = a +% b; 42 | // c = a -% b; 43 | // c = a *% b; 44 | // c = a / b; 45 | // c = a % b; 46 | // return undefined; 47 | // } 48 | -------------------------------------------------------------------------------- /test/cases/translate/macros_with_field_targets.c: -------------------------------------------------------------------------------- 1 | typedef unsigned int GLbitfield; 2 | typedef void (*PFNGLCLEARPROC) (GLbitfield mask); 3 | typedef void(*OpenGLProc)(void); 4 | union OpenGLProcs { 5 | OpenGLProc ptr[1]; 6 | struct { 7 | PFNGLCLEARPROC Clear; 8 | } gl; 9 | }; 10 | extern union OpenGLProcs glProcs; 11 | #define glClearUnion glProcs.gl.Clear 12 | #define glClearPFN PFNGLCLEARPROC 13 | 14 | // translate 15 | // 16 | // pub const GLbitfield = c_uint; 17 | // pub const PFNGLCLEARPROC = ?*const fn (mask: GLbitfield) callconv(.c) void; 18 | // pub const OpenGLProc = ?*const fn () callconv(.c) void; 19 | // const struct_unnamed_1 = extern struct { 20 | // Clear: PFNGLCLEARPROC = null, 21 | // }; 22 | // pub const union_OpenGLProcs = extern union { 23 | // ptr: [1]OpenGLProc, 24 | // gl: struct_unnamed_1, 25 | // }; 26 | // pub extern var glProcs: union_OpenGLProcs; 27 | // 28 | // pub const glClearPFN = PFNGLCLEARPROC; 29 | // 30 | // pub inline fn glClearUnion(mask: GLbitfield) void { 31 | // return glProcs.gl.Clear.?(mask); 32 | // } 33 | // 34 | // pub const OpenGLProcs = union_OpenGLProcs; 35 | -------------------------------------------------------------------------------- /test/cases/translate/post_increment_and_decrement.c: -------------------------------------------------------------------------------- 1 | void foo(void) { 2 | int i = 0; 3 | unsigned u = 0; 4 | i++; 5 | i--; 6 | u++; 7 | u--; 8 | i = i++; 9 | i = i--; 10 | u = u++; 11 | u = u--; 12 | } 13 | 14 | // translate 15 | // 16 | // pub export fn foo() void { 17 | // var i: c_int = 0; 18 | // _ = &i; 19 | // var u: c_uint = 0; 20 | // _ = &u; 21 | // i += 1; 22 | // i -= 1; 23 | // u +%= 1; 24 | // u -%= 1; 25 | // i = blk: { 26 | // const ref = &i; 27 | // const tmp = ref.*; 28 | // ref.* += 1; 29 | // break :blk tmp; 30 | // }; 31 | // i = blk: { 32 | // const ref = &i; 33 | // const tmp = ref.*; 34 | // ref.* -= 1; 35 | // break :blk tmp; 36 | // }; 37 | // u = blk: { 38 | // const ref = &u; 39 | // const tmp = ref.*; 40 | // ref.* +%= 1; 41 | // break :blk tmp; 42 | // }; 43 | // u = blk: { 44 | // const ref = &u; 45 | // const tmp = ref.*; 46 | // ref.* -%= 1; 47 | // break :blk tmp; 48 | // }; 49 | // } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (Expat) 2 | 3 | Copyright (c) Zig contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/cases/translate/macro_expressions_respect_C_operator_precedence.c: -------------------------------------------------------------------------------- 1 | int *foo = 0; 2 | #define FOO *((foo) + 2) 3 | #define VALUE (1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9) 4 | #define _AL_READ3BYTES(p) ((*(unsigned char *)(p)) \ 5 | | (*((unsigned char *)(p) + 1) << 8) \ 6 | | (*((unsigned char *)(p) + 2) << 16)) 7 | 8 | // translate 9 | // 10 | // pub inline fn FOO() @TypeOf((foo + @as(c_int, 2)).*) { 11 | // return (foo + @as(c_int, 2)).*; 12 | // } 13 | // 14 | // pub const VALUE = ((((@as(c_int, 1) + (@as(c_int, 2) * @as(c_int, 3))) + (@as(c_int, 4) * @as(c_int, 5))) + @as(c_int, 6)) << @as(c_int, 7)) | @intFromBool(@as(c_int, 8) == @as(c_int, 9)); 15 | // 16 | // pub inline fn _AL_READ3BYTES(p: anytype) @TypeOf((__helpers.cast([*c]u8, p).* | ((__helpers.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((__helpers.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) { 17 | // _ = &p; 18 | // return (__helpers.cast([*c]u8, p).* | ((__helpers.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((__helpers.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16)); 19 | // } 20 | -------------------------------------------------------------------------------- /test/cases/translate/enums_linux.c: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | a, 3 | b, 4 | c, 5 | } d; 6 | enum { 7 | e, 8 | f = 4, 9 | g, 10 | } h = e; 11 | struct Baz { 12 | enum { 13 | i, 14 | j, 15 | k, 16 | } l; 17 | d m; 18 | }; 19 | enum i { 20 | n, 21 | o, 22 | p, 23 | }; 24 | 25 | // translate 26 | // target=native-linux 27 | // 28 | // pub const a: c_int = 0; 29 | // pub const b: c_int = 1; 30 | // pub const c: c_int = 2; 31 | // pub const d = c_uint; 32 | // pub const e: c_int = 0; 33 | // pub const f: c_int = 4; 34 | // pub const g: c_int = 5; 35 | // const enum_unnamed_1 = c_uint; 36 | // pub export var h: enum_unnamed_1 = e; 37 | // pub const i: c_int = 0; 38 | // pub const j: c_int = 1; 39 | // pub const k: c_int = 2; 40 | // const enum_unnamed_2 = c_uint; 41 | // pub const struct_Baz = extern struct { 42 | // l: enum_unnamed_2 = @import("std").mem.zeroes(enum_unnamed_2), 43 | // m: d = @import("std").mem.zeroes(d), 44 | // }; 45 | // pub const n: c_int = 0; 46 | // pub const o: c_int = 1; 47 | // pub const p: c_int = 2; 48 | // pub const enum_i = c_uint; 49 | // 50 | // pub const Baz = struct_Baz; 51 | -------------------------------------------------------------------------------- /test/cases/translate/enums_MSVC.c: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | a, 3 | b, 4 | c, 5 | } d; 6 | enum { 7 | e, 8 | f = 4, 9 | g, 10 | } h = e; 11 | struct Baz { 12 | enum { 13 | i, 14 | j, 15 | k, 16 | } l; 17 | d m; 18 | }; 19 | enum i { 20 | n, 21 | o, 22 | p, 23 | }; 24 | 25 | // translate 26 | // target=native-windows-msvc 27 | // 28 | // pub const a: c_int = 0; 29 | // pub const b: c_int = 1; 30 | // pub const c: c_int = 2; 31 | // pub const d = c_int; 32 | // pub const e: c_int = 0; 33 | // pub const f: c_int = 4; 34 | // pub const g: c_int = 5; 35 | // const enum_unnamed_1 = c_int; 36 | // pub export var h: enum_unnamed_1 = e; 37 | // pub const i: c_int = 0; 38 | // pub const j: c_int = 1; 39 | // pub const k: c_int = 2; 40 | // const enum_unnamed_2 = c_int; 41 | // pub const struct_Baz = extern struct { 42 | // l: enum_unnamed_2 = @import("std").mem.zeroes(enum_unnamed_2), 43 | // m: d = @import("std").mem.zeroes(d), 44 | // }; 45 | // pub const n: c_int = 0; 46 | // pub const o: c_int = 1; 47 | // pub const p: c_int = 2; 48 | // pub const enum_i = c_int; 49 | // 50 | // pub const Baz = struct_Baz; 51 | -------------------------------------------------------------------------------- /test/cases/run/break_from_switch_statement.c: -------------------------------------------------------------------------------- 1 | #include 2 | int switcher(int x) { 3 | switch (x) { 4 | case 0: // no braces 5 | x += 1; 6 | break; 7 | case 1: // conditional break 8 | if (x == 1) { 9 | x += 1; 10 | break; 11 | } 12 | x += 100; 13 | case 2: { // braces with fallthrough 14 | x += 1; 15 | } 16 | case 3: // fallthrough to return statement 17 | x += 1; 18 | case 42: { // random out of order case 19 | x += 1; 20 | return x; 21 | } 22 | case 4: { // break within braces 23 | x += 1; 24 | break; 25 | } 26 | case 5: 27 | x += 1; // fallthrough to default 28 | default: 29 | x += 1; 30 | } 31 | return x; 32 | } 33 | int main(void) { 34 | int expected[] = {1, 2, 5, 5, 5, 7, 7}; 35 | for (int i = 0; i < sizeof(expected) / sizeof(int); i++) { 36 | int res = switcher(i); 37 | if (res != expected[i]) abort(); 38 | } 39 | if (switcher(42) != 43) abort(); 40 | return 0; 41 | } 42 | 43 | // run 44 | -------------------------------------------------------------------------------- /test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_used_result.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | int int1 = 1; 4 | int int2 = 2; 5 | int int100000000 = 100000000; 6 | signed short foo; 7 | signed short val = -1; 8 | foo = (val += int1); if (foo != 0) abort(); 9 | foo = (val -= int1); if (foo != -1) abort(); 10 | foo = (val *= int2); if (foo != -2) abort(); 11 | foo = (val /= int2); if (foo != -1) abort(); 12 | foo = (val %= int2); if (foo != -1) abort(); 13 | foo = (val <<= int1); if (foo != -2) abort(); 14 | foo = (val >>= int1); if (foo != -1) abort(); 15 | foo = (val += int100000000); // compile error if @truncate() not inserted 16 | unsigned short ufoo; 17 | unsigned short uval = 1; 18 | ufoo = (uval += int1); if (ufoo != 2) abort(); 19 | ufoo = (uval -= int1); if (ufoo != 1) abort(); 20 | ufoo = (uval *= int2); if (ufoo != 2) abort(); 21 | ufoo = (uval /= int2); if (ufoo != 1) abort(); 22 | ufoo = (uval %= int2); if (ufoo != 1) abort(); 23 | ufoo = (uval <<= int1); if (ufoo != 2) abort(); 24 | ufoo = (uval >>= int1); if (ufoo != 1) abort(); 25 | ufoo = (uval += int100000000); // compile error if @truncate() not inserted 26 | } 27 | 28 | // run 29 | -------------------------------------------------------------------------------- /test/cases/run/offsetof.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define container_of(ptr, type, member) ({ \ 4 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 5 | (type *)( (char *)__mptr - offsetof(type,member) );}) 6 | typedef struct { 7 | int i; 8 | struct { int x; char y; int z; } s; 9 | float f; 10 | } container; 11 | int main(void) { 12 | if (offsetof(container, i) != 0) abort(); 13 | if (offsetof(container, s) <= offsetof(container, i)) abort(); 14 | if (offsetof(container, f) <= offsetof(container, s)) abort(); 15 | 16 | container my_container; 17 | typeof(my_container.s) *inner_member_pointer = &my_container.s; 18 | float *float_member_pointer = &my_container.f; 19 | int *anon_member_pointer = &my_container.s.z; 20 | container *my_container_p; 21 | 22 | my_container_p = container_of(inner_member_pointer, container, s); 23 | if (my_container_p != &my_container) abort(); 24 | 25 | my_container_p = container_of(float_member_pointer, container, f); 26 | if (my_container_p != &my_container) abort(); 27 | 28 | if (container_of(anon_member_pointer, typeof(my_container.s), z) != inner_member_pointer) abort(); 29 | return 0; 30 | } 31 | 32 | // run 33 | -------------------------------------------------------------------------------- /test/cases/run/NAN_and_INFINITY.c: -------------------------------------------------------------------------------- 1 | // TODO: add isnan check for long double once bitfield support is added 2 | // (needed for x86_64-windows-gnu) 3 | // TODO: add isinf check for long double once std.math.isInf supports c_longdouble 4 | #include 5 | #include 6 | #include 7 | union uf { uint32_t u; float f; }; 8 | #define CHECK_NAN(STR, VAL) { \ 9 | union uf unpack = {.f = __builtin_nanf(STR)}; \ 10 | if (!isnan(unpack.f)) abort(); \ 11 | if (unpack.u != VAL) abort(); \ 12 | } 13 | int main(void) { 14 | float f_nan = NAN; 15 | if (!isnan(f_nan)) abort(); 16 | double d_nan = NAN; 17 | if (!isnan(d_nan)) abort(); 18 | CHECK_NAN("0", 0x7FC00000); 19 | CHECK_NAN("", 0x7FC00000); 20 | CHECK_NAN("1", 0x7FC00001); 21 | CHECK_NAN("0x7FC00000", 0x7FC00000); 22 | CHECK_NAN("0x7FC0000F", 0x7FC0000F); 23 | CHECK_NAN("0x7FC000F0", 0x7FC000F0); 24 | CHECK_NAN("0x7FC00F00", 0x7FC00F00); 25 | CHECK_NAN("0x7FC0F000", 0x7FC0F000); 26 | CHECK_NAN("0x7FCF0000", 0x7FCF0000); 27 | CHECK_NAN("0xFFFFFFFF", 0x7FFFFFFF); 28 | float f_inf = INFINITY; 29 | if (!isinf(f_inf)) abort(); 30 | double d_inf = INFINITY; 31 | if (!isinf(d_inf)) abort(); 32 | return 0; 33 | } 34 | 35 | // run 36 | // skip_windows=true 37 | -------------------------------------------------------------------------------- /test/cases/translate/float_types.c: -------------------------------------------------------------------------------- 1 | _Float16 a; 2 | _Float32 b; 3 | _Float64 c; 4 | _Float128 d; 5 | 6 | _Float32x e; 7 | _Float64x f; 8 | // _Float128x g; // unsupported on all targets 9 | 10 | __fp16 h; 11 | __bf16 i; 12 | float j; 13 | double k; 14 | long double l; 15 | __float128 m; 16 | 17 | _Decimal32 n; 18 | _Decimal64 o; 19 | _Decimal128 p; 20 | _Decimal64x q; 21 | 22 | // translate 23 | // target=x86_64-linux 24 | // 25 | // pub export var a: f16 = 0; 26 | // pub export var b: f32 = 0; 27 | // pub export var c: f64 = 0; 28 | // pub export var d: f128 = 0; 29 | // pub export var e: f64 = 0; 30 | // pub export var f: c_longdouble = 0; 31 | // pub export var h: f16 = 0; 32 | // 33 | // pub const i = @compileError("unable to translate variable declaration type"); 34 | // 35 | // pub export var j: f32 = 0; 36 | // pub export var k: f64 = 0; 37 | // pub export var l: c_longdouble = 0; 38 | // pub export var m: f128 = 0; 39 | // 40 | // pub const n = @compileError("unable to translate variable declaration type"); 41 | // 42 | // pub const o = @compileError("unable to translate variable declaration type"); 43 | // 44 | // pub const p = @compileError("unable to translate variable declaration type"); 45 | // 46 | // pub const q = @compileError("unable to translate variable declaration type"); 47 | --------------------------------------------------------------------------------