コンパイラFAQ


  1. コンパイラをサイレントインストールする方法について
  2. コンパイラが C9932E / C9558E エラーを返すときの対応について
  3. atan2f() を atan2f(0.f, 0.f) として呼んだ場合の挙動について
  4. すべてのwarningをerrorにする方法について
  5. --fpmode=fast 指定時に非有限値を扱うことができません
  6. --enum_is_int を指定してアプリケーションをビルドできません
  7. 最適化に関する不具合への対策について
  8. std::bitsetでto_string関数を使うとコンパイルエラーが発生します
  9. 先行宣言と実際の宣言で、クラスと構造体を間違えてもコンパイルエラーにならない
  10. プリコンパイルヘッダ使用時にコンパイラが出力するメッセージを非表示にする方法について
  11. テンプレート関数からstaticな関数を呼んだ場合に、コンパイルエラーが発生します
  12. C形式のソースからバイナリファイルを生成する方法について
  13. --gnu 指定時に警告メッセージ #94 「配列のサイズはゼロより大きくする必要があります」 を表示する方法について
  14. 浮動小数点数から整数への暗黙的なキャストが行われた際に警告を出す方法について
  15. 構造体を含む構造体配列で、本来最適化によって呼ばれるべきではないaeabi_vec_ctor_nocookie_nodotrが呼び出されています
  16. メンバ変数と同じ名前のオート変数を定義したときに警告を出す方法について
  17. --ltcgオプションの使用方法について
  18. VFP ベクタモードの使用可否について
  19. --fpmode=ieee_no_fenv オプションを使用したときの例外に関する挙動について
  20. ビルド時に #1620-D: Internal fault: translation failed. Please contact your supplier (ipa_nfuncs) というエラーが出る
  21. Releaseビルド時に、thisポインタの NULL チェックを行うコードが生成されません
  22. オブジェクトレベルでinline展開を行う方法について
  23. ヒープからではなく、スタックからアロケートする方法について
  24. プリコンパイルヘッダの作成側と参照側で統一させるべきコンパイルオプションの並び順について
  25. ライブラリ内の非 weak シンボルより、weak シンボルが優先してリンクされることがあります
  26. プリコンパイルするヘッダ内で、#pragma diag_suppress を使用した場合、プリコンパイルヘッダ生成時には
    pragma が有効になりますが、プリコンパイルヘッダ使用時に pragma が有効になりません
  27. メンバ関数の定義の際にクラス名を多重に書いてもエラーになりません
  28. インクルードパスを再帰的に検索する方法について
  29. __align に 16 や 32 を指定できません
  30. -Otime -O3 と -Otime -O2 との最適化の違いについて
  31. #2819-D の診断メッセージについて
  32. インラインアセンブラで、GCC のassmebler instruction template のような記法に対応する予定について
  33. --create_pch で作成したプリコンパイルヘッダを使用するとエラーが出ます
  34. --create_pch/--use_pch を使用する際に、-I オプションに相対パスを使用できるか
  35. --split_sections を指定しても、組み込みアセンブラで記述された関数がデッドストリップされません
  36. コンパイラが挿入したパディングの位置を知る方法について
  37. __forceinline を指定した関数を複数回呼び出すコードが最適化されません
  38. コンパイラで使用可能な文字コードについて
  39. スタティックイニシャライザの挙動について
  40. 配列へのポインタの扱いについて
  41. 無名名前空間の大域変数を組み込みアセンブラから使う方法について
  42. ARMCC での C++0x(C++11) の導入について
  43. fast ビルド時に、ARMv5T 用ではなく ARMv4 用のライブラリがリンクされます
  44. コンパイラを ARMCC5.x に変更したら、以前には出ていなかった警告が出ます
  45. コンパイラを ARMCC5.x に変更したら、--gnu 未指定時に #3093 のエラーになります
  46. ARMCC5.04 に変更したら、DLL モジュールのリンク時に L6244E のエラーになります
  47. ビルド時間を短縮する方法について
  48. マップファイルを生成しない方法について
  49. ARMCC5.04 に変更したら、デバッガが誤動作を起こします
  50. C++ 例外使用時に未使用関数が削除されない場合があります
  51. ARMCC4.1 b1454 の --conservative_init_expression_optimization オプションについて

1.

Q.

コンパイラをサイレントインストールする方法について

A.

コンパイラのサイレントインストールがうまくいかない場合、
EULAの同意部分に失敗していることが考えられます。

下記の通りに指定しますと、インストール可能です。

 start /wait msiexec /qn /i nintendo.msi /l*v nintendo_install.log EULA=1
 
 [オプションについて]
         /qn:            quiet install mode
         /i:             install
         /l*v            log all the information
         EULA=1  accepting EULA from command line


2.

Q.

コンパイラが C9932E / C9558E エラーを返すときの対応について

コンパイル時に、コンパイラが以下のようなメッセージを出力してエラーとなることがあります。

・RVCT4.0 / ARMCC4.1 / ARMCC5.03 / ARMCC5.04(build 82 以前)

Error: C9932E: Cannot obtain license for Compiler (feature besp_compiler_00) with license version >= 4.0
System clock has been set back
・ARMCC 5.04(build 146 以降)
Error: C9558E: System clock tampering detected. License checkout will fail.
Error: C9555E: License checkout for feature bsp_compiler5 with version 5.0201505 has been denied
 by Flex back-end. Error code: -1004
なお、コンパイラ以外の ARM ツールでは、メッセージ番号の最初の一文字が変わります。
(例:リンカでは L9932E / L9558E / L9555E エラーになります。)

A.

コンパイラのライセンスファイルチェックでは、ランダムに PC 上のファイルをチェックしており、
不正なタイムスタンプ(未来の日時)のファイルが存在した場合に上記のようなエラーが発生します。

上記のようなエラーが発生した場合は、Windows のファイル検索でタイムスタンプが未来の日時になっているものを検索し、
修正することで解決できます。

