introduce new test syntax

* remove setFnTest builtin
 * add test "name" { ... } syntax
 * remove --check-unused argument. functions are always lazy now.
This commit is contained in:
Andrew Kelley 2017-03-16 16:02:35 -04:00
parent 329457bb4f
commit af536ac343
58 changed files with 626 additions and 889 deletions

View File

@ -5,7 +5,9 @@
```
Root = many(TopLevelItem) "EOF"
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl
TestDecl = "test" String Block
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)

View File

@ -15,7 +15,7 @@ syn keyword zigConditional if else switch try
syn keyword zigRepeat while for
syn keyword zigConstant null undefined this
syn keyword zigKeyword fn use
syn keyword zigKeyword fn use test
syn keyword zigType bool f32 f64 void Unreachable type error
syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_long_double

View File

@ -311,6 +311,7 @@ enum NodeType {
NodeTypeVariableDeclaration,
NodeTypeTypeDecl,
NodeTypeErrorValueDecl,
NodeTypeTestDecl,
NodeTypeBinOpExpr,
NodeTypeUnwrapErrorExpr,
NodeTypeNumberLiteral,
@ -435,6 +436,14 @@ struct AstNodeErrorValueDecl {
ErrorTableEntry *err;
};
struct AstNodeTestDecl {
// always invalid if it's not VisibModPrivate but can be parsed that way
VisibMod visib_mod;
Buf *name;
AstNode *body;
};
enum BinOpType {
BinOpTypeInvalid,
BinOpTypeAssign,
@ -781,6 +790,7 @@ struct AstNode {
AstNodeVariableDeclaration variable_declaration;
AstNodeTypeDecl type_decl;
AstNodeErrorValueDecl error_value_decl;
AstNodeTestDecl test_decl;
AstNodeBinOpExpr bin_op_expr;
AstNodeUnwrapErrorExpr unwrap_err_expr;
AstNodePrefixOpExpr prefix_op_expr;
@ -1091,7 +1101,7 @@ enum FnInline {
struct FnTableEntry {
LLVMValueRef llvm_value;
AstNode *proto_node;
AstNode *fn_def_node;
AstNode *body_node;
ScopeFnDef *fndef_scope; // parent should be the top level decls or container decls
Scope *child_scope; // parent is scope for last parameter
ScopeBlock *def_scope; // parent is child_scope
@ -1161,7 +1171,6 @@ enum BuiltinFnId {
BuiltinFnIdTruncate,
BuiltinFnIdIntType,
BuiltinFnIdUnreachable,
BuiltinFnIdSetFnTest,
BuiltinFnIdSetFnVisible,
BuiltinFnIdSetDebugSafety,
BuiltinFnIdAlloca,
@ -1411,8 +1420,8 @@ struct CodeGen {
ZigList<const char *> lib_dirs;
uint32_t test_fn_count;
TypeTableEntry *test_fn_type;
bool check_unused;
bool each_lib_rpath;
ZigList<AstNode *> error_decls;
@ -1630,7 +1639,6 @@ enum IrInstructionId {
IrInstructionIdTypeOf,
IrInstructionIdToPtrType,
IrInstructionIdPtrTypeChild,
IrInstructionIdSetFnTest,
IrInstructionIdSetFnVisible,
IrInstructionIdSetDebugSafety,
IrInstructionIdArrayType,
@ -1973,12 +1981,6 @@ struct IrInstructionPtrTypeChild {
IrInstruction *value;
};
struct IrInstructionSetFnTest {
IrInstruction base;
IrInstruction *fn_value;
};
struct IrInstructionSetFnVisible {
IrInstruction base;

View File

@ -130,7 +130,6 @@ Scope *create_loop_scope(AstNode *node, Scope *parent) {
}
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) {
assert(!node || node->type == NodeTypeFnDef);
ScopeFnDef *scope = allocate<ScopeFnDef>(1);
init_scope(&scope->base, ScopeIdFnDef, node, parent);
scope->fn_entry = fn_entry;
@ -1756,7 +1755,8 @@ FnTableEntry *create_fn(AstNode *proto_node) {
FnTableEntry *fn_entry = create_fn_raw(inline_value, internal_linkage);
fn_entry->proto_node = proto_node;
fn_entry->fn_def_node = proto_node->data.fn_proto.fn_def_node;
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
proto_node->data.fn_proto.fn_def_node->data.fn_def.body;
return fn_entry;
}
@ -1799,76 +1799,107 @@ static void typecheck_panic_fn(CodeGen *g) {
}
}
static TypeTableEntry *get_test_fn_type(CodeGen *g) {
if (g->test_fn_type)
return g->test_fn_type;
FnTypeId fn_type_id = {0};
fn_type_id.return_type = g->builtin_types.entry_void;
g->test_fn_type = get_fn_type(g, &fn_type_id);
return g->test_fn_type;
}
static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
ImportTableEntry *import = tld_fn->base.import;
AstNode *proto_node = tld_fn->base.source_node;
assert(proto_node->type == NodeTypeFnProto);
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
AstNode *source_node = tld_fn->base.source_node;
if (source_node->type == NodeTypeFnProto) {
AstNodeFnProto *fn_proto = &source_node->data.fn_proto;
AstNode *fn_def_node = fn_proto->fn_def_node;
AstNode *fn_def_node = fn_proto->fn_def_node;
FnTableEntry *fn_table_entry = create_fn(tld_fn->base.source_node);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
FnTableEntry *fn_table_entry = create_fn(source_node);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
tld_fn->fn_entry = fn_table_entry;
tld_fn->fn_entry = fn_table_entry;
if (fn_table_entry->fn_def_node) {
fn_table_entry->fndef_scope = create_fndef_scope(
fn_table_entry->fn_def_node, tld_fn->base.parent_scope, fn_table_entry);
if (fn_table_entry->body_node) {
fn_table_entry->fndef_scope = create_fndef_scope(
fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry);
for (size_t i = 0; i < fn_proto->params.length; i += 1) {
AstNode *param_node = fn_proto->params.at(i);
assert(param_node->type == NodeTypeParamDecl);
if (buf_len(param_node->data.param_decl.name) == 0) {
add_node_error(g, param_node, buf_sprintf("missing parameter name"));
}
}
}
Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
fn_table_entry->type_entry = analyze_fn_type(g, proto_node, child_scope);
if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) {
tld_fn->base.resolution = TldResolutionInvalid;
return;
}
if (!fn_table_entry->type_entry->data.fn.is_generic) {
g->fn_protos.append(fn_table_entry);
if (fn_def_node)
g->fn_defs.append(fn_table_entry);
if (import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) {
if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {
g->main_fn = fn_table_entry;
if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) {
TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
if (actual_return_type != err_void) {
add_node_error(g, fn_proto->return_type,
buf_sprintf("expected return type of main to be '%%void', instead is '%s'",
buf_ptr(&actual_return_type->name)));
}
for (size_t i = 0; i < fn_proto->params.length; i += 1) {
AstNode *param_node = fn_proto->params.at(i);
assert(param_node->type == NodeTypeParamDecl);
if (buf_len(param_node->data.param_decl.name) == 0) {
add_node_error(g, param_node, buf_sprintf("missing parameter name"));
}
} else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
g->panic_fn = fn_table_entry;
typecheck_panic_fn(g);
}
} else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
g->panic_fn = fn_table_entry;
typecheck_panic_fn(g);
}
}
Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope);
if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) {
tld_fn->base.resolution = TldResolutionInvalid;
return;
}
if (!fn_table_entry->type_entry->data.fn.is_generic) {
g->fn_protos.append(fn_table_entry);
if (fn_def_node)
g->fn_defs.append(fn_table_entry);
if (import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) {
if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {
g->main_fn = fn_table_entry;
if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) {
TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
if (actual_return_type != err_void) {
add_node_error(g, fn_proto->return_type,
buf_sprintf("expected return type of main to be '%%void', instead is '%s'",
buf_ptr(&actual_return_type->name)));
}
}
} else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
g->panic_fn = fn_table_entry;
typecheck_panic_fn(g);
}
} else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
g->panic_fn = fn_table_entry;
typecheck_panic_fn(g);
}
}
}
} else if (source_node->type == NodeTypeTestDecl) {
FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, false);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
tld_fn->fn_entry = fn_table_entry;
fn_table_entry->proto_node = source_node;
fn_table_entry->fndef_scope = create_fndef_scope(source_node, tld_fn->base.parent_scope, fn_table_entry);
fn_table_entry->type_entry = get_test_fn_type(g);
fn_table_entry->body_node = source_node->data.test_decl.body;
fn_table_entry->is_test = true;
g->test_fn_count += 1;
g->fn_protos.append(fn_table_entry);
g->fn_defs.append(fn_table_entry);
} else {
zig_unreachable();
}
}
static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport ||
if (tld->visib_mod == VisibModExport ||
(buf_eql_str(tld->name, "panic") &&
(decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)))
(decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)) ||
(tld->id == TldIdVar && g->is_test_build))
{
g->resolve_queue.append(tld);
}
@ -1882,6 +1913,27 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
}
}
static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
assert(node->type == NodeTypeTestDecl);
if (node->data.test_decl.visib_mod != VisibModPrivate) {
add_node_error(g, node, buf_sprintf("tests require no visibility modifier"));
}
if (!g->is_test_build)
return;
ImportTableEntry *import = get_scope_import(&decls_scope->base);
if (import->package != g->root_package)
return;
Buf *test_name = node->data.test_decl.name;
TldFn *tld_fn = allocate<TldFn>(1);
init_tld(&tld_fn->base, TldIdFn, test_name, VisibModPrivate, node, &decls_scope->base);
g->resolve_queue.append(&tld_fn->base);
}
static void preview_error_value_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeErrorValueDecl);
@ -1975,6 +2027,9 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
// error value declarations do not depend on other top level decls
preview_error_value_decl(g, node);
break;
case NodeTypeTestDecl:
preview_test_decl(g, node, decls_scope);
break;
case NodeTypeContainerDecl:
case NodeTypeParamDecl:
case NodeTypeFnDecl:
@ -2650,7 +2705,8 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
fn_table_entry->anal_state = FnAnalStateProbing;
AstNode *return_type_node = fn_table_entry->proto_node->data.fn_proto.return_type;
AstNode *return_type_node = (fn_table_entry->proto_node != nullptr) ?
fn_table_entry->proto_node->data.fn_proto.return_type : fn_table_entry->fndef_scope->base.source_node;
assert(fn_table_entry->fndef_scope);
if (!fn_table_entry->child_scope)
@ -2674,7 +2730,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
}
if (g->verbose) {
fprintf(stderr, "\n");
ast_render(stderr, fn_table_entry->fn_def_node, 4);
ast_render(stderr, fn_table_entry->body_node, 4);
fprintf(stderr, "\n{ // (IR)\n");
ir_print(stderr, &fn_table_entry->ir_executable, 4);
fprintf(stderr, "}\n");

View File

@ -170,6 +170,8 @@ static const char *node_type_str(NodeType node_type) {
return "TypeDecl";
case NodeTypeErrorValueDecl:
return "ErrorValueDecl";
case NodeTypeTestDecl:
return "TestDecl";
case NodeTypeNumberLiteral:
return "NumberLiteral";
case NodeTypeStringLiteral:
@ -915,6 +917,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeErrorValueDecl:
case NodeTypeTestDecl:
case NodeTypeStructField:
case NodeTypeUse:
zig_panic("TODO more ast rendering");

View File

@ -138,10 +138,6 @@ void codegen_set_verbose(CodeGen *g, bool verbose) {
g->verbose = verbose;
}
void codegen_set_check_unused(CodeGen *g, bool check_unused) {
g->check_unused = check_unused;
}
void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) {
g->each_lib_rpath = each_lib_rpath;
}
@ -323,7 +319,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
return get_di_scope(g, scope->parent);
unsigned line_number = fn_table_entry->proto_node->line + 1;
unsigned scope_line = line_number;
bool is_definition = fn_table_entry->fn_def_node != nullptr;
bool is_definition = fn_table_entry->body_node != nullptr;
unsigned flags = 0;
bool is_optimized = g->is_release_build;
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
@ -2492,7 +2488,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdToPtrType:
case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetFnTest:
case IrInstructionIdSetFnVisible:
case IrInstructionIdSetDebugSafety:
case IrInstructionIdArrayType:
@ -4054,7 +4049,6 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2);
create_builtin_fn(g, BuiltinFnIdUnreachable, "unreachable", 0);
create_builtin_fn(g, BuiltinFnIdSetFnTest, "setFnTest", 1);
create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);

View File

@ -19,7 +19,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_is_release(CodeGen *codegen, bool is_release);
void codegen_set_is_test(CodeGen *codegen, bool is_test);
void codegen_set_check_unused(CodeGen *codegen, bool check_unused);
void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
void codegen_set_is_static(CodeGen *codegen, bool is_static);

View File

@ -282,10 +282,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *)
return IrInstructionIdPtrTypeChild;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
return IrInstructionIdSetFnTest;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) {
return IrInstructionIdSetFnVisible;
}
@ -1147,17 +1143,6 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN
return &instruction->base;
}
static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *fn_value)
{
IrInstructionSetFnTest *instruction = ir_build_instruction<IrInstructionSetFnTest>(irb, scope, source_node);
instruction->fn_value = fn_value;
ir_ref_instruction(fn_value, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn_value,
IrInstruction *is_visible)
{
@ -2287,13 +2272,6 @@ static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeCh
}
}
static IrInstruction *ir_instruction_setfntest_get_dep(IrInstructionSetFnTest *instruction, size_t index) {
switch (index) {
case 0: return instruction->fn_value;
default: return nullptr;
}
}
static IrInstruction *ir_instruction_setfnvisible_get_dep(IrInstructionSetFnVisible *instruction, size_t index) {
switch (index) {
case 0: return instruction->fn_value;
@ -2807,8 +2785,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index);
case IrInstructionIdPtrTypeChild:
return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index);
case IrInstructionIdSetFnTest:
return ir_instruction_setfntest_get_dep((IrInstructionSetFnTest *) instruction, index);
case IrInstructionIdSetFnVisible:
return ir_instruction_setfnvisible_get_dep((IrInstructionSetFnVisible *) instruction, index);
case IrInstructionIdSetDebugSafety:
@ -3810,15 +3786,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg;
return ir_build_typeof(irb, scope, node, arg);
}
case BuiltinFnIdSetFnTest:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
return ir_build_set_fn_test(irb, scope, node, arg0_value);
}
case BuiltinFnIdSetFnVisible:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@ -5543,6 +5510,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
zig_panic("TODO IR gen NodeTypeErrorValueDecl");
case NodeTypeTypeDecl:
zig_panic("TODO IR gen NodeTypeTypeDecl");
case NodeTypeTestDecl:
zig_panic("TODO IR gen NodeTypeTestDecl");
}
zig_unreachable();
}
@ -5633,10 +5602,7 @@ bool ir_gen_fn(CodeGen *codegen, FnTableEntry *fn_entry) {
assert(fn_entry);
IrExecutable *ir_executable = &fn_entry->ir_executable;
AstNode *fn_def_node = fn_entry->fn_def_node;
assert(fn_def_node->type == NodeTypeFnDef);
AstNode *body_node = fn_def_node->data.fn_def.body;
AstNode *body_node = fn_entry->body_node;
assert(fn_entry->child_scope);
@ -8180,7 +8146,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
result = entry->value;
} else {
// Analyze the fn body block like any other constant expression.
AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body;
AstNode *body_node = fn_entry->body_node;
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);
@ -8219,7 +8185,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
FnTableEntry *impl_fn = create_fn(fn_proto_node);
impl_fn->param_source_nodes = allocate<AstNode *>(new_fn_arg_count);
buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn);
impl_fn->fndef_scope = create_fndef_scope(impl_fn->body_node, parent_scope, impl_fn);
impl_fn->child_scope = &impl_fn->fndef_scope->base;
FnTypeId inst_fn_type_id = {0};
init_fn_type_id(&inst_fn_type_id, fn_proto_node, new_fn_arg_count);
@ -9582,24 +9548,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_type;
}
static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
IrInstructionSetFnTest *set_fn_test_instruction)
{
IrInstruction *fn_value = set_fn_test_instruction->fn_value->other;
FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value);
if (!fn_entry)
return ira->codegen->builtin_types.entry_invalid;
if (!fn_entry->is_test) {
fn_entry->is_test = true;
ira->codegen->test_fn_count += 1;
}
ir_build_const_from(ira, &set_fn_test_instruction->base);
return ira->codegen->builtin_types.entry_void;
}
static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
IrInstructionSetFnVisible *set_fn_visible_instruction)
{
@ -12253,8 +12201,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
case IrInstructionIdPtrTypeChild:
return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
case IrInstructionIdSetFnTest:
return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
case IrInstructionIdSetFnVisible:
return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction);
case IrInstructionIdSetGlobalAlign:
@ -12469,7 +12415,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCall:
case IrInstructionIdReturn:
case IrInstructionIdUnreachable:
case IrInstructionIdSetFnTest:
case IrInstructionIdSetFnVisible:
case IrInstructionIdSetDebugSafety:
case IrInstructionIdImport:

View File

@ -339,12 +339,6 @@ static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *ins
fprintf(irp->f, ")");
}
static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instruction) {
fprintf(irp->f, "@setFnTest(");
ir_print_other_instruction(irp, instruction->fn_value);
fprintf(irp->f, ")");
}
static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) {
fprintf(irp->f, "@setFnVisible(");
ir_print_other_instruction(irp, instruction->fn_value);
@ -932,9 +926,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdEnumFieldPtr:
ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
break;
case IrInstructionIdSetFnTest:
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
break;
case IrInstructionIdSetFnVisible:
ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction);
break;

View File

@ -56,7 +56,6 @@ static int usage(const char *arg0) {
" -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
" -mios-version-min [ver] (darwin only) set iOS deployment target\n"
" -framework [name] (darwin only) link against framework\n"
" --check-unused perform semantic analysis on unused declarations\n"
" --linker-script [path] use a custom linker script\n"
" -rpath [path] add directory to the runtime library search path\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
@ -141,7 +140,6 @@ int main(int argc, char **argv) {
bool rdynamic = false;
const char *mmacosx_version_min = nullptr;
const char *mios_version_min = nullptr;
bool check_unused = false;
const char *linker_script = nullptr;
ZigList<const char *> rpath_list = {0};
bool each_lib_rpath = false;
@ -166,8 +164,6 @@ int main(int argc, char **argv) {
municode = true;
} else if (strcmp(arg, "-rdynamic") == 0) {
rdynamic = true;
} else if (strcmp(arg, "--check-unused") == 0) {
check_unused = true;
} else if (strcmp(arg, "--each-lib-rpath") == 0) {
each_lib_rpath = true;
} else if (arg[1] == 'L' && arg[2] != 0) {
@ -354,7 +350,6 @@ int main(int argc, char **argv) {
codegen_set_is_release(g, is_release_build);
codegen_set_is_test(g, cmd == CmdTest);
codegen_set_linker_script(g, linker_script);
codegen_set_check_unused(g, check_unused);
if (each_lib_rpath)
codegen_set_each_lib_rpath(g, each_lib_rpath);

View File

@ -2417,6 +2417,27 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index
return node;
}
/*
TestDecl = "test" String Block
*/
static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
Token *first_token = &pc->tokens->at(*token_index);
if (first_token->id != TokenIdKeywordTest) {
return nullptr;
}
*token_index += 1;
Token *name_tok = ast_eat_token(pc, token_index, TokenIdStringLiteral);
AstNode *node = ast_create_node(pc, NodeTypeTestDecl, first_token);
node->data.test_decl.visib_mod = visib_mod;
node->data.test_decl.name = token_buf(name_tok);
node->data.test_decl.body = ast_parse_block(pc, token_index, true);
return node;
}
/*
TypeDecl = "type" "Symbol" "=" TypeExpr ";"
*/
@ -2443,7 +2464,7 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, Visib
}
/*
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)
*/
static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
@ -2491,6 +2512,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
continue;
}
AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index, visib_mod);
if (test_decl_node) {
top_level_decls->append(test_decl_node);
continue;
}
AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod);
if (type_decl_node) {
top_level_decls->append(type_decl_node);
@ -2585,6 +2612,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeErrorValueDecl:
// none
break;
case NodeTypeTestDecl:
visit_field(&node->data.test_decl.body, visit, context);
break;
case NodeTypeBinOpExpr:
visit_field(&node->data.bin_op_expr.op1, visit, context);
visit_field(&node->data.bin_op_expr.op2, visit, context);

View File

@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"return", TokenIdKeywordReturn},
{"struct", TokenIdKeywordStruct},
{"switch", TokenIdKeywordSwitch},
{"test", TokenIdKeywordTest},
{"this", TokenIdKeywordThis},
{"true", TokenIdKeywordTrue},
{"try", TokenIdKeywordTry},
@ -1508,6 +1509,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordReturn: return "return";
case TokenIdKeywordStruct: return "struct";
case TokenIdKeywordSwitch: return "switch";
case TokenIdKeywordTest: return "test";
case TokenIdKeywordThis: return "this";
case TokenIdKeywordTrue: return "true";
case TokenIdKeywordTry: return "try";

View File

@ -74,6 +74,7 @@ enum TokenId {
TokenIdKeywordReturn,
TokenIdKeywordStruct,
TokenIdKeywordSwitch,
TokenIdKeywordTest,
TokenIdKeywordThis,
TokenIdKeywordTrue,
TokenIdKeywordTry,

View File

@ -322,9 +322,7 @@ export fn __udivsi3(n: su_int, d: su_int) -> su_int {
return q;
}
fn test_umoddi3() {
@setFnTest(this);
test "test_umoddi3" {
test_one_umoddi3(0, 1, 0);
test_one_umoddi3(2, 1, 0);
test_one_umoddi3(0x8000000000000000, 1, 0x0);
@ -337,9 +335,7 @@ fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
assert(r == expected_r);
}
fn test_udivmoddi4() {
@setFnTest(this);
test "test_udivmoddi4" {
const cases = [][4]du_int {
[]du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
[]du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
@ -367,9 +363,7 @@ fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_
assert(r == expected_r);
}
fn test_udivsi3() {
@setFnTest(this);
test "test_udivsi3" {
const cases = [][3]su_int {
[]su_int{0x00000000, 0x00000001, 0x00000000},
[]su_int{0x00000000, 0x00000002, 0x00000000},

View File

@ -140,9 +140,7 @@ pub const Buffer0 = struct {
}
};
fn testSimpleBuffer0() {
@setFnTest(this);
test "simple Buffer0" {
var buf = %%Buffer0.initEmpty(&debug.global_allocator);
assert(buf.len() == 0);
%%buf.appendCStr(c"hello");
@ -162,9 +160,7 @@ fn testSimpleBuffer0() {
assert(buf.startsWithOther(&buf2));
}
fn testCStrFns() {
@setFnTest(this);
test "cstr fns" {
comptime testCStrFnsImpl();
testCStrFnsImpl();
}

View File

@ -291,9 +291,7 @@ fn digitToChar(digit: u8, uppercase: bool) -> u8 {
};
}
fn testBufPrintInt() {
@setFnTest(this);
test "testBufPrintInt" {
var buffer: [max_int_digits]u8 = undefined;
const buf = buffer[0...];
assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
@ -315,9 +313,7 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: u
return buf[0...formatIntBuf(buf, value, base, uppercase, width)];
}
fn testParseU64DigitTooBig() {
@setFnTest(this);
test "testParseU64DigitTooBig" {
parseUnsigned(u64, "123a", 10) %% |err| {
if (err == error.InvalidChar) return;
@unreachable();
@ -325,9 +321,7 @@ fn testParseU64DigitTooBig() {
@unreachable();
}
fn testParseUnsignedComptime() {
@setFnTest(this);
test "testParseUnsignedComptime" {
comptime {
assert(%%parseUnsigned(usize, "2", 10) == 2);
}

View File

@ -219,9 +219,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
}
}
fn basicHashMapTest() {
@setFnTest(this);
test "basicHashMapTest" {
var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
map.init(&debug.global_allocator);
defer map.deinit();

View File

@ -64,9 +64,7 @@ pub fn List(comptime T: type) -> type{
}
}
fn basicListTest() {
@setFnTest(this);
test "basicListTest" {
var list = List(i32).init(&debug.global_allocator);
defer list.deinit();

View File

@ -68,9 +68,7 @@ fn getReturnTypeForAbs(comptime T: type) -> type {
}
}
fn testMath() {
@setFnTest(this);
test "testMath" {
testMathImpl();
comptime testMathImpl();
}

View File

@ -117,17 +117,13 @@ pub fn writeInt(buf: []u8, value: var, big_endian: bool) {
assert(bits == 0);
}
fn testStringEquality() {
@setFnTest(this);
test "testStringEquality" {
assert(eql(u8, "abcd", "abcd"));
assert(!eql(u8, "abcdef", "abZdef"));
assert(!eql(u8, "abcdefg", "abcdef"));
}
fn testReadInt() {
@setFnTest(this);
test "testReadInt" {
testReadIntImpl();
comptime testReadIntImpl();
}
@ -149,9 +145,7 @@ fn testReadIntImpl() {
}
}
fn testWriteInt() {
@setFnTest(this);
test "testWriteInt" {
testWriteIntImpl();
comptime testWriteIntImpl();
}

View File

@ -158,9 +158,7 @@ fn MersenneTwister(
}
}
fn testFloat32() {
@setFnTest(this);
test "testFloat32" {
var r: Rand = undefined;
r.init(42);
@ -171,9 +169,7 @@ fn testFloat32() {
}}
}
fn testMT19937_64() {
@setFnTest(this);
test "testMT19937_64" {
var rng: MT19937_64 = undefined;
rng.init(rand_test.mt64_seed);
for (rand_test.mt64_data) |value| {
@ -181,9 +177,7 @@ fn testMT19937_64() {
}
}
fn testMT19937_32() {
@setFnTest(this);
test "testMT19937_32" {
var rng: MT19937_32 = undefined;
rng.init(rand_test.mt32_seed);
for (rand_test.mt32_data) |value| {

View File

@ -58,9 +58,7 @@ fn reverse(was: Cmp) -> Cmp {
// ---------------------------------------
// tests
fn testSort() {
@setFnTest(this);
test "testSort" {
const u8cases = [][]const []const u8 {
[][]const u8{"", ""},
[][]const u8{"a", "a"},
@ -96,9 +94,7 @@ fn testSort() {
}
}
fn testSortDesc() {
@setFnTest(this);
test "testSortDesc" {
const rev_cases = [][]const []const i32 {
[][]const i32{[]i32{}, []i32{}},
[][]const i32{[]i32{1}, []i32{1}},

View File

@ -1,9 +1,7 @@
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
fn arrays() {
@setFnTest(this);
test "arrays" {
var array : [5]u32 = undefined;
var i : u32 = 0;
@ -27,9 +25,7 @@ fn getArrayLen(a: []const u32) -> usize {
a.len
}
fn voidArrays() {
@setFnTest(this);
test "voidArrays" {
var array: [4]void = undefined;
array[0] = void{};
array[1] = array[2];
@ -37,18 +33,14 @@ fn voidArrays() {
assert(array.len == 4);
}
fn arrayLiteral() {
@setFnTest(this);
test "arrayLiteral" {
const hex_mult = []u16{4096, 256, 16, 1};
assert(hex_mult.len == 4);
assert(hex_mult[1] == 256);
}
fn arrayDotLenConstExpr() {
@setFnTest(this);
test "arrayDotLenConstExpr" {
assert(comptime {some_array.len == 4});
}
@ -58,9 +50,7 @@ const ArrayDotLenConstExpr = struct {
const some_array = []u8 {0, 1, 2, 3};
fn nestedArrays() {
@setFnTest(this);
test "nestedArrays" {
const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"};
for (array_of_strings) |s, i| {
if (i == 0) assert(mem.eql(u8, s, "hello"));
@ -79,9 +69,7 @@ const Sub = struct {
const Str = struct {
a: []Sub,
};
fn setGlobalVarArrayViaSliceEmbeddedInStruct() {
@setFnTest(this);
test "setGlobalVarArrayViaSliceEmbeddedInStruct" {
var s = Str { .a = s_array[0...]};
s.a[0].b = 1;

View File

@ -1,16 +1,12 @@
const assert = @import("std").debug.assert;
fn cmpxchg() {
@setFnTest(this);
test "cmpxchg" {
var x: i32 = 1234;
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
assert(x == 5678);
}
fn fence() {
@setFnTest(this);
test "fence" {
var x: i32 = 1234;
@fence(AtomicOrder.SeqCst);
x = 5678;

View File

@ -1,15 +1,11 @@
const assert = @import("std").debug.assert;
fn boolLiterals() {
@setFnTest(this);
test "boolLiterals" {
assert(true);
assert(!false);
}
fn castBoolToInt() {
@setFnTest(this);
test "castBoolToInt" {
const t = true;
const f = false;
assert(i32(t) == i32(1));
@ -22,18 +18,14 @@ fn nonConstCastBoolToInt(t: bool, f: bool) {
assert(i32(f) == i32(0));
}
fn boolCmp() {
@setFnTest(this);
test "boolCmp" {
assert(testBoolCmp(true, false) == false);
}
fn testBoolCmp(a: bool, b: bool) -> bool {
a == b
}
fn shortCircuitAndOr() {
@setFnTest(this);
test "shortCircuitAndOr" {
var a = true;
a &&= false;
assert(!a);
@ -49,9 +41,7 @@ const global_f = false;
const global_t = true;
const not_global_f = !global_f;
const not_global_t = !global_t;
fn compileTimeBoolnot() {
@setFnTest(this);
test "compileTimeBoolnot" {
assert(not_global_f);
assert(!not_global_t);
}

View File

@ -1,24 +1,18 @@
const assert = @import("std").debug.assert;
fn intToPtrCast() {
@setFnTest(this);
test "intToPtrCast" {
const x = isize(13);
const y = (&u8)(x);
const z = usize(y);
assert(z == 13);
}
fn numLitIntToPtrCast() {
@setFnTest(this);
test "numLitIntToPtrCast" {
const vga_mem = (&u16)(0xB8000);
assert(usize(vga_mem) == 0xB8000);
}
fn pointerReinterpretConstFloatToInt() {
@setFnTest(this);
test "pointerReinterpretConstFloatToInt" {
const float: f64 = 5.99999999999994648725e-01;
const float_ptr = &float;
const int_ptr = (&i32)(float_ptr);

View File

@ -2,9 +2,7 @@ const assert = @import("std").debug.assert;
var argv: &const &const u8 = undefined;
fn constSliceChild() {
@setFnTest(this);
test "constSliceChild" {
const strs = ([]&const u8) {
c"one",
c"two",

View File

@ -21,9 +21,7 @@ fn runSomeMaybeDefers(x: bool) -> ?bool {
return if (x) x else null;
}
fn mixingNormalAndErrorDefers() {
@setFnTest(this);
test "mixingNormalAndErrorDefers" {
assert(%%runSomeErrorDefers(true));
assert(result[0] == 'c');
assert(result[1] == 'a');
@ -38,9 +36,7 @@ fn mixingNormalAndErrorDefers() {
assert(result[2] == 'a');
}
fn mixingNormalAndMaybeDefers() {
@setFnTest(this);
test "mixingNormalAndMaybeDefers" {
assert(??runSomeMaybeDefers(true));
assert(result[0] == 'c');
assert(result[1] == 'a');

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn enumType() {
@setFnTest(this);
test "enumType" {
const foo1 = Foo.One {13};
const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }};
const bar = Bar.B;
@ -15,9 +13,7 @@ fn enumType() {
assert(@sizeOf(Bar) == 1);
}
fn enumAsReturnValue () {
@setFnTest(this);
test "enumAsReturnValue" {
switch (returnAnInt(13)) {
Foo.One => |value| assert(value == 13),
else => @unreachable(),
@ -45,9 +41,7 @@ fn returnAnInt(x: i32) -> Foo {
}
fn constantEnumWithPayload() {
@setFnTest(this);
test "constantEnumWithPayload" {
var empty = AnEnumWithPayload.Empty;
var full = AnEnumWithPayload.Full {13};
shouldBeEmpty(empty);
@ -83,9 +77,7 @@ const Number = enum {
Four,
};
fn enumToInt() {
@setFnTest(this);
test "enumToInt" {
shouldEqual(Number.Zero, 0);
shouldEqual(Number.One, 1);
shouldEqual(Number.Two, 2);
@ -98,9 +90,7 @@ fn shouldEqual(n: Number, expected: usize) {
}
fn intToEnum() {
@setFnTest(this);
test "intToEnum" {
testIntToEnumEval(3);
}
fn testIntToEnumEval(x: i32) {

View File

@ -14,9 +14,7 @@ const ET = enum {
}
};
fn enumWithMembers() {
@setFnTest(this);
test "enumWithMembers" {
const a = ET.SINT { -42 };
const b = ET.UINT { 42 };
var buf: [20]u8 = undefined;

View File

@ -15,9 +15,7 @@ pub fn baz() -> %i32 {
return y + 1;
}
fn errorWrapping() {
@setFnTest(this);
test "errorWrapping" {
assert(%%baz() == 15);
}
@ -26,8 +24,7 @@ fn gimmeItBroke() -> []const u8 {
@errorName(error.ItBroke)
}
fn errorName() {
@setFnTest(this);
test "errorName" {
assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
}
@ -35,9 +32,7 @@ error AnError;
error ALongerErrorName;
fn errorValues() {
@setFnTest(this);
test "errorValues" {
const a = i32(error.err1);
const b = i32(error.err2);
assert(a != b);
@ -46,9 +41,7 @@ error err1;
error err2;
fn redefinitionOfErrorValuesAllowed() {
@setFnTest(this);
test "redefinitionOfErrorValuesAllowed" {
shouldBeNotEqual(error.AnError, error.SecondError);
}
error AnError;
@ -59,9 +52,7 @@ fn shouldBeNotEqual(a: error, b: error) {
}
fn errBinaryOperator() {
@setFnTest(this);
test "errBinaryOperator" {
const a = errBinaryOperatorG(true) %% 3;
const b = errBinaryOperatorG(false) %% 3;
assert(a == 3);
@ -77,18 +68,14 @@ fn errBinaryOperatorG(x: bool) -> %isize {
}
fn unwrapSimpleValueFromError() {
@setFnTest(this);
test "unwrapSimpleValueFromError" {
const i = %%unwrapSimpleValueFromErrorDo();
assert(i == 13);
}
fn unwrapSimpleValueFromErrorDo() -> %isize { 13 }
fn errReturnInAssignment() {
@setFnTest(this);
test "errReturnInAssignment" {
%%doErrReturnInAssignment();
}

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn compileTimeRecursion() {
@setFnTest(this);
test "compileTimeRecursion" {
assert(some_data.len == 21);
}
var some_data: [usize(fibonacci(7))]u8 = undefined;
@ -17,14 +15,11 @@ fn unwrapAndAddOne(blah: ?i32) -> i32 {
return ??blah + 1;
}
const should_be_1235 = unwrapAndAddOne(1234);
fn testStaticAddOne() {
@setFnTest(this);
test "testStaticAddOne" {
assert(should_be_1235 == 1235);
}
fn inlinedLoop() {
@setFnTest(this);
test "inlinedLoop" {
comptime var i = 0;
comptime var sum = 0;
inline while (i <= 5; i += 1)
@ -38,25 +33,20 @@ fn gimme1or2(comptime a: bool) -> i32 {
comptime var z: i32 = if (a) x else y;
return z;
}
fn inlineVariableGetsResultOfConstIf() {
@setFnTest(this);
test "inlineVariableGetsResultOfConstIf" {
assert(gimme1or2(true) == 1);
assert(gimme1or2(false) == 2);
}
fn staticFunctionEvaluation() {
@setFnTest(this);
test "staticFunctionEvaluation" {
assert(statically_added_number == 3);
}
const statically_added_number = staticAdd(1, 2);
fn staticAdd(a: i32, b: i32) -> i32 { a + b }
fn constExprEvalOnSingleExprBlocks() {
@setFnTest(this);
test "constExprEvalOnSingleExprBlocks" {
assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
}
@ -75,9 +65,7 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 {
fn staticallyInitalizedList() {
@setFnTest(this);
test "staticallyInitalizedList" {
assert(static_point_list[0].x == 1);
assert(static_point_list[0].y == 2);
assert(static_point_list[1].x == 3);
@ -96,9 +84,7 @@ fn makePoint(x: i32, y: i32) -> Point {
}
fn staticEvalListInit() {
@setFnTest(this);
test "staticEvalListInit" {
assert(static_vec3.data[2] == 1.0);
assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
}
@ -113,18 +99,14 @@ pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
}
fn constantExpressions() {
@setFnTest(this);
test "constantExpressions" {
var array : [array_size]u8 = undefined;
assert(@sizeOf(@typeOf(array)) == 20);
}
const array_size : u8 = 20;
fn constantStructWithNegation() {
@setFnTest(this);
test "constantStructWithNegation" {
assert(vertices[0].x == -0.6);
}
const Vertex = struct {
@ -141,9 +123,7 @@ const vertices = []Vertex {
};
fn staticallyInitalizedStruct() {
@setFnTest(this);
test "staticallyInitalizedStruct" {
st_init_str_foo.x += 1;
assert(st_init_str_foo.x == 14);
}
@ -154,18 +134,14 @@ const StInitStrFoo = struct {
var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };
fn staticallyInitializedArrayLiteral() {
@setFnTest(this);
test "staticallyInitializedArrayLiteral" {
const y : [4]u8 = st_init_arr_lit_x;
assert(y[3] == 4);
}
const st_init_arr_lit_x = []u8{1,2,3,4};
fn constSlice() {
@setFnTest(this);
test "constSlice" {
comptime {
const a = "1234567890";
assert(a.len == 10);
@ -175,9 +151,7 @@ fn constSlice() {
}
}
fn tryToTrickEvalWithRuntimeIf() {
@setFnTest(this);
test "tryToTrickEvalWithRuntimeIf" {
assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
}
@ -203,9 +177,7 @@ fn max(comptime T: type, a: T, b: T) -> T {
fn letsTryToCompareBools(a: bool, b: bool) -> bool {
max(bool, a, b)
}
fn inlinedBlockAndRuntimeBlockPhi() {
@setFnTest(this);
test "inlinedBlockAndRuntimeBlockPhi" {
assert(letsTryToCompareBools(true, true));
assert(letsTryToCompareBools(true, false));
assert(letsTryToCompareBools(false, true));
@ -244,17 +216,13 @@ fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 {
return result;
}
fn comptimeIterateOverFnPtrList() {
@setFnTest(this);
test "comptimeIterateOverFnPtrList" {
assert(performFn('t', 1) == 6);
assert(performFn('o', 0) == 1);
assert(performFn('w', 99) == 99);
}
fn evalSetDebugSafetyAtCompileTime() {
@setFnTest(this);
test "evalSetDebugSafetyAtCompileTime" {
const result = comptime fnWithSetDebugSafety();
assert(result == 1234);
}
@ -278,17 +246,13 @@ var simple_struct = SimpleStruct{ .field = 1234, };
const bound_fn = simple_struct.method;
fn callMethodOnBoundFnReferringToVarInstance() {
@setFnTest(this);
test "callMethodOnBoundFnReferringToVarInstance" {
assert(bound_fn() == 1237);
}
fn ptrToLocalArrayArgumentAtComptime() {
@setFnTest(this);
test "ptrToLocalArrayArgumentAtComptime" {
comptime {
var bytes: [10]u8 = undefined;
modifySomeBytes(bytes[0...]);

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn params() {
@setFnTest(this);
test "params" {
assert(testParamsAdd(22, 11) == 33);
}
fn testParamsAdd(a: i32, b: i32) -> i32 {
@ -10,9 +8,7 @@ fn testParamsAdd(a: i32, b: i32) -> i32 {
}
fn localVariables() {
@setFnTest(this);
test "localVariables" {
testLocVars(2);
}
fn testLocVars(b: i32) {
@ -21,9 +17,7 @@ fn testLocVars(b: i32) {
}
fn voidParameters() {
@setFnTest(this);
test "voidParameters" {
voidFun(1, void{}, 2, {});
}
fn voidFun(a: i32, b: void, c: i32, d: void) {
@ -34,9 +28,7 @@ fn voidFun(a: i32, b: void, c: i32, d: void) {
}
fn mutableLocalVariables() {
@setFnTest(this);
test "mutableLocalVariables" {
var zero : i32 = 0;
assert(zero == 0);
@ -47,9 +39,7 @@ fn mutableLocalVariables() {
assert(i == 3);
}
fn separateBlockScopes() {
@setFnTest(this);
test "separateBlockScopes" {
{
const no_conflict : i32 = 5;
assert(no_conflict == 5);
@ -62,22 +52,21 @@ fn separateBlockScopes() {
assert(c == 10);
}
fn callFnWithEmptyString() {
@setFnTest(this);
test "callFnWithEmptyString" {
acceptsString("");
}
fn acceptsString(foo: []u8) { }
fn @"weird function name"() {
@setFnTest(this);
fn @"weird function name"() -> i32 {
return 1234;
}
test "weird function name" {
assert(@"weird function name"() == 1234);
}
fn implicitCastFnUnreachableReturn() {
@setFnTest(this);
test "implicitCastFnUnreachableReturn" {
wantsFnWithVoid(fnWithUnreachable);
}
@ -88,9 +77,7 @@ fn fnWithUnreachable() -> unreachable {
}
fn functionPointers() {
@setFnTest(this);
test "functionPointers" {
const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, };
for (fns) |f, i| {
assert(f() == u32(i) + 5);

View File

@ -2,9 +2,7 @@ const std = @import("std");
const assert = std.debug.assert;
const mem = std.mem;
fn continueInForLoop() {
@setFnTest(this);
test "continueInForLoop" {
const array = []i32 {1, 2, 3, 4, 5};
var sum : i32 = 0;
for (array) |x| {
@ -17,9 +15,7 @@ fn continueInForLoop() {
if (sum != 6) @unreachable()
}
fn forLoopWithPointerElemVar() {
@setFnTest(this);
test "forLoopWithPointerElemVar" {
const source = "abcdefg";
var target: [source.len]u8 = undefined;
mem.copy(u8, target[0...], source);
@ -32,9 +28,7 @@ fn mangleString(s: []u8) {
}
}
fn basicForLoop() {
@setFnTest(this);
test "basicForLoop" {
const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 };
var buffer: [expected_result.len]u8 = undefined;

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn simpleGenericFn() {
@setFnTest(this);
test "simpleGenericFn" {
assert(max(i32, 3, -1) == 3);
assert(max(f32, 0.123, 0.456) == 0.456);
assert(add(2, 3) == 5);
@ -17,8 +15,7 @@ fn add(comptime a: i32, b: i32) -> i32 {
}
const the_max = max(u32, 1234, 5678);
fn compileTimeGenericEval() {
@setFnTest(this);
test "compileTimeGenericEval" {
assert(the_max == 5678);
}
@ -34,18 +31,14 @@ fn sameButWithFloats(a: f64, b: f64) -> f64 {
max(f64, a, b)
}
fn fnWithInlineArgs() {
@setFnTest(this);
test "fnWithInlineArgs" {
assert(gimmeTheBigOne(1234, 5678) == 5678);
assert(shouldCallSameInstance(34, 12) == 34);
assert(sameButWithFloats(0.43, 0.49) == 0.49);
}
fn varParams() {
@setFnTest(this);
test "varParams" {
assert(max_i32(12, 34) == 34);
assert(max_f64(1.2, 3.4) == 3.4);
}
@ -79,9 +72,7 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
}
}
fn functionWithReturnTypeType() {
@setFnTest(this);
test "functionWithReturnTypeType" {
var list: List(i32) = undefined;
var list2: List(i32) = undefined;
list.length = 10;
@ -91,9 +82,7 @@ fn functionWithReturnTypeType() {
}
fn genericStruct() {
@setFnTest(this);
test "genericStruct" {
var a1 = GenNode(i32) {.value = 13, .next = null,};
var b1 = GenNode(bool) {.value = true, .next = null,};
assert(a1.value == 13);
@ -108,9 +97,7 @@ fn GenNode(comptime T: type) -> type {
}
}
fn constDeclsInStruct() {
@setFnTest(this);
test "constDeclsInStruct" {
assert(GenericDataThing(3).count_plus_one == 4);
}
fn GenericDataThing(comptime count: isize) -> type {
@ -120,9 +107,7 @@ fn GenericDataThing(comptime count: isize) -> type {
}
fn useGenericParamInGenericParam() {
@setFnTest(this);
test "useGenericParamInGenericParam" {
assert(aGenericFn(i32, 3, 4) == 7);
}
fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T {
@ -130,9 +115,7 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T {
}
fn genericFnWithImplicitCast() {
@setFnTest(this);
test "genericFnWithImplicitCast" {
assert(getFirstByte(u8, []u8 {13}) == 13);
assert(getFirstByte(u16, []u16 {0, 13}) == 0);
}

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn gotoAndLabels() {
@setFnTest(this);
test "gotoAndLabels" {
gotoLoop();
assert(goto_counter == 10);
}
@ -21,9 +19,7 @@ var goto_counter: i32 = 0;
fn gotoLeaveDeferScope() {
@setFnTest(this);
test "gotoLeaveDeferScope" {
testGotoLeaveDeferScope(true);
}
fn testGotoLeaveDeferScope(b: bool) {

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn ifStatements() {
@setFnTest(this);
test "ifStatements" {
shouldBeEqual(1, 1);
firstEqlThird(2, 1, 2);
}
@ -26,9 +24,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) {
}
fn elseIfExpression() {
@setFnTest(this);
test "elseIfExpression" {
assert(elseIfExpressionF(1) == 1);
}
fn elseIfExpressionF(c: u8) -> u8 {

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
const a_namespace = @import("cases/import/a_namespace.zig");
fn callFnViaNamespaceLookup() {
@setFnTest(this);
test "callFnViaNamespaceLookup" {
assert(a_namespace.foo() == 1234);
}

View File

@ -15,9 +15,7 @@ fn getErrInt() -> %i32 { 0 }
error ItBroke;
fn irBlockDeps() {
@setFnTest(this);
test "irBlockDeps" {
assert(%%foo(1) == 0);
assert(%%foo(2) == 0);
}

View File

@ -1,60 +1,46 @@
const assert = @import("std").debug.assert;
fn exactDivision() {
@setFnTest(this);
test "exactDivision" {
assert(divExact(55, 11) == 5);
}
fn divExact(a: u32, b: u32) -> u32 {
@divExact(a, b)
}
fn floatDivision() {
@setFnTest(this);
test "floatDivision" {
assert(fdiv32(12.0, 3.0) == 4.0);
}
fn fdiv32(a: f32, b: f32) -> f32 {
a / b
}
fn overflowIntrinsics() {
@setFnTest(this);
test "overflowIntrinsics" {
var result: u8 = undefined;
assert(@addWithOverflow(u8, 250, 100, &result));
assert(!@addWithOverflow(u8, 100, 150, &result));
assert(result == 250);
}
fn shlWithOverflow() {
@setFnTest(this);
test "shlWithOverflow" {
var result: u16 = undefined;
assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
assert(result == 0b1011111111111100);
}
fn countLeadingZeroes() {
@setFnTest(this);
test "countLeadingZeroes" {
assert(@clz(u8(0b00001010)) == 4);
assert(@clz(u8(0b10001010)) == 0);
assert(@clz(u8(0b00000000)) == 8);
}
fn countTrailingZeroes() {
@setFnTest(this);
test "countTrailingZeroes" {
assert(@ctz(u8(0b10100000)) == 5);
assert(@ctz(u8(0b10001010)) == 1);
assert(@ctz(u8(0b00000000)) == 8);
}
fn modifyOperators() {
@setFnTest(this);
test "modifyOperators" {
var i : i32 = 0;
i += 5; assert(i == 5);
i -= 2; assert(i == 3);
@ -70,9 +56,7 @@ fn modifyOperators() {
i |= 3; assert(i == 7);
}
fn threeExprInARow() {
@setFnTest(this);
testThreeExprInARow(false, true);
test "threeExprInARow" {
}
fn testThreeExprInARow(f: bool, t: bool) {
assertFalse(f || f || f);
@ -94,9 +78,7 @@ fn assertFalse(b: bool) {
}
fn constNumberLiteral() {
@setFnTest(this);
test "constNumberLiteral" {
const one = 1;
const eleven = ten + one;
@ -106,9 +88,7 @@ const ten = 10;
fn unsignedWrapping() {
@setFnTest(this);
test "unsignedWrapping" {
testUnsignedWrappingEval(@maxValue(u32));
}
fn testUnsignedWrappingEval(x: u32) {
@ -118,9 +98,7 @@ fn testUnsignedWrappingEval(x: u32) {
assert(orig == @maxValue(u32));
}
fn signedWrapping() {
@setFnTest(this);
test "signedWrapping" {
testSignedWrappingEval(@maxValue(i32));
}
fn testSignedWrappingEval(x: i32) {
@ -130,9 +108,7 @@ fn testSignedWrappingEval(x: i32) {
assert(max_val == @maxValue(i32));
}
fn negationWrapping() {
@setFnTest(this);
test "negationWrapping" {
testNegationWrappingEval(@minValue(i16));
}
fn testNegationWrappingEval(x: i16) {
@ -141,9 +117,7 @@ fn testNegationWrappingEval(x: i16) {
assert(neg == -32768);
}
fn shlWrapping() {
@setFnTest(this);
test "shlWrapping" {
testShlWrappingEval(@maxValue(u16));
}
fn testShlWrappingEval(x: u16) {
@ -151,9 +125,7 @@ fn testShlWrappingEval(x: u16) {
assert(shifted == 65534);
}
fn unsigned64BitDivision() {
@setFnTest(this);
test "unsigned64BitDivision" {
const result = div(1152921504606846976, 34359738365);
assert(result.quotient == 33554432);
assert(result.remainder == 100663296);
@ -169,9 +141,7 @@ const DivResult = struct {
remainder: u64,
};
fn binaryNot() {
@setFnTest(this);
test "binaryNot" {
assert(comptime {~u16(0b1010101010101010) == 0b0101010101010101});
assert(comptime {~u64(2147483647) == 18446744071562067968});
testBinaryNot(0b1010101010101010);
@ -181,9 +151,7 @@ fn testBinaryNot(x: u16) {
assert(~x == 0b0101010101010101);
}
fn smallIntAddition() {
@setFnTest(this);
test "smallIntAddition" {
var x: @intType(false, 2) = 0;
assert(x == 0);
@ -202,9 +170,7 @@ fn smallIntAddition() {
assert(result == 0);
}
fn testFloatEquality() {
@setFnTest(this);
test "testFloatEquality" {
const x: f64 = 0.012;
const y: f64 = x + 1.0;

View File

@ -5,23 +5,21 @@ const cstr = @import("std").cstr;
// normal comment
/// this is a documentation comment
/// doc comment line 2
fn emptyFunctionWithComments() {
@setFnTest(this);
fn emptyFunctionWithComments() {}
test "emptyFunctionWithComments" {
emptyFunctionWithComments();
}
export fn disabledExternFn() {
@setFnVisible(this, false);
}
fn callDisabledExternFn() {
@setFnTest(this);
test "callDisabledExternFn" {
disabledExternFn();
}
fn intTypeBuiltin() {
@setFnTest(this);
test "intTypeBuiltin" {
assert(@intType(true, 8) == i8);
assert(@intType(true, 16) == i16);
assert(@intType(true, 32) == i32);
@ -55,9 +53,7 @@ const u63 = @intType(false, 63);
const i1 = @intType(true, 1);
const i63 = @intType(true, 63);
fn minValueAndMaxValue() {
@setFnTest(this);
test "minValueAndMaxValue" {
assert(@maxValue(u1) == 1);
assert(@maxValue(u8) == 255);
assert(@maxValue(u16) == 65535);
@ -86,9 +82,7 @@ fn minValueAndMaxValue() {
assert(@minValue(i64) == -9223372036854775808);
}
fn maxValueType() {
@setFnTest(this);
test "maxValueType" {
// If the type of @maxValue(i32) was i32 then this implicit cast to
// u32 would not work. But since the value is a number literal,
// it works fine.
@ -96,8 +90,7 @@ fn maxValueType() {
assert(x == 2147483647);
}
fn shortCircuit() {
@setFnTest(this);
test "shortCircuit" {
testShortCircuit(false, true);
}
@ -128,18 +121,14 @@ fn testShortCircuit(f: bool, t: bool) {
assert(hit_4);
}
fn truncate() {
@setFnTest(this);
test "truncate" {
assert(testTruncate(0x10fd) == 0xfd);
}
fn testTruncate(x: u32) -> u8 {
@truncate(u8, x)
}
fn assignToIfVarPtr() {
@setFnTest(this);
test "assignToIfVarPtr" {
var maybe_bool: ?bool = true;
if (const *b ?= maybe_bool) {
@ -153,27 +142,21 @@ fn first4KeysOfHomeRow() -> []const u8 {
"aoeu"
}
fn ReturnStringFromFunction() {
@setFnTest(this);
test "ReturnStringFromFunction" {
assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
}
const g1 : i32 = 1233 + 1;
var g2 : i32 = 0;
fn globalVariables() {
@setFnTest(this);
test "globalVariables" {
assert(g2 == 0);
g2 = g1;
assert(g2 == 1234);
}
fn memcpyAndMemsetIntrinsics() {
@setFnTest(this);
test "memcpyAndMemsetIntrinsics" {
var foo : [20]u8 = undefined;
var bar : [20]u8 = undefined;
@ -183,16 +166,12 @@ fn memcpyAndMemsetIntrinsics() {
if (bar[11] != 'A') @unreachable();
}
fn builtinStaticEval() {
@setFnTest(this);
test "builtinStaticEval" {
const x : i32 = comptime {1 + 2 + 3};
assert(x == comptime 6);
}
fn slicing() {
@setFnTest(this);
test "slicing" {
var array : [20]i32 = undefined;
array[5] = 1234;
@ -209,9 +188,7 @@ fn slicing() {
}
fn constantEqualFunctionPointers() {
@setFnTest(this);
test "constantEqualFunctionPointers" {
const alias = emptyFn;
assert(comptime {emptyFn == alias});
}
@ -219,27 +196,19 @@ fn constantEqualFunctionPointers() {
fn emptyFn() {}
fn hexEscape() {
@setFnTest(this);
test "hexEscape" {
assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
}
fn stringConcatenation() {
@setFnTest(this);
test "stringConcatenation" {
assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
}
fn arrayMultOperator() {
@setFnTest(this);
test "arrayMultOperator" {
assert(mem.eql(u8, "ab" ** 5, "ababababab"));
}
fn stringEscapes() {
@setFnTest(this);
test "stringEscapes" {
assert(mem.eql(u8, "\"", "\x22"));
assert(mem.eql(u8, "\'", "\x27"));
assert(mem.eql(u8, "\n", "\x0a"));
@ -249,9 +218,7 @@ fn stringEscapes() {
assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
}
fn multilineString() {
@setFnTest(this);
test "multilineString" {
const s1 =
\\one
\\two)
@ -261,9 +228,7 @@ fn multilineString() {
assert(mem.eql(u8, s1, s2));
}
fn multilineCString() {
@setFnTest(this);
test "multilineCString" {
const s1 =
c\\one
c\\two)
@ -274,9 +239,7 @@ fn multilineCString() {
}
fn typeEquality() {
@setFnTest(this);
test "typeEquality" {
assert(&const u8 != &u8);
}
@ -284,22 +247,17 @@ fn typeEquality() {
const global_a: i32 = 1234;
const global_b: &const i32 = &global_a;
const global_c: &const f32 = (&const f32)(global_b);
fn compileTimeGlobalReinterpret() {
@setFnTest(this);
test "compileTimeGlobalReinterpret" {
const d = (&const i32)(global_c);
assert(*d == 1234);
}
fn explicitCastMaybePointers() {
@setFnTest(this);
test "explicitCastMaybePointers" {
const a: ?&i32 = undefined;
const b: ?&f32 = (?&f32)(a);
}
fn genericMallocFree() {
@setFnTest(this);
test "genericMallocFree" {
const a = %%memAlloc(u8, 10);
memFree(u8, a);
}
@ -310,9 +268,7 @@ fn memAlloc(comptime T: type, n: usize) -> %[]T {
fn memFree(comptime T: type, memory: []T) { }
fn castUndefined() {
@setFnTest(this);
test "castUndefined" {
const array: [100]u8 = undefined;
const slice = ([]const u8)(array);
testCastUndefined(slice);
@ -320,9 +276,7 @@ fn castUndefined() {
fn testCastUndefined(x: []const u8) {}
fn castSmallUnsignedToLargerSigned() {
@setFnTest(this);
test "castSmallUnsignedToLargerSigned" {
assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
}
@ -330,9 +284,7 @@ fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { x }
fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { x }
fn implicitCastAfterUnreachable() {
@setFnTest(this);
test "implicitCastAfterUnreachable" {
assert(outer() == 1234);
}
fn inner() -> i32 { 1234 }
@ -341,9 +293,7 @@ fn outer() -> i64 {
}
fn pointerDereferencing() {
@setFnTest(this);
test "pointerDereferencing" {
var x = i32(3);
const y = &x;
@ -353,9 +303,7 @@ fn pointerDereferencing() {
assert(*y == 4);
}
fn callResultOfIfElseExpression() {
@setFnTest(this);
test "callResultOfIfElseExpression" {
assert(mem.eql(u8, f2(true), "a"));
assert(mem.eql(u8, f2(false), "b"));
}
@ -366,9 +314,7 @@ fn fA() -> []const u8 { "a" }
fn fB() -> []const u8 { "b" }
fn constExpressionEvalHandlingOfVariables() {
@setFnTest(this);
test "constExpressionEvalHandlingOfVariables" {
var x = true;
while (x) {
x = false;
@ -377,9 +323,7 @@ fn constExpressionEvalHandlingOfVariables() {
fn constantEnumInitializationWithDifferingSizes() {
@setFnTest(this);
test "constantEnumInitializationWithDifferingSizes" {
test3_1(test3_foo);
test3_2(test3_bar);
}
@ -413,18 +357,14 @@ fn test3_2(f: Test3Foo) {
}
fn characterLiterals() {
@setFnTest(this);
test "characterLiterals" {
assert('\'' == single_quote);
}
const single_quote = '\'';
fn takeAddressOfParameter() {
@setFnTest(this);
test "takeAddressOfParameter" {
testTakeAddressOfParameter(12.34);
}
fn testTakeAddressOfParameter(f: f32) {
@ -433,9 +373,7 @@ fn testTakeAddressOfParameter(f: f32) {
}
fn intToPtrCast() {
@setFnTest(this);
test "intToPtrCast" {
const x = isize(13);
const y = (&u8)(x);
const z = usize(y);
@ -443,9 +381,7 @@ fn intToPtrCast() {
}
fn pointerComparison() {
@setFnTest(this);
test "pointerComparison" {
const a = ([]const u8)("a");
const b = &a;
assert(ptrEql(b, b));
@ -455,9 +391,7 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) -> bool {
}
fn cStringConcatenation() {
@setFnTest(this);
test "cStringConcatenation" {
const a = c"OK" ++ c" IT " ++ c"WORKED";
const b = c"OK IT WORKED";
@ -470,9 +404,7 @@ fn cStringConcatenation() {
assert(b[len] == 0);
}
fn castSliceToU8Slice() {
@setFnTest(this);
test "castSliceToU8Slice" {
assert(@sizeOf(i32) == 4);
var big_thing_array = []i32{1, 2, 3, 4};
const big_thing_slice: []i32 = big_thing_array[0...];
@ -492,9 +424,7 @@ fn castSliceToU8Slice() {
assert(bytes[11] == @maxValue(u8));
}
fn pointerToVoidReturnType() {
@setFnTest(this);
test "pointerToVoidReturnType" {
%%testPointerToVoidReturnType();
}
fn testPointerToVoidReturnType() -> %void {
@ -507,17 +437,14 @@ fn testPointerToVoidReturnType2() -> &const void {
}
fn nonConstPtrToAliasedType() {
@setFnTest(this);
test "nonConstPtrToAliasedType" {
const int = i32;
assert(?&int == ?&i32);
}
fn array2DConstDoublePtr() {
@setFnTest(this);
test "array2DConstDoublePtr" {
const rect_2d_vertexes = [][1]f32 {
[]f32{1.0},
[]f32{2.0},
@ -530,9 +457,7 @@ fn testArray2DConstDoublePtr(ptr: &const f32) {
assert(ptr[1] == 2.0);
}
fn isInteger() {
@setFnTest(this);
test "isInteger" {
comptime {
assert(@isInteger(i8));
assert(@isInteger(u8));
@ -545,9 +470,7 @@ fn isInteger() {
}
}
fn isFloat() {
@setFnTest(this);
test "isFloat" {
comptime {
assert(!@isFloat(i8));
assert(!@isFloat(u8));
@ -560,9 +483,7 @@ fn isFloat() {
}
}
fn canImplicitCast() {
@setFnTest(this);
test "canImplicitCast" {
comptime {
assert(@canImplicitCast(i64, i32(3)));
assert(!@canImplicitCast(i32, f32(1.234)));
@ -570,18 +491,14 @@ fn canImplicitCast() {
}
}
fn typeName() {
@setFnTest(this);
test "typeName" {
comptime {
assert(mem.eql(u8, @typeName(i64), "i64"));
assert(mem.eql(u8, @typeName(&usize), "&usize"));
}
}
fn volatileLoadAndStore() {
@setFnTest(this);
test "volatileLoadAndStore" {
var number: i32 = 1234;
const ptr = &volatile number;
*ptr += 1;

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn namespaceDependsOnCompileVar() {
@setFnTest(this);
test "namespaceDependsOnCompileVar" {
if (some_namespace.a_bool) {
assert(some_namespace.a_bool);
} else {

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn nullableType() {
@setFnTest(this);
test "nullableType" {
const x : ?bool = @generatedCode(true);
if (const y ?= x) {
@ -28,9 +26,7 @@ fn nullableType() {
assert(num == 13);
}
fn assignToIfVarPtr() {
@setFnTest(this);
test "assignToIfVarPtr" {
var maybe_bool: ?bool = true;
if (const *b ?= maybe_bool) {
@ -40,17 +36,13 @@ fn assignToIfVarPtr() {
assert(??maybe_bool == false);
}
fn rhsMaybeUnwrapReturn() {
@setFnTest(this);
test "rhsMaybeUnwrapReturn" {
const x: ?bool = @generatedCode(true);
const y = x ?? return;
}
fn maybeReturn() {
@setFnTest(this);
test "maybeReturn" {
maybeReturnImpl();
comptime maybeReturnImpl();
}
@ -67,9 +59,7 @@ fn foo(x: ?i32) -> ?bool {
}
fn ifVarMaybePointer() {
@setFnTest(this);
test "ifVarMaybePointer" {
assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);
}
fn shouldBeAPlus1(p: Particle) -> u64 {
@ -90,9 +80,7 @@ const Particle = struct {
};
fn nullLiteralOutsideFunction() {
@setFnTest(this);
test "nullLiteralOutsideFunction" {
const is_null = here_is_a_null_literal.context == null;
assert(is_null);
@ -107,9 +95,7 @@ const here_is_a_null_literal = SillyStruct {
};
fn testNullRuntime() {
@setFnTest(this);
test "testNullRuntime" {
testTestNullRuntime(null);
}
fn testTestNullRuntime(x: ?i32) {
@ -117,9 +103,7 @@ fn testTestNullRuntime(x: ?i32) {
assert(!(x != null));
}
fn nullableVoid() {
@setFnTest(this);
test "nullableVoid" {
nullableVoidImpl();
comptime nullableVoidImpl();
}

View File

@ -1,17 +1,13 @@
const other = @import("cases/pub_enum/other.zig");
const assert = @import("std").debug.assert;
fn pubEnum() {
@setFnTest(this);
test "pubEnum" {
pubEnumTest(other.APubEnum.Two);
}
fn pubEnumTest(foo: other.APubEnum) {
assert(foo == other.APubEnum.Two);
}
fn castWithImportedSymbol() {
@setFnTest(this);
test "castWithImportedSymbol" {
assert(other.size_t(42) == 42);
}

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn sizeofAndTypeOf() {
@setFnTest(this);
test "sizeofAndTypeOf" {
const y: @typeOf(x) = 120;
assert(@sizeOf(@typeOf(y)) == 2);
}

View File

@ -5,27 +5,25 @@ const StructWithNoFields = struct {
};
const empty_global_instance = StructWithNoFields {};
fn callStructStaticMethod() {
@setFnTest(this);
test "callStructStaticMethod" {
const result = StructWithNoFields.add(3, 4);
assert(result == 7);
}
test "returnEmptyStructInstance" {
_ = returnEmptyStructInstance();
}
fn returnEmptyStructInstance() -> StructWithNoFields {
@setFnTest(this);
return empty_global_instance;
}
const should_be_11 = StructWithNoFields.add(5, 6);
fn invokeStaticMethodInGlobalScope() {
@setFnTest(this);
test "invokeStaticMethodInGlobalScope" {
assert(should_be_11 == 11);
}
fn voidStructFields() {
@setFnTest(this);
test "voidStructFields" {
const foo = VoidStructFieldsFoo {
.a = void{},
.b = 1,
@ -41,9 +39,7 @@ const VoidStructFieldsFoo = struct {
};
pub fn structs() {
@setFnTest(this);
test "fn" {
var foo: StructFoo = undefined;
@memset((&u8)(&foo), 0, @sizeOf(StructFoo));
foo.a += 1;
@ -74,9 +70,7 @@ const Val = struct {
x: i32,
};
fn structPointToSelf() {
@setFnTest(this);
test "structPointToSelf" {
var root : Node = undefined;
root.val.x = 1;
@ -89,9 +83,7 @@ fn structPointToSelf() {
assert(node.next.next.next.val.x == 1);
}
fn structByvalAssign() {
@setFnTest(this);
test "structByvalAssign" {
var foo1 : StructFoo = undefined;
var foo2 : StructFoo = undefined;
@ -108,9 +100,7 @@ fn structInitializer() {
}
fn fnCallOfStructField() {
@setFnTest(this);
test "fnCallOfStructField" {
assert(callStructField(Foo {.ptr = aFunc,}) == 13);
}
@ -125,9 +115,7 @@ fn callStructField(foo: Foo) -> i32 {
}
fn storeMemberFunctionInVariable() {
@setFnTest(this);
test "storeMemberFunctionInVariable" {
const instance = MemberFnTestFoo { .x = 1234, };
const memberFn = MemberFnTestFoo.member;
const result = memberFn(instance);
@ -139,17 +127,13 @@ const MemberFnTestFoo = struct {
};
fn callMemberFunctionDirectly() {
@setFnTest(this);
test "callMemberFunctionDirectly" {
const instance = MemberFnTestFoo { .x = 1234, };
const result = MemberFnTestFoo.member(instance);
assert(result == 1234);
}
fn memberFunctions() {
@setFnTest(this);
test "memberFunctions" {
const r = MemberFnRand {.seed = 1234};
assert(r.getSeed() == 1234);
}
@ -160,9 +144,7 @@ const MemberFnRand = struct {
}
};
fn returnStructByvalFromFunction() {
@setFnTest(this);
test "returnStructByvalFromFunction" {
const bar = makeBar(1234, 5678);
assert(bar.y == 5678);
}
@ -177,9 +159,7 @@ fn makeBar(x: i32, y: i32) -> Bar {
}
}
fn emptyStructMethodCall() {
@setFnTest(this);
test "emptyStructMethodCall" {
const es = EmptyStruct{};
assert(es.method() == 1234);
}
@ -190,9 +170,7 @@ const EmptyStruct = struct {
};
fn returnEmptyStructFromFn() {
@setFnTest(this);
test "returnEmptyStructFromFn" {
_ = testReturnEmptyStructFromFn();
}
const EmptyStruct2 = struct {};
@ -200,9 +178,7 @@ fn testReturnEmptyStructFromFn() -> EmptyStruct2 {
EmptyStruct2 {}
}
fn passSliceOfEmptyStructToFn() {
@setFnTest(this);
test "passSliceOfEmptyStructToFn" {
assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
}
fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize {
@ -214,9 +190,7 @@ const APackedStruct = packed struct {
y: u8,
};
fn packedStruct() {
@setFnTest(this);
test "packedStruct" {
var foo = APackedStruct {
.x = 1,
.y = 2,
@ -242,9 +216,7 @@ const bit_field_1 = BitField1 {
.c = 3,
};
fn bitFieldAccess() {
@setFnTest(this);
test "bitFieldAccess" {
var data = bit_field_1;
assert(getA(&data) == 1);
assert(getB(&data) == 2);
@ -282,9 +254,7 @@ const Foo96Bits = packed struct {
d: u24,
};
fn packedStruct24Bits() {
@setFnTest(this);
test "packedStruct24Bits" {
comptime {
assert(@sizeOf(Foo24Bits) == 3);
assert(@sizeOf(Foo96Bits) == 12);
@ -327,9 +297,7 @@ const FooArray24Bits = packed struct {
c: u16,
};
fn packedArray24Bits() {
@setFnTest(this);
test "packedArray24Bits" {
comptime {
assert(@sizeOf([9]Foo24Bits) == 9 * 3);
assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
@ -379,9 +347,7 @@ const FooArrayOfAligned = packed struct {
a: [2]FooStructAligned,
};
fn alignedArrayOfPackedStruct() {
@setFnTest(this);
test "alignedArrayOfPackedStruct" {
comptime {
assert(@sizeOf(FooStructAligned) == 2);
assert(@sizeOf(FooArrayOfAligned) == 2 * 2);

View File

@ -5,9 +5,7 @@ const Node = struct {
children: []Node,
};
fn structContainsSliceOfItself() {
@setFnTest(this);
test "structContainsSliceOfItself" {
var nodes = []Node {
Node {
.payload = 1,

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn switchWithNumbers() {
@setFnTest(this);
test "switchWithNumbers" {
testSwitchWithNumbers(13);
}
@ -15,9 +13,7 @@ fn testSwitchWithNumbers(x: u32) {
assert(result);
}
fn switchWithAllRanges() {
@setFnTest(this);
test "switchWithAllRanges" {
assert(testSwitchWithAllRanges(50, 3) == 1);
assert(testSwitchWithAllRanges(101, 0) == 2);
assert(testSwitchWithAllRanges(300, 5) == 3);
@ -33,9 +29,7 @@ fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 {
}
}
fn implicitComptimeSwitch() {
@setFnTest(this);
test "implicitComptimeSwitch" {
const x = 3 + 4;
const result = switch (x) {
3 => 10,
@ -50,9 +44,7 @@ fn implicitComptimeSwitch() {
}
}
fn switchOnEnum() {
@setFnTest(this);
test "switchOnEnum" {
const fruit = Fruit.Orange;
nonConstSwitchOnEnum(fruit);
}
@ -70,9 +62,7 @@ fn nonConstSwitchOnEnum(fruit: Fruit) {
}
fn switchStatement() {
@setFnTest(this);
test "switchStatement" {
nonConstSwitch(SwitchStatmentFoo.C);
}
fn nonConstSwitch(foo: SwitchStatmentFoo) {
@ -92,9 +82,7 @@ const SwitchStatmentFoo = enum {
};
fn switchProngWithVar() {
@setFnTest(this);
test "switchProngWithVar" {
switchProngWithVarFn(SwitchProngWithVarEnum.One {13});
switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});
switchProngWithVarFn(SwitchProngWithVarEnum.Meh);
@ -119,9 +107,7 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) {
}
fn switchWithMultipleExpressions() {
@setFnTest(this);
test "switchWithMultipleExpressions" {
const x = switch (returnsFive()) {
1, 2, 3 => 1,
4, 5, 6 => 2,
@ -149,8 +135,6 @@ fn returnsFalse() -> bool {
Number.Three => |x| return x > 12.34,
}
}
fn switchOnConstEnumWithVar() {
@setFnTest(this);
test "switchOnConstEnumWithVar" {
assert(!returnsFalse());
}

View File

@ -21,9 +21,7 @@ fn doThing(form_id: u64) -> %FormValue {
}
}
fn switchProngReturnsErrorEnum() {
@setFnTest(this);
test "switchProngReturnsErrorEnum" {
%%doThing(17);
assert(read_count == 1);
}

View File

@ -15,9 +15,7 @@ fn foo(id: u64) -> %FormValue {
}
}
fn switchProngImplicitCast() {
@setFnTest(this);
test "switchProngImplicitCast" {
const result = switch (%%foo(2)) {
FormValue.One => false,
FormValue.Two => |x| x,

View File

@ -28,15 +28,11 @@ fn factorial(x: i32) -> i32 {
}
}
fn thisReferToModuleCallPrivateFn() {
@setFnTest(this);
test "thisReferToModuleCallPrivateFn" {
assert(module.add(1, 2) == 3);
}
fn thisReferToContainer() {
@setFnTest(this);
test "thisReferToContainer" {
var pt = Point(i32) {
.x = 12,
.y = 34,
@ -46,8 +42,6 @@ fn thisReferToContainer() {
assert(pt.y == 35);
}
fn thisReferToFn() {
@setFnTest(this);
test "thisReferToFn" {
assert(factorial(5) == 120);
}

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn tryOnErrorUnion() {
@setFnTest(this);
test "tryOnErrorUnion" {
tryOnErrorUnionImpl();
comptime tryOnErrorUnionImpl();
@ -25,9 +23,7 @@ fn returnsTen() -> %i32 {
10
}
fn tryWithoutVars() {
@setFnTest(this);
test "tryWithoutVars" {
const result1 = try (failIfTrue(true)) {
1
} else {

View File

@ -5,8 +5,6 @@ type int = u8;
fn add(a: int, b: int) -> int {
a + b
}
fn typedef() {
@setFnTest(this);
test "typedef" {
assert(add(12, 34) == 46);
}

View File

@ -9,9 +9,7 @@ fn initStaticArray() -> [10]i32 {
return array;
}
const static_array = initStaticArray();
fn initStaticArrayToUndefined() {
@setFnTest(this);
test "initStaticArrayToUndefined" {
assert(static_array[0] == 1);
assert(static_array[4] == 2);
assert(static_array[7] == 3);
@ -37,9 +35,7 @@ fn setFooX(foo: &Foo) {
foo.x = 2;
}
fn assignUndefinedToStruct() {
@setFnTest(this);
test "assignUndefinedToStruct" {
comptime {
var foo: Foo = undefined;
setFooX(&foo);
@ -52,9 +48,7 @@ fn assignUndefinedToStruct() {
}
}
fn assignUndefinedToStructWithMethod() {
@setFnTest(this);
test "assignUndefinedToStructWithMethod" {
comptime {
var foo: Foo = undefined;
foo.setFooXMethod();

View File

@ -8,9 +8,7 @@ fn add(args: ...) -> i32 {
return sum;
}
fn testAddArbitraryArgs() {
@setFnTest(this);
test "testAddArbitraryArgs" {
assert(add(i32(1), i32(2), i32(3), i32(4)) == 10);
assert(add(i32(1234)) == 1234);
assert(add() == 0);
@ -20,15 +18,11 @@ fn readFirstVarArg(args: ...) {
const value = args[0];
}
fn sendVoidArgToVarArgs() {
@setFnTest(this);
test "sendVoidArgToVarArgs" {
readFirstVarArg({});
}
fn testPassArgsDirectly() {
@setFnTest(this);
test "testPassArgsDirectly" {
assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
assert(addSomeStuff(i32(1234)) == 1234);
assert(addSomeStuff() == 0);

View File

@ -6,9 +6,7 @@ const Foo = struct {
c: void,
};
fn compareVoidWithVoidCompileTimeKnown() {
@setFnTest(this);
test "compareVoidWithVoidCompileTimeKnown" {
comptime {
const foo = Foo {
.a = {},

View File

@ -1,8 +1,6 @@
const assert = @import("std").debug.assert;
fn whileLoop() {
@setFnTest(this);
test "whileLoop" {
var i : i32 = 0;
while (i < 4) {
i += 1;
@ -18,9 +16,7 @@ fn whileLoop2() -> i32 {
return 1;
}
}
fn staticEvalWhile() {
@setFnTest(this);
test "staticEvalWhile" {
assert(static_eval_while_number == 1);
}
const static_eval_while_number = staticWhileLoop1();
@ -33,9 +29,7 @@ fn staticWhileLoop2() -> i32 {
}
}
fn continueAndBreak() {
@setFnTest(this);
test "continueAndBreak" {
runContinueAndBreakTest();
assert(continue_and_break_counter == 8);
}
@ -53,9 +47,7 @@ fn runContinueAndBreakTest() {
assert(i == 4);
}
fn returnWithImplicitCastFromWhileLoop() {
@setFnTest(this);
test "returnWithImplicitCastFromWhileLoop" {
%%returnWithImplicitCastFromWhileLoopTest();
}
fn returnWithImplicitCastFromWhileLoopTest() -> %void {
@ -64,9 +56,7 @@ fn returnWithImplicitCastFromWhileLoopTest() -> %void {
}
}
fn whileWithContinueExpr() {
@setFnTest(this);
test "whileWithContinueExpr" {
var sum: i32 = 0;
{var i: i32 = 0; while (i < 10; i += 1) {
if (i == 5) continue;

View File

@ -14,6 +14,12 @@
#include <stdio.h>
#include <stdarg.h>
enum TestSpecial {
TestSpecialNone,
TestSpecialSelfHosted,
TestSpecialStd,
};
struct TestSourceFile {
const char *relative_path;
const char *source_code;
@ -32,7 +38,7 @@ struct TestCase {
ZigList<const char *> compiler_args;
ZigList<const char *> program_args;
bool is_parseh;
bool is_self_hosted;
TestSpecial special;
bool is_release_mode;
bool is_debug_safety;
AllowWarnings allow_warnings;
@ -79,7 +85,6 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons
test_case->compiler_args.append("--strip");
test_case->compiler_args.append("--color");
test_case->compiler_args.append("on");
test_case->compiler_args.append("--check-unused");
test_cases.append(test_case);
@ -93,9 +98,10 @@ static TestCase *add_simple_case_libc(const char *case_name, const char *source,
return tc;
}
static TestCase *add_compile_fail_case_extra(const char *case_name, const char *source, bool check_unused,
size_t count, va_list ap)
{
static TestCase *add_compile_fail_case(const char *case_name, const char *source, size_t count, ...) {
va_list ap;
va_start(ap, count);
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = case_name;
test_case->source_files.resize(1);
@ -122,31 +128,11 @@ static TestCase *add_compile_fail_case_extra(const char *case_name, const char *
test_case->compiler_args.append("--release");
test_case->compiler_args.append("--strip");
if (check_unused) {
test_case->compiler_args.append("--check-unused");
}
test_cases.append(test_case);
return test_case;
}
static TestCase *add_compile_fail_case_no_check_unused(const char *case_name, const char *source, size_t count, ...) {
va_list ap;
va_start(ap, count);
TestCase *result = add_compile_fail_case_extra(case_name, source, false, count, ap);
va_end(ap);
return result;
}
static TestCase *add_compile_fail_case(const char *case_name, const char *source, size_t count, ...) {
va_list ap;
va_start(ap, count);
TestCase *result = add_compile_fail_case_extra(case_name, source, true, count, ap);
va_end(ap);
return result;
}
static void add_debug_safety_case(const char *case_name, const char *source) {
{
TestCase *test_case = allocate<TestCase>(1);
@ -674,24 +660,27 @@ static void add_compile_failure_test_cases(void) {
add_compile_fail_case("multiple function definitions", R"SOURCE(
fn a() {}
fn a() {}
export fn entry() { a(); }
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
add_compile_fail_case("unreachable with return", R"SOURCE(
fn a() -> unreachable {return;}
export fn entry() { a(); }
)SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', found 'void'");
add_compile_fail_case("control reaches end of non-void function", R"SOURCE(
fn a() -> i32 {}
export fn entry() { _ = a(); }
)SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', found 'void'");
add_compile_fail_case("undefined function call", R"SOURCE(
fn a() {
export fn a() {
b();
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
add_compile_fail_case("wrong number of arguments", R"SOURCE(
fn a() {
export fn a() {
b(1);
}
fn b(a: i32, b: i32, c: i32) { }
@ -699,14 +688,16 @@ fn b(a: i32, b: i32, c: i32) { }
add_compile_fail_case("invalid type", R"SOURCE(
fn a() -> bogus {}
export fn entry() { _ = a(); }
)SOURCE", 1, ".tmp_source.zig:2:11: error: use of undeclared identifier 'bogus'");
add_compile_fail_case("pointer to unreachable", R"SOURCE(
fn a() -> &unreachable {}
export fn entry() { _ = a(); }
)SOURCE", 1, ".tmp_source.zig:2:12: error: pointer to unreachable not allowed");
add_compile_fail_case("unreachable code", R"SOURCE(
fn a() {
export fn a() {
return;
b();
}
@ -716,10 +707,11 @@ fn b() {}
add_compile_fail_case("bad import", R"SOURCE(
const bogus = @import("bogus-does-not-exist.zig");
export fn entry() { bogus.bogo(); }
)SOURCE", 1, ".tmp_source.zig:2:15: error: unable to find 'bogus-does-not-exist.zig'");
add_compile_fail_case("undeclared identifier", R"SOURCE(
fn a() {
export fn a() {
b +
c
}
@ -730,10 +722,11 @@ fn a() {
add_compile_fail_case("parameter redeclaration", R"SOURCE(
fn f(a : i32, a : i32) {
}
export fn entry() { f(1, 2); }
)SOURCE", 1, ".tmp_source.zig:2:15: error: redeclaration of variable 'a'");
add_compile_fail_case("local variable redeclaration", R"SOURCE(
fn f() {
export fn f() {
const a : i32 = 0;
const a = 0;
}
@ -743,71 +736,73 @@ fn f() {
fn f(a : i32) {
const a = 0;
}
export fn entry() { f(1); }
)SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");
add_compile_fail_case("variable has wrong type", R"SOURCE(
fn f() -> i32 {
export fn f() -> i32 {
const a = c"a";
a
}
)SOURCE", 1, ".tmp_source.zig:4:5: error: expected type 'i32', found '&const u8'");
add_compile_fail_case("if condition is bool, not int", R"SOURCE(
fn f() {
export fn f() {
if (0) {}
}
)SOURCE", 1, ".tmp_source.zig:3:9: error: integer value 0 cannot be implicitly casted to type 'bool'");
add_compile_fail_case("assign unreachable", R"SOURCE(
fn f() {
export fn f() {
const a = return;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: unreachable code");
add_compile_fail_case("unreachable variable", R"SOURCE(
fn f() {
export fn f() {
const a : unreachable = {};
}
)SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
add_compile_fail_case("unreachable parameter", R"SOURCE(
fn f(a : unreachable) {}
export fn entry() { f(); }
)SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
add_compile_fail_case("bad assignment target", R"SOURCE(
fn f() {
export fn f() {
3 = 3;
}
)SOURCE", 1, ".tmp_source.zig:3:7: error: cannot assign to constant");
add_compile_fail_case("assign to constant variable", R"SOURCE(
fn f() {
export fn f() {
const a = 3;
a = 4;
}
)SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
add_compile_fail_case("use of undeclared identifier", R"SOURCE(
fn f() {
export fn f() {
b = 3;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
fn f() {
export fn f() {
(const a = 0);
}
)SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");
add_compile_fail_case("array access of undeclared identifier", R"SOURCE(
fn f() {
export fn f() {
i[i] = i[i];
}
)SOURCE", 2, ".tmp_source.zig:3:5: error: use of undeclared identifier 'i'",
".tmp_source.zig:3:12: error: use of undeclared identifier 'i'");
add_compile_fail_case("array access of non array", R"SOURCE(
fn f() {
export fn f() {
var bad : bool = undefined;
bad[bad] = bad[bad];
}
@ -815,7 +810,7 @@ fn f() {
".tmp_source.zig:4:19: error: array access of non-array type 'bool'");
add_compile_fail_case("array access with non integer index", R"SOURCE(
fn f() {
export fn f() {
var array = "aoeu";
var bad = false;
array[bad] = array[bad];
@ -828,6 +823,7 @@ const x : i32 = 99;
fn f() {
x = 1;
}
export fn entry() { f(); }
)SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
@ -836,22 +832,25 @@ fn f(b: bool) {
const x : i32 = if (b) { 1 };
const y = if (b) { i32(1) };
}
export fn entry() { f(true); }
)SOURCE", 2, ".tmp_source.zig:3:30: error: integer value 1 cannot be implicitly casted to type 'void'",
".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");
add_compile_fail_case("direct struct loop", R"SOURCE(
const A = struct { a : A, };
export fn entry() -> usize { @sizeOf(A) }
)SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself");
add_compile_fail_case("indirect struct loop", R"SOURCE(
const A = struct { b : B, };
const B = struct { c : C, };
const C = struct { a : A, };
export fn entry() -> usize { @sizeOf(A) }
)SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself");
add_compile_fail_case("invalid struct field", R"SOURCE(
const A = struct { x : i32, };
fn f() {
export fn f() {
var a : A = undefined;
a.foo = 1;
const y = a.bar;
@ -873,7 +872,9 @@ const A = enum {};
add_compile_fail_case("redefinition of global variables", R"SOURCE(
var a : i32 = 1;
var a : i32 = 2;
)SOURCE", 1, ".tmp_source.zig:3:1: error: redeclaration of variable 'a'");
)SOURCE", 2,
".tmp_source.zig:3:1: error: redefinition of 'a'",
".tmp_source.zig:2:1: note: previous definition is here");
add_compile_fail_case("byvalue struct parameter in exported function", R"SOURCE(
const A = struct { x : i32, };
@ -893,7 +894,7 @@ const A = struct {
y : i32,
z : i32,
};
fn f() {
export fn f() {
const a = A {
.z = 1,
.y = 2,
@ -909,7 +910,7 @@ const A = struct {
y : i32,
z : i32,
};
fn f() {
export fn f() {
// we want the error on the '{' not the 'A' because
// the A could be a complicated expression
const a = A {
@ -925,7 +926,7 @@ const A = struct {
y : i32,
z : i32,
};
fn f() {
export fn f() {
const a = A {
.z = 4,
.y = 2,
@ -935,19 +936,19 @@ fn f() {
)SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");
add_compile_fail_case("invalid break expression", R"SOURCE(
fn f() {
export fn f() {
break;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop");
add_compile_fail_case("invalid continue expression", R"SOURCE(
fn f() {
export fn f() {
continue;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop");
add_compile_fail_case("invalid maybe type", R"SOURCE(
fn f() {
export fn f() {
if (const x ?= true) { }
}
)SOURCE", 1, ".tmp_source.zig:3:20: error: expected nullable type, found 'bool'");
@ -956,42 +957,39 @@ fn f() {
fn f() -> i32 {
i32(return 1)
}
export fn entry() { _ = f(); }
)SOURCE", 1, ".tmp_source.zig:3:8: error: unreachable code");
add_compile_fail_case("invalid builtin fn", R"SOURCE(
fn f() -> @bogus(foo) {
}
export fn entry() { _ = f(); }
)SOURCE", 1, ".tmp_source.zig:2:11: error: invalid builtin function: 'bogus'");
add_compile_fail_case("top level decl dependency loop", R"SOURCE(
const a : @typeOf(b) = 0;
const b : @typeOf(a) = 0;
export fn entry() {
const c = a + b;
}
)SOURCE", 1, ".tmp_source.zig:2:1: error: 'a' depends on itself");
add_compile_fail_case("noalias on non pointer param", R"SOURCE(
fn f(noalias x: i32) {}
export fn entry() { f(1234); }
)SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter");
add_compile_fail_case("struct init syntax for array", R"SOURCE(
const foo = []u16{.x = 1024,};
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax");
add_compile_fail_case("type variables must be constant", R"SOURCE(
var foo = u8;
)SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant");
add_compile_fail_case("variables shadowing types", R"SOURCE(
const Foo = struct {};
const Bar = struct {};
fn f(Foo: i32) {
var Bar : i32 = undefined;
export fn entry() -> foo {
return 1;
}
)SOURCE", 4,
".tmp_source.zig:5:6: error: redeclaration of variable 'Foo'",
".tmp_source.zig:2:1: note: previous declaration is here",
".tmp_source.zig:6:5: error: redeclaration of variable 'Bar'",
".tmp_source.zig:3:1: note: previous declaration is here");
)SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant");
add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(
fn f(x: u32) {
@ -1000,28 +998,36 @@ fn f(x: u32) {
else => true,
else => true,
};
}
export fn entry() {
f(1234);
}
)SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression");
add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE(
extern fn foo() -> i32;
const x = foo();
export fn entry() -> i32 { x }
)SOURCE", 1, ".tmp_source.zig:3:11: error: unable to evaluate constant expression");
add_compile_fail_case("array concatenation with wrong type", R"SOURCE(
const src = "aoeu";
const derp = usize(1234);
const a = derp ++ "foo";
export fn entry() -> usize { @sizeOf(@typeOf(a)) }
)SOURCE", 1, ".tmp_source.zig:4:11: error: expected array or C string literal, found 'usize'");
add_compile_fail_case("non compile time array concatenation", R"SOURCE(
fn f(s: [10]u8) -> []u8 {
s ++ "foo"
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:3:5: error: unable to evaluate constant expression");
add_compile_fail_case("@cImport with bogus include", R"SOURCE(
const c = @cImport(@cInclude("bogus.h"));
export fn entry() -> usize { @sizeOf(@typeOf(c.bogo)) }
)SOURCE", 2, ".tmp_source.zig:2:11: error: C import failed",
".h:1:10: note: 'bogus.h' file not found");
@ -1029,14 +1035,17 @@ const c = @cImport(@cInclude("bogus.h"));
const x = 3;
const y = &x;
fn foo() -> &const i32 { y }
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:4:26: error: expected type '&const i32', found '&const (integer literal)'");
add_compile_fail_case("integer overflow error", R"SOURCE(
const x : u8 = 300;
export fn entry() -> usize { @sizeOf(@typeOf(x)) }
)SOURCE", 1, ".tmp_source.zig:2:16: error: integer value 300 cannot be implicitly casted to type 'u8'");
add_compile_fail_case("incompatible number literals", R"SOURCE(
const x = 2 == 2.0;
export fn entry() -> usize { @sizeOf(@typeOf(x)) }
)SOURCE", 1, ".tmp_source.zig:2:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'");
add_compile_fail_case("missing function call param", R"SOURCE(
@ -1061,11 +1070,14 @@ const members = []member_fn_type {
fn f(foo: Foo, index: usize) {
const result = members[index]();
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:21:34: error: expected 1 arguments, found 0");
add_compile_fail_case("missing function name and param name", R"SOURCE(
fn () {}
fn f(i32) {}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 2,
".tmp_source.zig:2:1: error: missing function name",
".tmp_source.zig:3:6: error: missing parameter name");
@ -1075,6 +1087,7 @@ const fns = []fn(){ a, b, c };
fn a() -> i32 {0}
fn b() -> i32 {1}
fn c() -> i32 {2}
export fn entry() -> usize { @sizeOf(@typeOf(fns)) }
)SOURCE", 1, ".tmp_source.zig:2:21: error: expected type 'fn()', found 'fn() -> i32'");
add_compile_fail_case("extern function pointer mismatch", R"SOURCE(
@ -1082,18 +1095,23 @@ const fns = [](fn(i32)->i32){ a, b, c };
pub fn a(x: i32) -> i32 {x + 0}
pub fn b(x: i32) -> i32 {x + 1}
export fn c(x: i32) -> i32 {x + 2}
export fn entry() -> usize { @sizeOf(@typeOf(fns)) }
)SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', found 'extern fn(i32) -> i32'");
add_compile_fail_case("implicit cast from f64 to f32", R"SOURCE(
const x : f64 = 1.0;
const y : f32 = x;
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 1, ".tmp_source.zig:3:17: error: expected type 'f32', found 'f64'");
add_compile_fail_case("colliding invalid top level functions", R"SOURCE(
fn func() -> bogus {}
fn func() -> bogus {}
export fn entry() -> usize { @sizeOf(@typeOf(func)) }
)SOURCE", 2,
".tmp_source.zig:3:1: error: redefinition of 'func'",
".tmp_source.zig:2:14: error: use of undeclared identifier 'bogus'");
@ -1101,6 +1119,7 @@ fn func() -> bogus {}
add_compile_fail_case("bogus compile var", R"SOURCE(
const x = @compileVar("bogus");
export fn entry() -> usize { @sizeOf(@typeOf(x)) }
)SOURCE", 1, ".tmp_source.zig:2:23: error: unrecognized compile variable: 'bogus'");
@ -1110,6 +1129,8 @@ const Foo = struct {
};
var global_var: usize = 1;
fn get() -> usize { global_var }
export fn entry() -> usize { @sizeOf(@typeOf(Foo)) }
)SOURCE", 3,
".tmp_source.zig:6:21: error: unable to evaluate constant expression",
".tmp_source.zig:3:12: note: called from here",
@ -1121,6 +1142,8 @@ const Foo = struct {
field: i32,
};
const x = Foo {.field = 1} + Foo {.field = 2};
export fn entry() -> usize { @sizeOf(@typeOf(x)) }
)SOURCE", 1, ".tmp_source.zig:5:28: error: invalid operands to binary expression: 'Foo' and 'Foo'");
@ -1129,6 +1152,11 @@ const lit_int_x = 1 / 0;
const lit_float_x = 1.0 / 0.0;
const int_x = i32(1) / i32(0);
const float_x = f32(1.0) / f32(0.0);
export fn entry1() -> usize { @sizeOf(@typeOf(lit_int_x)) }
export fn entry2() -> usize { @sizeOf(@typeOf(lit_float_x)) }
export fn entry3() -> usize { @sizeOf(@typeOf(int_x)) }
export fn entry4() -> usize { @sizeOf(@typeOf(float_x)) }
)SOURCE", 4,
".tmp_source.zig:2:21: error: division by zero is undefined",
".tmp_source.zig:3:25: error: division by zero is undefined",
@ -1150,16 +1178,22 @@ fn f(n: Number) -> i32 {
Number.Three => i32(3),
}
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Number.Four' not handled in switch");
add_compile_fail_case("normal string with newline", R"SOURCE(
const foo = "a
b";
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:2:13: error: newline not allowed in string literal");
add_compile_fail_case("invalid comparison for function pointers", R"SOURCE(
fn foo() {}
const invalid = foo > foo;
export fn entry() -> usize { @sizeOf(@typeOf(invalid)) }
)SOURCE", 1, ".tmp_source.zig:3:21: error: operator not allowed for type 'fn()'");
add_compile_fail_case("generic function instance with non-constant expression", R"SOURCE(
@ -1167,10 +1201,12 @@ fn foo(comptime x: i32, y: i32) -> i32 { return x + y; }
fn test1(a: i32, b: i32) -> i32 {
return foo(a, b);
}
export fn entry() -> usize { @sizeOf(@typeOf(test1)) }
)SOURCE", 1, ".tmp_source.zig:4:16: error: unable to evaluate constant expression");
add_compile_fail_case("goto jumping into block", R"SOURCE(
fn f() {
export fn f() {
{
a_label:
}
@ -1185,15 +1221,19 @@ fn f(b: bool) {
label:
}
fn derp(){}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:3:12: error: no label in scope named 'label'");
add_compile_fail_case("assign null to non-nullable pointer", R"SOURCE(
const a: &u8 = null;
export fn entry() -> usize { @sizeOf(@typeOf(a)) }
)SOURCE", 1, ".tmp_source.zig:2:16: error: expected type '&u8', found '(null)'");
add_compile_fail_case("indexing an array of size zero", R"SOURCE(
const array = []u8{};
fn foo() {
export fn foo() {
const pointer = &array[0];
}
)SOURCE", 1, ".tmp_source.zig:4:27: error: index 0 outside array of size 0");
@ -1203,12 +1243,16 @@ const y = foo(0);
fn foo(x: i32) -> i32 {
1 / x
}
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 2,
".tmp_source.zig:4:7: error: division by zero is undefined",
".tmp_source.zig:2:14: note: called from here");
add_compile_fail_case("branch on undefined value", R"SOURCE(
const x = if (undefined) true else false;
export fn entry() -> usize { @sizeOf(@typeOf(x)) }
)SOURCE", 1, ".tmp_source.zig:2:15: error: use of undefined value");
@ -1217,12 +1261,16 @@ const seventh_fib_number = fibbonaci(7);
fn fibbonaci(x: i32) -> i32 {
return fibbonaci(x - 1) + fibbonaci(x - 2);
}
export fn entry() -> usize { @sizeOf(@typeOf(seventh_fib_number)) }
)SOURCE", 2,
".tmp_source.zig:4:21: error: evaluation exceeded 1000 backwards branches",
".tmp_source.zig:4:21: note: called from here");
add_compile_fail_case("@embedFile with bogus file", R"SOURCE(
const resource = @embedFile("bogus.txt");
export fn entry() -> usize { @sizeOf(@typeOf(resource)) }
)SOURCE", 1, ".tmp_source.zig:2:29: error: unable to find './bogus.txt'");
@ -1232,6 +1280,8 @@ const Foo = struct {
};
const a = Foo {.x = get_it()};
extern fn get_it() -> i32;
export fn entry() -> usize { @sizeOf(@typeOf(a)) }
)SOURCE", 1, ".tmp_source.zig:5:21: error: unable to evaluate constant expression");
add_compile_fail_case("non-const expression function call with struct return value outside function", R"SOURCE(
@ -1245,12 +1295,13 @@ fn get_it() -> Foo {
}
var global_side_effect = false;
export fn entry() -> usize { @sizeOf(@typeOf(a)) }
)SOURCE", 2,
".tmp_source.zig:7:24: error: unable to evaluate constant expression",
".tmp_source.zig:5:17: note: called from here");
add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE(
fn foo() {
export fn foo() {
test_a_thing();
}
fn test_a_thing() {
@ -1269,12 +1320,15 @@ const EnumWithData = enum {
fn bad_eql_2(a: EnumWithData, b: EnumWithData) -> bool {
a == b
}
export fn entry1() -> usize { @sizeOf(@typeOf(bad_eql_1)) }
export fn entry2() -> usize { @sizeOf(@typeOf(bad_eql_2)) }
)SOURCE", 2,
".tmp_source.zig:3:7: error: operator not allowed for type '[]u8'",
".tmp_source.zig:10:7: error: operator not allowed for type 'EnumWithData'");
add_compile_fail_case("non-const switch number literal", R"SOURCE(
fn foo() {
export fn foo() {
const x = switch (bar()) {
1, 2 => 1,
3, 4 => 2,
@ -1284,18 +1338,17 @@ fn foo() {
fn bar() -> i32 {
2
}
)SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type");
add_compile_fail_case("atomic orderings of cmpxchg - failure stricter than success", R"SOURCE(
fn f() {
export fn f() {
var x: i32 = 1234;
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {}
}
)SOURCE", 1, ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success");
add_compile_fail_case("atomic orderings of cmpxchg - success Monotonic or stricter", R"SOURCE(
fn f() {
export fn f() {
var x: i32 = 1234;
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {}
}
@ -1306,6 +1359,8 @@ const y = neg(-128);
fn neg(x: i8) -> i8 {
-x
}
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 2,
".tmp_source.zig:4:5: error: negation caused overflow",
".tmp_source.zig:2:14: note: called from here");
@ -1315,6 +1370,8 @@ const y = add(65530, 10);
fn add(a: u16, b: u16) -> u16 {
a + b
}
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 2,
".tmp_source.zig:4:7: error: operation caused overflow",
".tmp_source.zig:2:14: note: called from here");
@ -1325,6 +1382,8 @@ const y = sub(10, 20);
fn sub(a: u16, b: u16) -> u16 {
a - b
}
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 2,
".tmp_source.zig:4:7: error: operation caused overflow",
".tmp_source.zig:2:14: note: called from here");
@ -1334,6 +1393,8 @@ const y = mul(300, 6000);
fn mul(a: u16, b: u16) -> u16 {
a * b
}
export fn entry() -> usize { @sizeOf(@typeOf(y)) }
)SOURCE", 2,
".tmp_source.zig:4:7: error: operation caused overflow",
".tmp_source.zig:2:14: note: called from here");
@ -1343,10 +1404,12 @@ fn f() -> i8 {
const x: u32 = 10;
@truncate(i8, x)
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:4:19: error: expected signed integer type, found 'u32'");
add_compile_fail_case("%return in function with non error return type", R"SOURCE(
fn f() {
export fn f() {
%return something();
}
fn something() -> %void { }
@ -1361,7 +1424,7 @@ pub fn main(args: [][]u8) { }
add_compile_fail_case("invalid pointer for var type", R"SOURCE(
extern fn ext() -> usize;
var bytes: [ext()]u8 = undefined;
fn f() {
export fn f() {
for (bytes) |*b, i| {
*b = u8(i);
}
@ -1379,10 +1442,11 @@ extern fn foo(comptime x: i32, y: i32) -> i32;
fn f() -> i32 {
foo(1, 2)
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function");
add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE(
fn f() {
export fn f() {
var array: [5]u8 = undefined;
var foo = ([]const u32)(array)[0];
}
@ -1403,7 +1467,7 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
}
}
fn function_with_return_type_type() {
export fn function_with_return_type_type() {
var list: List(i32) = undefined;
list.length = 10;
}
@ -1417,6 +1481,7 @@ var self = "aoeu";
fn f(m: []const u8) {
m.copy(u8, self[0...], m);
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:4:6: error: no member named 'copy' in '[]const u8'");
add_compile_fail_case("wrong number of arguments for method fn call", R"SOURCE(
@ -1427,17 +1492,18 @@ fn f(foo: &const Foo) {
foo.method(1, 2);
}
export fn entry() -> usize { @sizeOf(@typeOf(f)) }
)SOURCE", 1, ".tmp_source.zig:7:15: error: expected 2 arguments, found 3");
add_compile_fail_case("assign through constant pointer", R"SOURCE(
fn f() {
export fn f() {
var cstr = c"Hat";
cstr[0] = 'W';
}
)SOURCE", 1, ".tmp_source.zig:4:11: error: cannot assign to constant");
add_compile_fail_case("assign through constant slice", R"SOURCE(
pub fn f() {
export fn f() {
var cstr: []const u8 = "Hat";
cstr[0] = 'W';
}
@ -1451,6 +1517,7 @@ pub fn main(args: [][]bogus) -> %void {}
fn foo(blah: []u8) {
for (blah) { }
}
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:3:5: error: for loop expression missing element parameter");
add_compile_fail_case("misspelled type with pointer only reference", R"SOURCE(
@ -1482,6 +1549,8 @@ fn foo() {
jll.init(1234);
var jd = JsonNode {.kind = JsonType.JSONArray , .jobject = JsonOA.JSONArray {jll} };
}
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:6:16: error: use of undeclared identifier 'JsonList'");
add_compile_fail_case("method call with first arg type primitive", R"SOURCE(
@ -1495,7 +1564,7 @@ const Foo = struct {
}
};
fn f() {
export fn f() {
const derp = Foo.init(3);
derp.init();
@ -1523,7 +1592,7 @@ pub const Allocator = struct {
field: i32,
};
fn foo() {
export fn foo() {
var x = List.init(&global_allocator);
x.init();
}
@ -1533,13 +1602,15 @@ fn foo() {
const TINY_QUANTUM_SHIFT = 4;
const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT;
var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1);
export fn entry() -> usize { @sizeOf(@typeOf(block_aligned_stuff)) }
)SOURCE", 1, ".tmp_source.zig:4:60: error: unable to perform binary not operation on type '(integer literal)'");
{
TestCase *tc = add_compile_fail_case("multiple files with private function error", R"SOURCE(
const foo = @import("foo.zig");
fn callPrivFunction() {
export fn callPrivFunction() {
foo.privateFunction();
}
)SOURCE", 2,
@ -1554,13 +1625,15 @@ fn privateFunction() { }
add_compile_fail_case("container init with non-type", R"SOURCE(
const zero: i32 = 0;
const a = zero{1};
export fn entry() -> usize { @sizeOf(@typeOf(a)) }
)SOURCE", 1, ".tmp_source.zig:3:11: error: expected type, found 'i32'");
add_compile_fail_case("assign to constant field", R"SOURCE(
const Foo = struct {
field: i32,
};
fn derp() {
export fn derp() {
const f = Foo {.field = 1234,};
f.field = 0;
}
@ -1580,6 +1653,8 @@ fn canFail() -> %void { }
pub fn maybeInt() -> ?i32 {
return 0;
}
export fn entry() -> usize { @sizeOf(@typeOf(testTrickyDefer)) }
)SOURCE", 1, ".tmp_source.zig:5:11: error: cannot return from defer expression");
add_compile_fail_case("attempt to access var args out of bounds", R"SOURCE(
@ -1590,6 +1665,8 @@ fn add(args: ...) -> i32 {
fn foo() -> i32 {
add(i32(1234))
}
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 2,
".tmp_source.zig:3:19: error: index 1 outside argument list of size 1",
".tmp_source.zig:7:8: note: called from here");
@ -1606,10 +1683,12 @@ fn add(args: ...) -> i32 {
fn bar() -> i32 {
add(1, 2, 3, 4)
}
export fn entry() -> usize { @sizeOf(@typeOf(bar)) }
)SOURCE", 1, ".tmp_source.zig:11:9: error: parameter of type '(integer literal)' requires comptime");
add_compile_fail_case("assign too big number to u16", R"SOURCE(
fn foo() {
export fn foo() {
var vga_mem: u16 = 0xB8000;
}
)SOURCE", 1, ".tmp_source.zig:3:24: error: integer value 753664 cannot be implicitly casted to type 'u16'");
@ -1619,10 +1698,11 @@ const some_data: [100]u8 = {
@setGlobalAlign(some_data, 3);
undefined
};
export fn entry() -> usize { @sizeOf(@typeOf(some_data)) }
)SOURCE", 1, ".tmp_source.zig:3:32: error: alignment value must be power of 2");
add_compile_fail_case("compile log", R"SOURCE(
fn foo() {
export fn foo() {
comptime bar(12, "hi");
}
fn bar(a: i32, b: []const u8) {
@ -1660,9 +1740,11 @@ fn foo(bit_field: &const BitField) -> u3 {
fn bar(x: &const u3) -> u3 {
return *x;
}
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:12:26: error: expected type '&const u3', found '&:3:6 const u3'");
add_compile_fail_case_no_check_unused("referring to a struct that is invalid without --check-unused", R"SOURCE(
add_compile_fail_case("referring to a struct that is invalid", R"SOURCE(
const UsbDeviceRequest = struct {
Type: u8,
};
@ -1679,7 +1761,7 @@ fn assert(ok: bool) {
".tmp_source.zig:7:20: note: called from here");
add_compile_fail_case("control flow uses comptime var at runtime", R"SOURCE(
fn foo() {
export fn foo() {
comptime var i = 0;
while (i < 5; i += 1) {
bar();
@ -1692,14 +1774,14 @@ fn bar() { }
".tmp_source.zig:4:21: note: compile-time variable assigned here");
add_compile_fail_case("ignored return value", R"SOURCE(
fn foo() {
export fn foo() {
bar();
}
fn bar() -> i32 { 0 }
)SOURCE", 1, ".tmp_source.zig:3:8: error: return value ignored");
add_compile_fail_case("integer literal on a non-comptime var", R"SOURCE(
fn foo() {
export fn foo() {
var i = 0;
while (i < 10; i += 1) { }
}
@ -1712,6 +1794,8 @@ pub fn pass(in: []u8) -> []u8 {
*out[0] = in[0];
return (*out)[0...1];
}
export fn entry() -> usize { @sizeOf(@typeOf(pass)) }
)SOURCE", 1, ".tmp_source.zig:5:5: error: attempt to dereference non pointer type '[10]u8'");
add_compile_fail_case("pass const ptr to mutable ptr fn", R"SOURCE(
@ -1723,6 +1807,8 @@ fn foo() -> bool {
fn ptrEql(a: &[]const u8, b: &[]const u8) -> bool {
return true;
}
export fn entry() -> usize { @sizeOf(@typeOf(foo)) }
)SOURCE", 1, ".tmp_source.zig:5:19: error: expected type '&[]const u8', found '&const []const u8'");
}
@ -2159,23 +2245,69 @@ static void run_self_hosted_test(bool is_release_mode) {
}
}
static void run_std_lib_test(bool is_release_mode) {
Buf std_index_file = BUF_INIT;
os_path_join(buf_create_from_str(ZIG_STD_DIR),
buf_create_from_str("index.zig"), &std_index_file);
Buf zig_stderr = BUF_INIT;
Buf zig_stdout = BUF_INIT;
ZigList<const char *> args = {0};
args.append("test");
args.append(buf_ptr(&std_index_file));
if (is_release_mode) {
args.append("--release");
}
Termination term;
os_exec_process(zig_exe, args, &term, &zig_stderr, &zig_stdout);
if (term.how != TerminationIdClean || term.code != 0) {
printf("\nstd lib tests failed:\n");
printf("./zig");
for (size_t i = 0; i < args.length; i += 1) {
printf(" %s", args.at(i));
}
printf("\n%s\n", buf_ptr(&zig_stderr));
exit(1);
}
}
static void add_self_hosted_tests(void) {
{
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = "self hosted tests (debug)";
test_case->is_self_hosted = true;
test_case->special = TestSpecialSelfHosted;
test_case->is_release_mode = false;
test_cases.append(test_case);
}
{
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = "self hosted tests (release)";
test_case->is_self_hosted = true;
test_case->special = TestSpecialSelfHosted;
test_case->is_release_mode = true;
test_cases.append(test_case);
}
}
static void add_std_lib_tests(void) {
{
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = "std (debug)";
test_case->special = TestSpecialStd;
test_case->is_release_mode = false;
test_cases.append(test_case);
}
{
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = "std (release)";
test_case->special = TestSpecialStd;
test_case->is_release_mode = true;
test_cases.append(test_case);
}
}
static void print_compiler_invocation(TestCase *test_case) {
printf("%s", zig_exe);
for (size_t i = 0; i < test_case->compiler_args.length; i += 1) {
@ -2193,8 +2325,10 @@ static void print_exe_invocation(TestCase *test_case) {
}
static void run_test(TestCase *test_case) {
if (test_case->is_self_hosted) {
if (test_case->special == TestSpecialSelfHosted) {
return run_self_hosted_test(test_case->is_release_mode);
} else if (test_case->special == TestSpecialStd) {
return run_std_lib_test(test_case->is_release_mode);
}
for (size_t i = 0; i < test_case->source_files.length; i += 1) {
@ -2366,6 +2500,7 @@ int main(int argc, char **argv) {
add_compile_failure_test_cases();
add_parseh_test_cases();
add_self_hosted_tests();
add_std_lib_tests();
run_all_tests(reverse);
cleanup();
}