コンパイラの既知の不具合について

コンパイラには、現在下記の不具合が確認されています。


  1. 【ARMCC4.1 b576 で修正済】最適化を有効にしても、命令順の最適化が有効にならない
  2. 【ARMCC5.01 b34 で修正済】#pragma push/pop を用いても、診断メッセージの保存ができない
  3. 【ARMCC4.1 b918 で修正済】std::stable_sort() を実行すると、NULL を指定した delete と 0Byte の new が呼び出される
  4. 【ARMCC4.1 b909 で修正済】ARMCC 4.1 にアップデート後、ベクタモード内での混合演算ができない
  5. 【ARMCC4.1 b640 で修正済】-Otime -O3 の最適化で for文内にインライン関数経由の配列アクセスを記述すると、不正なコードが生成される
  6. 【ARMCC4.1 b911 で修正済】ARMCC4.1 にてプリコンパイルヘッダを使用すると、Internal fault が発生することがある
  7. 【RVCT4.0】「-O3 -Otime」の組み合わせで有効になるループ最適化処理に不具合がある
  8. 【RVCT4.0】ビルド時に Warning: C3007E が表示される
  9. 【RVCT4.0】STL の algorithm 使用時に --gnu オプションを指定すると警告が発生する
  10. 【ARMCC4.1 b619 で修正済】最適化を上げると ? 演算子の挙動がおかしくなる
  11. 【ARMCC4.1 b654 で修正済】-Otime -O3 の最適化で、forループで配列に不正な値が書き込まれる
  12. 【ARMCC4.1 b713 で修正済】nn::math::Matrix を用いた関数呼び出しで、引数が破壊されることがある
  13. 【ARMCC4.1 b791 で修正済】シフト演算の結果が最適化レベルによって異なる
  14. 【ARMCC4.1 b907 で修正済】introsort_loop()を使用すると多量の再帰呼び出しが発生することがある
  15. 【ARMCC4.1 b791 で修正済】最適化レベルを上げると意図しないアドレスに書き込みが発生することがある
  16. 【ARMCC4.1 b713 で修正済】符号無し整数のデクリメントを使用するforループが無限ループになることがある
  17. 【ARMCC4.1 b713 で修正済】符号有り値と符号無し値を正しく変換できないことがある
  18. 【RVCT4.0】inlineキーワードを使用した関数を、-o3と-otimeのオプションでコンパイルすると、比較式で不正な値が使用されることがある
  19. 【ARMCC4.1 b640 で修正済】-Otime と-O3 の最適化で、配列の最後の部分を通過して不正なリードが発生する
  20. 【CTR-SDK 5.0 で修正済】"Warning 997 virtual function override intended?" が抑制されてしまう
  21. 【ARMCC4.1 b698 で修正済】-Otime -O3 の最適化において、無名名前空間内への関数呼び出しで不正なパラメータが渡される
  22. #634-D や #631-D などの警告が出る
  23. ゼロサイズ配列を生成するテンプレートで内部エラーが発生する
  24. 【ARMCC4.1 b911 で修正済】プリコンパイルヘッダ使用時にコンパイラがInternal faultを出します
  25. 【ARMCC4.1 b1247 で修正済】-Otime -O3 の最適化で、配列が不正にセットされることがある
  26. 【ARMCC4.1 b1247 で修正済】-O2 以上の最適化で、正常に演算が行われなくなることがある
  27. 【ARMCC4.1 b1247 で修正済】-Otime -O3 の最適化で、演算の処理順序がおかしくなることがある
  28. 【ARMCC4.1 b1307、ARMCC5.04 b27 で修正済】-O3 -Otime の最適化で、不正な変数の初期化が行われることがある
  29. 【ARMCC5.x】ARMCC5.x にアップデート後、--gnu 指定時に、関数テンプレートのオーバーロード関数が引数に依存して解決されない
  30. 【ARMCC4.1 b1307 で修正済】ARMCC4.1 b1247 にアップデート後、-O3 -Otime の最適化で、静的データへのポインタに NULL がセットされることがある
  31. 【ARMCC5.x】ARMCC5.x にアップデート後、パスに全角文字が含まれているとビルドに失敗する
  32. 【ARMCC4.1 b1440、ARMCC5.04 b49 で修正済】-O2 以上の最適化で、不正なオフセットを使用して構造体メンバ変数に書き込むことがある
  33. 【ARMCC5.04 b49 で修正済】ARMCC5.x にアップデート後、無名名前空間を使用しているソースで、コンパイラが不正終了することがある
  34. 【ARMCC4.1 b1440、ARMCC5.04 b82 で修正済】-Otime -O3 の最適化で、不正なループのコードが生成されることがある
  35. --diag_warning に error を指定するとコンパイルに失敗することがある
  36. 【ARMCC4.1】【ARMCC5.04 b146 で修正済】--diag_suppress に error を指定するとオブジェクトファイルが生成されないことがある
  37. alloca を使用している関数を __forceinline でインライン化すると Internal fault が発生する
  38. 【ARMCC4.1 b1454、ARMCC5.04 b146 で修正済】-Otime -O3 の最適化で、変数を初期化する関数が二重に呼び出されることがある
  39. 【ARMCC4.1 b1454 で修正済】-Otime -O3 の最適化で、ループ内で変数を初期化する関数が二重に呼び出されることがある
  40. std::vector::operator= で代入先のサイズが縮小されると、Allocator の deallocate に渡されるサイズが不正になることがある

