Skip to content

use of variables

KOYAMA Youichi edited this page Feb 20, 2017 · 3 revisions

arrayRefの仕様がXcodeML/CとXcodeML/C++で違う

XcodeML/C(0.9)において、arrayRefは次のように定義されている。

7.4 配列要素の参照の要素

配列への参照には、以下の要素を用いる。

  • arrayRef - 配列の先頭要素のアドレスを参照する式。内容に配列名を指定する。
  • arrayAddr - 配列のアドレスを参照する式。内容に配列名を指定する。

配列要素への参照は、arrayRefを用いてアドレス計算し、pointerRefで要素にアクセスする。変数参照の要素と同様に、scope属性を使い局所変数を区別する。

特に、arrayRefは子要素を持たない。

一方XcodeML/C++(1.2)において、arrayRefは次のように定義されている。

7.4 arrayRef要素 配列要素a[i]への参照を表現する。

<arrayRef> arrayAddr要素 式の要素 </arrayRef> 属性(必須): type

例:  int a[3]; と宣言されているとき、配列要素 a[i] の参照は、

	<arrayRef type="int">
	  <arrayAddr type="A5”scope="local">a</arrayAddr>
	  <Var type="int" scope="local">i</Var>
	</arrayRef>

のように表現される。配列要素のアドレス &a[i] の参照は、

	<addrOfExpr type="P232">
	  <arrayRef type="int">
	    <arrayAddr type="A5”scope="local">a</arrayAddr>
	    <Var type="int" scope="local">i</Var>
	  </arrayRef>
	</addrOfExpr>

のように表現される。ここでP232はint型へのポインタと宣言されている。後者はarrayAddr要素でないことに注意されたい。

このふたつは異なるが、意図されたものか。

XcodeML/Cが定めるCの仕様とC_Frontの動作が異なっている

上の問題に関連して、C_Frontは子要素をもつarrayRef要素を出力する。

たとえば、次のようなCプログラムに対して、

void f() {
  int a[3] = {1, 2, 3};
  a[0] = a[1];
}

C_Frontは次のXcodeMLを出力する。

            <exprStatement lineno="3" file="array.c">
              <assignExpr type="int">
                <arrayRef type="int">
                  <arrayAddr type="A0" scope="local">a</arrayAddr>
                  <intConstant type="int">0</intConstant>
                </arrayRef>
                <arrayRef type="int">
                  <arrayAddr type="A0" scope="local">a</arrayAddr>
                  <intConstant type="int">1</intConstant>
                </arrayRef>
              </assignExpr>
            </exprStatement>

これは

配列要素への参照は、arrayRefを用いてアドレス計算し、pointerRefで要素にアクセスする。変数参照の要素と同様に、scope属性を使い局所変数を区別する。

に反する。

仕様で定義されていないaddrOfExprがC_Front実装で使われている

次のCプログラム

void f() {
  int a3i[] = {1, 2, 3};
  int *pi = &(a3i[1]);
}

は、C_Frontによって以下のXcodeMLに変換される。

<varDecl lineno="3" file="array-dacay.c">
  <name>pi</name>
  <value>
    <addrOfExpr type="P0">
      <arrayRef type="int">
        <arrayAddr type="A0" scope="local">a3i</arrayAddr>
        <intConstant type="int">1</intConstant>
      </arrayRef>
    </addrOfExpr>
  </value>
</varDecl>

ここで、addrOfExprはXcodeML/C Version 0.9Jで定義されていない。C_FrontかXcodeML/Cのどちらかを修正するべきである。

addrOfExprはXcodeML/C++ V1.0J以降でも(未定義で)使われている。

構造体まわりの現在のC_Frontの変換仕様について

関係しそうなので引用。

以下の表のうち、「C言語表現」で & がついているものは全て addrOfExpr を使って表現した方が直交性が高くなり、 また「配列のアドレス」と「配列の要素のアドレス」を区別できない問題も解決できるので、 addrOfExpr を仕様に追加することを強く提案する。

要検討:構造体まわりの現在のC_Frontの変換仕様について

arrayRef要素([-@sec:expr.array]節)とmemberArrayRef要素、arrayAddr要素([-@sec:expr.var]節)とmemberArrayAddr要素は、それぞれ名前が似ているが意味の対称性がない。少なくとも名前を再考したい。他の点でも、今後構造体やクラスへの対応を考えると、整理しておきたいところ。

C言語表現 XcodeML表現 C言語表現 XcodeML表現
v * Var v s.v * memberRef v
** varAddr s
&v * varAddr v &s.v * memberAddr v
** varAddr s
a * arrayAddr a s.a * memberArrayRef a
** varAddr s
&a * arrayAddr a &s.a * memberArrayAddr a
** varAddr s
a[i] * arrayRef s.a[i] * pointerRef
** arrayAddr a ** plusExpr
** Var i *** memberArrayRef a
**** varAddr s
*** Var i
&a[i] * addrOfExpr &s.a[i] * plusExpr
** arrayRef ** memberArrayRef a
*** arrayAddr a *** varAddr s
*** Var i ** Var i

(メンバの参照の要素(C++拡張) {#sec:expr.member})

コード例

Clone this wiki locally