From 3ef6a00bb8854119d39bba521a0256d4884001f5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 30 Jan 2018 11:52:03 -0500 Subject: add compile error for duplicate struct, enum, union fields closes #730 --- src/analyze.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 23 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 9afd4cedc8..4fa8dad7ce 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -633,20 +633,27 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t static void slice_type_common_init(CodeGen *g, TypeTableEntry *pointer_type, TypeTableEntry *entry) { unsigned element_count = 2; + Buf *ptr_field_name = buf_create_from_str("ptr"); + Buf *len_field_name = buf_create_from_str("len"); + entry->data.structure.layout = ContainerLayoutAuto; entry->data.structure.is_slice = true; entry->data.structure.src_field_count = element_count; entry->data.structure.gen_field_count = element_count; entry->data.structure.fields = allocate(element_count); - entry->data.structure.fields[slice_ptr_index].name = buf_create_from_str("ptr"); + entry->data.structure.fields_by_name.init(element_count); + entry->data.structure.fields[slice_ptr_index].name = ptr_field_name; entry->data.structure.fields[slice_ptr_index].type_entry = pointer_type; entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index; entry->data.structure.fields[slice_ptr_index].gen_index = 0; - entry->data.structure.fields[slice_len_index].name = buf_create_from_str("len"); + entry->data.structure.fields[slice_len_index].name = len_field_name; entry->data.structure.fields[slice_len_index].type_entry = g->builtin_types.entry_usize; entry->data.structure.fields[slice_len_index].src_index = slice_len_index; entry->data.structure.fields[slice_len_index].gen_index = 1; + entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); + entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]); + assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type)); if (pointer_type->data.pointer.child_type->zero_bits) { entry->data.structure.gen_field_count = 1; @@ -1555,6 +1562,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f struct_type->data.structure.zero_bits_known = true; struct_type->data.structure.complete = true; struct_type->data.structure.fields = allocate(field_count); + struct_type->data.structure.fields_by_name.init(field_count); ZigLLVMDIType **di_element_types = allocate(field_count); LLVMTypeRef *element_types = allocate(field_count); @@ -1566,6 +1574,9 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f field->type_entry = field_types[i]; field->src_index = i; field->gen_index = i; + + auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); + assert(prev_entry == nullptr); } struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); @@ -2102,6 +2113,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { enum_type->data.enumeration.src_field_count = field_count; enum_type->data.enumeration.fields = allocate(field_count); + enum_type->data.enumeration.fields_by_name.init(field_count); Scope *scope = &enum_type->data.enumeration.decls_scope->base; @@ -2139,6 +2151,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; type_enum_field->name = field_node->data.struct_field.name; type_enum_field->decl_index = field_i; + type_enum_field->decl_node = field_node; if (field_node->data.struct_field.type != nullptr) { 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) { buf_sprintf("consider 'union(enum)' here")); } + auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); + if (field_entry != nullptr) { + ErrorMsg *msg = add_node_error(g, field_node, + buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name))); + add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); + enum_type->data.enumeration.is_invalid = true; + continue; + } + AstNode *tag_value = field_node->data.struct_field.value; // In this first pass we resolve explicit tag values. @@ -2242,6 +2264,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { size_t field_count = decl_node->data.container_decl.fields.length; struct_type->data.structure.src_field_count = (uint32_t)field_count; struct_type->data.structure.fields = allocate(field_count); + struct_type->data.structure.fields_by_name.init(field_count); Scope *scope = &struct_type->data.structure.decls_scope->base; @@ -2250,6 +2273,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { AstNode *field_node = decl_node->data.container_decl.fields.at(i); TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; type_struct_field->name = field_node->data.struct_field.name; + type_struct_field->decl_node = field_node; if (field_node->data.struct_field.type == nullptr) { 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) { continue; } + auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); + if (field_entry != nullptr) { + ErrorMsg *msg = add_node_error(g, field_node, + buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name))); + add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); + struct_type->data.structure.is_invalid = true; + continue; + } + TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); type_struct_field->type_entry = field_type; type_struct_field->src_index = i; @@ -2344,6 +2377,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { } union_type->data.unionation.src_field_count = field_count; union_type->data.unionation.fields = allocate(field_count); + union_type->data.unionation.fields_by_name.init(field_count); uint32_t biggest_align_bytes = 0; @@ -2395,6 +2429,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { tag_type->data.enumeration.layout = ContainerLayoutAuto; tag_type->data.enumeration.src_field_count = field_count; tag_type->data.enumeration.fields = allocate(field_count); + tag_type->data.enumeration.fields_by_name.init(field_count); tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; tag_type->data.enumeration.complete = true; } else if (enum_type_node != nullptr) { @@ -2424,6 +2459,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { Buf *field_name = field_node->data.struct_field.name; TypeUnionField *union_field = &union_type->data.unionation.fields[i]; union_field->name = field_node->data.struct_field.name; + union_field->decl_node = field_node; + + auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field); + if (field_entry != nullptr) { + ErrorMsg *msg = add_node_error(g, field_node, + buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name))); + add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); + union_type->data.unionation.is_invalid = true; + continue; + } TypeTableEntry *field_type; if (field_node->data.struct_field.type == nullptr) { @@ -2456,6 +2501,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { union_field->enum_field = &tag_type->data.enumeration.fields[i]; union_field->enum_field->name = field_name; union_field->enum_field->decl_index = i; + union_field->enum_field->decl_node = field_node; + + auto prev_entry = tag_type->data.enumeration.fields_by_name.put_unique(union_field->enum_field->name, union_field->enum_field); + assert(prev_entry == nullptr); // caught by union de-duplicator above AstNode *tag_value = field_node->data.struct_field.value; // In this first pass we resolve explicit tag values. @@ -3499,37 +3548,35 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) { } TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) { - for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { - TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; - if (buf_eql_buf(type_enum_field->name, name)) { - return type_enum_field; - } - } - return nullptr; + assert(enum_type->id == TypeTableEntryIdEnum); + if (enum_type->data.enumeration.src_field_count == 0) + return nullptr; + auto entry = enum_type->data.enumeration.fields_by_name.maybe_get(name); + if (entry == nullptr) + return nullptr; + return entry->value; } TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) { assert(type_entry->id == TypeTableEntryIdStruct); assert(type_entry->data.structure.complete); - for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; - if (buf_eql_buf(field->name, name)) { - return field; - } - } - return nullptr; + if (type_entry->data.structure.src_field_count == 0) + return nullptr; + auto entry = type_entry->data.structure.fields_by_name.maybe_get(name); + if (entry == nullptr) + return nullptr; + return entry->value; } TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { assert(type_entry->id == TypeTableEntryIdUnion); assert(type_entry->data.unionation.zero_bits_known); - for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { - TypeUnionField *field = &type_entry->data.unionation.fields[i]; - if (buf_eql_buf(field->enum_field->name, name)) { - return field; - } - } - return nullptr; + if (type_entry->data.unionation.src_field_count == 0) + return nullptr; + auto entry = type_entry->data.unionation.fields_by_name.maybe_get(name); + if (entry == nullptr) + return nullptr; + return entry->value; } TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { -- cgit v1.2.3 From 44f38b04b0cc374fcd377df0fe68f29c824185ff Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 31 Jan 2018 11:13:39 -0500 Subject: fix assertion fail when using global var number literal closes #697 --- src/analyze.cpp | 4 ++++ test/compile_errors.zig | 7 +++++++ 2 files changed, 11 insertions(+) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 4fa8dad7ce..2812c9d79e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3295,6 +3295,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { is_const, init_val, &tld_var->base); tld_var->var->linkage = linkage; + if (implicit_type != nullptr && type_is_invalid(implicit_type)) { + tld_var->var->value->type = g->builtin_types.entry_invalid; + } + if (var_decl->align_expr != nullptr) { if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { tld_var->var->value->type = g->builtin_types.entry_invalid; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 223646e767..3267ea7435 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,13 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("use invalid number literal as array index", + \\var v = 25; + \\export fn entry() void { + \\ var arr: [v]u8 = undefined; + \\} + , ".tmp_source.zig:1:1: error: unable to infer variable type"); + cases.add("duplicate struct field", \\const Foo = struct { \\ Bar: i32, -- cgit v1.2.3 From 0090c2d70b89cc6b5ab02bdc02aa49c4caf71a5a Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 7 Feb 2018 20:38:49 +0100 Subject: DRY 'is slice?' conditionals in parser (#750) --- src/analyze.cpp | 6 +----- src/ir.cpp | 8 ++------ 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 2812c9d79e..4c982c160c 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3380,11 +3380,7 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * } // slice const - if (expected_type->id == TypeTableEntryIdStruct && - actual_type->id == TypeTableEntryIdStruct && - expected_type->data.structure.is_slice && - actual_type->data.structure.is_slice) - { + if (is_slice(expected_type) && is_slice(actual_type)) { TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry; TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry; if ((!actual_ptr_type->data.pointer.is_const || expected_ptr_type->data.pointer.is_const) && diff --git a/src/ir.cpp b/src/ir.cpp index 1dc717286a..ae8ef00f2f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6369,10 +6369,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, } // implicit [N]T to []const T - if (expected_type->id == TypeTableEntryIdStruct && - expected_type->data.structure.is_slice && - actual_type->id == TypeTableEntryIdArray) - { + if (is_slice(expected_type) && actual_type->id == TypeTableEntryIdArray) { TypeTableEntry *ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry; assert(ptr_type->id == TypeTableEntryIdPointer); @@ -6384,8 +6381,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, } // implicit &const [N]T to []const T - if (expected_type->id == TypeTableEntryIdStruct && - expected_type->data.structure.is_slice && + if (is_slice(expected_type) && actual_type->id == TypeTableEntryIdPointer && actual_type->data.pointer.is_const && actual_type->data.pointer.child_type->id == TypeTableEntryIdArray) -- cgit v1.2.3