add several __has_something macro

With these macros implemented we can write codes just like we can assume
the compiler being clang.  MSC_VERSION_SINCE is defined to implement
those macros, but turned out to be handy for other places.  The -fdeclspec
compiler flag is necessary for clang to properly handle __has_declspec().
This commit is contained in:
卜部昌平 2019-12-02 14:58:43 +09:00
parent 863dbb21d8
commit 0958e19ffb
Notes: git 2019-12-26 20:46:07 +09:00
8 changed files with 115 additions and 30 deletions

View File

@ -5373,11 +5373,9 @@ rb_integer_float_cmp(VALUE x, VALUE y)
#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */
COMPILER_WARNING_PUSH
#ifdef __has_warning
#if __has_warning("-Wimplicit-int-float-conversion")
COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
#endif
#endif
static const double LONG_MAX_as_double = LONG_MAX;
COMPILER_WARNING_POP
#endif

View File

@ -481,6 +481,8 @@ AS_IF([test x"${RPATHFLAG}" = x], [
rpathflag=`echo "$RPATHFLAG" | sed 's/%.*//'`
])
RUBY_TRY_CFLAGS(-fdeclspec, [RUBY_APPEND_OPTIONS(XCFLAGS, -fdeclspec)])
AS_CASE([$RUBY_PATCHLEVEL], [-*],
[RUBY_DEVEL=yes], [RUBY_DEVEL=no])
particular_werror_flags=$RUBY_DEVEL

View File

@ -10,6 +10,103 @@
* file COPYING are met. Consult the file for details.
*/
#include "ruby/defines.h" /* for GCC_VERSION_SINCE */
#ifdef _MSC_VER
# define MSC_VERSION_SINCE(_) (_MSC_VER >= _)
# define MSC_VERSION_BEFORE(_) (_MSC_VER < _)
#else
# define MSC_VERSION_SINCE(_) 0
# define MSC_VERSION_BEFORE(_) 0
#endif
#ifndef __has_attribute
# define __has_attribute(...) __has_attribute_##__VA_ARGS__
# /* GCC <= 4 lacks __has_attribute predefined macro, while has attributes
# * themselves. We can simulate the macro like the following: */
# define __has_attribute_aligned GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_alloc_size GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_artificial GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_always_inline GCC_VERSION_SINCE(3, 1, 0)
# define __has_attribute_cdecl GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_cold GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_const GCC_VERSION_SINCE(2, 6, 0)
# define __has_attribute_deprecated GCC_VERSION_SINCE(3, 1, 0)
# define __has_attribute_dllexport GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_dllimport GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_error GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_format GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_hot GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_leaf GCC_VERSION_SINCE(4, 6, 0)
# define __has_attribute_malloc GCC_VERSION_SINCE(3, 0, 0)
# define __has_attribute_no_address_safety_analysis GCC_VERSION_SINCE(4, 8, 0)
# define __has_attribute_no_sanitize_address GCC_VERSION_SINCE(4, 8, 0)
# define __has_attribute_no_sanitize_undefined GCC_VERSION_SINCE(4, 9, 0)
# define __has_attribute_noinline GCC_VERSION_SINCE(3, 1, 0)
# define __has_attribute_nonnull GCC_VERSION_SINCE(3, 3, 0)
# define __has_attribute_noreturn GCC_VERSION_SINCE(2, 5, 0)
# define __has_attribute_nothrow GCC_VERSION_SINCE(3, 3, 0)
# define __has_attribute_pure GCC_VERSION_SINCE(2, 96, 0)
# define __has_attribute_returns_nonnull GCC_VERSION_SINCE(4, 9, 0)
# define __has_attribute_returns_twice GCC_VERSION_SINCE(4, 1, 0)
# define __has_attribute_stdcall GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_unused GCC_VERSION_SINCE(0, 0, 0)
# define __has_attribute_visibility GCC_VERSION_SINCE(3, 3, 0)
# define __has_attribute_visibility GCC_VERSION_SINCE(3, 3, 0)
# define __has_attribute_warn_unused_result GCC_VERSION_SINCE(3, 4, 0)
# define __has_attribute_warning GCC_VERSION_SINCE(4, 3, 0)
# define __has_attribute_weak GCC_VERSION_SINCE(0, 0, 0)
# /* Note that 0,0,0 might be inaccurate. */
#endif
#ifndef __has_c_attribute
# /* As of writing everything that lacks __has_c_attribute also completely
# * lacks C2x attributes as well. Might change in future? */
# define __has_c_attribute(...) 0
#endif
#ifndef __has_declspec_attribute
# define __has_declspec_attribute(...) __has_declspec_attribute_##__VA_ARGS__
# define __has_declspec_attribute_align MSC_VERSION_SINCE( 800)
# define __has_declspec_attribute_deprecated MSC_VERSION_SINCE(1300)
# define __has_declspec_attribute_dllexport MSC_VERSION_SINCE( 800)
# define __has_declspec_attribute_dllimport MSC_VERSION_SINCE( 800)
# define __has_declspec_attribute_noalias MSC_VERSION_SINCE( 800)
# define __has_declspec_attribute_noinline MSC_VERSION_SINCE(1300)
# define __has_declspec_attribute_noreturn MSC_VERSION_SINCE(1100)
# define __has_declspec_attribute_nothrow MSC_VERSION_SINCE( 800)
# define __has_declspec_attribute_restrict MSC_VERSION_SINCE( 800)
# /* Note that 800 might be inaccurate. */
#endif
#ifndef __has_builtin
# /* :FIXME: Historically GCC has had tons of builtins, but it implemented
# * __has_builtin only since GCC 10. This section can be made more
# * granular. */
# /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */
# define __has_builtin(...) GCC_VERSION_SINCE(0, 0, 0)
#endif
#ifndef __has_feature
# define __has_feature(...) 0
#endif
#ifndef __has_extension
# /* Pre-3.0 clang had __has_feature but not __has_extension. */
# define __has_extension __has_feature
#endif
#ifndef __has_warning
# /* We cannot simulate __has_warning like the ones above, because it takes
# * string liteals (we can stringize a macro arugment but there is no such
# * thing like an unquote of strrings). */
# define __has_warning(...) 0
#endif
#ifndef __GNUC__
# define __extension__ /* void */
#endif
#ifndef MAYBE_UNUSED
# define MAYBE_UNUSED(x) x
#endif
@ -18,14 +115,6 @@
# define WARN_UNUSED_RESULT(x) x
#endif
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#ifndef __has_extension
# define __has_extension __has_feature
#endif
#define RB_OBJ_BUILTIN_TYPE(obj) rb_obj_builtin_type(obj)
#define OBJ_BUILTIN_TYPE(obj) RB_OBJ_BUILTIN_TYPE(obj)
#ifdef __GNUC__