具体的には、cygwin 上で下記のコマンドを実行することで、該当ファイルを修正できます。

$ cd /cygdrive/c
$ find -type f -mmin -1 -exec touch {} \;
$ find -type f -amin -1 -exec touch {} \;
また、RVCT 4.0 / ARMCC4.1 / ARMCC5.03 / ARMCC 5.04(build 166 以前)には、Timezone が +1~+12 の PCで、
1970/1/2 以前のタイムスタンプのファイルを不正なファイルとして誤検出する不具合があります。

上記のコマンドで問題が解決しない場合は、以下のコマンドも試してください。
$ cd /cygdrive/c
$ find -type f -mtime +16425 -exec touch {} \;
$ find -type f -atime +16425 -exec touch {} \;
コマンドの実行対象は、環境変数 %SystemDrive% 及び %TEMP% で指定されているドライブ(パス)です。
通常は C ドライブですが、C ドライブ以外に変更している場合は指定しているドライブで実行してください。

なお、ファイルのチェックはごみ箱の中身も対象となっているため、 上記のチェックで問題が解決しない場合、ごみ箱を空にして試してください。


3.

Q.

atan2f() を atan2f(0.f, 0.f) として呼んだ場合の挙動について

atan2f() を、atan2f(0.f, 0.f) として呼んだ場合、CTR の開発環境(RVCT4.0)では
NaN が返されますが、本来は0.0が返されるべきではないでしょうか?

A.

ISO 仕様では、上記関数で範囲外の引数が与えられた場合の挙動は
実装者に任せられており、RVCT4.0 の ARM Cライブラリでは NaN を返します。

その他の関数に関しての挙動は、パッケージ内のライブラリガイド(rvct_libraries_guide.pdf) の2.14を参照してください。

ARMCC4.1 では、特殊なケースでの数学関数の戻り値が POSIX/C99 要件に準拠するようになり、0.0f が返されるようになりました。


4.

Q.

すべてのwarningをerrorにする方法について

A.

コマンドラインオプションに--diag_error=warningを追加すると、
全ての警告をエラーにすることができます。


5.

Q.

--fpmode=fast 指定時に非有限値を扱うことができません

A.

--fpmode=fast 指定時には、IEEEで規定されている非有限値の取り扱いは完全に対応しておらず、
全ての最適化レベルによって同一の振る舞いを保証していません。
演算にNaNが想定されるような場合には、isnan()関数で事前に処理を切り分けるなどの対応をして下さい。


6.

Q.

--enum_is_int を指定してアプリケーションをビルドできません

A.

CTR-SDKは --enum_is_int を無効にしてビルドされています。
ライブラリとアプリケーションで、このオプションを変更してビルドすることはできません。
また、CTR-SDKで --enum_is_int オプションを有効にする予定はありません。


7.

Q.

最適化に関する不具合への対策について

A.

現状、-O3 -Otimeの組み合わせで使用した際に不具合が発生するケースが多いようです。
このオプションの組み合わせではループ最適化の機能が有効になるのですが、
この機能で不正な最適化を行ってしまうケースが幾つか発生しています。

対策としては、下記の方法があります。

■不正なコードを生成する関数を特定できていない場合

・ソースコードの先頭に以下の記述を追加し、ソースコードの最適化レベルを変更する。

#pragma Ospace

・特定の最適化レベルが指定されたときのみ最適化レベルを変更する。

#if __OPTIMISE_LEVEL == 3
#ifdef __OPTIMISE_TIME
#pragma Ospace
#endif
#endif


■不正なコードを生成する関数が特定できている場合

・特定の関数だけの最適化レベルを変更する。

#pragma push
#pragma Ospace
void foo()
{
  ...
}
#pragma pop


・-O3 -Otimeで有効になるループ最適化機能のみを無効にする。

#pragma push
#pragma Ono_vast
void foo()
{
  ...
}
#pragma pop

※この Ono_vast オプションは、ドキュメント化していない非公開のオプションですが、
この指定でループ最適化機能だけを無効にすることが出来ます。


8.

Q.

std::bitsetでto_string関数を使うとコンパイルエラーが発生します

下記のようなコードをコンパイルすると、(a)の箇所でコンパイルエラーになります。

std::string  foo()
{
 std::bitset<10>  bits = 100;
 std::string  str = bits.to_string();    // ---(a)
 return str;
}

A.

C++標準のライブラリ仕様では、to_stringはテンプレートメンバ関数を 使用するものが定義されているため、本症状は仕様となります。

正しい呼び出し方法は下記の通りとなります。
std::string str = bits.to_string< char, std::char_traits, std::allocator >();

また、非推奨ではありますが、_RWSTD_NO_MEMBER_TEMPLATES をマクロ名としてコンパイラに渡すことで、
非テンプレートメンバ関数版を使用することも可能です。

使用例:
armcc -c test.cpp -D_RWSTD_NO_MEMBER_TEMPLATES


9.

Q.

先行宣言と実際の宣言で、クラスと構造体を間違えてもコンパイルエラーにならない

A.

上記はコンパイラの仕様となります。

C++における struct と class の違いは、デフォルトのアクセス指定だけのため、
それが原因でソースコードの記述が問題とならなければ、ワーニングやエラーになりません。


10.

Q.

プリコンパイルヘッダ使用時にコンパイラが出力するメッセージを非表示にする方法について

A.

--no_pch_messagesコマンドを追加することで、プリコンパイルヘッダ関連のメッセージを抑止することができます。


11.

Q.

テンプレート関数からstaticな関数を呼んだ場合に、コンパイルエラーが発生します

A.

C++標準の[14.6.4.2]で定義されている依存名のルックアップ手続きに従い、外部リンケージを持つ 名前だけがルックアップの対象となっているためで、仕様となります。

ttp://www.csci.csusb.edu/dick/c++std/cd2/template.html#temp.dep.candidate

