Commit 32e0dfd4f0

Andrew Kelley <superjoe30@gmail.com>
2018-06-04 20:09:31
never call malloc with size 0
instead we return nullptr. this makes the behavior consistent across all platforms. closes #1044 closes #1045
1 parent d21a192
Changed files (2)
src/analyze.cpp
@@ -1860,7 +1860,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
     }
 
     assert(!struct_type->data.structure.zero_bits_loop_flag);
-    assert(struct_type->data.structure.fields);
+    assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
     assert(decl_node->type == NodeTypeContainerDecl);
 
     size_t field_count = struct_type->data.structure.src_field_count;
@@ -2677,8 +2677,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
             return;
         }
         tag_type = enum_type;
+        abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count
         covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);
-        abi_alignment_so_far = get_abi_alignment(g, enum_type);
     } else {
         tag_type = nullptr;
         abi_alignment_so_far = 0;
src/util.hpp
@@ -65,6 +65,11 @@ static inline int clzll(unsigned long long mask) {
 
 template<typename T>
 ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
+#ifndef NDEBUG
+    // make behavior when size == 0 portable
+    if (count == 0)
+        return nullptr;
+#endif
     T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T)));
     if (!ptr)
         zig_panic("allocation failed");
@@ -73,6 +78,11 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
 
 template<typename T>
 ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
+#ifndef NDEBUG
+    // make behavior when size == 0 portable
+    if (count == 0)
+        return nullptr;
+#endif
     T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T)));
     if (!ptr)
         zig_panic("allocation failed");
@@ -93,9 +103,7 @@ static inline void safe_memcpy(T *dest, const T *src, size_t count) {
 
 template<typename T>
 static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
-    T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
-    if (!ptr)
-        zig_panic("allocation failed");
+    T *ptr = reallocate_nonzero(old, old_count, new_count);
     if (new_count > old_count) {
         memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));
     }
@@ -104,6 +112,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
 
 template<typename T>
 static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) {
+#ifndef NDEBUG
+    // make behavior when size == 0 portable
+    if (new_count == 0 && old == nullptr)
+        return nullptr;
+#endif
     T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
     if (!ptr)
         zig_panic("allocation failed");