Commit 1f9734d1ee
Changed files (5)
src/all_types.hpp
@@ -271,6 +271,7 @@ struct AstNodeErrorValueDecl {
// populated by semantic analyzer
TopLevelDecl top_level_decl;
+ ErrorTableEntry *err;
};
enum BinOpType {
@@ -1034,6 +1035,7 @@ struct CodeGen {
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
HashMap<FnTypeId, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
+ HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
uint32_t next_unresolved_index;
@@ -1111,7 +1113,6 @@ struct CodeGen {
LLVMValueRef trap_fn_val;
bool error_during_imports;
uint32_t next_node_index;
- uint32_t next_error_index;
uint32_t error_value_count;
TypeTableEntry *err_tag_type;
LLVMValueRef int_overflow_fns[2][3][4]; // [0-signed,1-unsigned][0-add,1-sub,2-mul][0-8,1-16,2-32,3-64]
src/analyze.cpp
@@ -1290,36 +1290,39 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
}
}
-static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
+static void preview_error_value_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeErrorValueDecl);
ErrorTableEntry *err = allocate<ErrorTableEntry>(1);
- err->value = g->next_error_index;
- g->next_error_index += 1;
-
err->decl_node = node;
buf_init_from_buf(&err->name, &node->data.error_value_decl.name);
- auto existing_entry = import->block_context->error_table.maybe_get(&err->name);
+ auto existing_entry = g->error_table.maybe_get(&err->name);
if (existing_entry) {
- add_node_error(g, node, buf_sprintf("redefinition of error '%s'", buf_ptr(&err->name)));
+ // duplicate error definitions allowed and they get the same value
+ err->value = existing_entry->value->value;
} else {
- import->block_context->error_table.put(&err->name, err);
+ err->value = g->error_value_count;
+ g->error_value_count += 1;
+ g->error_table.put(&err->name, err);
}
+ node->data.error_value_decl.err = err;
+}
+
+static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
+ assert(node->type == NodeTypeErrorValueDecl);
+
+ ErrorTableEntry *err = node->data.error_value_decl.err;
+
+ import->block_context->error_table.put(&err->name, err);
+
bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
if (is_pub) {
for (int i = 0; i < import->importers.length; i += 1) {
ImporterInfo importer = import->importers.at(i);
- auto table_entry = importer.import->block_context->error_table.maybe_get(&err->name);
- if (table_entry) {
- add_node_error(g, importer.source_node,
- buf_sprintf("import of error '%s' overrides existing definition",
- buf_ptr(&err->name)));
- } else {
- importer.import->block_context->error_table.put(&err->name, err);
- }
+ importer.import->block_context->error_table.put(&err->name, err);
}
}
}
@@ -2516,7 +2519,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
add_node_error(g, node,
buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
- return get_error_type(g, g->builtin_types.entry_void);
+ return g->builtin_types.entry_invalid;
}
@@ -2759,6 +2762,16 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
are_equal = true;
}
}
+ if (bin_op_type == BinOpTypeCmpEq) {
+ answer = are_equal;
+ } else if (bin_op_type == BinOpTypeCmpNotEq) {
+ answer = !are_equal;
+ } else {
+ zig_unreachable();
+ }
+ } else if (resolved_type->id == TypeTableEntryIdPureError) {
+ bool are_equal = op1_val->data.x_err.err == op2_val->data.x_err.err;
+
if (bin_op_type == BinOpTypeCmpEq) {
answer = are_equal;
} else if (bin_op_type == BinOpTypeCmpNotEq) {
@@ -5402,7 +5415,7 @@ void semantic_analyze(CodeGen *g) {
target_import->importers.append({import, child});
} else if (child->type == NodeTypeErrorValueDecl) {
- g->error_value_count += 1;
+ preview_error_value_decl(g, child);
}
}
}
@@ -5428,8 +5441,6 @@ void semantic_analyze(CodeGen *g) {
}
}
- assert(g->error_value_count == g->next_error_index);
-
{
auto it = g->import_table.entry_iterator();
for (;;) {
src/codegen.cpp
@@ -28,10 +28,10 @@ CodeGen *codegen_create(Buf *root_source_dir) {
g->primitive_type_table.init(32);
g->unresolved_top_level_decls.init(32);
g->fn_type_table.init(32);
+ g->error_table.init(16);
g->is_release_build = false;
g->is_test_build = false;
g->root_source_dir = root_source_dir;
- g->next_error_index = 1;
g->error_value_count = 1;
g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
test/run_tests.cpp
@@ -1789,11 +1789,6 @@ enum A {}
enum A {}
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");
- add_compile_fail_case("redefinition of error values", R"SOURCE(
-error A;
-error A;
- )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of error 'A'");
-
add_compile_fail_case("redefinition of global variables", R"SOURCE(
var a : i32 = 1;
var a : i32 = 2;
test/self_hosted.zig
@@ -35,3 +35,14 @@ fn a_func() -> i32 { 13 }
fn call_struct_field(foo: Foo) -> i32 {
return foo.ptr();
}
+
+
+
+error AnError;
+error AnError;
+error SecondError;
+
+#attribute("test")
+fn redefinition_of_error_values_allowed() {
+ if (error.AnError == error.SecondError) unreachable{}
+}