なお、RVCTには、依存名に関して GCC や VC++ と同等の振る舞いを行う--no_dep_name オプションがあります。
--no_dep_name を追加すると、テンプレートが解析されるときの依存名のルックアップは無効になるので、
エラーの発生を抑止することができます。詳細は、コンパイラリファレンスガイドの「--dep_name,--no_dep_name」
の項目をご参照下さい。


12.

Q.

C形式のソースからバイナリファイルを生成する方法について

C形式のソースファイルからarmcc、armlinkを使用してaxfを作成し、fromelfでバイナリファイルを 作成したいのですが、リンク時にL6048Uのエラーが出ます。

A.

RVCT4.0 20100909版より、ライセンス保護の仕組み上、上記のような使い方ができないようになりました。
申し訳ありませんが、別の方法をご検討いただきますようお願いいたします。


13.

Q.

--gnu 指定時に警告メッセージ #94 「配列のサイズはゼロより大きくする必要があります」 を表示する方法について

A.

--gnu 指定時に警告メッセージ #94 を表示することは出来ません。


14.

Q.

浮動小数点数から整数への暗黙的なキャストが行われた際に警告を出す方法について

A.

現在のコンパイラではこのような機能はありません。
機能追加について検討を行いましたが、変更の予定はありません。


15.

Q.

構造体を含む構造体配列で、本来最適化によって呼ばれるべきではないaeabi_vec_ctor_nocookie_nodotrが呼び出されています

下記のようなコードで、デフォルトコンストラクタを定義すると、コンストラクタが本来最適化されてなくなるはずが、
aeabi_vec_ctor_nocookie_nodotrが呼び出されています。

デフォルトコンストラクタを定義しなければ、この症状は発生しません。

struct Point
{
 int x;
 int y;
 int z;

 // Comment this out in order to see "inlined" version
 Point() {}
};

struct Line
{
 Point ends[2];
};

extern "C" void nnMain()
{
 Line lines[10] __attribute__((unused));
 while(1){}
}

A.

現状のコンパイラでは、そのような最適化を行っていません。
修正について検討を行いましたが、変更の予定はありません。


16.

Q.

メンバ変数と同じ名前のオート変数を定義したときに警告を出す方法について

A.

現状では警告を出すことはできません。
機能追加について検討を行いましたが、変更の予定はありません。

17.

Q.

--ltcgオプションの使用方法について

A.

現状--ltcgオプションを使用することはできません。
使用できるように改善の検討を行いましたが、変更の予定はありません。

--multifile機能を使用することで、同等のことを実現することができます。


18.

Q.

VFP ベクタモードの使用可否について

A.

VFP ベクタモードは使用していただいて問題ありません。
RVCT のパッケージに含まれるドキュメント(DUI0204IJ_rvct_assembler_guide.pdf)の「5.17 VFP ベクタモード」には、
「 VFP ベクタモードの使用は廃止される予定です」という記述がありますが、CTRでのVFPベクタモードの使用が廃止されるという意味ではありません。

また、ドキュメントには「単一命令複数データ処理(SIMD)による並列処理が可能です」という記述がありますが、VFPは複数の演算を並列に行うのではなくシリアルに演算するもので、所謂「並列処理」という意味ではありません。


19.

Q.

--fpmode=ieee_no_fenv オプションを使用したときの例外に関する挙動について

コンパイラリファレンスガイドには、--fpmode=ieee_no_fenv を使用すると例外が発生されない、と書かれていますが、
この fpmode でデバッグした際に、プロセスが終了されることがあります。

A.

CTR-SDK では --fpmode=fast の指定が必須であり、--fpmode=ieee_no_fenv 指定時の動作はサポートしていません。

なお、コンパイラのマニュアルに記載されているとおり、--fpmode=ieee_no_fenv 指定時には、下記の例外は発生しなくなります。

  • 無効な演算(負数に対して平方根を求めようとしたなど)
  • 0 除算
  • オーバーフロー(結果が正しく表現できないほど大きくなった場合)
  • アンダーフロー(結果が正規数で表現できないほどに小さく非 0 であるが不正確な結果となった場合)
  • 不正確

Signal NaN, Quiet NaNが演算で使用された場合の挙動は、テクニカルリファレンスマニュアルの
『第17 章 VFP プログラマモデル 17.2.3 IEEE 754 規格実装の選択』の『表17-2 QNaN と SNaN の処理』に説明があります。

--fpmode=ieee_no_fenv を使用した場合、デフォルト NaN モードはオフになるため、例えば FCMPE 命令(VCMPE と等価です)で
Quiet NaN がオペランドにある場合には、表中に説明があるように『INV がセットされます。操作の処理がサポートコードに
バウンスされます。』となり、入力例外フラグがセットされ、例外が発生します。

一方、--fpmode=fast または --fpmode=std の場合は、_fp_init でデフォルト NaN モードをオンに設定するライブラリが
リンクされるため、例外処理は発生しません。

--fpmode=fast と --fpmode=ieee_* でコンパイルされたオブジェクトが混在する場合には、
リンカは、--fpmode=ieee_no_fenv と同様に IEEE 標準の初期化を行い、デフォルト NaNモードがオフになります。

上記理由により、--fpmode=ieee_no_fenv を CTR 環境で使用した場合には、VFP 初期化部分でデフォルト NaN モードが
オフになり、例外処理が発生します。


20.

Q.

ビルド時に #1620-D: Internal fault: translation failed. Please contact your supplier (ipa_nfuncs) というエラーが出る

A.

この内部エラー表示は実際には、診断メッセージが出力した 'internal fault' 文字列であり、エラーではありません。

このメッセージは、--remarks オプションにより発生し、なぜ各種最適化が失敗したかを表示しています。
上記のケースでは、変換ユニット内で10000を越える関数が含まれているために、最適化が難しく処理に失敗していることを
表しています。関数が10000以内になるよう、複数の変換ユニットに分割することで、この診断メッセージは表示されなくなり、
最適化が行われるようになります。


21.

Q.

Releaseビルド時に、thisポインタの NULL チェックを行うコードが生成されません

