mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 00:35:10 +00:00
Merge remote-tracking branch 'origin/master' into llvm8
This commit is contained in:
commit
bcbcb2e9ff
@ -6381,14 +6381,14 @@ fn List(comptime T: type) type {
|
|||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@truncate#}
|
{#header_open|@truncate#}
|
||||||
<pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
This function truncates bits from an integer type, resulting in a smaller
|
This function truncates bits from an integer type, resulting in a smaller
|
||||||
integer type.
|
integer type.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The following produces a crash in debug mode and undefined behavior in
|
The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
|
||||||
release mode:
|
{#link|ReleaseFast#} mode:
|
||||||
</p>
|
</p>
|
||||||
<pre>{#syntax#}const a: u16 = 0xabcd;
|
<pre>{#syntax#}const a: u16 = 0xabcd;
|
||||||
const b: u8 = u8(a);{#endsyntax#}</pre>
|
const b: u8 = u8(a);{#endsyntax#}</pre>
|
||||||
@ -6402,7 +6402,10 @@ const b: u8 = @truncate(u8, a);
|
|||||||
This function always truncates the significant bits of the integer, regardless
|
This function always truncates the significant bits of the integer, regardless
|
||||||
of endianness on the target platform.
|
of endianness on the target platform.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
|
||||||
|
then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}.
|
||||||
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@typeId#}
|
{#header_open|@typeId#}
|
||||||
@ -7870,7 +7873,7 @@ TopLevelComptime <- KEYWORD_comptime BlockExpr
|
|||||||
|
|
||||||
TopLevelDecl
|
TopLevelDecl
|
||||||
<- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
|
<- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
|
||||||
/ (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl
|
/ (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
|
||||||
/ KEYWORD_use Expr SEMICOLON
|
/ KEYWORD_use Expr SEMICOLON
|
||||||
|
|
||||||
FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
|
FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
|
||||||
@ -8330,6 +8333,7 @@ KEYWORD_struct <- 'struct' end_of_word
|
|||||||
KEYWORD_suspend <- 'suspend' end_of_word
|
KEYWORD_suspend <- 'suspend' end_of_word
|
||||||
KEYWORD_switch <- 'switch' end_of_word
|
KEYWORD_switch <- 'switch' end_of_word
|
||||||
KEYWORD_test <- 'test' end_of_word
|
KEYWORD_test <- 'test' end_of_word
|
||||||
|
KEYWORD_threadlocal <- 'threadlocal' end_of_word
|
||||||
KEYWORD_true <- 'true' end_of_word
|
KEYWORD_true <- 'true' end_of_word
|
||||||
KEYWORD_try <- 'try' end_of_word
|
KEYWORD_try <- 'try' end_of_word
|
||||||
KEYWORD_undefined <- 'undefined' end_of_word
|
KEYWORD_undefined <- 'undefined' end_of_word
|
||||||
@ -8350,7 +8354,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm
|
|||||||
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
|
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
|
||||||
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
|
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
|
||||||
/ KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
|
/ KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
|
||||||
/ KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try
|
/ KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
|
||||||
/ KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
|
/ KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
|
||||||
/ KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
|
/ KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|||||||
@ -594,6 +594,9 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
|
|||||||
// function types are technically pointers
|
// function types are technically pointers
|
||||||
entry->type_ref = child_type->type_ref;
|
entry->type_ref = child_type->type_ref;
|
||||||
entry->di_type = child_type->di_type;
|
entry->di_type = child_type->di_type;
|
||||||
|
if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
|
||||||
|
g->error_di_types.append(&entry->di_type);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(child_type->di_type);
|
assert(child_type->di_type);
|
||||||
// create a struct with a boolean whether this is the null value
|
// create a struct with a boolean whether this is the null value
|
||||||
|
|||||||
24
src/ir.cpp
24
src/ir.cpp
@ -18491,7 +18491,22 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_type->data.integral.bit_count == 0) {
|
if (dest_type->id == ZigTypeIdComptimeInt) {
|
||||||
|
return ir_implicit_cast(ira, target, dest_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr_is_comptime(target)) {
|
||||||
|
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
|
||||||
|
if (val == nullptr)
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
||||||
|
bigint_truncate(&result->value.data.x_bigint, &val->data.x_bigint,
|
||||||
|
dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) {
|
||||||
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
||||||
bigint_init_unsigned(&result->value.data.x_bigint, 0);
|
bigint_init_unsigned(&result->value.data.x_bigint, 0);
|
||||||
return result;
|
return result;
|
||||||
@ -18507,13 +18522,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->value.special == ConstValSpecialStatic) {
|
|
||||||
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
|
|
||||||
bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint,
|
|
||||||
dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
|
IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
|
||||||
instruction->base.source_node, dest_type_value, target);
|
instruction->base.source_node, dest_type_value, target);
|
||||||
new_instruction->value.type = dest_type;
|
new_instruction->value.type = dest_type;
|
||||||
|
|||||||
@ -24,11 +24,7 @@ pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
|
|||||||
/// equal, prints diagnostics to stderr to show exactly how they are not equal,
|
/// equal, prints diagnostics to stderr to show exactly how they are not equal,
|
||||||
/// then aborts.
|
/// then aborts.
|
||||||
/// The types must match exactly.
|
/// The types must match exactly.
|
||||||
pub fn expectEqual(expected: var, actual: var) void {
|
pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
|
||||||
if (@typeOf(actual) != @typeOf(expected)) {
|
|
||||||
@compileError("type mismatch. expected " ++ @typeName(@typeOf(expected)) ++ ", found " ++ @typeName(@typeOf(actual)));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (@typeInfo(@typeOf(actual))) {
|
switch (@typeInfo(@typeOf(actual))) {
|
||||||
TypeId.NoReturn,
|
TypeId.NoReturn,
|
||||||
TypeId.BoundFn,
|
TypeId.BoundFn,
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
const tests = @import("tests.zig");
|
const tests = @import("tests.zig");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.addTest(
|
||||||
|
"@truncate undefined value",
|
||||||
|
\\export fn entry() void {
|
||||||
|
\\ var z = @truncate(u8, u16(undefined));
|
||||||
|
\\}
|
||||||
|
,
|
||||||
|
".tmp_source.zig:2:30: error: use of undefined value",
|
||||||
|
);
|
||||||
|
|
||||||
cases.addTest(
|
cases.addTest(
|
||||||
"return invalid type from test",
|
"return invalid type from test",
|
||||||
\\test "example" { return 1; }
|
\\test "example" { return 1; }
|
||||||
@ -3335,7 +3344,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
cases.add(
|
cases.add(
|
||||||
"truncate sign mismatch",
|
"truncate sign mismatch",
|
||||||
\\fn f() i8 {
|
\\fn f() i8 {
|
||||||
\\ const x: u32 = 10;
|
\\ var x: u32 = 10;
|
||||||
\\ return @truncate(i8, x);
|
\\ return @truncate(i8, x);
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
|
|||||||
@ -330,3 +330,8 @@ test "optional error set is the same size as error set" {
|
|||||||
expect(S.returnsOptErrSet() == null);
|
expect(S.returnsOptErrSet() == null);
|
||||||
comptime expect(S.returnsOptErrSet() == null);
|
comptime expect(S.returnsOptErrSet() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "debug info for optional error set" {
|
||||||
|
const SomeError = error{Hello};
|
||||||
|
var a_local_variable: ?SomeError = null;
|
||||||
|
}
|
||||||
|
|||||||
@ -6,3 +6,26 @@ test "truncate u0 to larger integer allowed and has comptime known result" {
|
|||||||
const y = @truncate(u8, x);
|
const y = @truncate(u8, x);
|
||||||
comptime expect(y == 0);
|
comptime expect(y == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "truncate.u0.literal" {
|
||||||
|
var z = @truncate(u0, 0);
|
||||||
|
expect(z == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "truncate.u0.const" {
|
||||||
|
const c0: usize = 0;
|
||||||
|
var z = @truncate(u0, c0);
|
||||||
|
expect(z == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "truncate.u0.var" {
|
||||||
|
var d: u8 = 2;
|
||||||
|
var z = @truncate(u0, d);
|
||||||
|
expect(z == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "truncate sign mismatch but comptime known so it works anyway" {
|
||||||
|
const x: u32 = 10;
|
||||||
|
var result = @truncate(i8, x);
|
||||||
|
expect(result == 10);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user