Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature #20507] Allow compilation of C extensions with -Wconversion #10843

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions ext/-test-/public_header_warnings/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#
# Under compilers with WERRORFLAG, MakeMakefile.try_compile treats warnings as errors, so we can
# use append_cflags to test whether the public header files emit warnings with certain flags turned
# on.
#
def check_append_cflags(flag, msg = nil)
msg ||= "flag #{flag} is not acceptable"
!$CFLAGS.include?(flag) or raise("flag #{flag} already present in $CFLAGS")
append_cflags(flag)
$CFLAGS.include?(flag) or raise(msg)
end

if %w[gcc clang].include?(RbConfig::CONFIG['CC'])
config_string("WERRORFLAG") or raise("expected WERRORFLAG to be defined")

# should be acceptable on all modern C compilers
check_append_cflags("-D_TEST_OK", "baseline compiler warning test failed")

# Feature #20507: Allow compilation of C extensions with -Wconversion
check_append_cflags("-Wconversion", "-Wconversion raising warnings in public headers")
end

create_makefile("-test-/public_header_warnings")
14 changes: 7 additions & 7 deletions include/ruby/internal/arithmetic/long.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ RB_INT2FIX(long i)

/* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully
* defined. Also it can be compiled into a single LEA instruction. */
const unsigned long j = i;
const unsigned long j = RBIMPL_CAST((unsigned long)i);
const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG;
const long l = k;
const long l = RBIMPL_CAST((long)k);
const SIGNED_VALUE m = l; /* Sign extend */
const VALUE n = m;
const VALUE n = RBIMPL_CAST((VALUE)m);

RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n));
return n;
Expand Down Expand Up @@ -166,7 +166,7 @@ rbimpl_fix2long_by_idiv(VALUE x)
/* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because
* RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1
* below. */
const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG;
const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)(x - RUBY_FIXNUM_FLAG));
const SIGNED_VALUE z = y / 2;
const long w = RBIMPL_CAST((long)z);

Expand All @@ -193,7 +193,7 @@ rbimpl_fix2long_by_shift(VALUE x)

/* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this
* is noticeably faster than above. */
const SIGNED_VALUE y = x;
const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)x);
const SIGNED_VALUE z = y >> 1;
const long w = RBIMPL_CAST((long)z);

Expand Down Expand Up @@ -252,7 +252,7 @@ static inline unsigned long
rb_fix2ulong(VALUE x)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
return rb_fix2long(x);
return RBIMPL_CAST((unsigned long)rb_fix2long(x));
}

/**
Expand Down Expand Up @@ -323,7 +323,7 @@ static inline VALUE
rb_ulong2num_inline(unsigned long v)
{
if (RB_POSFIXABLE(v))
return RB_LONG2FIX(v);
return RB_LONG2FIX(RBIMPL_CAST((long)v));
else
return rb_uint2big(v);
}
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/internal/arithmetic/long_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static inline unsigned LONG_LONG
rb_num2ull_inline(VALUE x)
{
if (RB_FIXNUM_P(x))
return RB_FIX2LONG(x);
return RBIMPL_CAST((unsigned LONG_LONG)RB_FIX2LONG(x));
else
return rb_num2ull(x);
}
Expand Down
4 changes: 2 additions & 2 deletions include/ruby/internal/arithmetic/st_data_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline VALUE
RB_ST2FIX(st_data_t i)
{
SIGNED_VALUE x = i;
SIGNED_VALUE x = RBIMPL_CAST((SIGNED_VALUE)i);

if (x >= 0) {
x &= RUBY_FIXNUM_MAX;
Expand All @@ -69,7 +69,7 @@ RB_ST2FIX(st_data_t i)

RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x));
unsigned long y = RBIMPL_CAST((unsigned long)x);
return RB_LONG2FIX(y);
return RB_LONG2FIX(RBIMPL_CAST((long)y));
}

#endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */
2 changes: 1 addition & 1 deletion include/ruby/internal/encoding/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ enum ruby_encoding_consts {
static inline void
RB_ENCODING_SET_INLINED(VALUE obj, int encindex)
{
VALUE f = /* upcast */ encindex;
VALUE f = /* upcast */ RBIMPL_CAST((VALUE)encindex);

f <<= RUBY_ENCODING_SHIFT;
RB_FL_UNSET_RAW(obj, RUBY_ENCODING_MASK);
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/internal/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
static inline void *
rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
{
const size_t total_size = rbimpl_size_mul_or_raise(count, elsize);
const size_t total_size = rbimpl_size_mul_or_raise(RBIMPL_CAST((size_t)count), elsize);
const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE);
return rb_alloc_tmp_buffer_with_count(store, total_size, cnt);
}
Expand Down
4 changes: 2 additions & 2 deletions include/ruby/internal/special_consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ RB_TEST(VALUE obj)
*
* RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil).
*/
return obj & ~RUBY_Qnil;
return obj & RBIMPL_CAST((VALUE)~RUBY_Qnil);
}

RBIMPL_ATTR_CONST()
Expand Down Expand Up @@ -226,7 +226,7 @@ RB_NIL_OR_UNDEF_P(VALUE obj)
*
* NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil.
*/
const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil);
const VALUE mask = RBIMPL_CAST((VALUE)~(RUBY_Qundef ^ RUBY_Qnil));
const VALUE common_bits = RUBY_Qundef & RUBY_Qnil;
return (obj & mask) == common_bits;
}
Expand Down