Issue #12479 has been updated by Usaku NAKAMURA.

Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.1: DONTNEED, 2.2: DONTNEED, 2.3: DONTNEED

----------------------------------------
Bug #12479: mistaken  macro GCC_VERSION_SINCE
https://bugs.ruby-lang.org/issues/12479#change-59915

* Author: Naohisa Goto
* Status: Closed
* Priority: Normal
* Assignee: 
* ruby -v: 
* Backport: 2.1: DONTNEED, 2.2: DONTNEED, 2.3: DONTNEED
----------------------------------------
いつからかは不明ですが、Solaris 10上の古いGCCでコンパイルすると、以下のエラーにて make test-all が失敗します。(r55344にて確認。)

~~~
  1) Failure:
TestMkmf::TestConvertible#test_typeof_builtin [/XXXXX-55344/test/mkmf/test_convertible.rb:9]:
convertible_int: checking for convertible type of short... -------------------- short

--------------------

convertible_int: checking for convertible type of int... -------------------- int

--------------------

convertible_int: checking for convertible type of long... -------------------- long

--------------------

convertible_int: checking for convertible type of signed short... -------------------- failed

"/usr/sfw/bin/gcc -o conftest -I. -I/XXXXX-55344/.ext/include/sparc-solaris2.10 -I/XXXXX-55344/include -I./test -I/usr/local/include  -D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64   -O conftest.c  -L. -L/XXXXX-55344 -Wl,-R/XXXXX-55344 -L. -L/usr/local/lib -R/usr/local/lib     -Wl,-R/XXXXX/sparc32-gcc3-trunk/lib -L/XXXXX/sparc32-gcc3-trunk/lib -lruby-static  -lpthread -lrt -lgmp -lsocket -ldl -lcrypt -lm   -lc"
In file included from /XXXXX-55344/include/ruby.h:33,
                 from conftest.c:1:
/XXXXX-55344/include/ruby/ruby.h:567: warning: `error' attribute directive ignored
/XXXXX-55344/include/ruby/ruby.h:592: warning: `error' attribute directive ignored
/XXXXX-55344/include/ruby/ruby.h:593: warning: `warning' attribute directive ignored
/XXXXX-55344/include/ruby/ruby.h:1346: warning: `warning' attribute directive ignored
checked program was:
/* begin */
1: #include "ruby.h"
2: 
3: int main(int argc, char **argv)
4: {
5:   return 0;
6: }
/* end */

~~~

コンパイルに使用したGCCのバージョンは、以下のように、たいへん古いものです。

~~~
$ /usr/sfw/bin/gcc --version
gcc (GCC) 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~~~

上記にて Warningが出ていた include/ruby/ruby.h の567行め付近は以下の内容です。

~~~
566: #if GCC_VERSION_SINCE(4,4,0)
567: void rb_check_safe_str(VALUE) __attribute__((error("rb_check_safe_str() and Check_SafeStr() are obsolete; use SafeStringValue() instead")));
568: # define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
569: #else
~~~

`#if GCC_VERSION_SINCE(4,4,0)` の中なので、GCC 3.4.3 ではコンパイルされないはずの部分なのに、なぜかコンパイルされてしまい、知らないattributeなので無視した旨のwarningが出てしまっています。

このマクロ GCC_VERSION_SINCE は、include/ruby/defines.h にて、以下のように定義されていました。

~~~
#define GCC_VERSION_SINCE(major, minor, patchlevel) \
  (defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && \
   ((__GNUC__ > (major)) ||  \
    ((__GNUC__ == (major) && \
      (__GNUC_MINOR__ > (minor)) || \
      (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))))
~~~

上記マクロの下3行を端的に表現すると `(X && Y || Z)` となり、
X は `__GNUC__ == (major)`
Y は `(__GNUC_MINOR__ > (minor))`
Z は `(__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))`
ということになりますが、
`X && Y || Z` は括弧が無いため左結合となり `(X && Y) || Z` と解釈され、
つまり、Z が正の場合は、X や Y の値と無関係に、この条件式は正になります。

そして、`#if GCC_VERSION_SINCE(4,4,0)` に対する GCC 3.4.3 は、Z が正となる条件にぴったり当てはまることになります。

今更 GCC 3系列のような古いGCCでコンパイルを試みる人はほとんど居なかったので、気がつかれなかったのだと思います。

なお、`X && (Y || Z)` が本来希望していた演算内容となりますので、そうなるように括弧を追加します。




-- 
https://bugs.ruby-lang.org/