From 06aafeb4b3a855966262da4855a5ba43d672d5e4 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 15 May 2021 20:58:26 +0200 Subject: Fix clang -Wcompound-token-split-by-macro warning in ruby.h Building certain ruby gem native extensions (such as thrift), with clang 12.0.0 or later fails, because they have -Werror in their CFLAGS, resulting in complaints about the expansion of the `rb_intern()` macro: ``` current directory: /wrkdirs/usr/ports/devel/rubygem-thrift/work/stage/usr/local/lib/ruby/gems/2.7/gems/thrift-0.14.0/ext make "DESTDIR=" compiling binary_protocol_accelerated.c binary_protocol_accelerated.c:404:68: error: '(' and '{' tokens introducing statement expression appear in different macro expansion contexts [-Werror,-Wcompound-token-split-by-macro] VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol")); ^~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/include/ruby-2.7/ruby/ruby.h:1847:23: note: expanded from macro 'rb_intern' __extension__ (RUBY_CONST_ID_CACHE((ID), (str))) : \ ^ binary_protocol_accelerated.c:404:68: note: '{' token is here VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol")); ^~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/include/ruby-2.7/ruby/ruby.h:1847:24: note: expanded from macro 'rb_intern' __extension__ (RUBY_CONST_ID_CACHE((ID), (str))) : \ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/include/ruby-2.7/ruby/ruby.h:1832:5: note: expanded from macro 'RUBY_CONST_ID_CACHE' { \ ^ ``` Part of the `rb_intern()` macro expands to `(RUBY_CONST_ID_CACHE((ID), (str)))`, and in turn `RUBY_CONST_ID_CACHE()` expands to a brace enclosed compound statement. The intended effect is to get a gcc statement expression, which is normally delimited by `({ ... })`. However, clang 12.0.0 and later have a warning enabled by default, about pasting together the `(` and `{` tokens via different macros (see ). To work around this warning: * Add `RUBY_CONST_ID_CACHE_NB()` (i.e. no-brace) which contains the code itself, without any braces * `RUBY_CONST_ID_CACHE()` which uses `RUBY_CONST_ID_CACHE_NB()`, but puts braces around it (so no existing code using this macro breaks) * Finally, change `rb_intern()` so the `__extension__` directly creates a gcc statement expression, using the `RUBY_CONST_ID_CACHE_NB()` macro --- include/ruby/ruby.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 1ce73d5559..bd95d5b0b1 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -1828,12 +1828,14 @@ VALUE rb_sym2str(VALUE); VALUE rb_to_symbol(VALUE name); VALUE rb_check_symbol(volatile VALUE *namep); -#define RUBY_CONST_ID_CACHE(result, str) \ - { \ +#define RUBY_CONST_ID_CACHE_NB(result, str) \ static ID rb_intern_id_cache; \ if (!rb_intern_id_cache) \ rb_intern_id_cache = rb_intern2((str), (long)strlen(str)); \ - result rb_intern_id_cache; \ + result rb_intern_id_cache; +#define RUBY_CONST_ID_CACHE(result, str) \ + { \ + RUBY_CONST_ID_CACHE_NB(result, str) \ } #define RUBY_CONST_ID(var, str) \ do RUBY_CONST_ID_CACHE((var) =, (str)) while (0) @@ -1844,7 +1846,7 @@ VALUE rb_check_symbol(volatile VALUE *namep); * since gcc-2.7.2.3 at least. */ #define rb_intern(str) \ (__builtin_constant_p(str) ? \ - __extension__ (RUBY_CONST_ID_CACHE((ID), (str))) : \ + __extension__ ({RUBY_CONST_ID_CACHE_NB((ID), (str))}) : \ rb_intern(str)) #define rb_intern_const(str) \ (__builtin_constant_p(str) ? \ -- cgit v1.2.3