A.

this ポインタが NULL の状態で、メンバ関数を呼び出した際の実装は未定義です。
RVCT では、デフォルトで最適化時に NULL チェックのコードを削除するため、本件は実装仕様となります。

コマンドラインオプション --allow_null_this を使うことで、this ポインタの NULL チェックを有効にし、
最適化による削除を無効にすることができます。


22.

Q.

オブジェクトレベルでinline展開を行う方法について

リンカで--inlineを指定した場合に、少し複雑な関数でもリンカレベルでインライン展開する方法はないでしょうか?

A.

リンカでのインライン展開は、コンパイラが生成した関数コール部分のコードに関数の実体を挿入する機能のため、
複雑なインライン処理を行うことは出来ません。--multifileオプションの利用をご検討下さい。


23.

Q.

ヒープからではなく、スタックからアロケートする方法について

A.

ARMCC4.1 b640より、alloca関数を使用することでスタックからアロケートできます。
RVCT4.0では対応予定はありません。


24.

Q.

プリコンパイルヘッダの作成側と参照側で統一させるべきコンパイルオプションの並び順について

A.

コンパイラはコマンドラインまたはviaファイル経由のオプションを種類ごとにソートしてから使用します。
複数の該当オプション(例えば、-I)の間に別の種類のコンパイラオプションが指定されていても、種類ごとに
ソートされた後の順番が一致していればコマンドライン指定が同じであると認識されます。

例えば:
  --create_pch=file.pch -O3 -Iaaa -Otime -Ibbb
  --use_pch=file.pch -O3 -Otime -Iaaa -Ibbb

という二つのコマンドライン指定は、
  -O3 -Otime -Iaaa -Ibbb
という種類順でソートされますので、プリコンパイルヘッダを使用することが可能です。
これに該当するオプションは、-D/-U/-I/-J/--preincludeのように、複数回指定できるオプションが該当します。

--diag_suppressなどのように一つのオプション指定で複数の要素が設定できる場合は、要素を単純に連結して処理します。

例えば:
  --diag_suppress=1 --diag_suppress=2 --diag_suppress=3

は、以下のように変換されます。
  --diag_suppress=1,2,3

一方、
  --diag_suppress=1,3 --diag_suppress=2

は、以下の様に連結されるため注意が必要です。
  --diag_suppress=1,3,2
なお、 種類順にソートされた結果は、以下のいずれかで確認することが出来ます。
  1. --show_cmdline で標準出力に表示される
  2. --asm指定時に、アセンブラ出力ファイルの「; commandline armcc」で表示される部分に出力される


25.

Q.

ライブラリ内の非 weak シンボルより、weak シンボルが優先してリンクされることがあります

A.

ライブラリ内の非 weak シンボルは、使用方法によっては先にリンクされている weak シンボルを
置き換えないことがあります。この動作は、RVCT リンカの仕様です。

RVCT コンパイラリファレンスガイドの「4.1.19 __weak」には以下のように記載されています。

--
リンカは、他のコンパイルで関数や変数が非 weak で使用されている場合を除き、
ライブラリから関数や変数をロードしません。
--

weak シンボルを、ライブラリ内の非 weak シンボルで置き換えようとする場合、実際に置き換えられているかどうか注意してください。
この仕様の改善について検討を行いましたが、変更の予定はありません。


26.

Q.

プリコンパイルするヘッダ内で、#pragma diag_suppress を使用した場合、プリコンパイルヘッダ生成時には
pragma が有効になりますが、プリコンパイルヘッダ使用時に pragma が有効になりません

A.

これは、プリコンパイルヘッダの仕組みとして正しい振る舞いです。
この動作が問題となる場合には、以下のいずれかの方法をご検討下さい。

  1. #pragma diag_suppress をヘッダファイルではなく、ソースファイルに記述する(#include の後に指定する)
  2.   main.cpp ソースファイルの例:
      #include "main.h"
      #pragma diag_suppress 177
    
  3. #pragma diag_suppress を別のヘッダファイルに記述し、プリコンパイルヘッダの対象から外す
  4.     main.cpp ソースファイルの例:
        #include "main.h"
        #pragma hdrstop // プリコンパイルヘッダ生成の終了
        #include "user.h" // このファイル内に #pragma diag_suppress を記述する
    


27.

Q.

メンバ関数の定義の際にクラス名を多重に書いてもエラーになりません

下記のようなコードでエラーが検出されません。

例)
class MyClass {
public:
 MyClass();
 ~MyClass();
 void DoAnything();
};
MyClass::MyClass::MyClass() {} // no error
MyClass::MyClass::MyClass::~MyClass() {} // no error
void MyClass::MyClass::MyClass::MyClass::DoAnything() {} // no error

A.

C++標準仕様の9.0.2章に関連した記述があり、C++の仕様となります。

A class-name is inserted into the scope in which it is declared
immediately after the class-name is seen. The class-name is also
inserted into the scope of the class itself; this is known as
the injected-class-name. For purposes of access checking, the
injected-class-name is treated as if it were a public member
name.

【JIS X3014での翻訳】
≪クラス名≫は、≪クラス名≫が現れると即座に、宣言される有効範囲に加えられる。
≪クラス名≫は、クラス自身の有効範囲にも加えられる(補正クラス名と呼ぶ。)。
アクセス検査に当たっては、補正クラス名は、公開メンバ名であるかのように扱われる。
このクラス名は、そのクラスの有効範囲に挿入されたクラス名(injected-class-name)です。


28.

Q.

インクルードパスを再帰的に検索する方法について

A.

インクルードパスを再帰的に検索する方法はありません。
また、機能追加の予定もありません。


29.

Q.

__align に 16 や 32 を指定できません

A.

上記はコンパイラの仕様となります。
また、他のツールにも影響を及ぼす部分であるため、対応する予定はありません。


30.

Q.

-Otime -O3 と -Otime -O2 との最適化の違いについて

A.

