1.
■症状 最適化を有効にしても、命令順の最適化が有効にならない。 ■原因 本来機能するはずのプレスケジューラ最適化が、期待通りに動作しないケースがありました。 ■問題の発生するバージョン
- ARMCC4.1 b576 以前 ■回避策 ありません。 ■対応状況
- ARMCC4.1 b576 で修正しました。 |
2.
■症状 #pragma push/pop を用いても、診断メッセージの保存ができない ■原因
コンパイラに不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策 ありません。 ■対応状況
- ARMCC5.01 b34 で修正しました。 |
3.
■症状 std::stable_sort() を実行すると、NULL を指定した delete と 0Byte の new が呼び出される ■原因 RVCT で使用している RogueWave C++ ライブラリに不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策 ありません。 ■対応状況
- ARMCC4.1 b918 で修正しました。 |
4.
■症状 ARMCC 4.1 にアップデート後、ベクタモード内での混合演算ができません。 vfpassert vector<3> fmuls s16<3>, s8<3>, s0<> vfpassert scalar エラー: error A1422: This combination of vector and scalar operands is not allowedまた、fmuls の行を次のように変更すると、異なるエラーが出ます。 fmuls s16<3>, s8<3>, s0<1> エラー: error A1416: Vector length does not match current vector length 3 ■原因 ARMCC4.1 に含まれる、armasm に不具合がありました。 ■問題の発生するバージョン - ARMCC4.1 ■回避策 ありません。 ■対応状況 - ARMCC4.1 b909 で修正しました。 |
5.
■症状 -Otime -O3 の最適化で for文内にインライン関数経由の配列アクセスを記述すると、不正なコードが生成されます。 -- struct Vec { Vec() : x(0), y(0) {} int x, y; }; class Array { public: Array(); Vec* get() { return mArray; } private: Vec mArray[ NUM ]; }; Array::Array() { for( int i = 0; i < NUM; ++i ) { mArray[i].x = i; mArray[i].y = i; } } void test() { Array* a = new Array; Vec* v = a->get(); for( int i = 0; i <= NUM-1; ++i ) { a->get()[i].y = 0; // ここで Unhandled Exception になる } } -- ■原因 原因について調査中ですが、本症状は ARMCC 4.1 b640 以降では発生していません。 ■問題の発生するバージョン
- ARMCC4.1 b640 以前 ■回避策 該当関数で #pragma Ospace を指定してください。 -- #pragma push #pragma Ospace void test() { ... } #pragma pop -- ■対応状況
- ARMCC4.1 b640 以降では問題は発生しません。 |
6.
■症状 ARMCC4.1 にてプリコンパイルヘッダを使用すると、Internal fault が発生することがある ■原因 コンパイラのフロントエンド部分に不具合がありました。 ■問題の発生するバージョン - ARMCC4.1 ■回避策
有効な回避策がないため、以下の様にしてプリコンパイルヘッダの読み込みを行わないようにしてください。 -- #pragma hdrstop #include "test.h" // プリコンパイルしたヘッダ -- ■対応状況 - ARMCC4.1 b911 で修正しました。 |
7.
■症状 RVCT 4.0 で、「-O3 -Otime」の組み合わせで有効になるループ最適化処理に不具合があります。 -- #include<nw/gfx.h> using namespace nw::math; static MTX34 OptErrSub2() { return MTX34::Identity(); } inline MTX34 operator*(const MTX34 &lhs, const MTX34 &rhs) { MTX34 res; MTX34Mult (&res, &lhs, &rhs); return res; } inline f32 OptErrSub1() { MTX34 mf = OptErrSub2()*OptErrSub2(); return mf.a[0]; } f32 OptErrTest() { f32 res; s32 ok = 1; do { res = OptErrSub1(); } while( ok == 0 ); return res; } -- ■原因
上記コードでは、OptErrTest() 関数に operator* および OptErrSub1() がインライン展開されています。 ■問題の発生するバージョン - RVCT4.0 ■回避策
RVCT 4.0 は更新予定が無いため、下記のように対応してください。 -- #pragma push #pragma Ospace f32 OptErrTest() { ・・・ } #pragma pop -- ■対応状況 RVCT4.0 での修正予定はありません。 |
8.
■症状 RVCT 4.0 で、ビルド時に Warning: C3007E が表示される ■原因
RVCT 4.0 に不具合がありました。 ■問題の発生するバージョン - RVCT4.0 ■回避策
- コマンドラインオプションに、--diag_suppress=3007 を追加する。 #pragma push #pragma O0 // 該当する関数 (ワーニング3007が発生している関数) #pragma pop ■対応状況 RVCT4.0 での修正予定はありません。 |
9.
■症状 STL の algorithm 使用時に --gnu オプションを指定すると警告が発生する ■原因 RVCT 4.0 に不適切なワーニングが表示される不具合がありました。 ■問題の発生するバージョン - RVCT4.0 ■回避策 ありません。 ■対応状況 RVCT4.0 での修正予定はありません。 |
10.
■症状 最適化を上げると ? 演算子の挙動がおかしくなる ■原因
コンパイラ に不具合がありました。 -- unsigned foo(unsigned *curr, unsigned *last) { unsigned tot = 0; for(int i = 0; i < 10; ++i) { unsigned diff = (curr[i] >= last[i]) ? (curr[i] - last[i]) : (last[i] - curr[i]); tot += diff; } return tot; } -- ■問題の発生するバージョン
- ARMCC4.1 b619 以前 ■回避策 該当部分の最適化レベルを下げてください。 ■対応状況
- ARMCC4.1 b619 で修正しました。 |
11.
■症状 -Otime -O3 の最適化で、forループで配列に不正な値が書き込まれる ■原因
-Otime -O3で有効となるループ最適化に不具合がありました。 -- static __declspec(noinline) void test(u32 seed) { u32 x = (seed | 1U) & 0xFFFFFFFFU; u32 *s = &sState[1]; int j; for(*s++=x, j=N; --j; *s++ = (x*=69069U) & 0xFFFFFFFFU) { ; } } -- ■問題の発生するバージョン
- ARMCC4.1 b654 以前 ■回避策
#pragma Ospace を指定するなどで、本不具合を回避してください。 -- #pragma push #pragma Ospace static __declspec(noinline) void test(u32 seed) { ... } #pragma pop -- ■対応状況
- ARMCC4.1 b654 で修正しました。 |
12.
■症状 nn::math::Matrix を用いた関数呼び出しで、引数が破壊されることがある ■原因
コンパイラに不具合がありました。 -- #include<nn.h> using nn::math::Matrix34; Matrix34 func(const Matrix34& in) { Matrix34 out(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); // out のアドレスと in のアドレスが同じになっている in.Report(); // 既に in が破壊されている out.f._00 = in.f._00; // 正しい結果が得られない return out; } void nnMain(void) { Matrix34 a(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 1.0f, 2.0f, 3.0f); a = func(a); a.Report(); return; } -- ■問題の発生するバージョン
- ARMCC4.1 b713 以前 ■回避策
funcの返り値を一時変数に格納することで回避してください。 -- //a = func(a); MTX34 tmp = func(a); a=tmp; -- ■対応状況
- ARMCC4.1 b713 で修正しました。 |
13.
■症状 シフト演算の結果が最適化レベルによって異なる 下記のようなコードを実行すると、DebugビルドとReleaseビルドで結果が異なります。 #include <stdio.h> #include <nn/os.h> #include <nn/dbg.h> extern "C" void nnMain() { s16 buff[ 2 ] = { 0xffff, 0x00ff }; u32 data = (u32)( buff[ 0 ] | buff[ 1 ] << 16 ); NN_LOG( "%08x\n", data ); while(1){} } 結果 ・Debug時 :ffffffff ・Release時:00ffffff ■原因
-O2以上の指定で有効になるローテーション最適化に不具合があり、符号拡張が無効になっていました。 ■問題の発生するバージョン
- ARMCC4.1 b791 以前 ■回避策 該当するコードが記述されている関数内の最適化レベルを変更してください。 #pragma push #if __OPTIMISE_LEVEL >= 2 #pragma O1 #endif extern "C" void nnMain() { s16 buff[ 2 ] = { 0xffff, 0x00ff }; u32 data = (u32)( buff[ 0 ] | buff[ 1 ] << 16 ); NN_LOG( "%08x\n", data ); while(1){} } #pragma pop ■対応状況 - ARMCC4.1 b791で修正しました。 |
14.
■症状 std::sort()を使用すると多量の再帰呼び出しが発生することがある ■原因
std::sort()内で使用しているstd::__introsort_loop()関数に不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策
include/algorithm.ccの956行目にある__introsort_loop()の前に下記のコードを ■対応状況
- ARMCC4.1 b907 で修正しました。 |
15.
■症状 最適化レベルを上げると意図しないアドレスに書き込みが発生することがある 下記のコードを最適化レベル3でビルドすると、意図しないアドレスへの書き込みが発生します。 void arm11_test(void) { unsigned char dst_obj[64 * 4]; unsigned char ref_obj[64 * 4]; unsigned char *dst; unsigned char *ref; unsigned long rx = 1; unsigned long v0, v1, v2, v3, v4; signed long ref_skip; signed long i; dst = dst_obj; ref = ref_obj; ref_skip = rx; for (i = 0; i < 3; i++) { v0 = *(unsigned long *)(ref + 0); v1 = *(unsigned long *)(ref + 1); v2 = *(unsigned long *)(ref + 2); v3 = *(unsigned long *)(ref + 3); v4 = (unsigned long)*( ref + 4); v0 = (unsigned long)(((v0) >> 1) | ((v1) << 1)); v1 = (unsigned long)(((v1) >> 1) | ((v2) << 1)); *(unsigned long *)(dst) = v0; *(unsigned long *)(dst + 4) = v1; v2 = (unsigned long)(((v2) >> 1) | ((v3) << 1)); v4 = (unsigned long)(((v3) >> 1) | ((v4) << 1)); // ここで、dstの64倍と先のアドレスに書き込むことを期待していますが、 // 72バイト先のアドレスにストアされてしまいます。 *(unsigned long *)(dst + 64) = v2; *(unsigned long *)(dst + 64 + 4) = v4; ref += ref_skip; dst += 8; } } ■原因 コンパイラがLDM/STM命令を最適化する処理に不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 b791以前 ■回避策 この最適化は-O2以上で有効となるため、下記の方法で回避可能です。 #pragma push #pragma O1 void arm11_test(void) { // 省略 } #pragma pop ■対応状況 - ARMCC 4.1 b791 で修正しました。 |
16.
■症状 符号無し整数のデクリメントを使用するforループが無限ループになることがある -O3 -Otime でコンパイルした際に、符号無し整数のデクリメントを使用する for ループが無限ループになることがあります。 ■原因
コンパイラに不具合がありました。 以下のようなコードで発生する場合があります。 ---------------------------- for( unsigned int i = 100; i != (unsigned int)-1 ; --i ) { ... } ---------------------------- ■問題の発生するバージョン
- ARMCC4.1 b619 以前 ■回避策 インクリメントループに置き換えて、(unsigned)-1との比較を行わないコードに変更することで、回避することが出来ます。 ■対応状況
- ARMCC4.1 b713 で修正しました。 |
17.
■症状 符号有り値と符号無し値を正しく変換できないことがある
RVCT4.0/ARMCC4.1 を使用して、下記のようなコードをコンパイルすると、 u16 uVal = 0x999c; s16 sVal = *(s16*)&uVal; int intVal = (int)sVal; ※intVal には 0xFFFF999c (-26212) が入るべきにもかかわらず、 0x999c (39324) が入っている。 ■原因 コンパイラに不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 b713 以前 ■回避策
s16 sVal = (s16)uVal とするか、下記のように符号付き整数をテンポラリ変数として使用し、 u16 uVal = 0x999c; s32 tmp = *(s16*)&uVal; s16 sVal = (s16)tmp; int intVal = (int)sVal; ■対応状況
- ARMCC4.1 b713 で修正しました。 |
18.
■症状 inlineキーワードを使用した関数を、-O3と-Otimeのオプションでコンパイルすると、比較式で不正な値が使用されることがある ■原因 コンパイラの共通部分式除去(Common subexpression elimination) の最適化に不具合がありました。 ■問題の発生するバージョン - RVCT4.0 ■回避策
RVCT 4.0は、今後の更新予定がありませんので、以下の様な #pragma を inline関数を #pragma push #pragma Ono_cse float hogehoge(unsigned int var1) { ・・・ } #pragma pop ■対応状況 - RVCT4.0 での修正予定はありません。 |
19.
■症状 -Otime と-O3 の最適化で、配列の最後の部分を通過して不正なリードが発生する ■原因
Otime と-O3 の最適化で、コンパイラは、次の繰り返しのためにデータをプリフェッチする目的で 以下のようなコードで発生します。 int test(int* input, int length) { int r = 0; for (int i = 0; i < length; i++) { r += *input++; } return r; }メモリヒープの終端を配列領域に使用するような場合には、アクセス違反が発生する場合があります。 ■問題の発生するバージョン
- ARMCC4.1 b640 以前 ■回避策 #pragma Ospace を指定することで回避してください。 #pragma push #pragma Ospace int test(int* input, int length) { ... } #pragma pop ■対応状況
- ARMCC4.1 b640 で修正しました。 |
20.
■症状 "Warning 997 virtual function override intended?" が抑制されてしまう
<nn/fs.h>をインクルードすると、"Warning 997 virtual function override intended?" の ■原因
<nn/fs.h>内で上記警告を抑制しており、#pragma push/pop を用いても、診断メッセージの保存ができない ■問題の発生するバージョン
- ARMCC4.1 ■回避策
#include <nn/fs.h> の直後に、 #pragma diag_warning 997 と書くことによって、警告を出すことができるようになります。 ■対応状況 - CTR-SDK 5.0 で修正されました。 |
21.
■症状 -Otime -O3 の最適化において、無名名前空間内への関数呼び出しで不正なパラメータが渡される ■原因
コンパイラに不具合がありました。 namespace { volatile int& s_Reg = *reinterpret_cast(0x00100000); void Test0(int x) { s_Reg = x; } } void Test1() { Test0(0x1234); int tmp; __asm { mrs tmp, cpsr } } void Test2() { Test0(0x5678); } ■問題の発生するバージョン
- ARMCC4.1 b640 以前 ■回避策 RVCT4.0 は今後の更新予定がありませんので、#pragma Ospace を指定するなどで、本不具合を回避してください。 namespace { volatile int& s_Reg = *reinterpret_cast(0x00100000); #pragma push #pragma Ospace void Test0(int x) { s_Reg = x; } #pragma pop ■対応状況
- ARMCC4.1 b698 で修正しました。 |
22.
■症状 #634-D や #631-D などの警告が出る ■原因
このワーニングが発生する主な原因としては、ホスト側でアドレス空間配置のランダム化(ASLR)が ■問題の発生するバージョン
- ARMCC4.1/5.x ■回避策 ビルド時にセキュリティ用ソフトウェアを無効にしてください。 ■対応状況 - ARMCC4.1/5.x、RVCT4.0 での修正予定はありません。 |
23.
■症状 ゼロサイズ配列を生成するテンプレートで内部エラーが発生する
下記のようなコードを書いてテンプレートを実体化した場合、
template ■原因 コンパイラのフロントエンドに不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1/5.x ■回避策 ありません。 ■対応状況 - ARMCC4.1/5.x、RVCT4.0 での修正予定はありません。 |
24.
■症状 プリコンパイルヘッダ使用時にコンパイラがInternal faultを出します ■原因 コンパイラに不具合がありました。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策
問題の発生するソースでは、 #pragma hdrstop を使用して、プリコンパイルヘッダを ■対応状況 - ARMCC4.1 b911 で修正しました。 |
25.
■症状 -Otime -O3 の最適化で、配列が不正にセットされることがある ■原因 -O3 -Otime で有効になる最適化時に、不正に型情報を取り扱う不具合です。 以下のようなコードで発生します。 struct Element { float x, y, z, u0, v0, u1, v1; }; #define DIVISOR 5 void SetData(Element* elements, f32 v0) { Element* e = elements; for (int t = 0; t < DIVISOR + 1; t++) { f32 v = v0 * t; for (int s = 0; s < DIVISOR + 1; s++) { e++->v0 = v; } } } ■問題の発生するバージョン - ARMCC4.1 b1133 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。 1) #pragma O2 を指定する #pragma push #pragma O2 void SetData(Element* elements, float v0) { // 中略 } #pragma pop 2) 明示的な型変換を行う(float 型でキャストする) float v = v0 * (float)t; ■対応状況 - ARMCC4.1 b1247 で修正しました。 |
26.
■症状 -O2 以上の最適化で、正常に演算が行われなくなることがある ■原因 共通部分式除去最適化に関連した不具合です。 以下のようなコードで発生します。 struct Test { unsigned short _n; }; inline static void add(Test* __restrict p) { ++p->_n; } inline static void run(Test* __restrict p) { add( p ); ++p->_n; p->_n += p->_n; } Test gTest; extern "C" void nnMain(void) { run( &gTest ); nn::dbg::detail::Printf( "\nResult: N = %04x\n", gTest._n ); for( ;; ); } ■問題の発生するバージョン
- ARMCC4.1 b1133 以前 ■回避策
-O0 または -O1 オプションを使用するか、非公開コンパイラオプション -Ono_cse_restrict を指定することで、 ■対応状況 - ARMCC4.1 b1247 で修正しました。 |
27.
■症状 -Otime -O3 の最適化で、演算の処理順序がおかしくなることがある ■原因 -O3 -Otime の組み合わせで有効になる最適化の不具合です。 以下のようなコードで発生します。 #pragma no_inline class DMY{}; void* testSub(DMY, const char* a, size_t* size) { *size = 160; return (void*)a; } void test() { size_t size; void* p = testSub(DMY(), "hoge", &size); int n = size/8; printf("n: %d\n", n); if (p==NULL) return; printf("p: %s\n", p); } ■問題の発生するバージョン
- ARMCC4.1 b1133 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。 1) 該当する関数の最適化レベルを変更し、-O3 -Otime 以外の組み合わせにする #pragma push #pragma Ospace void test() { // 中略 } #pragma pop 2) 非公開コンパイラオプション -Ono_vast を追加し、不具合の原因となる最適化のみを無効にする ■対応状況 - ARMCC4.1 b1247 で修正しました。 |
28.
■症状 -O3 -Otime の最適化で、不正な変数の初期化が行われることがある ■原因 -O3 -Otime で有効になるループ最適化の不具合です。 以下のようなコードで発生します。 u32 foo() { // 中略 case CASE_ooo: for (j = 0, i = 0; j < 2; j++) { // 中略 for (k = 8; k--; i++) { p->m_bar[i] = hoge; // 中略 } } // 中略 }p->m_bar[i]へのストア処理のインデックスの生成が正しく行われておらず、不正な結果となっていました。 ■問題の発生するバージョン
- ARMCC4.1 b1247 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。 1) 該当する関数の最適化レベルを変更し、-O3 -Otime 以外の組み合わせにする #pragma push #pragma O2 u32 foo() { // 中略 } #pragma pop 2) 変数の初期化をループの外側で行う case CASE_ooo: i = 0; for (j = 0; j < 2; j++) { ■対応状況
- ARMCC4.1 b1307 で修正しました。 |
29.
■症状 ARMCC5.x にアップデート後、--gnu 指定時に、関数テンプレートのオーバーロード関数が引数に依存して解決されない ■原因 ARMCC5.x で使用しているフロントエンドの、GNU互換モードのGCCバグエミュレートによるものです。 以下のようなコードで発生します。 template関数 bar(const Y*, const X*) は、テンプレート foo(const U* u) を呼び出し、 この関数の内部で引数 u からconst 修飾子がストリップされ(const_cast オペレータが使用されたため)、 foo 関数が呼び出されます。 C++標準仕様では、コンパイラは、関数名 "foo" を可視性がある(visible)と見なします。したがって、 他のオーバーロード関数の引数依存の照合を開始し、関数テンプレート foo(U * U)を検索します。 GCC は、引数依存ルックアップを実行しないため、foo(U *u) ではなく foo(const U* u) を使用します。 これは、GCC の不具合であり、4.4.4 で修正されていますが、ARMCC5.x の gnu 互換モードでは、 GCC の不適切な振る舞いをエミュレートしています。 ■問題の発生するバージョン
- ARMCC5.x ■回避策 ありません。 ■対応状況 - ARMCC5.x での修正予定はありません。 |
30.
■症状 ARMCC4.1 b1247 にアップデート後、-O3 -Otime の最適化で、静的データへのポインタに NULL がセットされることがある ■原因 -O3 -Otime で有効になる最適化の不具合です。 以下のようなコードで発生します。 class Hoge : HogeBase { public : static const char* cHoge_A[]; static const char* cHoge_B[]; private : void foo(bool b); }; const char* Hoge::cHoge_A[] = { (中略) }; const char* Hoge::cHoge_B[] = { (中略) }; void Hoge::foo(bool b) { Index i = GetIndex(); const char* pName = b ? cHoge_A[i] : cHoge_B[i]; (中略) }pName に未初期化の値が読み込まれてしまい、NULL がセットされていました。 ■問題の発生するバージョン
- ARMCC4.1 b1247 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを変更し、-O3 -Otime 以外の組み合わせにする #pragma push #pragma O2 void Hoge::foo(bool b) { (中略) } #pragma pop 2) 三項演算子の部分と変数の宣言を分ける 【変更前】 const char* pName = b ? cHoge_A[i] : cHoge_B[i]; 【変更後】 const char* pName; pName = b ? cHoge_A[i] : cHoge_B[i]; ■対応状況 - ARMCC4.1 b1307 で修正しました。 |
31.
■症状 ARMCC5.x にアップデート後、パスに全角文字が含まれているとビルドに失敗する ■原因 ARMCC 5.0 以降で変更を行ったコンパイラフロントエンドに関連する不具合です。 ■問題の発生するバージョン
- ARMCC5.x ■回避策 ビルドで使用するパスに全角文字を含まないようにして回避してください。 ■対応状況 - ARMCC5.x での修正予定はありません。 |
32.
■症状 -O2 以上の最適化で、不正なオフセットを使用して構造体メンバ変数に書き込むことがある ■原因 -O2 以上で有効になる最適化の不具合です。 以下のようなコードで発生します。 template< class Hoge1, class Hoge2, int n, typename Hoge3 > class Hoge { public: Hoge1* hoge1; Hoge2 hoge2a; Hoge2 hoge2b; Hoge3 hoge3[ n ]; public: Hoge() : hoge1( 0 ), hoge2a( ( Hoge2 )0 ), hoge2b( ( Hoge2 )0 ) { ::memset( hoge3, 0, sizeof( hoge3 ) ); } void Foo( Hoge1* h1, const Hoge3* h3, size_t len ) { hoge1 = h1; ::memcpy( hoge3, h3, sizeof( Hoge3 ) * n ); } };hoge1 への代入時に誤ったオフセットを使用するコードが生成されていました。
コンパイルの終盤の最適化処理での問題で、発生条件を詳細に特定することはできませんが、以下の事が判明しています。 ■問題の発生するバージョン
- ARMCC4.1 b1307 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを -O1 以下に変更する #pragma push #pragma O1 void Bar::Bar() { (中略) hoge.Foo(this, p, n) (中略) } #pragma pop 2) 問題が発生する関数をインライン展開しないようにする 【変更前】 void Foo( Hoge1* h1, const Hoge3* h3, size_t len ) 【変更後】 void Foo( Hoge1* h1, const Hoge3* h3, size_t len ) __attribute__((noinline)); ■対応状況
- ARMCC4.1 b1440 で修正しました。 |
33.
■症状 ARMCC5.x にアップデート後、無名名前空間を使用しているソースで、コンパイラが不正終了することがある ■原因 ARMCC5.x のコンパイラフロントエンドの不具合です。 以下のようなコードで発生します。 1) 無名名前空間と dynamic_cast の組み合わせ class Base { public: virtual ~Base() { } }; bool is_derived(Base *i_base); namespace { class Derived : public Base { }; } class AClass { public: static bool down_cast_test(Base *i_base) { Derived *d = dynamic_cast 2) 無名名前空間と クラスの delete の組み合わせ namespace { class Foo { public: Foo():_member(0) { } virtual ~Foo() { } protected: int _member; }; } namespace code { class Bar { Foo* _member; Bar() { _member = new Foo(); } virtual ~Bar() { delete _member; } }; } ■問題の発生するバージョン
- ARMCC5.04 b27 以前 ■回避策 問題が発生している無名名前空間では、名前付きの名前空間を使用してください。 ■対応状況 - ARMCC5.04 b49 で修正しました。 |
34.
■症状 -Otime -O3 の最適化で、不正なループのコードが生成されることがある ■原因 -O3 -Otime で有効になる最適化の不具合です。 以下のようなコードで発生します。 void foo( int first, int last ) { int sum = 0; int i, j; for( i = first, j = last; i <= last; j = i++ ) { sum += j; } NN_LOG( "sum = %d, i = %d, j = %d\n", sum, i, j ); }上記のコードでは、変数 j の値が誤って加算され、変数 sum も不正な値となっていました。 ■問題の発生するバージョン
- ARMCC4.1 b1307 以前 ■回避策 該当する関数の最適化レベルを -O3 -Otime 以外に指定して回避してください。 #pragma push #pragma O2 void foo( int first, int last ) { // 中略 } #pragma pop ■対応状況
- ARMCC4.1 b1440 で修正しました。 |
35.
■症状 --diag_suppress に error を指定するとコンパイルに失敗することがある ■原因
--diag_suppress=error で、すべての降格可能エラーを非表示に降格すると、降格できないエラーを ■問題の発生するバージョン
- ARMCC4.1/5.x ■回避策 --diag_suppress では error を指定せず、非表示に降格したいメッセージ番号を直接指定して回避してください。 ■対応状況 - ARMCC4.1/5.x での修正予定はありません。 |
36.
■症状 --diag_warning に error を指定するとオブジェクトファイルが生成されないことがある ■原因 --diag_warning=error で、すべての降格可能エラーを警告に降格すると、オブジェクトファイルを出力せずにコンパイルが終了することがあります。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策 --diag_warning では error を指定せず、警告に降格したいメッセージ番号を直接指定して回避してください。 ■対応状況
- ARMCC4.1 での修正予定はありません。 |
37.
■症状 alloca を使用している関数を __forceinline でインライン化すると Internal fault が発生する ■原因
alloca を使用する関数は inline キーワード指定や自動インラインでのインライン化の対象ではありませんが、 ■問題の発生するバージョン
- ARMCC4.1/5.x ■回避策 alloca を使用している関数には __forceinline を指定しないようにして回避してください。 ■対応状況 - ARMCC4.1/5.x での修正予定はありません。 |
38.
■症状 -Otime -O3 の最適化で、変数を初期化する関数が二重に呼び出されることがある ■原因 -Otime -O3 で有効になる最適化の不具合です。 以下のようなコードで発生します。 struct Type1 { Type1(); }; struct Type2 { Type2(); }; struct Builder { Type1 method1(); Type2 method2(Type1); }; void broken(Builder *builder) { Type1 t1 = builder->method1(); // 二重に呼び出される const Type2 &t2 = builder->method2(t1); }上記のコードでは、以下の発生要因を満たしているため、method1 が二重に呼び出されます。 1) あるメソッド(method1)の結果(t1)が別のメソッド(method2)の引数として渡される 2) 後者のメソッド(method2)の結果が const の参照(const Type2 &t2)に割り当てられる ■問題の発生するバージョン
- ARMCC4.1 b1247 以降 b1440 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを変更し、-Otime -O3 以外の組み合わせにする #pragma push #pragma Ospace void broken(Builder *builder) { Type1 t1 = builder->method1(); const Type2 &t2 = builder->method2(t1); } #pragma pop 2) method2 の結果を const ではなく、通常の変数に割り当てる Type2 t2 = builder->method2(t1); ■対応状況
- ARMCC4.1 b1454 で修正しました。
ARMCC4.1 b1454 では、同様の問題の予防措置としてコンパイラオプションを追加しています。 No. 51「ARMCC4.1 b1454 の --conservative_init_expression_optimization オプションについて」 |
39.
■症状 -Otime -O3 の最適化で、ループ内で変数を初期化する関数が二重に呼び出されることがある ■原因 -Otime -O3 で有効になる最適化の不具合です。 以下のようなコードで発生します。 struct X { X(); }; struct Y { Y(); }; X makeX(); bool proc(X, Y); void broken() { Y y; while (1) { X x = makeX(); // 二重に呼び出される bool result = proc(x, y); } }また、proc がどのような定義か、x および y がどのように proc に与えられるかによりません。 例えば以下のようなコードでも発生します。 struct X { X(); }; struct Y { Y(); }; X makeX(); bool proc(void *, void*); void *convX(X); void *convY(Y); void broken() { Y y; while (1) { X x = makeX(); // 二重に呼び出される bool result = proc(convX(x), convY(y)); } }上記のコードでは、以下の発生要因を満たしているため、makeX が二重に呼び出されます。 1) 変数 x と result のスコープが共にループ内にある 2) 変数 x がいくつかの関数(proc)経由で result の算出に使用される 3) 関数(proc)がループの外にスコープがある別の変数(y)を引数にとる ■問題の発生するバージョン
- ARMCC4.1 b1247 以降 b1440 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを変更し、-Otime -O3 以外の組み合わせにする #pragma push #pragma Ospace void broken() { { (中略) } #pragma pop 2) 変数 x または result の宣言をループの外に出す(または、両方の宣言をループの外に出す) void not_broken() { Y y; bool result; while (1) { X x = makeX(); result = proc(x, y); } } ■対応状況
- ARMCC4.1 b1454 で修正しました。
ARMCC4.1 b1454 では、同様の問題の予防措置としてコンパイラオプションを追加しています。 No. 51「ARMCC4.1 b1454 の --conservative_init_expression_optimization オプションについて」 |
40.
■症状 std::vector::operator= で代入先のサイズが縮小されると、Allocator の deallocate に渡されるサイズが不正になることがある ■原因 ARMCC の C++ ライブラリの不具合です。 std::vector::operator= で、dest_vector = source_vector を実行したときに、以下の条件が全て真の場合に発生します。
1) source_vector.size() <= dest_vector.capacity()
このとき、dest_vector.capacity() は、割当済みのサイズに関わらず source_vector.size() と一致し、 ■問題の発生するバージョン
- ARMCC4.1 ■回避策 C++ ライブラリ include\vector.cc の vector<_TypeT,_Allocator>::operator= (const vector<_TypeT,_Allocator>& __x)を、以下のように修正して回避してください。 修正前: else if (size() >= __x.size()) { iterator __it = copy (__x.begin (), __x.end (), begin ()); _C_destroy (__it, end ()); _C_end_of_storage = _C_finish = _C_start + __x.size(); }修正後: else if (size() >= __x.size()) { iterator __it = copy (__x.begin (), __x.end (), begin ()); _C_destroy (__it, end ()); _C_finish = _C_start + __x.size(); } ■対応状況
- ARMCC4.1 での修正予定はありません。 |
41.
■症状 コンパイラが C9932E / C9558E エラーを不正に出力することがある ■原因
PC 上に 1970/1/2 以前のタイムスタンプのファイルがあると、コンパイル時に以下のようなメッセージを出力してエラーとなることがあります。 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 エラーになります。) この問題は、Timezoneが+1~+12のHostPCで発生し、1970/1/1 + Timezone よりも以前のタイムスタンプのファイルを不正なファイルとして誤検出し、 エラーとなります。 ■問題の発生するバージョン
- ARMCC4.1 ■回避策
PC 上の 1970/1/2 以前のファイルのタイムスタンプのファイルを修正して回避してください。 No. 2「コンパイラが C9932E / C9558E エラーを返すときの対応について」 ■対応状況
- ARMCC4.1 での修正予定はありません。 |
42.
■症状 ARMCC4.1 の -Otime -O3 の最適化で、変数を初期化する関数が呼び出されないことがある ■原因
-Otime -O3 で有効になる最適化の不具合です。 No. 38「-Otime -O3 の最適化で、変数を初期化する関数が二重に呼び出されることがある」 No. 39「-Otime -O3 の最適化で、ループ内で変数を初期化する関数が二重に呼び出されることがある」と同一原因の不具合です。 以下のようなコードで発生します。 struct C { int m_i; int m_fn1(); int m_fn2(int); int test(); }; C* get_c(); C *glob_c_ptr = get_c(); int C::test() { int a = m_fn1(); int b = a; int c = glob_c_ptr->m_fn2(m_i); return b; }上記のコードでは、以下の発生要因を満たしているため、m_fn1 が呼び出されません。 1) 関数(またはメソッド)の呼び出しを含む式の変数宣言 2) その関数呼び出しの引数が、それ以前の初期化によるもの ■問題の発生するバージョン
- ARMCC4.1 b1247 以降 b1440 以前 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを変更し、-Otime -O3 以外の組み合わせにする #pragma push #pragma Ospace int C::test() { { (中略) } #pragma pop 2) 変数の宣言を初期化と分ける int C::test() { int a; a = m_fn1(); int b; b = a; int c; c = glob_c_ptr->m_fn2(m_i); return b; } ■対応状況
- ARMCC4.1 b1454 で修正しました。
ARMCC4.1 b1454 では、同様の問題の予防措置としてコンパイラオプションを追加しています。 No. 51「ARMCC4.1 b1454 の --conservative_init_expression_optimization オプションについて」 |
43.
■症状 ARMCC4.1 の -Otime -O3 の最適化で、ループ内の配列アクセスのオフセットが不正になることがある ■原因 -Otime -O3 で有効になるループアンロール最適化の不具合です。 以下のようなコードで発生します。 void Hoge::foo( const u8 work[4] ) { for( u8 i = 0; i < 4; i++ ) { m_pWork->m_work[i] = work[i]; } }上記のようなコードで、以下の発生要因を満たした場合に、配列のオフセットが不正になることがあります。 1) コンパイル時に値が決まっている定数による loop iterator がある 2) ループ内で、その loop iterator を index として用いた配列を使用し、その配列がループアンロールされる ■問題の発生するバージョン
- ARMCC4.1 ■回避策 以下のいずれかの方法で、本不具合を回避してください。1) 該当する関数の最適化レベルを変更し、-Otime -O3 以外の組み合わせにする #pragma push #pragma Ospace void Hoge::foo( const u8 work[4] ) { (中略) } #pragma pop 2) ループ内の配列の代わりにポインタを用いる void Hoge::foo( const u8 work[4] ) { for( u8 i = 0; i < 4; i++ ) { *(m_pWork->m_work + i) = work[i]; } } ■対応状況 - ARMCC4.1 での修正予定はありません。 |