1.

■症状

最適化を有効にしても、命令順の最適化が有効にならない。

■原因

本来機能するはずのプレスケジューラ最適化が、期待通りに動作しないケースがありました。

■問題の発生するバージョン

- ARMCC4.1 b576 以前
- RVCT4.0

■回避策

ありません。

■対応状況

- ARMCC4.1 b576 で修正しました。
- RVCT4.0 での修正予定はありません。


2.

■症状

#pragma push/pop を用いても、診断メッセージの保存ができない

■原因

コンパイラに不具合がありました。
diag_suppress で指定した状態を、 #pragma push/pop で保存できません。

■問題の発生するバージョン

- ARMCC4.1
- RVCT4.0

■回避策

ありません。

■対応状況

- ARMCC5.01 b34 で修正しました。
- ARMCC4.1、RVCT4.0 での修正予定はありません。


3.

■症状

std::stable_sort() を実行すると、NULL を指定した delete と 0Byte の new が呼び出される

■原因

RVCT で使用している RogueWave C++ ライブラリに不具合がありました。

■問題の発生するバージョン

- ARMCC4.1
- RVCT4.0

■回避策

ありません。

■対応状況

- ARMCC4.1 b918 で修正しました。
- RVCT4.0 での修正予定はありません。


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文内にインライン関数経由の配列アクセスを記述すると、不正なコードが生成されます。
以下のようなコードで Unhandled Exception が発生します。

--
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 以前
- RVCT4.0

■回避策

該当関数で #pragma Ospace を指定してください。

--
#pragma push
#pragma Ospace
void test() 
{
...
}
#pragma pop
--

■対応状況

- ARMCC4.1 b640 以降では問題は発生しません。
- RVCT4.0 での修正予定はありません。


6.

■症状

ARMCC4.1 にてプリコンパイルヘッダを使用すると、Internal fault が発生することがある

■原因

コンパイラのフロントエンド部分に不具合がありました。

■問題の発生するバージョン

- ARMCC4.1

■回避策

有効な回避策がないため、以下の様にしてプリコンパイルヘッダの読み込みを行わないようにしてください。
※PCH を再利用する側(--use_pch)のソースコードの先頭に、以下の pragma を追加します。

--
#pragma hdrstop
#include "test.h" // プリコンパイルしたヘッダ
--

■対応状況

- ARMCC4.1 b911 で修正しました。


7.

■症状

