本文へジャンプ

Hitachi

株式会社 日立超LSIシステムズ

H8S,H8/300シリーズ C/C++コンパイラ Ver.4.0.05で対策した制限事項

1. union初期値不正

現象

char配列をメンバに持つ共用体型auto変数の初期値に、配列サイズを超える長さの文字列リテラルを{ }なしで指定すると、エラーとならずに文字列全体をコピーするコードが生成され、スタックを破壊してしまう問題点を修正しました。

[例]
void test()
{
    union {char c[4];} x = "long string"; 
	             /* 配列に収まりきらないがエラーとならない */
}


発生条件

次の条件を全て満たす時、発生します。

(a) char/unsigned char型配列をメンバに持つ共用体型auto変数が存在する。
(b) (a)の変数の初期値に、配列サイズを超える長さの文字列リテラルを{ }なしで指定している。

2. 無名ビットフィールド不正

現象

構造体の先頭に無名ビットフィールドがあり、その直後のメンバが配列または構造体である構造体に初期値を設定した場合、無名ビットフィールドのギャップ分が出力されない問題を修正しました。

[例]
struct S {
    char :1;
    char a[3];
} s = {"abc"};
[正しい出力コード]
_s:
    .data.l h'00616263
[不正な出力コード]
_s:
    .data.l h'61626300    ; 無名ビットフィールドのギャップが出力されない


発生条件

次の条件を全て満たす時、発生します。

(a) 構造体の先頭メンバに無名ビットフィールドを宣言している。
(b) (a)の直後のメン バが、配列または構造体を宣言している。
(c) 上記構造体変数に初期値を設定している。

3. ポインタ型cast不正

現象

H8/300またはノーマルモード時の定数式演算において、定数値をポインタ型へキャスト時、定数値の上位ワードをクリアせず、その後の演算で結果が不正となる場合がある問題点を修正しました。

[例]
long x = (long)(char *)0x12345678;
[出力コード]
    .section D,data
_x:
    .data.l h'12345678  /* 上位2byteがクリアされない */


発生条件

次の条件を全て満たす時、発生する場合があります。

(a) cpu=300,300l,300hn,2000nまたは2600nを指定している。
(b) 定数値をポインタ型へキャストしている。
(c) (b)の定数値が2byteを超えている。

4. 分岐削除不正

現象

switch文を記述した場合、不正に分岐する場合がある問題点を修正しました。

