Commit b738cbdc76

Andrew Kelley <superjoe30@gmail.com>
2016-09-15 20:07:35
fix compiler crash involving slice with const slice child
also fix compiler crash for multiple errors in main fn prototype closes #191
1 parent 3f05fdc
src/analyze.cpp
@@ -558,100 +558,125 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
     } else {
         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
 
+        // If the child type is []const T then we need to make sure the type ref
+        // and debug info is the same as if the child type were []T.
+        if (is_slice(child_type)) {
+            TypeTableEntry *ptr_type = child_type->data.structure.fields[0].type_entry;
+            assert(ptr_type->id == TypeTableEntryIdPointer);
+            if (ptr_type->data.pointer.is_const) {
+                TypeTableEntry *non_const_child_type = get_slice_type(g,
+                    ptr_type->data.pointer.child_type, false);
+                TypeTableEntry *var_peer = get_slice_type(g, non_const_child_type, false);
+
+                entry->type_ref = var_peer->type_ref;
+                entry->di_type = var_peer->di_type;
+            }
+        }
+
         buf_resize(&entry->name, 0);
         buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
-        entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
-
-        ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
-        ZigLLVMDIFile *di_file = nullptr;
-        unsigned line = 0;
-        entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
-            ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
-            compile_unit_scope, di_file, line);
 
+        slice_type_common_init(g, child_type, is_const, entry);
         if (child_type->zero_bits) {
-            LLVMTypeRef element_types[] = {
-                g->builtin_types.entry_usize->type_ref,
-            };
-            LLVMStructSetBody(entry->type_ref, element_types, 1, false);
-
-            slice_type_common_init(g, child_type, is_const, entry);
-
             entry->data.structure.gen_field_count = 1;
             entry->data.structure.fields[0].gen_index = -1;
             entry->data.structure.fields[1].gen_index = 0;
+        }
 
-            TypeTableEntry *usize_type = g->builtin_types.entry_usize;
-            uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
-            uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
-            uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
-
-            uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
-            uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
-
-            ZigLLVMDIType *di_element_types[] = {
-                ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
-                        "len", di_file, line,
-                        len_debug_size_in_bits,
-                        len_debug_align_in_bits,
-                        len_offset_in_bits,
-                        0, usize_type->di_type),
-            };
-            ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
-                    compile_unit_scope,
-                    buf_ptr(&entry->name),
-                    di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
-                    nullptr, di_element_types, 1, 0, nullptr, "");
-
-            ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
-            entry->di_type = replacement_di_type;
-        } else {
-            TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
-
-            unsigned element_count = 2;
-            LLVMTypeRef element_types[] = {
-                pointer_type->type_ref,
-                g->builtin_types.entry_usize->type_ref,
-            };
-            LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
-
-            slice_type_common_init(g, child_type, is_const, entry);
-
-
-            uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);
-            uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);
-            uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
-
-            TypeTableEntry *usize_type = g->builtin_types.entry_usize;
-            uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
-            uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
-            uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
-
-            uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
-            uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
+        if (!entry->type_ref) {
+            entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
 
-            ZigLLVMDIType *di_element_types[] = {
-                ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
-                        "ptr", di_file, line,
-                        ptr_debug_size_in_bits,
-                        ptr_debug_align_in_bits,
-                        ptr_offset_in_bits,
-                        0, pointer_type->di_type),
-                ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
-                        "len", di_file, line,
-                        len_debug_size_in_bits,
-                        len_debug_align_in_bits,
-                        len_offset_in_bits,
-                        0, usize_type->di_type),
-            };
-            ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
-                    compile_unit_scope,
-                    buf_ptr(&entry->name),
-                    di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
-                    nullptr, di_element_types, 2, 0, nullptr, "");
+            ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
+            ZigLLVMDIFile *di_file = nullptr;
+            unsigned line = 0;
+            entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
+                ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
+                compile_unit_scope, di_file, line);
 
