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

This commit is contained in:
Andrew Kelley 2019-02-10 11:03:17 -05:00
commit bcbcb2e9ff
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
7 changed files with 68 additions and 20 deletions

View File

@ -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 &lt;- KEYWORD_comptime BlockExpr
TopLevelDecl TopLevelDecl
&lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) &lt;- (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 &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) FnProto &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
KEYWORD_suspend &lt;- 'suspend' end_of_word KEYWORD_suspend &lt;- 'suspend' end_of_word
KEYWORD_switch &lt;- 'switch' end_of_word KEYWORD_switch &lt;- 'switch' end_of_word
KEYWORD_test &lt;- 'test' end_of_word KEYWORD_test &lt;- 'test' end_of_word
KEYWORD_threadlocal &lt;- 'threadlocal' end_of_word
KEYWORD_true &lt;- 'true' end_of_word KEYWORD_true &lt;- 'true' end_of_word
KEYWORD_try &lt;- 'try' end_of_word KEYWORD_try &lt;- 'try' end_of_word
KEYWORD_undefined &lt;- 'undefined' end_of_word KEYWORD_undefined &lt;- 'undefined' end_of_word
@ -8350,7 +8354,7 @@ keyword &lt;- 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#}

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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);
\\} \\}
\\ \\

View File

@ -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;
}

View File

@ -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);
}