From 7b8c5578c6c174893c5dd08e89cf3b3492ae065f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 25 Feb 2019 16:28:23 -0500 Subject: [PATCH] fix infinite recursion in type_has_one_possible_value closes #2006 --- src/all_types.hpp | 14 +++++++++++--- src/analyze.cpp | 14 ++++++++++++-- src/analyze.hpp | 5 ----- test/stage1/behavior.zig | 1 + test/stage1/behavior/bugs/2006.zig | 12 ++++++++++++ 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 test/stage1/behavior/bugs/2006.zig diff --git a/src/all_types.hpp b/src/all_types.hpp index 8099f99f48..44c1cc0956 100644 --- a/src/all_types.hpp +++ b/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 { diff --git a/src/analyze.cpp b/src/analyze.cpp index 0ecff11142..5d9b0df8ee 100644 --- a/src/analyze.cpp +++ b/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; diff --git a/src/analyze.hpp b/src/analyze.hpp index de4785fb27..e8838ae57e 100644 --- a/src/analyze.hpp +++ b/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, diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index f7fc1c42a4..d18f127f92 100644 --- a/test/stage1/behavior.zig +++ b/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"); diff --git a/test/stage1/behavior/bugs/2006.zig b/test/stage1/behavior/bugs/2006.zig new file mode 100644 index 0000000000..dad78a9ba0 --- /dev/null +++ b/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); +}