-            ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
-            entry->di_type = replacement_di_type;
+            if (child_type->zero_bits) {
+                LLVMTypeRef element_types[] = {
+                    g->builtin_types.entry_usize->type_ref,
+                };
+                LLVMStructSetBody(entry->type_ref, element_types, 1, false);
+
+                slice_type_common_init(g, child_type, is_const, entry);
+
+                entry->data.structure.gen_field_count = 1;
+                entry->data.structure.fields[0].gen_index = -1;
+                entry->data.structure.fields[1].gen_index = 0;
+
+                TypeTableEntry *usize_type = g->builtin_types.entry_usize;
+                uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
+                uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
+                uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
+
+                uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
+                uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
+
+                ZigLLVMDIType *di_element_types[] = {
+                    ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
+                            "len", di_file, line,
+                            len_debug_size_in_bits,
+                            len_debug_align_in_bits,
+                            len_offset_in_bits,
+                            0, usize_type->di_type),
+                };
+                ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
+                        compile_unit_scope,
+                        buf_ptr(&entry->name),
+                        di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
+                        nullptr, di_element_types, 1, 0, nullptr, "");
+
+                ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
+                entry->di_type = replacement_di_type;
+            } else {
+                TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
+
+                unsigned element_count = 2;
+                LLVMTypeRef element_types[] = {
+                    pointer_type->type_ref,
+                    g->builtin_types.entry_usize->type_ref,
+                };
+                LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
+
+                slice_type_common_init(g, child_type, is_const, entry);
+
+
+                uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);
+                uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);
+                uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
+
+                TypeTableEntry *usize_type = g->builtin_types.entry_usize;
+                uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
+                uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
+                uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
+
+                uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
+                uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
+
+                ZigLLVMDIType *di_element_types[] = {
+                    ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
+                            "ptr", di_file, line,
+                            ptr_debug_size_in_bits,
+                            ptr_debug_align_in_bits,
+                            ptr_offset_in_bits,
+                            0, pointer_type->di_type),
+                    ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
+                            "len", di_file, line,
+                            len_debug_size_in_bits,
+                            len_debug_align_in_bits,
+                            len_offset_in_bits,
+                            0, usize_type->di_type),
+                };
+                ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
+                        compile_unit_scope,
+                        buf_ptr(&entry->name),
+                        di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
+                        nullptr, di_element_types, 2, 0, nullptr, "");
+
+                ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
+                entry->di_type = replacement_di_type;
+            }
         }
 
 
@@ -1695,6 +1720,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
 
             bool is_main_fn = !is_generic_instance &&
                 !parent_decl && (import == g->root_import) &&
+                !proto_node->data.fn_proto.skip &&
                 buf_eql_str(proto_name, "main");
             if (is_main_fn) {
                 g->main_fn = fn_table_entry;
test/cases/const_slice_child.zig
@@ -0,0 +1,48 @@
+const assert = @import("std").debug.assert;
+
+var argv: &&const u8 = undefined;
+
+#attribute("test")
+fn constSliceChild() {
+    const strs = ([]&const u8) {
+        c"one",
+        c"two",
+        c"three",
+    };
+    argv = &strs[0];
+    bar(strs.len);
+}
+
+#static_eval_enable(false)
+fn foo(args: [][]const u8) {
+    assert(args.len == 3);
+    assert(streql(args[0], "one"));
+    assert(streql(args[1], "two"));
+    assert(streql(args[2], "three"));
+}
+
+#static_eval_enable(false)
+fn bar(argc: usize) {
+    var args: [argc][]u8 = undefined;
+    for (args) |_, i| {
+        const ptr = argv[i];
+        args[i] = ptr[0...strlen(ptr)];
+    }
+    foo(args);
+}
+
+#static_eval_enable(false)
+fn strlen(ptr: &const u8) -> usize {
+    var count: usize = 0;
+    while (ptr[count] != 0; count += 1) {}
+    return count;
+}
+
+#static_eval_enable(false)
+fn streql(a: []const u8, b: []const u8) -> bool {
+    if (a.len != b.len) return false;
+    for (a) |item, index| {
+        if (b[index] != item) return false;
+    }
+    return true;
+}
test/run_tests.cpp
@@ -1491,6 +1491,10 @@ pub fn f() {
   cstr[0] = 'W';
 }
     )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
+
+    add_compile_fail_case("main function with bogus args type", R"SOURCE(
+pub fn main(args: [][]bogus) -> %void {}
+    )SOURCE", 1, ".tmp_source.zig:2:23: error: use of undeclared identifier 'bogus'");
 }
 
 //////////////////////////////////////////////////////////////////////////////
test/self_hosted.zig
@@ -10,6 +10,7 @@ const test_sizeof_and_typeof = @import("cases/sizeof_and_typeof.zig");
 const test_maybe_return = @import("cases/maybe_return.zig");
 const test_max_value_type = @import("cases/max_value_type.zig");
 const test_var_params = @import("cases/var_params.zig");
+const test_const_slice_child = @import("cases/const_slice_child.zig");
 
 // normal comment
 /// this is a documentation comment