[例]
typedef struct { char a; char* b; char* c; }st;
void func(st x)
{
    int i;
    switch(x.a)
    {
    case 0:
        func1(x->b);    /* 共通式 */
        func1(x->c);
            :
        break;
    case 1:
        func1(x->b);    /* 共通式 */
            :
        break;
    case 2:
        func1(x->b);    /* 共通式 */
        break;
    case 3:
        func1(x->b);    /* 共通式 */
        break;
          <以下省略>
[出力コード]
      switch(x.a)
    MOV.W    @ER6,R1
    CMP.W    #-3879,R1
    BEQ      L1647:16
          :
    CMP.W    #-3884,R1
    BEQ      L1671:16    <---- (本来 L1673に分岐)
    CMP.W    #-3883,R1
    BEQ      L1671:16
          :
          :
L1671:
          :
L1673:


発生条件

switch文にcase文が複数あり、各case文内の式に共通式が存在する場合、発生することがあります。

5. ビットフィールド判定でオブジェクト不正

現象

1ビットのビットフィールドの値を判定する式があり、かつその前後で0を設定する式が記述された場合、0の設定コードが削除され、オブジェクト不正となる場合がある問題を修正しました。

[例]
unsigned char X,Y;
struct{
    unsigned char F1:1;
    unsigned char F0:1;
} BIT1,BIT2;
void test(void){
    X = 0;
    if( BIT1.F0 ){
	        /* 1ビットのビットフィールドの値を判定します  */
        if( BIT2.F0 != (Y==0 ? 0 : 1) ){ 
		    /* 3項演算子内で0を代入する式が記述されている */
            BIT2.F0 = (Y==0 ? 0 : 1); 
			/* ためオブジェクト不正となる可能性があります */
        }
    }
}
[出力コード]
      BIT2.F0 = (Y==0 ? 0 : 1);
                      ; sub.b    r0l,r0lの命令を不正に削除
    mov.b    r1l,r0h
    beq      l12:8
    mov.b    #1,r0l
l12:
    bld.b    #0,r0l
    bst.b    #6,@_bit2:32

発生条件

次の条件を全て満たす時、発生する場合があります。

(a) 1ビットフィールドの判定式が存在する。
(b) (a)の式の前後に0を設定する式が存在する。

6. unsigned long 比較でオブジェクト不正

現象

unsigned long 型への型変換を実施した変数と、unsigned long型の定数を比較(<、<=、>、>=)した場合、結果が不正となる場合がある問題点を修正しました。

[例]
unsigned int  ui1;
int sub()
{
    if (((unsigned long)ui1) > 0x80000000L)
        return(0);
    return(1);
}
[出力コード]
_sub:
    sub.w    r0,r0    ; 判定式が常に真となり、リターン値が不正となります
    rts

発生条件

次の条件を全て満たす時、発生する場合があります。

(a) (unsigned long)変数と定数の比較(<、<=、>、>=)を行っている。
(b) (a)の変数が unsigned char、unsigned short、unsigned int のいずれかである。
(c) 定数が0x80000000〜0xFFFFFFFFの範囲内のである(-2147483648〜-1)。
(※但し、0xFFFFFFFF(-1)の場合の <=-1、 >-1は除く)

7. ビットフィールド演算不正

現象

同一データ領域内のビットフィールドへの設定が連続して記述された場合、不正なオブジェクトが生成される場合がある問題点を修正しました。

 
[例]
struct{
    int s1 :1;
    int s2 :3;
    int s3 :1;
    int s4 :3;
}bit;
void func()
{
    if (x)
        bit.s1=1;
    else
        bit.s2=2;
}
[出力コード]
<不正コード>            <正常コード>
_func:                      _func:
   mov.w    r0,r0            mov.w    r0,r0
   beq      l5:8             beq      l5:8
   mov.l    #_bit,er0        bset.b   #7,@_bit:32  ; ビットが不正に統合される
   mov.w    @er0,r1
   and.w    #-20481,r1
   bra      l7:8             rts
l5:                       l5:
   mov.l    #_bit,er0        mov.b    @_bit:32,r0l
   mov.w    @er0,r1          and.b    #-113,r0l
   or.w     #-24576,r1       or.b     #32,r0l
l7:
   mov.w    r1,@er0          mov.b    r0l,@_bit:32
   rts                       rts

発生条件

同一データ領域内のビットフィールドへの設定を以下の条件の(ア)、(イ)の形で記述した場合、発生する場合があります。

 (a) if文
    if(---)
      (ア)
    else
      (イ)
 (b) while文
    while((ア))
      (イ)
 (c) カンマ式
    ((ア) ? (イ) : EXP)
    (EXP ? (ア) : (イ))

8. ビットフィールド設定不正

現象

long型のビットフィールド(ビットオフセット+ビットサイズ<=16またはビットオフセット>16)へ定数値を設定する時、正しく設定できない場合がある問題点を修正しました。

[例]
#include <stdio.h>
struct ST {
    char C1;
    char C2;
    long UL1:6;
    long L1 :4;
} st;
void main(){
    st.C1 = 10;
    st.C2 = 10;
    st.L1 = 7;
    printf("st.L1 : %ld \n",st.L1);
}
[出力コード]
    .cpu    2600a:24
    .section p,code,align=2
_main:
    push.l   er6
         :
/* st.L1 = 7; */
/* 不正コード */      /* 正しいコード */
 and.b    #-4,r0h    mov.w    @(2:16,er6),e0 ; メンバの参照・設定コードが
 and.b    #63,r0l    and.w    #-961,e0       ; 不正に削除されます
 or.b     #1,r0h     or.w     #448,e0
 or.b     #-64,r0l   mov.w    e0,@(2:16,er6)
         :
    pop.l    er6
    rts

発生条件

次の条件を全て満たす時、発生する場合があります。

(a) long/unsigned long型のビットフィールドへの設定コードで、ビットオフセット+ビットサイズ<=16、またはビットオフセット>16である。
(b) 設定値が定数である。
(c) 最適化有り(-optimize=1、デフォルト)指定している。
(d) 300、300L以外のCPU指定している。

9. ビットフィールドの乗算の複合代入

現象

代入先がビットフィールドの乗算の複合代入演算式を記述した場合、生成コードが不正となる場合がある問題点を修正しました。

[例]
struct ST {
    unsigned int bit1 :6;
    signed int bit2 :3;
} st1,st2,*stp;
sub()
{
    //省略
    stp->bit1 *=  st2.bit2;
    //省略
}
[出力コード]
    mov.w    @_st2:32,r0
    mov.w    #1539,r1
    jsr      @$bfsi$3:24    // st2.bit2の値をr0に設定
    mov.l    @_stp:32,er2
    mov.b    @er2,r1l
    shlr.b   #2,r1l
    extu.w   r1             // stp->bit1の値をr1に設定
    mov.w    r0,@(2:16,sp)  // r0を退避
    mov.w    r1,r0          // r0を破壊
    mulxu.w  r0,er0         // 破壊されたr0をst2.bit2として使用
        :

発生条件

次の条件を全て満たす時、発生する場合があります。

(a) 乗算の複合代入演算式が存在している。
(b) (a)の代入先の変数がビットフィールドであり、そのビットフィールドがポインタ参照である。
(c) -regexpansion(デフォルト)を指定している。
(d) 最適化(-optimize=1、デフォルト)を指定している。
(e) レジスタ変数が[E]R3〜[E]R6全て使用されている。

10. カンマ式での変数への設定コード未出力

現象

カンマ式の第1子に、その結果を使用しないビットごとの論理演算の(&,^,|)を記述した時、ビット演算の式の中に変数への設定値があった場合でも、その設定値が削除されてしまう問題点を修正しました。

[例]
int  i1,i2,i3;
sub()
{
    ((long)(i2++) & (i3=1)), i1 = 8;    /* i2++, i3=1が不正に実行されない */
}

発生条件

次の条件を全て満たす時、発生する場合があります。

(a) カンマ式の第1子に、その結果を使用しないビットごとの論理演算を記述している。
(b) (a)の第1子、および第2子に変数を更新する式の記述がある(一方が構造体のメンバ記述でも該当)。
(c) (a)の第1子、または第2子に型変換(cast)の記述がある。

11. ローカル変数のデバッグ情報不正

現象

無限ループのある関数で、スタック上に割付られた局所変数や引数のデバッグ情報が誤ってしまい、正しくシンボルデバッグができない問題点を修正しました。

[例]
extern int a;
void func()
{
    char c[4];    /* cの変数のシンボルデバッグができない */
    c[3] = 1;
    for(;;){
        a++;
    }
}

発生条件

次の条件を全て満たす時、発生します。

(a) debugオプションとoptimizeオプションを指定している。
(b) 関数内に無限ループが存在し、局所変数または引数がスタック上に割りついている。

1. 単項マイナス演算子に関する不正コード

char/short/int型の変数に対し、型変換後(暗黙の型変換も含む)に単項マイナス演算を行なった場合、演算結果が不正となる不具合を修正しました。

[例1]
  char  c;
  short s;
  int   i;
  long  l;
  vois sub()
  {
      s=-c;        /* c=-128   の時,s=-128   (正しくはs=128)   */
      i=-c;        /* c=-128   の時,i=-128   (正しくはi=128)   */
      l=-(long)c;  /* c=-128   の時,l=-128   (正しくはl=128)   */
      l=-(long)s;  /* s=-32768 の時,l=-32768 (正しくはl=32768) */
      l=-(long)i;  /* i=-32768 の時,l=-32768 (正しくはl=32768) */
  }
[正しくない出力コード]  不具合例1の s=-c; の場合
    MOV.B    @_c,R0L
    NEG.B    R0L
    EXTS.W   R0
    MOV.W    R0,@_s
[正しい出力コード]  不具合例1の s=-c; の場合
    MOV.B    @_c,R0L
    EXTS.W   R0
    NEG.W    R0
    MOV.W    R0,@_s

[例2]
  char c;
  int  i1,i2;
  i1 = -c + i2;     /* c=-128の時,-cが-128 (正しくは-cは128) */

[例3]
  char c;
  int  func();
  int  func()
  {
      return(-c);   /* c=-128の時,-cが-128 (正しくは-cは128) */
  }

2. 不正なAND命令生成

シフト演算後にビットごとAND演算を行なった場合、または連続して複合代入(&=,|=,^=)を行なった場合、コンパイル実行環境によって不正なAND命令が生成されることがある不具合を修正しました。
本件はコンパイラ解放済みメモリ領域の値に依存するため、同一プログラム同一オプションの条件であっても必ず発生するものではありません。

[例1]
  unsigned int X;
  sub(unsigned int Y)
  {
      X = (Y >> 14) & 0x2;
  }
[正しくない出力コード] 
    MOV.W    @_Y,     R0
    ROTL.W   #H'2,    R0
    AND.L    #H'20002,ER0   <--- 正しくないコード
    MOV.W    R0,      @_X
[正しい出力コード]
    MOV.W    @_Y,     R0
    ROTL.W   #H'2,    R0
    AND.W    #H'2,    R0    <--- 正しいコード
    MOV.W    R0,      @_X

[例2]
  int sub(int Y)
  {
      Y &= 0x3;
      Y &= 0x2;
      return Y;
  }
[正しくない出力コード] 
    AND.L    #H'20002,ER0   <--- 正しくないコード
[正しい出力コード]
    AND.W    #H'2,    R0    <--- 正しいコード

3. ループ内の不変式の括り出し最適化が効くように修正

コンパイラの最適化の1つである“ループ内の不変式の括り出し最適化”がコンパイル実行環境によって効かない場合がある現象を修正しました。

4. 不正な分岐

比較演算で被比較式の演算結果がオーバーフローする場合、正常に比較分岐できない場合がある不具合を修正しました(ア)。
なお、型変換の記述によりコンパイラの演算最適化(int演算をすべきところchar演算とする)が実施され、その結果オーバーフローになる場合も含まれます(イ)。

[(ア)の例] (i1 - i2)の結果は-32768であり、"OK"にもかかわらず"NG"となってしまう。

  int   i1 = 1;
  int   i2 = -32767;

  if((i1 - i2) < 0)
      printf("OK\n");
  else
      printf("NG\n");

[(イ)の例] (char)(c1 - c2)の結果は-128であり、"OK"にもかかわらず"NG"となってしまう。

  char   c1 = 1;   
  char   c2 = -127;

  if((char)(c1 - c2) < 0)
      printf("OK\n");
  else
      printf("NG\n");

1. C++初期処理/後処理データ領域(C$INIT),C++仮想関数表領域(C$VTBL)の出力不正

C++コンパイル時に、abs16オプションを指定してコンパイルした場合、C$INIT,C$VTBLセクションが生成されず、そこに割りつくオブジェクトが$ABS16Cセクションに割り付いていた問題点を修正しました。

2. absオプションによるセクション不正

C++コンパイル時に、abs8またはabs16オプションを使用すると、#pragma abs8 sectionまたは#pragma abs16 sectionで指定しているセクション名の切り替えが無効になる問題点を修正しました。

3. メンバ型情報不正

構造体のメンバを関数へのポインタでそのポインタを関数のプロトタイプ形式で宣言した場合、デバbグ情報が不正となる問題点を修正しました。

 
[例]
  struct sample {
     void (*fp)(int);
  };

4. コンパイラの不正終了

C++コンパイル時に、メンバ関数と同名の宣言済み関数をメンバ内で再宣言するとコンパイラが不正終了する問題点を修正しました。

[例]
  void func();
  struct S {
     void func() {
        extern void func();
     }
  };

5. セクション演算子によるオブジェクト不正

セクションアドレス演算子の結果をデータ以外の目的で絶対アドレスとして使用する場合、オブジェクト不正となる問題点を修正しました。

[例]
  void sub(void){
     (*((void (*)(void))__sectop("P")))();
  }

6. class内配列情報読み込み不正

C++コンパイル時でdebugオプションが指定されたとき、構造体/クラスのメンバにstatic宣言した配列メンバがあり、そのメンバを引数や局所変数として使用した場合、内部エラーが発生する問題点を修正しました。

[例]
  class B {
     static char EMPTY[];
     char *m;
  };
  class B a;
  void func(class B b) {
     a=b;
  }

7. defineオプションの解釈変更

オプションで-define=マクロと指定した場合、-define=マクロ=1と同等の動作を行っていた問題点を修正しました。

8. 1ビット演算時のコード不正

1ビットのビットフィールドのみの変数同士で、ビットフィールドの型指定子のサイズが互いに異なる時に、ビット演算(&, |, ^, &=, ^=)を実施した場合、不正なコードが出力されることがある問題点を修正しました。

[例]
  struct {
     char  char1 :1;
     int   int1  :1;
  } x1,x2,x3;
  void sub(){
     x1.int1 |= x2.char1 | x3.char1;
  }
[出力コード]
  _sub:
    BLD.B   #7,@_x2:32
    BOR.B   #7,@_x3:32
    BST.B   #0,R0L
    BLD.B   #7,@_x1+2:32     正しいコード
    BOR.B   #0,R1H    ←-- BOR.B   #0,R0L
    BST.B   #7,@_x1+2:32
    RTS

9. debugオプション不正

Solaris版コンパイラにおいてdebugオプションを指定してコンパイルを行うと、インターナルエラーが発生することがある問題点を修正しました。

1. 構造体サイズのデバッグ情報不正

構造体サイズが256バイト以上の時、デバッグ情報が不正となっていた問題点を解決しました。

2. デバッグ情報(行情報)不正

1つのファイルの中のインクルードファイル数が256を超えた時、デバッグ情報が不正になっていた問題点を解決しました。

3. 無限ループ関数で引数値の不正参照

無限ループを含む関数においてスタック渡し引数が有る場合、当該引数の参照コードが不正となっていた問題点を解決しました。

4. アドレスの引数を渡す時にコード不正

-stack=smallの指定時に関数の引数として局所変数のアドレスを記述した時、コード不正となる問題点を解決しました。

5. ABS16セクションのアライン不正

現ファイル中に存在しないセクションをセクションアドレス演算子で指定する時、セクション名が"$abs16"で始まるセクションのアラインを1から2へ変更しました。

6. C++初期値のCONST属性欠落

C++プログラムで構造体配列の初期値に定数アドレスを指定した時、静的な初期値とならずに代入式を生成してしまう問題点を解決しました。

7. #pragma sectionの不当エラー

C++プログラムで#pragma sectionに"_"を含むセクション名を指定すると、不正に5987エラーを出力する問題点を解決しました。

8. Pから始まるダミーセクション属性の変更

セクションアドレス演算子で指定されたセクションが当該ファイル中に存在しない場合、コンパイラが自動生成するサイズ0のセクションの属性を"常にDATAとする"から"Pで始まるセクションはCODEとする"に変更しました。

1. longreg指定時のコード不正(cpu=300,300l)

現象

cpu=300かつlongregオプションを指定したとき、[unsigned]long型,または,float型の引数が正しく渡らない。

[例]
int X,Y,Z;
void sub1(long p2)
{
    volatile int i1;
  for (i1=0;i1<10;i1++)
        X++;
    Z = (int)p2;
}
[出力コード]
 _sub1:
     <省略>
   MOV.W   #_X,R1 <- 外部変数のレジスタ割り付けで引数R1が破壊されている
   MOV.W   R0,@(2:16,SP)
   MOV.W   R1,@(4:16,SP) <- 引数p2の下位2byteが不正(#_Xの値が入っている)
   SUB.W   R0,R0
   MOV.W   R0,@SP
   BRA     L9
  L8:
     <省略>


発生条件

次の条件を全て満たす時、発生します。

(a) cpu=300または300lを指定。
(b) 最適化あり(optimize=1)を指定。
(c) 引数に[unsigned]long型、またはfloat型を指定。
(d) 上記(c)の引数がオプション-longregによりレジスタ渡しとなる。(R0とR1 または R1とR2)
(e) 関数内で外部変数を使用しており、その変数がレジスタに割りついている。

2. structreg指定時のコード不正(cpu=300hn,2000n,2600n)

現象

cpu=300hn,2000n,2600nかつstructregオプションを指定したとき、引数として渡された構造体ポインタを用いて2byteサイズの構造体を引数とする関数を呼び出した場合、構造体引数が正しく渡らない。

[例]
struct ST{
    char c1,c2;
};
void sub1(int a, struct ST *p)
{
    func1(a, *p);   // 構造体へのポインタpを用いて、2byte構造体を引数に指定
}
 [出力コード]
  _sub2:                  <- R0(a), E0(p)
    MOV.W   E0,R1      
    MOV.B   @ER1+,R1H   <- R1H = p->c1; ここでR1(p)を破壊
    MOV.B   @ER1,R1L    <- R1L = p->c2;
    MOV.W   R1,E0
    JMP     @_func1:16

発生条件

次の条件を全て満たす時、発生します。

(a) cpu=300hn, 2600n, 2000nを指定。
(b) structregを指定。
(c) 当該関数が2byte構造体へのポインタ引数を持ち、レジスタで渡される。
(d) 当該関数内に2byte構造体引数を持った関数呼び出しがあり、(c)のポインタを用いて構造体引数を設定。

3. ネストした構造体の代入式のコード不正

3.1 事例1

現象

1バイトと3バイトで構成されるネストした構造体/共用体を使用し、かつ、その構造体/共用体変数の3バイトの部分の値を代入式で記述した場合、正しく値が設定されない。

[例]
struct A {
    char  a1;
    struct B { char b1,b2,b3; } b;
};
struct A  sta;
struct B  stb;
void sub()
{
    struct A x;
    x  = sta;
    stb = x.b;   // x.bの参照不正により代入コードが生成されない。
}

発生条件

次の条件を全て満たす時、発生します。

(a) 最適化あり(optimize=1)を指定。
(b) 1バイトと3バイトで構成されるネストした構造体/共用体を使用している。
(c) 当該構造体/共用体の3バイトの部分を代入式で参照している。
(d) 当該構造体/共用体はローカル変数で使用され、レジスタに割りついている。

3.2 事例2

現象

ネストした構造体/共用体を使用し、かつその構造体/共用体変数に関数のリターン値を代入した場合、正しく値が設定されない。

[例]
union A{
    struct B{ int i1; } b;
    struct C{char c1,c2; } c;
};
struct B stb, func();
void sub()
{
    union A a;
    a.b = func();
    stb = a.b;
}
 [出力コード]
  _sub2:
    PUSH.W  R6
    PUSH.L  ER0   
    JSR     @_func:24
    ADDS.L  #4,SP
        MOV.W   R6,@_stb:32
    POP.W   R6
        RTS

 [正しいコード]
  _sub2:
    SUB.L   #2,SP
        MOV.L   SP,ER2
    PUSH.L  ER2   
    JSR     @_func:24
    ADDS.L  #4,SP
        MOV.W   @ER2,R3
        MOV.W   R3,@_stb:32
        RTS

発生条件

次の条件を全て満たす時、発生します。

(a) 最適化あり(optimize=1)を指定。
(b) ネストした構造体/共用体を使用し、構造体メンバに関数のリターン値を代入。
(c) 当該構造体/共用体はローカル変数で使用され、レジスタに割りついている。

4. structreg指定時のdiv関数(ライブラリ)の実行結果不正

現象

div関数を呼び出すとき、structregオプションを指定すると実行結果が不正になる。(-cpu=300,300l以外)

[例]
#include <stdlib.h>
div_t ret;
void sub()
{
    ret = div(10,3);  // 商と余りが逆に設定される
}

発生条件

次の条件を全て満たす時、発生します。

(a) cpu=300hn, 2600n, 2000nを指定。
(b) structregを指定。
(c) 標準ライブラリ関数divを使用

5. 外部変数のデバッグ情報不正

現象

シンボルの外部定義より前に外部参照宣言がある時、当該外部変数のシンボリックデバッグができない。

[例]
 extern int i;
  int i;      // デバッガ(HDI)では"out of scope"になる
 void func()
 {
     i++;
 }

発生条件

次の条件を全て満たす時、発生します。

(a) debugオプションを指定。
(b) シンボルの外部定義より前に、当該シンボルの外部参照宣言がある。

6. 非最適化時のローカル変数デバッグ情報不正

現象

非最適化時(optimize=0指定)、次のプログラムにおいてローカル変数がシンボリックデバッグできない。

[例]
  int a;      
 void func()
 {
     while(1){  // 無限ループ
        a=0;
      }
      a=1;
 }


発生条件

次の条件を全て満たす時、発生します。

(a) 最適化なし(optimize=0)を指定。
(b) debugオプションを指定。
(c) 関数内で無限ループがある。
(d) 無限ループから外へ出るコーディングがない。

7. インターナルエラー4633

現象

1バイトと3バイトで構成される構造体を使用した場合、次のプログラムにおいてインターナルエラー4633が発生する。

[例]
struct A{
    char a1;
    struct B{
        char b1;
        char b2;
        char b3;
    }v;
};
void sub1()
{
    struct A x;  // xはレジスタに割りついている
    x.v.b2 = 10;
    func(x.v);   // 構造体xの3バイトのメンバvを引数として使用
}

発生条件

次の条件を全て満たす時、発生します。

(a) 最適化あり(optimize=1)を指定している。
(b) cpu=300以外を指定している。
(c) 1バイトと3バイトで構成されるローカル構造体を使用している。
(d) 上記構造体の3バイトの部分を関数の引数、またはリターン値として使用している。
(e) 上記構造体はレジスタに割りついている。

8. インターナルエラー4099,4603

8.1 事例1

現象

関数コールの後にあるif文の中で、再度同じ関数をコールしている場合に、インターナルエラー4099が発生する。

[例]
void func(int p){ }
void sub(int x)
{
    func(1);
    if(x==10)
        func(1);  
}

発生条件

次の条件を全て満たす時、発生します。

(a) 最適化あり(optimize=1)を指定している。
(b) 関数呼び出しの後、then節しかないif文がある。
(c) if文の直前にある式(複数でも可)と、if文のthen節の最終式が同一。
(d) (c)の同一式の中に関数呼び出しがある。

8.2 事例2

現象

char型の初期値なし変数が512個以上あるファイルをコンパイルした場合に、インターナルエラー4099または4603が発生する。

[例]
#pragma abs8 a1;
char a1;
 :
char a520;

発生条件

次の条件を全て満たす時、発生します。

(a) 1ファイルに[unsigned]char型の変数、配列、[unsigned]char型で構成される構造体または共用体定義が512個以上ある。
【注】#pragma section, abs8 section, abs16 section, #pragma abs8, abs16, __abs8, __abs16使用時は512個より少なくても発生する場合がある。
(b) alignオプション(デフォルト)を指定。

9. インターナルエラー4677

現象

[unsigned]char型の512バイト以上の初期値付き変数、配列、構造体を持つファイルをコンパイルした場合に、インターナルエラー4677が発生する。

[例]
char  x[1023] = {
    0,0,0,0,0,0,0,0,0,0,
            :
            :
    0,0,0,0,0,0,0,0,0,0
};
char  a = 1;
int   b = 2;


発生条件

次の条件を全て満たす時、発生します。

(a) [unsigned]char型の初期値付き変数、配列、構造体のサイズの合計が512バイト以上あり、かつ奇数バイトである。
【注】#pragma section, abs8 section, abs16 section, #pragma abs8, abs16, __abs8, __abs16使用時は512個より少なくても発生する場合がある。
(b) (a)の変数の後に出現する初期値付きの変数が、1バイトアライン変数、2バイトアライン変数の順である。
(c) alignオプション(デフォルト)を指定。

10. インターナルエラー4774または4954

10.1 事例1

現象

if文で1ビット同士の論理OR(||)演算を記述した場合、インターナルエラー4774(または4954)が発生する。

[例]
struct BIT{
    char b1:1;
    char b2:1;
}B1,B2;
int x;
void sub1()
{
    if(B1.b1){        
        if(B1.b1 || B2.b2)   // 1bit同士の論理OR演算
            x++;             // B1.b1の値はレジスタに割りついている
    }
}

発生条件

次の条件を全て満たす時、発生します。

(a) 最適化あり(optimize=1)を指定している。
(b) if文で1ビット同士の論理OR(||)演算を記述している。
(c) (a)の1ビット変数の一方または両方がレジスタに割りついている。

10.2 事例2

現象

[unsigned] char型変数と2バイト構造体をメンバにもつ構造体を使用した場合、インターナルエラー4774が発生する。

[例]
struct A{
    char d;
    struct B { char b1; char b2; }s1;
};
struct C{
    struct B s1,s2;
}
struct A sta;
struct C stc;
void sub()
{
  struct A a;  // En(上位byte):a.d,En(下位byte):a.s1.b1,RnH:a.s1.b2
  struct C c;  // Em:c.s1,Rm:c.s2
  a.s1 = c.s1; 
 sta = a;
}

発生条件

次の条件を全て満たす時、発生します。

(a) [unsigned] char型変数と2バイト構造体(構造体B)をメンバにもつ構造体(構造体A)を使用している。
(b) 構造体Aの構造体メンバ(構造体B)に単純代入式(=)による代入を記述。
(c) 構造体Aはローカル変数で、かつレジスタに割りついている。
(d) 代入元の構造体もレジスタEn側に割りついている。
(e) 最適化あり(optimize=1)を指定。
(f) cpu=300, 300l以外を指定。

11. リンク時インターナルエラ―4000(8001)

現象

割り込み関数指定時に、割り込み関数終了指定としてsy=$<シンボル名>を指定した場合、リンク時に次のインターナルエラーが発生する。

** L4000 (-) Internal error : (8001) "File:in_cainf.cpp Line:2169   / IOP Reference Symbol Name Not Found:_<シンボル名>" / "<ファイル名>"


[例]
#pragma interrupt func(sy=$sub)
void func()
{
}

12. goptimize指定なし時のスタック使用量不正

現象

goptimize指定なし時、実行時ルーチンを呼び出す場合にスタック使用量が不正になる。

[例]
long LL;
volatile long a,b;

void func()
{
    LL=a/b;   // 実行時ルーチン$DIVL$3が呼び出される
    g();
}
g(){}


発生条件

次の条件を全て満たす時、発生します。

(a) goptimizeオプションを指定しない。
(b) ファイル内に外部参照シンボルが存在しない。
(c) 実行時ルーチン呼び出しのコードが生成される。

13. code=asmcode指定時のベクタテーブル属性不正

現象

code=asmcode指定時、割り込み関数やエントリ関数などでベクタテーブル出力を指定した場合、ベクタテーブルが不正にcode属性で出力される。

[例]
#pragma entry func(vect=2)
void func(){}

発生条件

次の条件を全て満たす時、発生します。

(a) code=asmcodeオプションを指定。
(b) #pragma, キーワードによりベクタテーブル出力を指定。

14. __STDC__マクロ定義

現象

__STDC__マクロが未定義となる。

[例]
  #ifdef __STDC__
  #define CONST const
  #else
  #define CONST
  #endif

  CONST int a=0;  // V3ではCセクションに割りついていたが、
                  // V4ではDセクションに割りついてしまう。

15. "L2310 Undefined external symbol"エラー(標準ライブラリ構築ツール)

現象

head=stdio指定で生成したライブラリをリンクしたときに、次のメッセージが発生する。

** L2310 (W) Undefined external symbol "_modf" referenced in "_log10"

発生条件

次のいずれかの条件を満たす時、発生します。

(a) head=stdioを指定時にhead=mathまたはmathfを指定していない。
(b) head=ios指定時にhead=stdio, stdlib, ctypeまたはstringを指定していない。
(c) head=complex指定時にhead=mathまたはmathfを指定していない。
(d) head=cppstring指定時にhead=stringを指定していない(Windows版)。
(e) head=cppstring指定時にhead=stringまたはnewを指定していない(UNIX版)。