きりかノート 3冊め

おあそびプログラミング

clang-3.1でruby-trunkが-Werror=shorten-64-to-32に引っかかる件

まとめているうちに修正されちゃった(r35874)んだけど、まあ途中まで書いたし残しとこう。

誰の発言だったか忘れちゃったんですが、TLで「ruby-1.9.3がclang-3.1でコンパイルとおらない」というのを見かけたので試してみた。

   compiling regparse.c
   regparse.c:582:15: error: implicit conversion loses integer precision: 'st_index_t'
         (aka 'unsigned long') to 'int' [-Werror,-Wshorten-64-to-32]
       return t->num_entries;
       ~~~~~~ ~~~^~~~~~~~~~~
   1 error generated.

メッセージにあるとおり、regparse.cのonig_number_of_names()の返り値がintなのにt->num_entriesがunsigned longなので-Werror=shorten-64-to-32に該当するってこと。人間がコード読んでもそのとおりなのを確認(NameTableはst_table include/ruby/st.h)。

   extern int
   onig_number_of_names(regex_t* reg)
   {
     NameTable* t = (NameTable* )reg->name_table;

     if (IS_NOT_NULL(t))
       return t->num_entries;
     else
       return 0;
   }

また、trunkでも同様のコンパイルエラーが再現した。(前述のとおり6/2に修正済み)

調べてみた感じ、

  • shorten-64-to-32は、Applegccに入ってた独自オプションである
  • clangにも同様のオプションがある
  • clang-3.1で判定が以前より賢くなったので以前にはとおっていたところが見つかるようになった
    • 通る: Xcode 4.3.2 gcc - i686-apple-darwin11-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
    • 通る: Xcode 4.3.2 clang - Apple clang version 3.1 (tags/Apple/clang-318.0.58) (based on LLVM 3.1svn)
    • エラー: clang-3.1 (MacPorts) - clang version 3.1 (branches/release_31)

といったところ。Xcode 4.3.2のclangは3.1リリースちょっと前の開発版で、そのへんの差がでたってことかな。clangの実装についてはテスト見るのが手っ取り早いので、opensource.apple.comのclangと比べてみよう。

   --- .../clang-318.0.45/src/tools/clang/test/Sema/conversion-64-32.c 2011-11-09 14:02:00.000000000 +0900
   +++ Sema/conversion-64-32.c 2012-06-05 00:03:39.000000000 +0900
   @@ -13,3 +13,7 @@
      int4  v127 = a;  // no warning.
      return v127;
    }
   +
   +int test2(long v) {
   +  return v / 2; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}}
   +}

test/Sema/conversion-64-32.cになんか追加があるけれど、これが該当するものかはわからないねえ。