RVCT 4.0 で、「-O3 -Otime」の組み合わせで有効になるループ最適化処理に不具合があります。
下記のようなコードを Release ビルドすると、結果が不定になります。

--
#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() がインライン展開されています。
このとき、ループ最適化処理は関数内の変数 mf の属性を正しく扱わずに、ループの外側で値をリード
していました。そのため、OptErrSub1() からの戻り値を使用する変数 res に不正な値を設定していました。

■問題の発生するバージョン

- RVCT4.0

■回避策

RVCT 4.0 は更新予定が無いため、下記のように対応してください。

--
#pragma push
#pragma Ospace
f32 OptErrTest()
{
・・・
}
#pragma pop
-- 

■対応状況

RVCT4.0 での修正予定はありません。


8.

■症状

RVCT 4.0 で、ビルド時に Warning: C3007E が表示される

■原因

RVCT 4.0 に不具合がありました。
ARMCC 4.1 で上記のエラーが発生しない場合、生成されるコードに問題はありません。

■問題の発生するバージョン

- 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.

■症状

最適化を上げると ? 演算子の挙動がおかしくなる

■原因

コンパイラ に不具合がありました。
コンパイラがループ最適化時に、2つの符号なし変数の差の絶対値の計算条件式を不正に取り扱います。
下記のようなコードで発生します。

--
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 以前
- RVCT4.0

■回避策

該当部分の最適化レベルを下げてください。

■対応状況

- ARMCC4.1 b619 で修正しました。
- RVCT4.0 での修正予定はありません。


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 以前
- RVCT4.0

■回避策

#pragma Ospace を指定するなどで、本不具合を回避してください。

--
#pragma push
#pragma Ospace
static __declspec(noinline) void test(u32 seed) 
{
...
}
#pragma pop
--

■対応状況

- ARMCC4.1 b654 で修正しました。
- RVCT4.0 での修正予定はありません。


12.

■症状

nn::math::Matrix を用いた関数呼び出しで、引数が破壊されることがある

■原因

コンパイラに不具合がありました。
下記のような nn::math::Matrix34 を使用した関数呼び出しで、const 参照で与えている引数が破壊されてしまいます。

--
#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 以前
- RVCT4.0

■回避策

funcの返り値を一時変数に格納することで回避してください。

--
//a = func(a);
 MTX34 tmp = func(a);
 a=tmp; 
--

■対応状況

- ARMCC4.1 b713 で修正しました。
- RVCT4.0 での修正予定はありません。


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
- RVCT4.0

■回避策

include/algorithm.ccの956行目にある__introsort_loop()の前に下記のコードを
挿入することで回避可能です。
__max_depth /= 2;

■対応状況

- ARMCC4.1 b907 で修正しました。
- RVCT4.0 での修正予定はありません。


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 ループが無限ループになることがあります。

■原因

コンパイラに不具合がありました。
-O3 -Otime の最適化で、符号なし整数のデクリメントを使用するforループの終了条件に、符号なし整数の
最大値となるような条件を指定したときに、コンパイラが無限ループとなるコードを生成することがあります。

以下のようなコードで発生する場合があります。

----------------------------
for( unsigned int i = 100; i != (unsigned int)-1 ; --i )
{
 ...
}
----------------------------

■問題の発生するバージョン

- ARMCC4.1 b619 以前
- RVCT4.0

■回避策

インクリメントループに置き換えて、(unsigned)-1との比較を行わないコードに変更することで、回避することが出来ます。

■対応状況

- ARMCC4.1 b713 で修正しました。
- RVCT4.0 での修正予定はありません。


17.

■症状

符号有り値と符号無し値を正しく変換できないことがある

RVCT4.0/ARMCC4.1 を使用して、下記のようなコードをコンパイルすると、
コンパイラが符号有り値と符号無し値を正しく変換できない。

u16 uVal = 0x999c;
s16 sVal = *(s16*)&uVal;
int intVal = (int)sVal;

※intVal には 0xFFFF999c (-26212) が入るべきにもかかわらず、
0x999c (39324) が入っている。

■原因

