| ... | @@ -65,6 +65,11 @@ static inline int clzll(unsigned long long mask) { | ... | @@ -65,6 +65,11 @@ static inline int clzll(unsigned long long mask) { |
| 65 | | 65 | |
| 66 | template<typename T> | 66 | template<typename T> |
| 67 | ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) { | 67 | ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) { |
| | 68 | #ifndef NDEBUG |
| | 69 | // make behavior when size == 0 portable |
| | 70 | if (count == 0) |
| | 71 | return nullptr; |
| | 72 | #endif |
| 68 | T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T))); | 73 | T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T))); |
| 69 | if (!ptr) | 74 | if (!ptr) |
| 70 | zig_panic("allocation failed"); | 75 | zig_panic("allocation failed"); |
| ... | @@ -73,6 +78,11 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) { | ... | @@ -73,6 +78,11 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) { |
| 73 | | 78 | |
| 74 | template<typename T> | 79 | template<typename T> |
| 75 | ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) { | 80 | ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) { |
| | 81 | #ifndef NDEBUG |
| | 82 | // make behavior when size == 0 portable |
| | 83 | if (count == 0) |
| | 84 | return nullptr; |
| | 85 | #endif |
| 76 | T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T))); | 86 | T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T))); |
| 77 | if (!ptr) | 87 | if (!ptr) |
| 78 | zig_panic("allocation failed"); | 88 | zig_panic("allocation failed"); |
| ... | @@ -93,9 +103,7 @@ static inline void safe_memcpy(T *dest, const T *src, size_t count) { | ... | @@ -93,9 +103,7 @@ static inline void safe_memcpy(T *dest, const T *src, size_t count) { |
| 93 | | 103 | |
| 94 | template<typename T> | 104 | template<typename T> |
| 95 | static inline T *reallocate(T *old, size_t old_count, size_t new_count) { | 105 | static inline T *reallocate(T *old, size_t old_count, size_t new_count) { |
| 96 | T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T))); | 106 | T *ptr = reallocate_nonzero(old, old_count, new_count); |
| 97 | if (!ptr) | | |
| 98 | zig_panic("allocation failed"); | | |
| 99 | if (new_count > old_count) { | 107 | if (new_count > old_count) { |
| 100 | memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T)); | 108 | memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T)); |
| 101 | } | 109 | } |
| ... | @@ -104,6 +112,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) { | ... | @@ -104,6 +112,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) { |
| 104 | | 112 | |
| 105 | template<typename T> | 113 | template<typename T> |
| 106 | static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) { | 114 | static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) { |
| | 115 | #ifndef NDEBUG |
| | 116 | // make behavior when size == 0 portable |
| | 117 | if (new_count == 0 && old == nullptr) |
| | 118 | return nullptr; |
| | 119 | #endif |
| 107 | T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T))); | 120 | T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T))); |
| 108 | if (!ptr) | 121 | if (!ptr) |
| 109 | zig_panic("allocation failed"); | 122 | zig_panic("allocation failed"); |