-Otime -O3 では、以下の特徴があります。

  • ハイレベルループ最適化(VAST)
  • レジスタアロケーション前のスケジューリング
  • インラインに関する最適化において、インラインの閾値が増加することによる、関数のさらなるインライン化
  • RVCT4.0の-O3では暗黙的に--multifileが使用され、複数のソースファイルがコマンドラインから指定された場合に、
    連結した1つのソースとしてコンパイルされる。


31.

Q.

#2819-D の診断メッセージについて

テンプレートクラス内で仮想関数を使用すると、#2819-D の診断メッセージが表示されますが、
「テンプレートメンバ関数の暗黙的インスタンス化がキー関数として選択される」とはどういう意味でしょうか?

A.

本診断メッセージは、キー関数がテンプレートメンバ関数だった場合に、暗黙的にインスタンス化されることを
通知するための診断メッセージです。
(キー関数とは、クラスで最初に宣言される、インライン関数ではなく、純粋仮想関数でない仮想関数です。)

下記の対応で回避することができます。

  • 該当する関数をインライン化する
  • --no_implicit_key_function オプションを指定する


32.

Q.

インラインアセンブラで、GCC のassmebler instruction template のような記法に対応する予定について

A.

追加機能として検討されていますが、長期的な計画として検討されているため、
ARMCC 5.x での対応予定はありません。


33.

Q.

--create_pch で作成したプリコンパイルヘッダを使用するとエラーが出ます

A.

