Commit b774832e authored by dearblue's avatar dearblue

Make `mrb_static_assert()` a variable argument

`mrb_static_assert()` extends the macro function to take one or two arguments.
If the argument is other than that, an error will occur.

References:
- static_assert のメッセージ省略を許可 - cpprefjp C++日本語リファレンス
  https://cpprefjp.github.io/lang/cpp17/extending_static_assert.html
- c - Overloading Macro on Number of Arguments - Stack Overflow
  https://stackoverflow.com/a/11763277
parent 7850549a
......@@ -69,14 +69,18 @@
#define mrb_assert_int_fit(t1,n,t2,max) ((void)0)
#endif
#if (defined __cplusplus && __cplusplus >= 201103L) || \
#if (defined __cplusplus && __cplusplus >= 201703L)
# define mrb_static_assert(...) static_assert(__VA_ARGS__)
# define mrb_static_assert1(exp) static_assert(exp)
# define mrb_static_assert2(exp, str) static_assert(exp, str)
#elif (defined __cplusplus && __cplusplus >= 201103L) || \
(defined _MSC_VER) || \
(defined __GXX_EXPERIMENTAL_CXX0X__) /* for old G++/Clang++ */
# define mrb_static_assert(exp, str) static_assert(exp, str)
# define mrb_static_assert2(exp, str) static_assert(exp, str)
#elif defined __STDC_VERSION__ && \
((__STDC_VERSION__ >= 201112L) || \
(defined __GNUC__ && __GNUC__ * 100 + __GNUC_MINOR__ >= 406))
# define mrb_static_assert(exp, str) _Static_assert(exp, str)
# define mrb_static_assert2(exp, str) _Static_assert(exp, str)
#else
# /* alternative implementation of static_assert() */
# define _mrb_static_assert_cat0(a, b) a##b
......@@ -86,10 +90,24 @@
# else
# define _mrb_static_assert_id(prefix) _mrb_static_assert_cat(prefix, __LINE__)
# endif
# define mrb_static_assert(exp, str) \
# define mrb_static_assert2(exp, str) \
struct _mrb_static_assert_id(_mrb_static_assert_) { char x[(exp) ? 1 : -1]; }
#endif
#define mrb_static_assert1(exp) mrb_static_assert(exp, #exp)
#ifndef mrb_static_assert
# define mrb_static_assert1(exp) mrb_static_assert2(exp, #exp)
# define mrb_static_assert_expand(...) __VA_ARGS__ /* for MSVC behaviour - https://stackoverflow.com/q/5530505 */
# define mrb_static_assert_selector(a, b, name, ...) name
/**
* The `mrb_static_assert()` macro function takes one or two arguments.
*
* !!!c
* mrb_static_assert(expect_condition);
* mrb_static_assert(expect_condition, error_message);
*/
# define mrb_static_assert(...) \
mrb_static_assert_expand(mrb_static_assert_selector(__VA_ARGS__, mrb_static_assert2, mrb_static_assert1)(__VA_ARGS__))
#endif
#include "mrbconf.h"
......
......@@ -54,7 +54,7 @@ union mrb_value_ {
mrb_value value;
};
mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_));
mrb_static_assert(sizeof(mrb_value) == sizeof(union mrb_value_));
static inline union mrb_value_
mrb_val_union(mrb_value v)
......
......@@ -130,7 +130,7 @@ union mrb_value_ {
mrb_value value;
};
mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_));
mrb_static_assert(sizeof(mrb_value) == sizeof(union mrb_value_));
static inline union mrb_value_
mrb_val_union(mrb_value v)
......
......@@ -355,7 +355,7 @@ void mrb_mruby_random_gem_init(mrb_state *mrb)
struct RClass *random;
struct RClass *array = mrb->array_class;
mrb_static_assert1(sizeof(rand_state) <= ISTRUCT_DATA_SIZE);
mrb_static_assert(sizeof(rand_state) <= ISTRUCT_DATA_SIZE);
mrb_define_method(mrb, mrb->kernel_module, "rand", random_f_rand, MRB_ARGS_OPT(1));
mrb_define_method(mrb, mrb->kernel_module, "srand", random_f_srand, MRB_ARGS_OPT(1));
......
......@@ -200,7 +200,7 @@ gettimeofday_time(void)
#define GC_RED MRB_GC_RED
#define GC_WHITES (GC_WHITE_A | GC_WHITE_B)
#define GC_COLOR_MASK 7
mrb_static_assert1(MRB_GC_RED <= GC_COLOR_MASK);
mrb_static_assert(MRB_GC_RED <= GC_COLOR_MASK);
#define paint_gray(o) ((o)->color = GC_GRAY)
#define paint_black(o) ((o)->color = GC_BLACK)
......
......@@ -69,8 +69,8 @@
#define AR_MAX_SIZE 16
#define H_MAX_SIZE EA_MAX_CAPA
mrb_static_assert1(offsetof(struct RHash, iv) == offsetof(struct RObject, iv));
mrb_static_assert1(AR_MAX_SIZE < (1 << MRB_HASH_AR_EA_CAPA_BIT));
mrb_static_assert(offsetof(struct RHash, iv) == offsetof(struct RObject, iv));
mrb_static_assert(AR_MAX_SIZE < (1 << MRB_HASH_AR_EA_CAPA_BIT));
typedef struct hash_entry {
mrb_value key;
......@@ -243,7 +243,7 @@ DEFINE_SWITCHER(ht, HT)
* assumptions.
*/
# define HT_ASSERT_SAFE_READ(attr_name) \
mrb_static_assert1( \
mrb_static_assert( \
offsetof(hash_table, attr_name) + sizeof(((hash_table*)0)->attr_name) <= \
sizeof(hash_entry))
HT_ASSERT_SAFE_READ(ea);
......
......@@ -98,7 +98,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
if (irep->ilen > 0) {
size_t data_len = sizeof(mrb_code) * irep->ilen +
sizeof(struct mrb_irep_catch_handler) * irep->clen;
mrb_static_assert1(sizeof(struct mrb_irep_catch_handler) == 13);
mrb_static_assert(sizeof(struct mrb_irep_catch_handler) == 13);
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
return FALSE;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment