Commit 7b8c5578c6

Andrew Kelley <andrew@ziglang.org>
2019-02-25 22:28:23
fix infinite recursion in type_has_one_possible_value
closes #2006
1 parent 33cbb29
Changed files (5)
src/all_types.hpp
@@ -1240,6 +1240,12 @@ enum ZigTypeId {
     ZigTypeIdVector,
 };
 
+enum OnePossibleValue {
+    OnePossibleValueInvalid,
+    OnePossibleValueNo,
+    OnePossibleValueYes,
+};
+
 struct ZigType {
     ZigTypeId id;
     Buf name;
@@ -1247,9 +1253,6 @@ struct ZigType {
     LLVMTypeRef type_ref;
     ZigLLVMDIType *di_type;
 
-    bool zero_bits; // this is denormalized data
-    bool gen_h_loop_flag;
-
     union {
         ZigTypePointer pointer;
         ZigTypeInt integral;
@@ -1275,6 +1278,11 @@ struct ZigType {
     // If we generate a constant name value for this type, we memoize it here.
     // The type of this is array
     ConstExprValue *cached_const_name_val;
+
+    OnePossibleValue one_possible_value;
+
+    bool zero_bits; // this is denormalized data
+    bool gen_h_loop_flag;
 };
 
 struct PackageTableEntry {
src/analyze.cpp
@@ -5129,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) {
 // 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);
+
+    if (type_entry->one_possible_value != OnePossibleValueInvalid)
+        return type_entry->one_possible_value;
+
     Error err;
     if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
         return OnePossibleValueInvalid;
@@ -5176,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
         case ZigTypeIdInt:
         case ZigTypeIdVector:
             return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
-        case ZigTypeIdPointer:
-            return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
+        case ZigTypeIdPointer: {
+            ZigType *elem_type = type_entry->data.pointer.child_type;
+            // If the recursive function call asks, then we are not one possible value.
+            type_entry->one_possible_value = OnePossibleValueNo;
+            // Now update it to be the value of the recursive call.
+            type_entry->one_possible_value = type_has_one_possible_value(g, elem_type);
+            return type_entry->one_possible_value;
+        }
         case ZigTypeIdUnion:
             if (type_entry->data.unionation.src_field_count > 1)
                 return OnePossibleValueNo;
src/analyze.hpp
@@ -226,11 +226,6 @@ enum ReqCompTime {
 };
 ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
 
-enum OnePossibleValue {
-    OnePossibleValueInvalid,
-    OnePossibleValueNo,
-    OnePossibleValueYes,
-};
 OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
 
 Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
test/stage1/behavior/bugs/2006.zig
@@ -0,0 +1,12 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+const S = struct {
+    p: *S,
+};
+test "bug 2006" {
+    var a: S = undefined;
+    a = S{ .p = undefined };
+    expect(@sizeOf(S) != 0);
+    expect(@sizeOf(*void) == 0);
+}
test/stage1/behavior.zig
@@ -19,6 +19,7 @@ comptime {
     _ = @import("behavior/bugs/1442.zig");
     _ = @import("behavior/bugs/1486.zig");
     _ = @import("behavior/bugs/1851.zig");
+    _ = @import("behavior/bugs/2006.zig");
     _ = @import("behavior/bugs/394.zig");
     _ = @import("behavior/bugs/421.zig");
     _ = @import("behavior/bugs/655.zig");