authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-23 00:07:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-23 00:07:08-07:00
log1543043bf5b5633de485dccee88872a3d4f6c454
tree98de24dfa20e440a5c201727c8bb87102694e131
parentbfceb186319f52011762129c879abbe27eaa0161

fix no error emitted for redeclaring global var

closes #81

4 files changed, 103 insertions(+), 41 deletions(-)

src/all_types.hpp+10
...@@ -22,6 +22,7 @@ struct FnTableEntry;...@@ -22,6 +22,7 @@ struct FnTableEntry;
22struct BlockContext;22struct BlockContext;
23struct TypeTableEntry;23struct TypeTableEntry;
24struct VariableTableEntry;24struct VariableTableEntry;
25struct ErrorTableEntry;
25struct BuiltinFnEntry;26struct BuiltinFnEntry;
26struct LabelTableEntry;27struct LabelTableEntry;
27struct TypeStructField;28struct TypeStructField;
...@@ -69,6 +70,7 @@ struct ConstExprValue {...@@ -69,6 +70,7 @@ struct ConstExprValue {
69 bool x_bool;70 bool x_bool;
70 FnTableEntry *x_fn;71 FnTableEntry *x_fn;
71 TypeTableEntry *x_type;72 TypeTableEntry *x_type;
73 ErrorTableEntry *x_err;
72 ConstExprValue *x_maybe;74 ConstExprValue *x_maybe;
73 ConstEnumValue x_enum;75 ConstEnumValue x_enum;
74 ConstStructValue x_struct;76 ConstStructValue x_struct;
...@@ -996,6 +998,7 @@ struct CodeGen {...@@ -996,6 +998,7 @@ struct CodeGen {
996 LLVMValueRef memset_fn_val;998 LLVMValueRef memset_fn_val;
997 bool error_during_imports;999 bool error_during_imports;
998 uint32_t next_node_index;1000 uint32_t next_node_index;
1001 uint32_t next_error_index;
999};1002};
10001003
1001struct VariableTableEntry {1004struct VariableTableEntry {
...@@ -1010,12 +1013,19 @@ struct VariableTableEntry {...@@ -1010,12 +1013,19 @@ struct VariableTableEntry {
1010 int gen_arg_index;1013 int gen_arg_index;
1011};1014};
10121015
1016struct ErrorTableEntry {
1017 Buf name;
1018 uint32_t value;
1019 AstNode *decl_node;
1020};
1021
1013struct BlockContext {1022struct BlockContext {
1014 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot1023 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot
1015 FnTableEntry *fn_entry; // null at the module scope1024 FnTableEntry *fn_entry; // null at the module scope
1016 BlockContext *parent; // null when this is the root1025 BlockContext *parent; // null when this is the root
1017 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;1026 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
1018 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;1027 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
1028 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1019 ZigList<AstNode *> cast_alloca_list;1029 ZigList<AstNode *> cast_alloca_list;
1020 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;1030 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1021 ZigList<VariableTableEntry *> variable_list;1031 ZigList<VariableTableEntry *> variable_list;
src/analyze.cpp+76-41
...@@ -224,48 +224,26 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {...@@ -224,48 +224,26 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
224 return child_type->error_parent;224 return child_type->error_parent;
225 } else {225 } else {
226 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdError);226 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdError);
227 zig_panic("TODO get_error_type");
228 // create a struct with a boolean whether this is the null value
229 assert(child_type->type_ref);227 assert(child_type->type_ref);
230 LLVMTypeRef elem_types[] = {
231 child_type->type_ref,
232 LLVMInt1Type(),
233 };
234 entry->type_ref = LLVMStructType(elem_types, 2, false);
235 buf_resize(&entry->name, 0);
236 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
237 entry->size_in_bits = child_type->size_in_bits + 8;
238 entry->align_in_bits = child_type->align_in_bits;
239 assert(child_type->di_type);228 assert(child_type->di_type);
240229
230 buf_resize(&entry->name, 0);
231 buf_appendf(&entry->name, "%%%s", buf_ptr(&child_type->name));
241232
242 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);233 entry->data.error.child_type = child_type;
243 LLVMZigDIFile *di_file = nullptr;
244 unsigned line = 0;
245 entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder,
246 LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),
247 compile_unit_scope, di_file, line);
248
249 LLVMZigDIType *di_element_types[] = {
250 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
251 "val", di_file, line, child_type->size_in_bits, child_type->align_in_bits, 0, 0,
252 child_type->di_type),
253 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
254 "maybe", di_file, line, 8, 8, 8, 0,
255 child_type->di_type),
256 };
257 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
258 compile_unit_scope,
259 buf_ptr(&entry->name),
260 di_file, line, entry->size_in_bits, entry->align_in_bits, 0,
261 nullptr, di_element_types, 2, 0, nullptr, "");
262234
263 LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);235 if (child_type->size_in_bits == 0) {
264 entry->di_type = replacement_di_type;236 TypeTableEntry *tag_type = get_smallest_unsigned_int_type(g, g->next_error_index);
237 entry->type_ref = tag_type->type_ref;
238 entry->size_in_bits = tag_type->size_in_bits;
239 entry->align_in_bits = tag_type->align_in_bits;
240 entry->di_type = tag_type->di_type;
265241
266 entry->data.maybe.child_type = child_type;242 } else {
243 zig_panic("TODO get_error_type non-void");
244 }
267245
268 child_type->maybe_parent = entry;246 child_type->error_parent = entry;
269 return entry;247 return entry;
270 }248 }
271}249}
...@@ -938,6 +916,40 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -938,6 +916,40 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
938 }916 }
939}917}
940918
919static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
920 assert(node->type == NodeTypeErrorValueDecl);
921
922 ErrorTableEntry *err = allocate<ErrorTableEntry>(1);
923
924 err->value = g->next_error_index;
925 g->next_error_index += 1;
926
927 err->decl_node = node;
928 buf_init_from_buf(&err->name, &node->data.error_value_decl.name);
929
930 auto existing_entry = import->block_context->error_table.maybe_get(&err->name);
931 if (existing_entry) {
932 add_node_error(g, node, buf_sprintf("redefinition of error '%s'", buf_ptr(&err->name)));
933 } else {
934 import->block_context->error_table.put(&err->name, err);
935 }
936
937 bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
938 if (is_pub) {
939 for (int i = 0; i < import->importers.length; i += 1) {
940 ImporterInfo importer = import->importers.at(i);
941 auto table_entry = importer.import->block_context->error_table.maybe_get(&err->name);
942 if (table_entry) {
943 add_node_error(g, importer.source_node,
944 buf_sprintf("import of error '%s' overrides existing definition",
945 buf_ptr(&err->name)));
946 } else {
947 importer.import->block_context->error_table.put(&err->name, err);
948 }
949 }
950 }
951}
952
941static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {953static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
942 switch (node->type) {954 switch (node->type) {
943 case NodeTypeExternBlock:955 case NodeTypeExternBlock:
...@@ -984,10 +996,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -984,10 +996,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
984 break;996 break;
985 }997 }
986 case NodeTypeErrorValueDecl:998 case NodeTypeErrorValueDecl:
987 {999 resolve_error_value_decl(g, import, node);
988 zig_panic("TODO resolve_top_level_decl NodeTypeErrorValueDecl");1000 break;
989 break;
990 }
991 case NodeTypeUse:1001 case NodeTypeUse:
992 // nothing to do here1002 // nothing to do here
993 break;1003 break;
...@@ -1388,6 +1398,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -1388,6 +1398,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
1388 context->parent = parent;1398 context->parent = parent;
1389 context->variable_table.init(8);1399 context->variable_table.init(8);
1390 context->type_table.init(8);1400 context->type_table.init(8);
1401 context->error_table.init(8);
13911402
1392 if (parent) {1403 if (parent) {
1393 context->parent_loop_node = parent->parent_loop_node;1404 context->parent_loop_node = parent->parent_loop_node;
...@@ -1799,6 +1810,13 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F...@@ -1799,6 +1810,13 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F
1799 return fn->type_entry;1810 return fn->type_entry;
1800}1811}
18011812
1813static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) {
1814 Expr *expr = get_resolved_expr(node);
1815 expr->const_val.ok = true;
1816 expr->const_val.data.x_err = err;
1817 return get_error_type(g, g->builtin_types.entry_void);
1818}
1819
1802static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value) {1820static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value) {
1803 Expr *expr = get_resolved_expr(node);1821 Expr *expr = get_resolved_expr(node);
1804 expr->const_val.ok = true;1822 expr->const_val.ok = true;
...@@ -2333,7 +2351,13 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block...@@ -2333,7 +2351,13 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block
23332351
2334 if (name) {2352 if (name) {
2335 buf_init_from_buf(&variable_entry->name, name);2353 buf_init_from_buf(&variable_entry->name, name);
2336 VariableTableEntry *existing_var = find_local_variable(context, name);2354 VariableTableEntry *existing_var;
2355
2356 if (context->fn_entry) {
2357 existing_var = find_local_variable(context, name);
2358 } else {
2359 existing_var = find_variable(context, name);
2360 }
23372361
2338 if (existing_var) {2362 if (existing_var) {
2339 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));2363 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
...@@ -2511,7 +2535,18 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry...@@ -2511,7 +2535,18 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
2511static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,2535static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2512 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)2536 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
2513{2537{
2514 zig_panic("TODO analyze_error_literal_expr");2538 Buf *err_name = &node->data.error_literal.symbol;
2539
2540 auto err_table_entry = import->block_context->error_table.maybe_get(err_name);
2541
2542 if (err_table_entry) {
2543 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
2544 }
2545
2546 add_node_error(g, node,
2547 buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
2548
2549 return get_error_type(g, g->builtin_types.entry_void);
2515}2550}
25162551
2517static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,2552static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
src/codegen.cpp+1
...@@ -26,6 +26,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {...@@ -26,6 +26,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {
26 g->unresolved_top_level_decls.init(32);26 g->unresolved_top_level_decls.init(32);
27 g->build_type = CodeGenBuildTypeDebug;27 g->build_type = CodeGenBuildTypeDebug;
28 g->root_source_dir = root_source_dir;28 g->root_source_dir = root_source_dir;
29 g->next_error_index = 1;
2930
30 return g;31 return g;
31}32}
test/run_tests.cpp+16
...@@ -1484,6 +1484,21 @@ struct A { x : i32, }...@@ -1484,6 +1484,21 @@ struct A { x : i32, }
1484struct A { y : i32, }1484struct A { y : i32, }
1485 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");1485 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");
14861486
1487 add_compile_fail_case("redefinition of enums", R"SOURCE(
1488enum A {}
1489enum A {}
1490 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");
1491
1492 add_compile_fail_case("redefinition of error values", R"SOURCE(
1493%.A;
1494%.A;
1495 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of error 'A'");
1496
1497 add_compile_fail_case("redefinition of global variables", R"SOURCE(
1498var a : i32 = 1;
1499var a : i32 = 2;
1500 )SOURCE", 1, ".tmp_source.zig:3:1: error: redeclaration of variable 'a'");
1501
1487 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(1502 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
1488struct A { x : i32, }1503struct A { x : i32, }
1489export fn f(a : A) => {}1504export fn f(a : A) => {}
...@@ -1608,6 +1623,7 @@ extern {...@@ -1608,6 +1623,7 @@ extern {
1608}1623}
1609const x = foo();1624const x = foo();
1610 )SOURCE", 1, ".tmp_source.zig:5:11: error: global variable initializer requires constant expression");1625 )SOURCE", 1, ".tmp_source.zig:5:11: error: global variable initializer requires constant expression");
1626
1611}1627}
16121628
1613static void print_compiler_invocation(TestCase *test_case) {1629static void print_compiler_invocation(TestCase *test_case) {