Commit 32b37e695a

Andrew Kelley <andrew@ziglang.org>
2019-11-13 03:34:06
fix anonymous struct literal assigned to variable
closes #3667
1 parent 37318bf
Changed files (5)
src/analyze.cpp
@@ -5432,7 +5432,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
     return false;
 }
 
-// Whether the type has bits at runtime.
+// Deprecated. Use type_has_bits2.
 bool type_has_bits(ZigType *type_entry) {
     assert(type_entry != nullptr);
     assert(!type_is_invalid(type_entry));
@@ -5440,6 +5440,27 @@ bool type_has_bits(ZigType *type_entry) {
     return type_entry->abi_size != 0;
 }
 
+// Whether the type has bits at runtime.
+Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) {
+    Error err;
+
+    if (type_is_invalid(type_entry))
+        return ErrorSemanticAnalyzeFail;
+
+    if (type_entry->id == ZigTypeIdStruct &&
+        type_entry->data.structure.resolve_status == ResolveStatusBeingInferred)
+    {
+        *result = true;
+        return ErrorNone;
+    }
+
+    if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
+        return err;
+
+    *result = type_entry->abi_size != 0;
+    return ErrorNone;
+}
+
 // Whether you can infer the value based solely on the type.
 OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
     assert(type_entry != nullptr);
src/analyze.hpp
@@ -46,6 +46,8 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
 bool handle_is_ptr(ZigType *type_entry);
 
 bool type_has_bits(ZigType *type_entry);
+Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
+
 Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result);
 bool ptr_allows_addr_zero(ZigType *ptr_type);
 bool type_is_nonnull_ptr(ZigType *type);
src/codegen.cpp
@@ -3622,9 +3622,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_
 }
 
 static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
+    Error err;
+
     ZigType *ptr_type = instruction->ptr->value.type;
     assert(ptr_type->id == ZigTypeIdPointer);
-    if (!type_has_bits(ptr_type))
+    bool ptr_type_has_bits;
+    if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits)))
+        codegen_report_errors_and_exit(g);
+    if (!ptr_type_has_bits)
         return nullptr;
     if (instruction->ptr->ref_count == 0) {
         // In this case, this StorePtr instruction should be elided. Something happened like this:
src/ir.cpp
@@ -15513,15 +15513,16 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
     result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
     result->base.value.data.x_ptr.data.ref.pointee = pointee;
 
-    if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
+    bool var_type_has_bits;
+    if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits)))
         return ira->codegen->invalid_instruction;
     if (align != 0) {
         if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown)))
             return ira->codegen->invalid_instruction;
-        if (!type_has_bits(var_type)) {
-                ir_add_error(ira, source_inst,
-                    buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned",
-                        name_hint, buf_ptr(&var_type->name)));
+        if (!var_type_has_bits) {
+            ir_add_error(ira, source_inst,
+                buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned",
+                    name_hint, buf_ptr(&var_type->name)));
             return ira->codegen->invalid_instruction;
         }
     }
@@ -22138,15 +22139,15 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
             }
             for (size_t i = 0; i < errors_len; i += 1) {
                 Stage2ErrorMsg *clang_err = &errors_ptr[i];
-		// Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null
-		if (clang_err->source && clang_err->filename_ptr) {
+                // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null
+                if (clang_err->source && clang_err->filename_ptr) {
                     ErrorMsg *err_msg = err_msg_create_with_offset(
                         clang_err->filename_ptr ?
                             buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
                         clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
                         buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
                     err_msg_add_note(parent_err_msg, err_msg);
-		}
+                }
             }
 
             return ira->codegen->invalid_instruction;
test/stage1/behavior/struct.zig
@@ -755,7 +755,7 @@ test "fully anonymous struct" {
 test "fully anonymous list literal" {
     const S = struct {
         fn doTheTest() void {
-            dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
+            dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
         }
         fn dump(args: var) void {
             expect(args.@"0" == 1234);
@@ -768,3 +768,12 @@ test "fully anonymous list literal" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "anonymous struct literal assigned to variable" {
+    var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
+    expect(vec.@"0" == 22);
+    expect(vec.@"1" == 55);
+    expect(vec.@"2" == 99);
+    vec.@"1" += 1;
+    expect(vec.@"1" == 56);
+}