Eliminate implicit conversions

Use explicit conversions everywhere. Adding bounds check assertions when
necessary.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-03-30 09:07:21 +00:00
parent 532a90d573
commit 0037b7e5fb
35 changed files with 786 additions and 671 deletions

View File

@ -3,6 +3,7 @@
#pragma once
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
@ -42,13 +43,51 @@ safe_isnan(double a) {
} while (0)
/// Same as assert, but evaluates the expression even in release builds
#define CHECK(expr) \
#define CHECK(expr) \
do { \
__auto_type __tmp = (expr); \
assert(__tmp); \
(void)__tmp; \
} while (0)
// Some macros for checked cast
#define to_int_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= INT_MIN && tmp <= INT_MAX); \
(int)tmp; \
})
#define to_char_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= CHAR_MIN && tmp <= CHAR_MAX); \
(char)tmp; \
})
#define to_u16_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= 0 && tmp <= UINT16_MAX); \
(uint16_t) tmp; \
})
#define to_i16_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= INT16_MIN && tmp <= INT16_MAX); \
(int16_t) tmp; \
})
#define to_u32_checked(val) \
({ \
auto tmp = (val); \
int64_t max = UINT32_MAX; /* silence clang tautological comparison \
warning*/ \
assert(tmp >= 0 && tmp <= max); \
(uint32_t) tmp; \
})
/**
* Normalize an int value to a specific range.
*
@ -65,33 +104,11 @@ static inline int attr_const normalize_i_range(int i, int min, int max) {
return i;
}
/**
* Select the larger integer of two.
*/
static inline int attr_const max_i(int a, int b) {
return (a > b ? a : b);
}
#define min2(a, b) ((a) > (b) ? (b) : (a))
#define max2(a, b) ((a) > (b) ? (a) : (b))
/**
* Select the smaller integer of two.
*/
static inline int attr_const min_i(int a, int b) {
return (a > b ? b : a);
}
/**
* Select the larger long integer of two.
*/
static inline long attr_const max_l(long a, long b) {
return (a > b ? a : b);
}
/**
* Select the smaller long integer of two.
*/
static inline long attr_const min_l(long a, long b) {
return (a > b ? b : a);
}
/// clamp `val` into interval [min, max]
#define clamp(val, min, max) max2(min2(val, max), min)
static inline int attr_const popcountl(unsigned long a) {
return __builtin_popcountl(a);
@ -147,11 +164,20 @@ allocchk_(const char *func_name, const char *file, unsigned int line, void *ptr)
#define cvalloc(size) allocchk(malloc(size))
/// @brief Wrapper of calloc().
#define ccalloc(nmemb, type) ((type *)allocchk(calloc((nmemb), sizeof(type))))
#define ccalloc(nmemb, type) \
({ \
auto tmp = (nmemb); \
assert(tmp >= 0); \
((type *)allocchk(calloc((size_t)tmp, sizeof(type)))); \
})
/// @brief Wrapper of ealloc().
#define crealloc(ptr, nmemb) \
((__typeof__(ptr))allocchk(realloc((ptr), (nmemb) * sizeof(*(ptr)))))
#define crealloc(ptr, nmemb) \
({ \
auto tmp = (nmemb); \
assert(tmp >= 0); \
((__typeof__(ptr))allocchk(realloc((ptr), (size_t)tmp * sizeof(*(ptr))))); \
})
/// RC_TYPE generates a reference counted type from `type`
///