authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 11:03:17-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 11:03:17-05:00
logbcbcb2e9ffbfef63d3692ea45eea2e2babacc3a9
tree48f4df2e6ce5e12077743a84433c4c2537dd4fc2
parent1864acd32608ae917f8afc11b11f08a4bb362cef
parent2f9fedabf0805a47aba5c348e5369c1c28f6cf21
signature Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm8


7 files changed, 68 insertions(+), 20 deletions(-)

doc/langref.html.in+10-6
......@@ -6381,14 +6381,14 @@ fn List(comptime T: type) type {
63816381 {#header_close#}
63826382
63836383 {#header_open|@truncate#}
6384 <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
6384 <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>
63856385 <p>
63866386 This function truncates bits from an integer type, resulting in a smaller
63876387 integer type.
63886388 </p>
63896389 <p>
6390 The following produces a crash in debug mode and undefined behavior in
6391 release mode:
6390 The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
6391 {#link|ReleaseFast#} mode:
63926392 </p>
63936393 <pre>{#syntax#}const a: u16 = 0xabcd;
63946394const b: u8 = u8(a);{#endsyntax#}</pre>
......@@ -6402,7 +6402,10 @@ const b: u8 = @truncate(u8, a);
64026402 This function always truncates the significant bits of the integer, regardless
64036403 of endianness on the target platform.
64046404 </p>
6405
6405 <p>
6406 If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
6407 then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}.
6408 </p>
64066409 {#header_close#}
64076410
64086411 {#header_open|@typeId#}
......@@ -7870,7 +7873,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr
78707873
78717874TopLevelDecl
78727875 &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
7873 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl
7876 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
78747877 / KEYWORD_use Expr SEMICOLON
78757878
78767879FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
......@@ -8330,6 +8333,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word
83308333KEYWORD_suspend &lt;- 'suspend' end_of_word
83318334KEYWORD_switch &lt;- 'switch' end_of_word
83328335KEYWORD_test &lt;- 'test' end_of_word
8336KEYWORD_threadlocal &lt;- 'threadlocal' end_of_word
83338337KEYWORD_true &lt;- 'true' end_of_word
83348338KEYWORD_try &lt;- 'try' end_of_word
83358339KEYWORD_undefined &lt;- 'undefined' end_of_word
......@@ -8350,7 +8354,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm
83508354 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
83518355 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
83528356 / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
8353 / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try
8357 / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
83548358 / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
83558359 / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
83568360 {#header_close#}
src/analyze.cpp+3
......@@ -594,6 +594,9 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
594594 // function types are technically pointers
595595 entry->type_ref = child_type->type_ref;
596596 entry->di_type = child_type->di_type;
597 if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
598 g->error_di_types.append(&entry->di_type);
599 }
597600 } else {
598601 assert(child_type->di_type);
599602 // create a struct with a boolean whether this is the null value
src/ir.cpp+16-8
......@@ -18491,7 +18491,22 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
1849118491 return ira->codegen->invalid_instruction;
1849218492 }
1849318493
18494 if (src_type->data.integral.bit_count == 0) {
18494 if (dest_type->id == ZigTypeIdComptimeInt) {
18495 return ir_implicit_cast(ira, target, dest_type);
18496 }
18497
18498 if (instr_is_comptime(target)) {
18499 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
18500 if (val == nullptr)
18501 return ira->codegen->invalid_instruction;
18502
18503 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18504 bigint_truncate(&result->value.data.x_bigint, &val->data.x_bigint,
18505 dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
18506 return result;
18507 }
18508
18509 if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) {
1849518510 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
1849618511 bigint_init_unsigned(&result->value.data.x_bigint, 0);
1849718512 return result;
......@@ -18507,13 +18522,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
1850718522 return ira->codegen->invalid_instruction;
1850818523 }
1850918524
18510 if (target->value.special == ConstValSpecialStatic) {
18511 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18512 bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint,
18513 dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
18514 return result;
18515 }
18516
1851718525 IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
1851818526 instruction->base.source_node, dest_type_value, target);
1851918527 new_instruction->value.type = dest_type;
std/testing.zig+1-5
......@@ -24,11 +24,7 @@ pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
2424/// equal, prints diagnostics to stderr to show exactly how they are not equal,
2525/// then aborts.
2626/// The types must match exactly.
27pub fn expectEqual(expected: var, actual: var) void {
28 if (@typeOf(actual) != @typeOf(expected)) {
29 @compileError("type mismatch. expected " ++ @typeName(@typeOf(expected)) ++ ", found " ++ @typeName(@typeOf(actual)));
30 }
31
27pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
3228 switch (@typeInfo(@typeOf(actual))) {
3329 TypeId.NoReturn,
3430 TypeId.BoundFn,
test/compile_errors.zig+10-1
......@@ -1,6 +1,15 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addTest(
5 "@truncate undefined value",
6 \\export fn entry() void {
7 \\ var z = @truncate(u8, u16(undefined));
8 \\}
9 ,
10 ".tmp_source.zig:2:30: error: use of undefined value",
11 );
12
413 cases.addTest(
514 "return invalid type from test",
615 \\test "example" { return 1; }
......@@ -3335,7 +3344,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
33353344 cases.add(
33363345 "truncate sign mismatch",
33373346 \\fn f() i8 {
3338 \\ const x: u32 = 10;
3347 \\ var x: u32 = 10;
33393348 \\ return @truncate(i8, x);
33403349 \\}
33413350 \\
test/stage1/behavior/error.zig+5
......@@ -330,3 +330,8 @@ test "optional error set is the same size as error set" {
330330 expect(S.returnsOptErrSet() == null);
331331 comptime expect(S.returnsOptErrSet() == null);
332332}
333
334test "debug info for optional error set" {
335 const SomeError = error{Hello};
336 var a_local_variable: ?SomeError = null;
337}
test/stage1/behavior/truncate.zig+23
......@@ -6,3 +6,26 @@ test "truncate u0 to larger integer allowed and has comptime known result" {
66 const y = @truncate(u8, x);
77 comptime expect(y == 0);
88}
9
10test "truncate.u0.literal" {
11 var z = @truncate(u0, 0);
12 expect(z == 0);
13}
14
15test "truncate.u0.const" {
16 const c0: usize = 0;
17 var z = @truncate(u0, c0);
18 expect(z == 0);
19}
20
21test "truncate.u0.var" {
22 var d: u8 = 2;
23 var z = @truncate(u0, d);
24 expect(z == 0);
25}
26
27test "truncate sign mismatch but comptime known so it works anyway" {
28 const x: u32 = 10;
29 var result = @truncate(i8, x);
30 expect(result == 10);
31}