View File

@ -47,11 +47,9 @@ RUBY_SYMBOL_EXPORT_END
rb_wb_unprotected_newobj_of(klass, flags))
#define NEWOBJ_OF(obj,type,klass,flags) RB_NEWOBJ_OF(obj,type,klass,flags)
#ifdef __has_attribute
#if __has_attribute(alloc_align)
__attribute__((__alloc_align__(1)))
#endif
#endif
void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_MALLOC RUBY_ATTR_ALLOC_SIZE((2));
size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */

View File

@ -1389,7 +1389,7 @@ rb_float_equal(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
@ -1397,7 +1397,7 @@ rb_float_equal(VALUE x, VALUE y)
return num_equal(x, y);
}
a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a == b)?Qtrue:Qfalse;
@ -1513,14 +1513,14 @@ rb_float_gt(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, '>');
}
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a > b)?Qtrue:Qfalse;
@ -1550,14 +1550,14 @@ flo_ge(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, idGE);
}
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a >= b)?Qtrue:Qfalse;
@ -1587,14 +1587,14 @@ flo_lt(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, '<');
}
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a < b)?Qtrue:Qfalse;
@ -1624,14 +1624,14 @@ flo_le(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, idLE);
}
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a <= b)?Qtrue:Qfalse;
@ -1656,7 +1656,7 @@ rb_float_eql(VALUE x, VALUE y)
if (RB_TYPE_P(y, T_FLOAT)) {
double a = RFLOAT_VALUE(x);
double b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
if (isnan(a) || isnan(b)) return Qfalse;
#endif
if (a == b)

View File

@ -137,7 +137,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b)
const uint128_t m = ((uint128_t)1 << dig) | 1;
uint128_t x = ((uint128_t)a << 32) | b;
r = (double)(uint64_t)((x * m) >> 64);
#elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200)
#elif defined HAVE_UINT64_T && !MSC_VERSION_BEFORE(1300)
uint64_t x = ((uint64_t)a << dig_u) +
(((uint64_t)b + (a >> dig_u)) >> dig_r64);
r = (double)x;

View File

@ -38,7 +38,7 @@ typedef unsigned int rb_atomic_t; /* Anything OK */
# define RUBY_ATOMIC_GENERIC_MACRO 1
#elif defined _WIN32
#if defined _MSC_VER && _MSC_VER > 1200
#if MSC_VERSION_SINCE(1300)
#pragma intrinsic(_InterlockedOr)
#endif
typedef LONG rb_atomic_t;
@ -48,7 +48,7 @@ typedef LONG rb_atomic_t;
# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
#if defined __GNUC__
# define ATOMIC_OR(var, val) __asm__("lock\n\t" "orl\t%1, %0" : "=m"(var) : "Ir"(val))
#elif defined _MSC_VER && _MSC_VER <= 1200
#elif MSC_VERSION_BEFORE(1300)
# define ATOMIC_OR(var, val) rb_w32_atomic_or(&(var), (val))
static inline void
rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
@ -66,7 +66,7 @@ rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
#endif
# define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
# define ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval))
# if defined _MSC_VER && _MSC_VER <= 1200
# if MSC_VERSION_BEFORE(1300)
static inline rb_atomic_t
rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval)
{

View File

@ -1424,11 +1424,9 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag)
static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd);
#ifdef __has_attribute
#if __has_attribute(artificial)
__attribute__((__artificial__))
#endif
#endif
static inline vm_call_handler
calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me)
{
@ -1817,7 +1815,7 @@ check_match(rb_execution_context_t *ec, VALUE pattern, VALUE target, enum vm_che
}
#if defined(_MSC_VER) && _MSC_VER < 1300
#if MSC_VERSION_BEFORE(1300)
#define CHECK_CMP_NAN(a, b) if (isnan(a) || isnan(b)) return Qfalse;
#else
#define CHECK_CMP_NAN(a, b) /* do nothing */