コンパイラに不具合がありました。

■問題の発生するバージョン

- ARMCC4.1 b713 以前
- RVCT4.0

■回避策

s16 sVal = (s16)uVal とするか、下記のように符号付き整数をテンポラリ変数として使用し、
明示的に符号拡張させる方法を試して下さい。

u16 uVal = 0x999c;
s32 tmp = *(s16*)&uVal;
s16 sVal = (s16)tmp;
int intVal = (int)sVal;

■対応状況

- ARMCC4.1 b713 で修正しました。
- RVCT4.0 での修正予定はありません。


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 以前
- RVCT4.0

■回避策

#pragma Ospace を指定することで回避してください。

#pragma push
#pragma Ospace
int test(int* input, int length)
{
...
}
#pragma pop

■対応状況

- ARMCC4.1 b640 で修正しました。
- RVCT4.0 での修正予定はありません。


20.

■症状

"Warning 997 virtual function override intended?" が抑制されてしまう

<nn/fs.h>をインクルードすると、"Warning 997 virtual function override intended?" の
警告メッセージが抑制されてしまいます。

■原因

<nn/fs.h>内で上記警告を抑制しており、#pragma push/pop を用いても、診断メッセージの保存ができない
の影響で、<nn/fs.h>をインクルードすると997の警告が抑制されてしまいます。

■問題の発生するバージョン

- ARMCC4.1
- RVCT4.0

■回避策

#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

■回避策

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 で修正しました。
- RVCT4.0 での修正予定はありません。


22.

■症状

#634-D や #631-D などの警告が出る

■原因

このワーニングが発生する主な原因としては、ホスト側でアドレス空間配置のランダム化(ASLR)が
有効になっている場合があり、これが今回の問題となっている可能性があります。
Windows XPでASLRが有効となっているかは不明ですが、Windows自身ではなく他のセキュリティ用
ソフトウェアが同様のことを行っている可能性があります。

■問題の発生するバージョン

- ARMCC4.1/5.x
- RVCT4.0

■回避策

ビルド時にセキュリティ用ソフトウェアを無効にしてください。

■対応状況

- 近い将来での修正予定はありません。


23.

■症状

ゼロサイズ配列を生成するテンプレートで内部エラーが発生する

下記のようなコードを書いてテンプレートを実体化した場合、
コンパイル時に『Internal fault: [0x462f69:410683]』が発生します。

template
class TEST{
// COMPILE_ASSERT(DIM != 0);
public:
    TYPE _aData[DIM];
    TEST(){}
};

extern "C" void nnMain(){
   
   TEST test;
   
   while(1){}
}

■原因

コンパイラのフロントエンドに不具合がありました。

■問題の発生するバージョン

- ARMCC4.1/5.x
- RVCT4.0

■回避策

ありません。

■対応状況

- 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 以前
- ARMCC5.03 b102 以前

■回避策

以下のいずれかの方法で、本不具合を回避してください。

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 で修正しました。
- ARMCC5.04 b27 で修正しました。


29.

■症状

ARMCC5.x にアップデート後、--gnu 指定時に、関数テンプレートのオーバーロード関数が引数に依存して解決されない

■原因

ARMCC5.x で使用しているフロントエンドの、GNU互換モードのGCCバグエミュレートによるものです。

以下のようなコードで発生します。

template
T foo(const U* u) { return foo(const_cast(u)); }

template
T foo(U* u) { return static_cast(u); }

class X {};
class Y : public X {};

const Y* bar(const Y* y, const X* x)
{
    return foo(x);
}
関数 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

■回避策

ありません。

■対応状況

未定です。


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

■回避策

ビルドで使用するパスに全角文字を含まないようにして回避してください。

■対応状況

- 未定です。


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 への代入時に誤ったオフセットを使用するコードが生成されていました。

コンパイルの終盤の最適化処理での問題で、発生条件を詳細に特定することはできませんが、以下の事が判明しています。