--create_pch で作成したプリコンパイルヘッダを使用する際には下記の点に注意してください。

  • -I, -J オプションや、ソース内での #include 指定時に、ソースファイルのディレクトリ位置からの
    相対パス(#include "..\..\test.h" など)を使用しない
  • コンパイルオプションとして --sys_include を指定して、ソースファイルディレクトリを
    インクルード検索パスから除外する


34.

Q.

--create_pch/--use_pch を使用する際に、-I オプションに相対パスを使用できるか

A.

ARMCC 4.1 build 640 以降で、--force_pch_reuse オプションをサポートしました。
(ARMCC 4.1 の更新履歴にのみ記載しているオプションです。)

このオプションは、PCHファイルを再利用する場合にディレクトリチェックを強制的に無効にします。
ソースコードのディレクトリが変更されたり、PCHファイルが移動された場合に使用することが出来ます。
通常コンパイラがPCHファイルの再利用を安全のために拒否した場合、元々生成されたPCHファイルを再利用出来るようにします。

注意:
このオプションは通常のチェックをバイパスするため、安全な振る舞いを保証することが出来ません。
再利用されたPCHファイルが実際に有効であるか確認するのはユーザーの責任となります。
異なったソースディレクトリから使用されたり、それらが移動された場合、PCHファイルは無効である場合があります。
例えば、"." や ".." などの相対インクルードディレクトリへの参照でヘッダファイルからPCHファイルが生成された場合等です。

このオプションはコンパイラがPCHファイルを再利用する場合、以下のように任意のPCHオプションと組み合わせて使用することができます。

  armcc --force_pch_reuse --use_pch=foo.pch 
  armcc --force_pch_reuse --pch
マニュアルに記載していない非公開のオプションですが、ARMCC 5.x でも同様の条件で使用できます。


35.

Q.

--split_sections を指定しても、組み込みアセンブラで記述された関数がデッドストリップされません

A.

--split_sections が組み込みアセンブラで記述した関数で有効にならないのは仕様です。
下記の通り、#pragma arm section を使用して関数単位でセクション名を明示的に設定する必要があります。

#pragma push

#pragma arm section code="AAAA_Asm"
AAAA_Asm() {...}
#pragma arm section code="BBBB_Asm"
BBBB_Asm() {...}
#pragma arm section code="CCCC_Asm"
CCCC_Asm() {...}
: 省略

#pragma pop


36.

Q.

コンパイラが挿入したパディングの位置を知る方法について

クラスや構造体のアライメントのために以下の警告が出ますが、これがどこに、何バイトの
パディングを挿入したか知る方法はありますか?

#1301-D: padding inserted in XXXXX

A.

現状ではありません。
ARMCC 5.x での対応予定はありません。


37.

Q.

__forceinline を指定した関数を複数回呼び出すコードが最適化されません

__forceinline を指定した関数を複数回呼び出すようなコードを -O3 -Otime でビルドした際に、
最適化が期待通りに行われませんが、改善される予定はありますか?

A.

改善が検討されていますが、ARMCC 5.x での対応予定はありません。
マクロを使用した場合は、重複した関数呼び出しのうち、最後の1回だけがコードとして残ります。


38.

Q.

コンパイラで使用可能な文字コードについて

A.

ARMCCでのマルチバイトコードの扱いは、使用するホストOSに依存します。
Windows版では、Shift-JIS または UTF-8 (with BOM)のみとなっており、
EUCコードはサポートしていません。

また、コンパイル後のオブジェクトファイルの文字コードは、マルチバイト文字では ソースコードと同じ文字コードに、ワイド文字列ではUTF-16LEとなります。


39.

Q.

スタティックイニシャライザの挙動について

インラインでコンストラクタを書いた場合以下のようなソースコードのビルドが通ります。

---
・A.cpp

#include <nn.h>

class C {
public:
    C() {
        NN_LOG("AAA:%s(%d)\n", __FILE__, __LINE__);
    }
};

C A;

---
・B.cpp

#include <nn.h>

class C {
public:
    C() {
        NN_LOG("BBB:%s(%d)\n", __FILE__, __LINE__);
    }
};

C B;
---

これを実行すると、インスタンスA、Bのスタティックイニシャライザはコンストラクタを
片方のものでしか呼びません。リンクでエラーとなるかそれぞれのコンストラクタが呼ばれるのが
正しいのではないでしょうか?

A.

ビルドオプションに、--retain=calls を指定している場合、スタティックイニシャライザによる
グローバルオブジェクトの初期化は、インライン展開されず関数呼び出しとなります。

__sti___5_A_cpp PROC
        PUSH     {r4,lr}
        LDR      r0,|L1.16|
        BL       _ZN1CC1Ev    ; C::C() の呼び出し
        POP      {r4,pc}
        ENDP
これにより、クラス C のコンストラクタ _ZN1CC1Ev への参照が発生します。
リンカはこれを解決しますが、クラス C のコンストラクタ_ZN1CC1Ev は同名で
複数のオブジェクト内で定義されており、これらは同名の共通グループ(COMGROUP)が
使用されます。
AREA ||i._ZN1CC1Ev||, COMGROUP=_ZN1CC1Ev, CODE, READONLY, ALIGN=2

_ZN1CC2Ev                  ; Alternate entry point
_ZN1CC1Ev PROC
ドキュメント「リンカの使用」内の「5.2 共通グループまたは共通セクションの削除」に
説明があるように、リンカは最初に検出したグループを保持し、それ以外を削除します。
このため、多重定義などのリンクエラーは発生しません。

--retain=calls を指定しなかった場合、コンストラクタはインライン展開され、
グローバルオブジェクトの初期化は以下の様になります。

__sti___5_A_cpp PROC
        MOV      r2,#6
        ADR      r1,|L1.16|
        ADR      r0,|L1.52|
        B        _ZN2nn3dbg6detail6PrintfEPKcz
これにより、同一変換ユニット内のそれぞれのコンストラクタが呼び出されます。
--retain=calls 以外でも、--no_inline を指定した場合は、コンストラクタはインライン展開
されませんので、同名のコンストラクタを別のコンパイル単位で意図的に使用する場合には、ご注意下さい。


40.

Q.

配列へのポインタの扱いについて

以下のコードをコンパイルしても、エラーにならず通ってしまいます。

char (*str)[256] = new (char(*)[256])[2];
右辺は「配列へのポインタ」ですが左辺は「配列へのポインタの配列(の先頭アドレス)」なので、
間接参照のレベルが違います。左辺について、配列へのポインタの配列というのはそもそも new できる
ものなのでしょうか。(VisualStudio 2008 ではできませんでした)

A.

上記コードは、以下の様に置き換えることが出来ます。

  typedef char(*the_type)[256];
  the_type str = new (the_type)[2];
ここでの式 'new (the_type)[2]' は、C++では有効な記述ではないため、厳密なC++準拠を指定する
モード(--strict)ではエラーになります。また、--strict_warnings では、警告メッセージが表示
されます。デフォルトの非厳密モード(--no_strict)では、以下の様に取り扱います。
  the_type str = (new (the_type))[2];
the_type は、256 chars の配列へのポインタです。(new (the_type))は、このポインタをアロケートし、
このアドレスを返します。(new (the_type))[2] はこれを行い、その後に配列として返される値を扱い、
その二番目の(the_type 型を持つ)要素を返します。

配列へのポインタの配列をアロケートする場合には、以下の様になります(明確にするため、ここでもtypedefを使用します)

  typedef char array_type[256];
  typedef array_type *array_type_ptr;
  array_type_ptr *str = new array_type_ptr[2];
これは 256 chars の配列へのポインタの2つの要素を持った配列をアロケートし、'str' にポインタの
配列の最初の要素をセットします。

C++標準規格では、new expression でパーレン(丸括弧)の使用は'can have surprising effects'
(予期しない効果を持つ可能性がある)と述べられていますので、通常は typedef を使用することを推奨します。


41.

Q.

無名名前空間の大域変数を組み込みアセンブラから使う方法について

無名名前空間内にある変数のアドレスを得たいのですが、うまくいきません。
下記のようなコードで、L6218Eエラーが発生します。

namespace{
 float  localValue;

 asm float *GetLocalValueAddr()
 {
     LDR    r0,=__cpp(&localValue)
     BX    lr
 }
}

main()
{
 NN_LOG("local Addr:%p\n",GetLocalValueAddr());
} 

A.

組み込みアセンブラで記述した __asm 関数は同一変換ユニット内での複数の __asm 関数が
連結され、コンパイル時に内部的にarmasmが呼び出され、その後1つのオブジェクトに統合
されます。
無名名前空間のシンボルは外部リンケージ(export属性)を持ちません。localValue 変数は
GetLocalValueAddr() 関数と同じ無名名前空間に存在しますがexport属性の定義が存在しない
ためリンク時に参照が解決されず、リンクエラーとなります。

__cpp キーワードでは、外部リンケージを使用するデータまたは関数アドレスのみを取り扱う
ことが可能です。回避策としては、変数を無名名前空間から出し、static等を指定しない
グローバル変数として使用してください。


42.

Q.

ARMCC での C++0x(C++11) の導入について

A.

ARMCC5.05 以降での導入を検討してきましたが、機能実装のためのフロントエンドコンパイラ変更による影響が大きく、
また、ARMCC4.1/5.04 とのバイナリ互換性が完全に保証できないことが判明したため、CTR 開発用のコンパイラでは導入を
見送ることになりました。


43.

Q.

fast ビルド時に、ARMv5T 用ではなく ARMv4 用のライブラリがリンクされます

A.

リンカのデフォルトオプションでは、入力オブジェクトが ARM コードのみである場合は、
ARM 命令のみの ARMv4 用のライブラリ( c_4.l 等)を選択する仕様となっています。
入力オブジェクトに Thumb コードが含まれている場合は、ARMv5T 用のライブラリ( c_5.l 等)
が選択されます。

リンカのオプションに --cpu=MPCore を指定することで、入力オブジェクトがARM コードのみの
場合でも、ARMv5T 用のライブラリ( c_5.l 等)が選択されます。

CTR-SDK 4.0 のビルドルールで、リンカのデフォルトオプションに --cpu=MPCore が追加されました。


44.

Q.

コンパイラを ARMCC5.x に変更したら、以前には出ていなかった警告が出ます

A.

ARMCC5.x でのフロントエンドコンパイラ変更の影響で、以前には出ていなかった警告が出る場合があります。
意図的にエラーチェックを強化した訳ではありませんが、警告としては正しいものとなります。

例を挙げると、以下のような警告が出る場合があります。

  • #177-D: variable "ooo" was declared but never referenced
  • #550-D: variable "ooo" was set but never used
  • #836-D: returning reference to local variable
  • #2938-D: the initialization of member "ooo" will be done before that of member "ooo"

45.

Q.

コンパイラを ARMCC5.x に変更したら、--gnu 未指定時に #3093 のエラーになります

A.

コンパイラは、--gnu モードが指定された場合、またはソースコード中に "#pragma anon_unions" が
記述された場合に、構造体中に埋め込まれた無名の共用体または構造体をサポートします。

しかしながら、以前はこれらの2つのオプションが使用されていない場合においても、
無名の共用体・構造体の使用についてコンパイラは適切なエラーを表示していませんでした。

不正なコードの生成の原因となるため、ARMCC5.x ではエラーを出力するように修正しています。


46.

Q.

ARMCC5.04 に変更したら、DLL モジュールのリンク時に L6244E のエラーになります

A.

ARMCC 5.04 のリンカでは、ダイナミックリロケーションが生成された場合、--no_legacyalign が デフォルトとなるように仕様を変更しています。

CTR-SDK のビルドシステムは、この仕様変更に対応していないため、DLL モジュールのリンク時に L6244E のエラーが発生します。
また、DLL アプリのリンク時には ctr_makerom32 の実行時に「Too large section size」というエラーが発生します。

ARMCC5.04 では DLL アプリ / モジュールのリンク時には、--no_force-dynamic-natural-alignment を指定するようにしてください。

CTR-SDK 11.3.0 の SampleDemos でオプションを追加しています。
VSI-CTR Platform 2.3.4 以降では、ARMCC5.04 以降の --no_force-dynamic-natural-alignment オプション指定に対応しています。


47.

Q.

ビルド時間を短縮する方法について

A.

ビルド時間を短縮する方法として、以下のような方法が考えられます。

1.ビルド時間全体に影響する方法

- 並列実行を活用する
 ビルド環境に複数プロセッサが搭載されている場合には、omake の -j オプションや VSI-CTR の設定で、
 複数のコンパイルを並列実行することができます。
 また、サードパーティツールの「IncrediBuild Extension Package for Nintendo 3DS」等の導入による
 分散ビルド環境も、ビルド時間の短縮効果が見込めます。

- ビルド環境に十分なメモリを実装する
 omake の -j オプション等で複数のコンパイラやリンカを並列に実行する場合には、実装しているメモリ以上の
 仮想メモリが使用され、ビルドのパフォーマンスに大きな影響が出ることがあります。
 また、実装メモリに余裕があれば、システムのファイルキャッシュにより、ビルドのパフォーマンスに好影響が見込めます。

- ビルドで使用するファイルを高速なディスクに配置する
 ビルド時の入力・出力となるファイルを高速なディスクに配置することで、コンパイラやリンカのファイル入出力に
 必要となる時間を短縮する効果が見込めます。

  • ソースファイル
  • ヘッダファイル
  • ライブラリファイル
  • 中間ファイル出力フォルダ
  • 出力ファイルフォルダ
  • システム環境変数 TMP で指定されているフォルダ

2.コンパイル時間に影響する方法

- ヘッダファイル検索順を調整する
 使用頻度の高いヘッダファイルを、-I オプション等で指定するヘッダファイル検索順の先頭方向になるよう
 調整することで、コンパイル時のヘッダファイル検索に必要となる時間を短縮できます。

- プリコンパイルヘッダを使用する
 プリコンパイルヘッダを使用して、使用頻度の高いヘッダファイルをあらかじめ処理しておくことで、
 コンパイルごとに必要となるヘッダファイルの処理時間の短縮が見込めます。

- 不要なデバッグ情報を出力しない
 デバッグ済みのライブラリなどでデバッグ情報を出力しないようにすると、コンパイル時に必要となる処理と
 メモリ使用量を削減できます。また、リンク時に必要とするデバッグ情報の処理等も削減されます。

- コンパイル単位をまとめる
 小さなファイルを複数コンパイルするのではなく、一つのファイルにまとめてコンパイルすることで、
 ファイル入出力処理の時間の削減など、コンパイル時間の短縮効果が見込めます。

3.リンク時間に影響する方法

- マップファイルとコールグラフを生成しない
 SDK のデフォルトのビルドルールで生成しているマップファイルとコールグラフファイルを生成しないように、
 することで、リンク時間の短縮を見込めます。

- 逆アセンブルリストを生成しない
 SDK のデフォルトのビルドルールで生成している逆アセンブルリストを生成しないようにすることで、
 リンク後に fromelf コマンドを実行する時間が削減できます。

- 入力オブジェクトファイルのデバッグ情報を減らす
 ライブラリなど、デバッグの対象ではないソースファイルのデバッグ情報を減らすことで、
 リンク時に必要となる処理とメモリ使用量を削減できます。

- DLL アプリ・モジュールの部分リンク時にデバッグ情報を出力しない
 SDK のデフォルトのビルドルールでは、DLL の部分リンク(--partial オプション指定のリンク)時に
 デバッグ情報を出力していますが、このデバッグ情報は、後続のビルドプロセスとアプリのデバッグ時に
 必要ではありません。
 デバッグ情報を出力しないことで、部分リンクの時間を短縮でき、メモリ使用量も削減できます。

 CTR-SDK 7.2.1 以降で、DLL の部分リンク時にはデバッグ情報を作成しないように対応しました。
 VSI-CTR で CTR-SDK 7.2.1 用より前のプロジェクトを使用している場合は、「プリリンカー」で --no_debug
 オプションを使用することで対応できます。


48.

Q.

マップファイルを生成しない方法について

A.

SDK のデフォルトのビルドルールでは、以下のオプションで指定した情報を、--list オプションで指定するファイル(.map)
に出力しています。

 --info, --map, --symbols, --verbose, --xref

上記のオプションを指定しないようにしたうえで、--list オプションを指定しないことで、コンソールに出力される情報を
最小限にし、マップファイルを生成しないようにできます。

SDK のビルドルールでは、ビルド変数 LDFLAGS_INFO を変更してください。


49.

Q.

ARMCC5.04 に変更したら、デバッガが誤動作を起こします

A.

ARMCC 5.04 では、デバッガが参照する出力ファイル(.axf ファイル)内の情報に変更がありました。
未対応のデバッガでは、デバッグ情報を正しく読み込めず、誤動作を起こす場合があります。

ARMCC 5.04 で作成したアプリケーションをデバッグするには、PARTNER-CTR 5.70-040(2014/01/23 版)以降を使用してください。
また、プロファイリングを行う場合は、Nintendo 3DS CPU Profiler 3.01f 以降を使用してください。


50.

Q.

C++ 例外使用時に未使用関数が削除されない場合があります

A.

未使用関数は、リンカの未使用セクションの削除により最終イメージから削除されますが、
C++ 例外を使用するアプリケーションでは削除できない場合があります。

以下にリンカの未使用セクションの削除処理について説明します。

未使用セクション削除に関して、セクションは以下の3つの内部ステートの中のどれか一つになります。

1) Unused : リンカは最初に全てのセクションが未使用だと仮定します
2) Strongly Used : エントリポイントからの再配置のいくつかのチェーンを介して到達したセクション
3) Weakly Used : 弱く使用されているセクションは、...$$Base 及び...$$Limitのシンボル参照を含んだ
 セクションテーブルからの再配置のチェーンを介して到達可能なセクション。
 (C++例外については、.ARM.exidx$$Base と .ARM.exidx$$Limit 等)

