Given a pointer operand `ptr` and a signed integer operand `idx`
`ptr + idx` and `idx + ptr` -> ptr + @bitCast(usize, @intCast(isize, idx))
`ptr - idx` -> ptr - @bitCast(usize, @intCast(isize, idx))
Thanks @LemonBoy for pointing out that we can take advantage of wraparound
to dramatically simplify the code.
Add support for OffsetOfExpr that contain exactly 1 component, when that component
is a field.
For example, given:
```c
struct S {
float f;
double d;
};
struct T {
long l;
int i;
struct S s[10];
};
```
Then:
```c
offsetof(struct T, i) // supported
offsetof(struct T, s[2].d) // not supported currently
```
When two pointers are subtracted, both shall point to elements of the
same array object, or one past the last element of the array object;
the result is the difference of the subscripts of the two array elements.
The size of the result is implementation-defined, and its type
(a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
If the result is not representable in an object of that type,
the behavior is undefined.
See C Standard, §6.5.6 [ISO/IEC 9899:2011]
Fixes#7216
If the type is a reference to a global declaration that has not yet
been translated we need to use the global scope for translation
so that other functions can also reference it.
The previous iteration of translate-c used an incorrect block label
in the break statement for a translated C statement expression. This adds
a test to ensure the correct label is used in the new intermediate AST
version of translate-c.
In C, if a function has return type `int` and the return expression
is a boolean expression, there is no implicit cast. Therefore the
translated Zig code needs to call @boolToInt() on the result.
Written with feedback from @Vexu
Fixes#6215
Adds support for wide, UTF-16, and UTF-32 string literals. If used to initialize
an incomplete array, the same logic as narrow strings is used. Otherwise they
are translated as global "anonymous" arrays of the relevant underlying char type.
A dot is used in the name to ensure the generated names do not conflict with any
other names in the translated program.
For example:
```c
void my_fn() {
const uint32_t *foo = U"foo";
}
```
becomes:
```zig
const @"zig.UTF32_string_2" = [4]c_uint{
'\u{66}',
'\u{6f}',
'\u{6f}',
0,
};
pub export fn my_fn() void {
var foo: [*c]const u32 = &@"zig.UTF32_string_2";
}
```
1. For incomplete arrays with initializer list (`int x[] = {1};`) use the
initializer size as the array size.
2. For arrays initialized with a string literal translate it as an array
of character literals instead of `[*c]const u8`
3. Don't crash if an empty initializer is used for an incomplete array.
4. Add a test for multi-character character constants
Additionally lay some groundwork for supporting wide string literals.
fixes#4831#7832#7842
Add support for L'<wchar_t>', u'<char16_t>', and U'<char32_t>'. Currently
this just translates wide char literals to \u{NNNNNN} escape codes
(e.g. U'💯' -> '\u{1f4af}')
Another approach would be to emit UTF-8 encoded character literals
directly, but in my opinion this approaches Unicode-complete because it
would require knowledge of which Unicode codepoints have graphical
representations for the emitted source to be readable.
We could also just emit integer literals, but the current method makes
it clear that we have translated a wide character literal and not just
an integer constant.
Fixes two scenarios where @boolToInt() calls were missing:
1. Boolean expression cast to different-size int (char, long, etc)
2. Boolean expression used as parameter for function with int argument
In strictly conforming C, identifiers cannot container dollar signs.
However GCC and Clang allow them by default, so translate-c should
handle them. See http://gcc.gnu.org/onlinedocs/cpp/Tokenization.html
I encountered this in the wild in windows.h
Fixes#7585
If a static function is defined with no argument list and no prototype
is given, it should be treated as a function that takes no arguments
rather than as a variadic function.
Fixes#7594
Previously casting a bool to an int would result in the following Zig code:
@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))));
This is incorrect if `b` is true, since bitcasting a `u1` with the value 1
to an `i1` will result in the value -1. Instead, generate the following code:
@as(c_int, @boolToInt(b));
Since @boolToInt returns a `u1`, this is only disallowed if the destination
type is one-bit and signed, which can only happen if it's a bitfield
(currently not supported by translate-c)
C compiler intrinsics can only appear as part of a function call. When called
they are implicitly cast to a function pointer; treat this as a non-null
pointer so that it emits as a regular Zig function call.
Put `pub usingnamespace @import("std").c.builtins;` at the top of translated
C files so that they will have access to builtin functions defined there.
Fixes#6707
In C, enums are represented as signed integers, so casting from an enum to an integer
should use the "cast integer to integer" translation code path. Previously it used the
"cast enum to generic non-enum" code path, because enums were not being treated as integers.
Ultimately this can produce zig code that fails to compile if the destination type does not
support the full range of enum values (e.g. translated C code that casts an enum value to an
unsigned integer would fail to compile since enums are signed integers, and unsigned integers
cannot represent the full range of values that signed ones can).
One interesting thing that came up during testing is that the implicit enum-to-int cast that
occurs when an enum is used in a boolean expression was parsed as an (int) by some versions of
the zig compiler, and an (unsigned int) cast by others. Specifically, the following code:
```c
enum Foo {Bar, Baz};
// ...
enum Foo foo = Bar;
if (0 || foo) {
// do something
}
```
When tested on MacOS, Linux, and Windows using a compiler built from the Windows Zig Compiler
Dev Kit, the above code would emit a cast to c_uint:
`if (false or (@bitCast(c_uint, @enumToInt(foo)) != 0)) {}`
However when tested on Windows with a Zig compiler built using MSVC, it produces:
`if (false or (@bitCast(c_int, @enumToInt(foo)) != 0)) {}`
In this particular case I don't think it matters, since a c_int and c_uint will have the same
representation for zero, but I'm not sure if this is ultimately the result of
implementation-defined behavior or something else.
Because of this, I added explicit casts in the `translate_c.zig` tests, to ensure that the
emitted zig source exactly matches across platforms. I also added a behavior test in
`run_translated_c.zig` that uses the old implicit casts from `translate_c.zig` to ensure
that the emitted Zig code behaves the same as the C code regardless of what cast is used.
Pre-requisite for having a test case for #5062
In complex C statements which are outside of macros,
it is valid C to perform e.g. a bitor between an
integer and a boolean `5 | (8 == 9)`
Currently this results in a zig error after translating
as `c_int | bool` is invalid Zig.
Detects if a sub-expression of a numeric operator is
boolean and if so converts it to int
Translate C: Put an alignCast in c style pointer casts to allow opaque types to cast properly in C macros
Translate C: add test case for aligning opaque types in pointer casts
Translate C: Fix @typeId -> @typeInfo
Add test case to run_translated_c for casting from pointer to opaque type