1) この不具合は、-O2 以上(-Ospace と -Otime どちらでも)で non-volatile ストアのみ発生します。
2) この誤った最適化は、サイズ 4 または 8 バイトの少なくとも2つの即値オフセットストア処理が含まれる基本ブロックでのみ発生します。
3) 不具合を含むブロックに到達するコンパイラの1つの要件は、ストア命令でソースレジスタはベースレジスタと同じであることです。
  構造体自体の内部構造体へのポインタをストアする場合、これが発生する可能性の1つになります。

■問題の発生するバージョン

- ARMCC4.1 b1307 以前
- ARMCC5.04 b27 以前

■回避策

以下のいずれかの方法で、本不具合を回避してください。

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 で修正しました。
- ARMCC5.04 b49 で修正しました。


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(i_base);
		return (d != NULL);
	}
};

bool is_derived(Base *i_base){
	return AClass::down_cast_test(i_base);
}

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 以前
- ARMCC5.04 b49 以前

■回避策

該当する関数の最適化レベルを -O3 -Otime 以外に指定して回避してください。

#pragma push
#pragma O2
void foo( int first, int last )
{
// 中略
}
#pragma pop

■対応状況

- ARMCC4.1 b1440 で修正しました。
- ARMCC5.04 b82 で修正しました。


35.

■症状

--diag_warning に error を指定するとコンパイルに失敗することがある

■原因

--diag_warning=error で、すべての降格可能エラーを警告に降格するよう指定すると、降格できないエラーを警告に
降格してしまう不具合がありました。そのため、コンパイル時に Internal fault や 異常終了が発生することがあります。

■問題の発生するバージョン

- ARMCC4.1/5.x

■回避策

--diag_warning では error を指定せず、降格したいメッセージ番号を直接指定して回避してください。

■対応状況

- ARMCC4.1 での修正予定はありません。
- ARMCC5.x での対応は未定です。


36.

■症状

--diag_suppress に error を指定するとオブジェクトファイルが生成されないことがある

■原因

--diag_suppress=error ですべてのエラーを非表示にした場合に、オブジェクトファイルを出力せずにコンパイルが終了することがあります。

■問題の発生するバージョン

- ARMCC4.1
- ARMCC5.04 b82 以前

■回避策

--diag_suppress では error を指定せず、非表示にしたいメッセージ番号を直接指定して回避してください。

■対応状況

- ARMCC4.1 での修正予定はありません。
- ARMCC5.04 b146 で修正しました。


37.

■症状

alloca を使用している関数を __forceinline でインライン化すると Internal fault が発生する

■原因

alloca を使用する関数は inline キーワード指定や自動インラインでのインライン化の対象ではありませんが、
__forceinline 指定時に、インライン化しようとして Internal fault が発生する不具合がありました。

■問題の発生するバージョン

- ARMCC4.1/5.x

■回避策

alloca を使用している関数には __forceinline を指定しないようにして回避してください。

■対応状況

- ARMCC4.1 での修正予定はありません。
- ARMCC5.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 以前
- ARMCC5.04 b82 以前

■回避策

以下のいずれかの方法で、本不具合を回避してください。

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 で修正しました。
- ARMCC5.04 b146 で修正しました。


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 で修正しました。


40.

■症状

std::vector::operator= で代入先のサイズが縮小されると、Allocator の deallocate に渡されるサイズが不正になることがある

■原因

ARMCC の C++ ライブラリの不具合です。

std::vector::operator= で、dest_vector = source_vector を実行したときに、以下の条件が全て真の場合に発生します。

1) source_vector.size() <= dest_vector.capacity()
2) dest_vector.size() >= source_vector.size()
3) dest_vector.capacity() != source_vector.size()

このとき、dest_vector.capacity() は、割当済みのサイズに関わらず source_vector.size() と一致し、
vector で使用する Allocator の deallocate に渡されるサイズが不正となります。

■問題の発生するバージョン

- ARMCC4.1/5.x

■回避策

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 での修正予定はありません。
- ARMCC5.x での対応は未定です。