Weakly Used セクションは、使用済みとしてマークされたすべてのコードセクションから例外テーブルと
静的コンストラクタの削除を防ぐために設定されたものです。

Weakly Used セクションを使用する未使用セクションの削除手順の概要を以下に示します。

1) 全ての C++ 関数は、例外テーブルエントリを持ちます。この例外テーブルエントリには、
セクションへの参照が存在します。

2) コードセクションから例外テーブルへの参照が無い場合はエントリポイントからの再配置が通常の
チェーンで行われ、全ての例外テーブルは破棄されます。これは、イメージで例外をスローしない
場合に行われます。

3) Strongly used セクションから参照される section_name$$Base と section_name$$Limit のシンボルを
持つ個々のセクションは Weakly Used としてマークされます。

4) Weakly Used セクションから参照される全てのセクションは、Weakly Used としてマークされます
(既に Strongly Used でない場合)。Weakly Used セクションは、いくつかの section_name$$Base
と section_name$$Limit のコード処理で間接的に到達するセクションです。

5) Weakly used セクションが、同一オブジェクト(同一コンパイル単位)内のStrongly Used セクションを
参照している場合は、Weakly Used セクションは Strongly Used セクションとなります。

6) 全ての Strongly Used セクションは保持され、残った全ての Weakly Used と Unused セクションは、
削除されます。

