authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-30 11:52:03-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-30 11:52:03-05:00
log3ef6a00bb8854119d39bba521a0256d4884001f5
treeb0ae89e6811a01c300207b6cd02524176e1057dd
parent0995a81b8b59b627654ecbf55fa86cd8e98161c6

add compile error for duplicate struct, enum, union fields

closes #730

4 files changed, 117 insertions(+), 25 deletions(-)

src/all_types.hpp+9
......@@ -331,12 +331,14 @@ struct TypeEnumField {
331331 Buf *name;
332332 BigInt value;
333333 uint32_t decl_index;
334 AstNode *decl_node;
334335};
335336
336337struct TypeUnionField {
337338 Buf *name;
338339 TypeEnumField *enum_field;
339340 TypeTableEntry *type_entry;
341 AstNode *decl_node;
340342 uint32_t gen_index;
341343};
342344
......@@ -961,6 +963,7 @@ struct TypeStructField {
961963 size_t packed_bits_offset;
962964 size_t packed_bits_size;
963965 size_t unaligned_bit_count;
966 AstNode *decl_node;
964967};
965968struct TypeTableEntryStruct {
966969 AstNode *decl_node;
......@@ -982,6 +985,8 @@ struct TypeTableEntryStruct {
982985 bool zero_bits_loop_flag;
983986 bool zero_bits_known;
984987 uint32_t abi_alignment; // also figured out with zero_bits pass
988
989 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
985990};
986991
987992struct TypeTableEntryMaybe {
......@@ -1013,6 +1018,8 @@ struct TypeTableEntryEnum {
10131018
10141019 bool generate_name_table;
10151020 LLVMValueRef name_table;
1021
1022 HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
10161023};
10171024
10181025uint32_t type_ptr_hash(const TypeTableEntry *ptr);
......@@ -1045,6 +1052,8 @@ struct TypeTableEntryUnion {
10451052
10461053 uint32_t union_size_bytes;
10471054 TypeTableEntry *most_aligned_union_member;
1055
1056 HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
10481057};
10491058
10501059struct FnGenParamInfo {
src/analyze.cpp+70-23
......@@ -633,20 +633,27 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
633633
634634static void slice_type_common_init(CodeGen *g, TypeTableEntry *pointer_type, TypeTableEntry *entry) {
635635 unsigned element_count = 2;
636 Buf *ptr_field_name = buf_create_from_str("ptr");
637 Buf *len_field_name = buf_create_from_str("len");
638
636639 entry->data.structure.layout = ContainerLayoutAuto;
637640 entry->data.structure.is_slice = true;
638641 entry->data.structure.src_field_count = element_count;
639642 entry->data.structure.gen_field_count = element_count;
640643 entry->data.structure.fields = allocate<TypeStructField>(element_count);
641 entry->data.structure.fields[slice_ptr_index].name = buf_create_from_str("ptr");
644 entry->data.structure.fields_by_name.init(element_count);
645 entry->data.structure.fields[slice_ptr_index].name = ptr_field_name;
642646 entry->data.structure.fields[slice_ptr_index].type_entry = pointer_type;
643647 entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index;
644648 entry->data.structure.fields[slice_ptr_index].gen_index = 0;
645 entry->data.structure.fields[slice_len_index].name = buf_create_from_str("len");
649 entry->data.structure.fields[slice_len_index].name = len_field_name;
646650 entry->data.structure.fields[slice_len_index].type_entry = g->builtin_types.entry_usize;
647651 entry->data.structure.fields[slice_len_index].src_index = slice_len_index;
648652 entry->data.structure.fields[slice_len_index].gen_index = 1;
649653
654 entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);
655 entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);
656
650657 assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type));
651658 if (pointer_type->data.pointer.child_type->zero_bits) {
652659 entry->data.structure.gen_field_count = 1;
......@@ -1555,6 +1562,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
15551562 struct_type->data.structure.zero_bits_known = true;
15561563 struct_type->data.structure.complete = true;
15571564 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
1565 struct_type->data.structure.fields_by_name.init(field_count);
15581566
15591567 ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(field_count);
15601568 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
......@@ -1566,6 +1574,9 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
15661574 field->type_entry = field_types[i];
15671575 field->src_index = i;
15681576 field->gen_index = i;
1577
1578 auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
1579 assert(prev_entry == nullptr);
15691580 }
15701581
15711582 struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name);
......@@ -2102,6 +2113,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21022113
21032114 enum_type->data.enumeration.src_field_count = field_count;
21042115 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
2116 enum_type->data.enumeration.fields_by_name.init(field_count);
21052117
21062118 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
21072119
......@@ -2139,6 +2151,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21392151 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
21402152 type_enum_field->name = field_node->data.struct_field.name;
21412153 type_enum_field->decl_index = field_i;
2154 type_enum_field->decl_node = field_node;
21422155
21432156 if (field_node->data.struct_field.type != nullptr) {
21442157 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
......@@ -2147,6 +2160,15 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21472160 buf_sprintf("consider 'union(enum)' here"));
21482161 }
21492162
2163 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
2164 if (field_entry != nullptr) {
2165 ErrorMsg *msg = add_node_error(g, field_node,
2166 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
2167 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2168 enum_type->data.enumeration.is_invalid = true;
2169 continue;
2170 }
2171
21502172 AstNode *tag_value = field_node->data.struct_field.value;
21512173
21522174 // In this first pass we resolve explicit tag values.
......@@ -2242,6 +2264,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
22422264 size_t field_count = decl_node->data.container_decl.fields.length;
22432265 struct_type->data.structure.src_field_count = (uint32_t)field_count;
22442266 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
2267 struct_type->data.structure.fields_by_name.init(field_count);
22452268
22462269 Scope *scope = &struct_type->data.structure.decls_scope->base;
22472270
......@@ -2250,6 +2273,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
22502273 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
22512274 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
22522275 type_struct_field->name = field_node->data.struct_field.name;
2276 type_struct_field->decl_node = field_node;
22532277
22542278 if (field_node->data.struct_field.type == nullptr) {
22552279 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
......@@ -2257,6 +2281,15 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
22572281 continue;
22582282 }
22592283
2284 auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);
2285 if (field_entry != nullptr) {
2286 ErrorMsg *msg = add_node_error(g, field_node,
2287 buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));
2288 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2289 struct_type->data.structure.is_invalid = true;
2290 continue;
2291 }
2292
22602293 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
22612294 type_struct_field->type_entry = field_type;
22622295 type_struct_field->src_index = i;
......@@ -2344,6 +2377,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23442377 }
23452378 union_type->data.unionation.src_field_count = field_count;
23462379 union_type->data.unionation.fields = allocate<TypeUnionField>(field_count);
2380 union_type->data.unionation.fields_by_name.init(field_count);
23472381
23482382 uint32_t biggest_align_bytes = 0;
23492383
......@@ -2395,6 +2429,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23952429 tag_type->data.enumeration.layout = ContainerLayoutAuto;
23962430 tag_type->data.enumeration.src_field_count = field_count;
23972431 tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
2432 tag_type->data.enumeration.fields_by_name.init(field_count);
23982433 tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
23992434 tag_type->data.enumeration.complete = true;
24002435 } else if (enum_type_node != nullptr) {
......@@ -2424,6 +2459,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
24242459 Buf *field_name = field_node->data.struct_field.name;
24252460 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
24262461 union_field->name = field_node->data.struct_field.name;
2462 union_field->decl_node = field_node;
2463
2464 auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field);
2465 if (field_entry != nullptr) {
2466 ErrorMsg *msg = add_node_error(g, field_node,
2467 buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name)));
2468 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2469 union_type->data.unionation.is_invalid = true;
2470 continue;
2471 }
24272472
24282473 TypeTableEntry *field_type;
24292474 if (field_node->data.struct_field.type == nullptr) {
......@@ -2456,6 +2501,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
24562501 union_field->enum_field = &tag_type->data.enumeration.fields[i];
24572502 union_field->enum_field->name = field_name;
24582503 union_field->enum_field->decl_index = i;
2504 union_field->enum_field->decl_node = field_node;
2505
2506 auto prev_entry = tag_type->data.enumeration.fields_by_name.put_unique(union_field->enum_field->name, union_field->enum_field);
2507 assert(prev_entry == nullptr); // caught by union de-duplicator above
24592508
24602509 AstNode *tag_value = field_node->data.struct_field.value;
24612510 // In this first pass we resolve explicit tag values.
......@@ -3499,37 +3548,35 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {
34993548}
35003549
35013550TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
3502 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
3503 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
3504 if (buf_eql_buf(type_enum_field->name, name)) {
3505 return type_enum_field;
3506 }
3507 }
3508 return nullptr;
3551 assert(enum_type->id == TypeTableEntryIdEnum);
3552 if (enum_type->data.enumeration.src_field_count == 0)
3553 return nullptr;
3554 auto entry = enum_type->data.enumeration.fields_by_name.maybe_get(name);
3555 if (entry == nullptr)
3556 return nullptr;
3557 return entry->value;
35093558}
35103559
35113560TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
35123561 assert(type_entry->id == TypeTableEntryIdStruct);
35133562 assert(type_entry->data.structure.complete);
3514 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
3515 TypeStructField *field = &type_entry->data.structure.fields[i];
3516 if (buf_eql_buf(field->name, name)) {
3517 return field;
3518 }
3519 }
3520 return nullptr;
3563 if (type_entry->data.structure.src_field_count == 0)
3564 return nullptr;
3565 auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);
3566 if (entry == nullptr)
3567 return nullptr;
3568 return entry->value;
35213569}
35223570
35233571TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
35243572 assert(type_entry->id == TypeTableEntryIdUnion);
35253573 assert(type_entry->data.unionation.zero_bits_known);
3526 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
3527 TypeUnionField *field = &type_entry->data.unionation.fields[i];
3528 if (buf_eql_buf(field->enum_field->name, name)) {
3529 return field;
3530 }
3531 }
3532 return nullptr;
3574 if (type_entry->data.unionation.src_field_count == 0)
3575 return nullptr;
3576 auto entry = type_entry->data.unionation.fields_by_name.maybe_get(name);
3577 if (entry == nullptr)
3578 return nullptr;
3579 return entry->value;
35333580}
35343581
35353582TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
src/analyze.hpp+1-1
......@@ -60,8 +60,8 @@ bool type_is_complete(TypeTableEntry *type_entry);
6060bool type_is_invalid(TypeTableEntry *type_entry);
6161bool type_has_zero_bits_known(TypeTableEntry *type_entry);
6262void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry);
63TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
6463ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
64TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
6565TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
6666TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
6767TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
test/compile_errors.zig+37-1
......@@ -1,6 +1,43 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: &tests.CompileErrorContext) void {
4 cases.add("duplicate struct field",
5 \\const Foo = struct {
6 \\ Bar: i32,
7 \\ Bar: usize,
8 \\};
9 \\export fn entry() void {
10 \\ const a: Foo = undefined;
11 \\}
12 ,
13 ".tmp_source.zig:3:5: error: duplicate struct field: 'Bar'",
14 ".tmp_source.zig:2:5: note: other field here");
15
16 cases.add("duplicate union field",
17 \\const Foo = union {
18 \\ Bar: i32,
19 \\ Bar: usize,
20 \\};
21 \\export fn entry() void {
22 \\ const a: Foo = undefined;
23 \\}
24 ,
25 ".tmp_source.zig:3:5: error: duplicate union field: 'Bar'",
26 ".tmp_source.zig:2:5: note: other field here");
27
28 cases.add("duplicate enum field",
29 \\const Foo = enum {
30 \\ Bar,
31 \\ Bar,
32 \\};
33 \\
34 \\export fn entry() void {
35 \\ const a: Foo = undefined;
36 \\}
37 ,
38 ".tmp_source.zig:3:5: error: duplicate enum field: 'Bar'",
39 ".tmp_source.zig:2:5: note: other field here");
40
441 cases.add("calling function with naked calling convention",
542 \\export fn entry() void {
643 \\ foo();
......@@ -10,7 +47,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
1047 ".tmp_source.zig:2:5: error: unable to call function with naked calling convention",
1148 ".tmp_source.zig:4:9: note: declared here");
1249
13
1450 cases.add("function with invalid return type",
1551 \\export fn foo() boid {}
1652 , ".tmp_source.zig:1:17: error: use of undeclared identifier 'boid'");