なお、アプリ側での明示的な例外のスロー処理がない場合でも、コンパイラオプションで --exceptions が
指定されると、vectorのコンストラクタ等には例外をスロー可能なシンボル(__cxa_vec_ctor)が使用され、
それがトリガとなって、スタック巻き戻し用のunwinderがリンクされ、例外テーブルは破棄されなくなります
(上記 2) が行われません)。

以下のようなソースで、アプリ内で used_function() 使用され、unused_function() が
使用されていない場合を例にとります。

void foo()
{
}

void used_function()
{
	foo();
}

void unused_function()
{
	foo();
}
Unused セクションの unused_function() は例外テーブルエントリから参照されていますが、C++ 例外が使用されなければ、
2) により例外テーブルが破棄されるため、Unused として削除されます。

C++ 例外が使用されている場合、 unused_function() は例外テーブルエントリからの参照があるため 4) により
Weakly Used としてマークされます。また、unused_function() から Strongly Used セクションである foo() が
参照されているため、5) により Strongly Used セクションとなります。unused_function() は 6) により
削除の対象にはなりません。

Weakly Used セクションの取り扱いに関しては、やや慎重な扱いをしており、現行のリンカ仕様では、
上記の条件にあてはまる関数を未使用として判断することは出来ません。そのため、最終イメージで
削除されずに残る場合があります。

上記の例の場合では、unused_function()を、参照する Strongly Used セクションとは別のソースに移動する
ことで、5) が適用されなくなり、Weakly used セクションとして削除されるようになります。


51.

Q.

ARMCC4.1 b1454 の --conservative_init_expression_optimization オプションについて

A.

ARMCC4.1 b1454 では、まれに初期化式を不正に生成する重複した関数呼び出しを引き起こす、以下の 2つの不具合を修正しています。

  • O3 -Otimeにて、関数の宣言及び2つの変数 A と B の初期化で、B の初期化が A に依存した引数を持つ関数 F() を呼び出すとき、
    コンパイラは不正に関数 F() を2回呼び出すことがありました。
  • O3 -Otimeにて、関数 F() の呼び出しによる関数の宣言及び変数の初期化のとき、コンパイラは、まれな状況で不正に関数 F() を
    2回呼び出すことがありました。
ARMCC4.1 b1454 のリリース時点では類似の未解決不具合はありませんが、予防措置として、必要に応じて初期化式に適用する
最適化を制限するオプション --conservative_init_expression_optimization を追加しています。

--remarks オプションを併用すると、--conservative_init_expression_optimization によって最適化が無効となった箇所で、

"test.cpp", line 19: #2463-D: Unsupported feature: (Auto splitting initialization from declaration)
のような診断結果が表示されます。この表示によって、本オプションによる最適化への影響を確認できます。