Skip to content

progress

NAGAMINE Hideaki edited this page Mar 7, 2017 · 67 revisions

CXXtoXML, XcodeMLtoCXXの改善 (2017/03/07)

マージ済み

#59

  • 正変換の際に 必要に応じて 型情報を登録するようにした
  • localTypeTableの出力に対応できるよう型情報テーブルの構造を変えた(スタックにした)
  • -dump-typemapオプションが実装不可能になったため削除した。 ただし型情報の登録漏れに起因するエラーが出ることはもうないのでいまやこのオプションは不要である。

作業中

hnagamin-20170306-stringtree

  • 逆変換
    • 従来XMLを読みながら文字列を吐いていたが、一度ASTに近い木を構築してから出力するようにしている
    • クラス型を表現するオブジェクトの構造を変え、friend宣言などメンバー変数宣言以外の要素にも対応できるようにしている
  • 正変換
    • globalSymbols/symbols要素にもっと多くの名前を出力するようにしている
      • friend宣言中で定義された関数名
      • (普通の、およびネストされた)クラスの名前
      • extern "C"ブロック中で宣言された名前
    • globalSymbols要素に不適切な要素が出ていたので修正

仕様の提案(2017/03/07)

#55 NNS定義要素の追加

#60 class要素をclassType要素に名称変更

#61 class要素で派生と継承を表現する方法について明記

CXXtoXMLの改善 (2017/03/02)

#57, #58

  • リファレンス型の元になる型を登録していなかったので登録するようにした
  • XMLを吐く際にリンケージや言語リンケージについての情報を出すようにした
  • XSLTを追加した
    • member要素
    • intConstant要素(文字リテラル)
    • Var要素
    • varDecl要素
  • CXXtoXML用のテスト環境を整備した

XcodeMLtoCXXの改善 (2017/02/24)

C++プログラムを出力するときの仕組みを改善した(#47, #53)。従来はアドホックにインデントの調整を行っていたが、これにより自動的に調整されるようになった。

XcodeML/C++の新しい仕様 (2017/02/24)

提案済

  • #50 演算子オーバーロードに関するいくつかの記述を削除
  • #51 標準(型)変換を表現する <implicitCastExpr>要素を追加
  • #54 <pointerType>などの要素を使ってリファレンスを表現する

作業中

  • #55 nns属性の定義
  • #56 リファレンス型を表現する<referenceType>要素の追加

CXXtoXMLの改善 (2017/02/15)

型情報の補完

作業ブランチはhnagamin-20170208-clangastwalker。 逆変換(XcodeML -> C++,XcodeMLtoCXX)を行うには名前と型の対応関係を知っている必要があるが、一部の型について対応関係がCXXtoXMLの出力するXMLに含まれていなかったためこれを修正した。

XSLTの強化

CXXtoXMLの出力するXML文書をXSLTでXcodeML文書に変換している(/CXXtoXML/src/XSLTs/)。このXSLTに処理を追加した。

-dump-typemapオプションの追加

型とデータ型識別名の対応関係を出力するオプションを追加した(#45)。

$ ./CXXtoXML -dump-typeTable sample.cpp --
Pointer0: int *
Function0: int (int)
int: int

CXXtoXMLの改善 (2017/02/09)

先週議論した文字列リテラルの問題

また、これらをとりあえず回避した状態で、現状の CXXtoXML で処理させると、文字列リテラルを扱っている部分で segmentation fault になる。 これはどうやら「文字列リテラルの型は、 const char * ではなく、 const char [文字数+1] になるので、その型がどこにも宣言されていないから」らしく、...

について、これを修正し文字列リテラルの型を正しく扱うようにした(#43)。 また、文字列リテラルを出力する処理がCXXtoXMLに含まれていなかったので出力するようにした(同PR)。

CppTest コードでの実験 (2017/2/3)

いただいたソースは全体的に C++ として正しくない部分が多い。 g++ ではいちおう全部コンパイルできるようだが、 clang++ ではエラーでコンパイルできない部分が多い。

  • main() 関数の返り値が宣言されていない (int main() に修正しないとだめ)
  • 名前空間内の名前を参照する using を使わない古い記法(クラスフィールドで単に A::x; などと書く記法)が用いられている。 これは -std=c++03 にすることでエラーは回避できるが Warning は出る (-Wno-deprecated でそれも抑制できるが…)。
  • リテラル文字列を non const のポインタ変数に代入している。これも -std=c++03 にすることで一応回避できるが…。
  • デフォルト値を持つ引数の使い方が正しくなくて、デフォルトコンストラクタと宣言がかぶっていたり、 friend 宣言が間違っている。 member046.cc, member059.cc, member060.cc はこのためにコンパイルできない。
  • 可視属性に違反した関数呼び出しなどがある。上記の3つに加え、 access045.cc, access046.cc はこのためにコンパイルできない。

これ以外に、 -std=c++03 にしても大量の警告が出る。

  • 未使用変数、未使用パラメータ、未使用privateフィールド、などの警告が出るが、これはまあ問題はない。
  • c++03 だとすると long long 型がないことになるのだが、使用されている。これもまあ問題はない。
  • printf の %x でポインタ値を表示しようとしている(正しくは %p を使うべきなところ)。これもまあ無視できるレベル。
  • signed の値と unsigned の値を直接比較している。とりあえず無視してもよいレベル。
  • コンストラクタの初期化指定の並びの順が正しくなく、基底クラスの初期化指定がフィールドの初期化指定よりも後ろに並んでいる。 (access003.cc, access005.cc, member048.cc, member049.cc, member050.cc, member051.cc, member058.cc, overload005.cc, overload007.cc)
  • 関数引数部に何も書いていない関数宣言( f() など ) があり、オーバーロードやプロトタイプ宣言が正しく行われていないフシがある。 (derive029.cc, derice049.cc, member045.cc)
  • ビットフィールドに char 値をキャストなしで代入している。 (class051.cc)
  • 未初期化変数を使っている。 (derive061.cc)

また、これらをとりあえず回避した状態で、現状の CXXtoXML で処理させると、文字列リテラルを扱っている部分で segmentation fault になる。 これはどうやら「文字列リテラルの型は、 const char * ではなく、 const char [文字数+1] になるので、その型がどこにも宣言されていないから」らしく、とりあえず typedef const char char1[1]; typedef const char char2[2]; …と書き並べていくことで回避できたが要修正。 (また、 CXXtoXML に --ignore-unknown-type というオプションをつけても回避できる。ただしこの場合 typeTable は不完全)

CXXtoXMLの実装(2017/01/13)

ヌルポインタ参照することがあったので修正した。#42

また、commitはしていないが、現在pragmaを扱う処理を実装中である。 参照: Issue #10

CXXtoXMLの実装(2017/01/06)

CXXtoXMLのビルド方法

cd CXXtoXML
make

comment要素

ある種のコメントに対してcomment要素を出力するようにした。入出力例は#40を参照せよ。

CXXtoXMLの改良

もっと多くの情報を出力するようにした。(#40)

  • access属性 アクセス指定を表現する。(bf851b7)
  • clangCastKind属性 キャスト式の種類を表現する。(2d3b530)
  • clangNestedNameSpecifier要素 nested-name-specifier(A::B::xA::B::)を表現する。(d550e98)
  • class属性 文法要素の種類を表現する。(388a4ce)
  • decimalNotation属性 整数リテラル式について、その十進表現を文字列としてもつ。(9bdf273)
  • has_init属性 変数宣言が初期化子をもっているかどうかを表現する。(94f79d6)
  • is_const属性 メンバー関数のconst性を表現する。(e246ef2)
  • is_static属性 メンバー関数のstatic性を表現する。(e246ef2)
  • is_virtual属性 メンバー関数のvirtual性を表現する。(e246ef2)
  • token属性 整数リテラル式について、そのソースコードにおける表現を文字列としてもつ。(2ec73c0)
  • valueCategory属性 式のvalue categoryを表現する。(e36268e)
  • xcodemlType属性 式がもつ型のXcodeMLにおける名前(データ型識別名)を表現する。(8d96db6)

XSLT

CXXtoXMLの出力するXML文書をXcodeML/C++の形式に近付けるためにXSLTを書いていた。(#40)

XcodeMLtoCXXの実装 (2016/09/14)

Pull Request #32#34、および開発ブランチから。

int b[1][2][3][4][5];
  • 配列型のconst, volatile属性に対応。array_cv.src.cに対して以下のように出力する。
void f(int const a[const 10], double b[const volatile 20]){
{
}
}
struct A{
int i;
};
struct B{
double d;
int i;
};
struct C{
char * pc;
double d;
int i;
};
struct A{
unsigned int a : 3;
unsigned int b : 10;
unsigned int  : 5;
unsigned int c : 10;
unsigned int  : 0;
double g;
int d : 15;
int e : 17;
int f : 20;
int h : 4;
};
  • CtoXcodeMLのunsigned_intデータ型識別名に対応。出力例略。
  • C_Frontでのテストに対応(08eb2f2d)。以下のコマンドで実行できる。
cd XcodeMLtoCXX/
make check CTOXCODEML=C_Front CTOXCODEMLFLAGS=

不具合修正

  • 基本型のデータ型識別名(long_longなど)をそのままC++ソースコードとして出力するのを修正 (#32)
  • arrayType要素がelemTypeよりも先に定義されていた場合に異常終了するのを修正(#33)
  • 関数宣言で引数の順番が変わるのを修正(e0468cc4)
  • 無名引数を使ったコードに対してC_Frontが出力したXcodeML文書をXcodeMLtoCXXに入力すると異常終了するのを修正(991ecd8c)
  • C_Frontの関数宣言を扱うとき、関数本体が{}で囲まれていなかったのを修正(c2bc9a10)
  • 関数ポインターを返す関数宣言の修正。コミットメッセージ参照。(4c575d96)

XcodeML/C++ 仕様の拡張方針についての議論 (2016/09/06)

  • XcodeML/Cのname要素との整合性を保ったままXcodeML/C++で名前解決の仕組みを扱う方法について議論した。nnsTableのページに記載。
  • template のページに「typeTable と nnsTable の入れ子構造」の節を追記。
  • 仕様書を google docs に配置し、2章を修正中。 https://docs.google.com/document/d/11GnZwwGS72cLGinPaBgV0YFS_QHG2ByC4RFtra_wI-k
  • template および nnsTable の仕様検討のたたき台のため、正変換ツールをいったん「Clang AST になるべくそのまま沿う形」で実装しなおし、 Clang AST からどのような情報を引き出せばよいのかについて試している。 CXXtoXML サブディレクトリ内で作業中。

XcodeML/C++ 仕様の拡張方針についての議論 (2016/08/31)

C++ の参照をどう表現するか、および template をどう表現するかについて、それぞれ referencetemplate のページに記載。

XcodeMLtoCXXの実装 (2016/08/31)

CV修飾子を出力するようにした(#28)。

例えば次のコードは、

const int f(int * const p) {
  const int i = 0;
  const int * q = p;
  const int * const r = q;
  return i;
}

void g() {
  volatile int vi;
  const volatile double cvd = 0;
  int * const volatile cvpi = 0;
}

CtoXcodeMLとXcodeMLtoCXXにより次のように変形される。

int const  f(int * const p)
{
        int const i = 0;
        int const * q = p;
        int const * const r = q;
        return i;
}
void  g()
{
        int volatile vi;
        double const volatile cvd = 0;
        int * const volatile cvpi = 0;
}

XcodeMLtoCXXの実装 (2016/08/24)

型を表すクラス(XcodeMl::Type)の設計に難があったので修正を行った。

  • C++の型は階層構造をもつが、これをポインターによる参照で表現するのをやめデータ型識別名による参照で表現するようにした(#25)。これにより関数へのポインターを正しく扱えない問題(#14)が解消された。 ただし、データ型識別名が現行仕様で厳密に定義されていない型がある(unnnamed namespace中で定義されたクラスなど)ので、将来仕様を定めるなど対応をとる必要がある。
  • 関数定義における名前の有効範囲の取り扱い方にバグがあったため修正した(#26)。

現在は、CV修飾子を出力する機能の追加に取り組んでいる。この作業ブランチはまだpushしていない。

XcodeMLtoCXXの実装 (2016/08/10)

https://github.com/omni-compiler/ClangXcodeML/tree/hnagamin-20160808-bugfix/type のブランチで下記作業中。

  • XcodeML の typeTable の情報を XcodeMLtoCXX の内部データ構造(C++ のクラス)として保持している部分について、 XcodeML での名前(type=属性に指定される名前)を用いずにデータ構造を構築しようとしていた(ポインタを張り巡らす構造にしようとしていた)のを根本的に見直し、素直に type 名を文字列のキーとして検索できる構造に修正中。
  • ただし、 basicType においては、 type 名は違うけれど実態としては同じ型(たとえば const int が複数の basicType になる)ということことがありえて、これを単純に上記の戦略で扱うと同じものに複数の名前がついている(が内部的には別々のものだとされてしまう)ので、逆変換時までそのような認識のままで大丈夫なのかどうか、少々不安は残る(おそらく大丈夫だが…)。
  • struct については XcodeML での type=属性 の名前ではなく、ソースコード上の tag 名があればその名前で復元できるように調整中。(tag 名の無い struct については XcodeML での名前をもとにして適当に発行した名前をつける。)

XMLschema の作業 (2016/08/10)

https://github.com/omni-compiler/ClangXcodeML/commits/hnagamin-20160702-XMLSchema のブランチで下記作業中。

  • exprStatement, compoundStatement, ifStatement について追記。
  • ifStatement については、 C_Front 実装を確認する限りにおいては then 部と else 部を必ず compoundStatement で囲う実装になっているが、 forStatement や whileStatement はむしろ必ず囲わない実装になっているので、統一感がない。仕様では統一性を考えてどちらかにまとめたほうがいいのではないか。(もちろん compoundStatement で余分に囲うのは構わないとする)

XcodeMLtoCXXの実装 (2016/08/01)

C の構造体をパースする部分について、

  • XcodeML での名前を用いて前方宣言として生成しておく部分を実装。これにより、ポインタのみの利用であれば順番が問題になることはない。
  • ただし、 placeholder が真に必要となるような状況(関数内の局所クラス定義や、ネストされたクラス定義など)においては、前方宣言も「前方宣言がソースコード上に置かれていた場所」に適切に配置する必要があり、定義本体とは別に前方宣言用の placeholder が必要になると思われるので、これは XcodeML 自体の仕様の問題として考える必要がある。
  • 中身のパース (typeTable の中にある セクションを適切に処理する部分) を実装中。

チェックシートの作成 (2016/07/09)

C++11 のコア言語 ( http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml ) の各部についての対応状況をチェックするためのシートを作成した。

これは https://github.com/omni-compiler/ClangXcodeML/milestone/3 のマイルストーンの作業に対応する。 このマイルストーンに対応する Issue を 5 つ登録した。

https://docs.google.com/spreadsheets/d/1kb-X9b-w5b4kvUL59yb7H5PS-NY-RmEpfZBx5ukvOEw で閲覧可能(google アカウントを持っている人には個別に編集権限を付与することもできる)。

現状では

  • 縦軸と横軸を作成(Issue#15 に対応、すでに closed)
  • 列のうち、「XcodeML_CXX_1.1.docx (Mar 30, 2016) での状況」の列をひととおり記入(Issue#16 に対応、すでに closed)
  • 残りの列は思いついた範囲で書き込んだのみなので未完成 (Issue#17, #18, #19 に対応) というところまで。

XcodeMLtoCXXの実装 (2016/07/02)

  • for文
  • while文
  • do-while文
  • return文

を扱う処理を実装した。

また出力されるソースコードのインデントを整えるようにした。

例えば次のようなコードは、

void f() {
  int i = 0;
  for (i = 0; i - 10; i = i + 1) {
    int num = 1;
  }
  while (1 == 2) {
    return;
  }
  do {
    i = i - 1;
  } while (i);
}

int square(int x) {
  return x * x;
}

CtoXcodeMLとXcodeMLtoCXXにより次のように変形される。

void f()
{
	int i = 0;
	for ((i = 0);(i - 10);(i = (i + 1)))
	{
		{
			int num = 1;
		}
	}
	while (12)
	{
		return;
	}
	do 	{
(i = (i - 1));
	}
	while (i);
}
int square(int x)
{
	return (x * x);
}

コンパイル

masterにマージされたのでブランチを指定する必要がなくなった。

$ git clone https://github.com/omni-compiler/ClangXcodeML.git
$ cd ClangXcodeML/XcodeMLtoCXX
$ make

XcodeMLtoCXXの実装 (2016/06/27)

XcodeML文書をC++ソースコードに変換するプログラムを実装中である。現在次のコマンドによってコンパイルできる。

$ git clone -b hnagamin-20160623-XcodeMlType-shared_ptr https://github.com/omni-compiler/ClangXcodeML.git
$ cd ClangXcodeML/XcodeMLtoCXX
$ make

現在対応している文法要素は次の通りである。

  • 関数定義
  • ローカル変数宣言
  • 式文
    • 整数, 文字列リテラル
    • 変数
    • 単項演算(負数, sizeof, 論理否定, ビット否定)
    • 二項演算(加減乗除算, 剰余, 代入)
    • 三項演算
    • 関数呼び出し
    • this

例えば次のようなコードは、

void f(int i, int j) {
  int x = 42;
  int y = (-i + x) * j;
  bool cond = !0;
  const char* str = "some string";
  x = (i + j) ? x : y;
  f(x, x);
}

CtoXcodeMLとXcodeMLtoCXXにより次のように変形される。

void f(int i, int j)
{
int x = 42;
int y = ((-(i) + x) * j);
bool cond = !(0);
char* str = "some string";
(x = (i + j) ? x : y);
f(x,x);
}

対応していないXcodeML要素はただ単に無視される(if文を含むコードを変形してみよ)。

fullName属性の実装 (2016/03/22)

name要素にfullName属性を追加する処理を実装した。 fullName属性は、関数およびメンバー関数のqualified nameを表す。

次のコードを

class A {
  void f(int x, int y);
  int operator* () { return 42; }
};

void A::f(int x, int y) {
};

次のように変換する。

<?xml version="1.0" encoding="UTF-8"?>
<XcodeProgram source="/home/hnagamin/Documents/ClangXcodeML/src/class.cc" language="C" time="2016-03-22 20:07:11">
  <typeTable>
    <name type="int">x</name>
    <name type="int">y</name>
    <classType type="Class0">
      <name>A</name>
      <symbols>
        <id type="Function0" sclass="extern_def" access="private">
          <name>f</name>
        </id>
        <id type="Function1" sclass="extern_def" access="private"/>
      </symbols>
    </classType>
    <functionType type="Function0" return_type="void">
      <params>
        <name type="int">x</name>
        <name type="int">y</name>
      </params>
    </functionType>
    <functionType type="Function1" return_type="int">
      <params/>
    </functionType>
  </typeTable>
  <globalSymbols/>
  <globalDeclarations>
    <Decl_CXXRecord type="Class0"/>
    <functionDecl>
      <name fullName="A::f">f</name>
    </functionDecl>
    <functionDefinition>
      <operator fullName="A::operator*">pointerRef</operator>
      <symbols/>
      <params/>
      <body>
        <compoundStatement>
          <symbols/>
          <declarations/>
          <body>
            <returnStatement>
              <intConstant type="int">42</intConstant>
            </returnStatement>
          </body>
        </compoundStatement>
      </body>
    </functionDefinition>
    <functionDefinition>
      <NestedNameSpecifier_TypeSpec/>
      <name fullName="A::f">f</name>
      <symbols>
        <id type="int" sclass="param">
          <name>x</name>
        </id>
        <id type="int" sclass="param">
          <name>y</name>
        </id>
      </symbols>
      <params>
        <name type="int">x</name>
        <name type="int">y</name>
      </params>
      <body>
        <compoundStatement>
          <symbols/>
          <declarations/>
        </compoundStatement>
      </body>
    </functionDefinition>
  </globalDeclarations>
</XcodeProgram>

課題

無名名前空間(unnamed namespace)は"(anonymous namespace)"、無名クラスは"(anonymous class)"として処理される。 このような場合のfullName属性の仕様をまず考える必要がある。

アクセス指定子の実装 (2016/02/26)

  • クラス派生時の基本クラスのアクセス指定
  • クラスメンバのアクセス指定 をtypeTable中で表示する処理を実装した。 次のコードを
class A {
  int x, y;
public:
  int getX() { return x; }
  int getY();
protected:
};

int A::getY() { return y; }

class B {};

class C : virtual public A, public B {
public:
  int getSum(int z) { return getX() + getY() + z; }
};

次のように変換する。

<?xml version="1.0" encoding="UTF-8"?>
<XcodeProgram source="/home/hnagamin/Documents/ClangXcodeML/src/class.cc" language="C" time="2016-02-26 18:23:46">
  <typeTable>
    <pointerType type="Pointer0" ref="Class0"/>
    <pointerType type="Pointer1" ref="Class2"/>
    <pointerType type="Pointer2" ref="int"/>
    <classType type="Class0">
      <name>A</name>
      <symbols>
        <id type="int" access="private">
          <name>x</name>
        </id>
        <id type="int" access="private">
          <name>y</name>
        </id>
        <id type="Function0" sclass="extern_def" access="public">
          <name>getX</name>
        </id>
        <id type="Function0" sclass="extern_def" access="public">
          <name>getY</name>
        </id>
      </symbols>
    </classType>
    <classType type="Class1">
      <name>B</name>
      <symbols/>
    </classType>
    <classType type="Class2">
      <name>C</name>
      <inheritedFrom>
        <typeName ref="Class0" access="public" is_virtual="1"/>
        <typeName ref="Class1" access="public"/>
      </inheritedFrom>
      <symbols>
        <id type="Function1" sclass="extern_def" access="public">
          <name>getSum</name>
        </id>
      </symbols>
    </classType>
    <functionType type="Function0" return_type="int">
      <params/>
    </functionType>
    <functionType type="Function1" return_type="int">
      <params>
        <name type="int">z</name>
      </params>
    </functionType>
  </typeTable>
  <globalSymbols/>
  <globalDeclarations>
    <Decl_CXXRecord>
      <id type="int">
        <name>x</name>
      </id>
      <id type="int">
        <name>y</name>
      </id>
      <functionDefinition>
        <name>getX</name>
        <symbols/>
        <params/>
        <body>
          <compoundStatement>
            <symbols/>
            <declarations/>
            <body>
              <returnStatement>
                <memberRef type="int" member="x">
                  <Stmt_CXXThisExprClass/>
                </memberRef>
              </returnStatement>
            </body>
          </compoundStatement>
        </body>
      </functionDefinition>
      <functionDecl>
        <name>getY</name>
      </functionDecl>
    </Decl_CXXRecord>
    <functionDefinition>
      <NestedNameSpecifier_TypeSpec/>
      <name>getY</name>
      <symbols/>
      <params/>
      <body>
        <compoundStatement>
          <symbols/>
          <declarations/>
          <body>
            <returnStatement>
              <memberRef type="int" member="y">
                <Stmt_CXXThisExprClass/>
              </memberRef>
            </returnStatement>
          </body>
        </compoundStatement>
      </body>
    </functionDefinition>
    <Decl_CXXRecord/>
    <Decl_CXXRecord>
      <inheritedFrom>
        <typeName ref="Class0"/>
        <typeName ref="Class1"/>
      </inheritedFrom>
      <functionDefinition>
        <name>getSum</name>
        <symbols>
          <id type="int" sclass="param">
            <name>z</name>
          </id>
        </symbols>
        <params>
          <name type="int">z</name>
        </params>
        <body>
          <compoundStatement>
            <symbols/>
            <declarations/>
            <body>
              <returnStatement>
                <plusExpr type="int">
                  <plusExpr type="int">
                    <Stmt_CXXMemberCallExprClass>
                      <memberRef type="_bound_member_function_type_" member="getX">
                        <Stmt_CXXThisExprClass/>
                      </memberRef>
                    </Stmt_CXXMemberCallExprClass>
                    <Stmt_CXXMemberCallExprClass>
                      <memberRef type="_bound_member_function_type_" member="getY">
                        <Stmt_CXXThisExprClass/>
                      </memberRef>
                    </Stmt_CXXMemberCallExprClass>
                  </plusExpr>
                  <Var type="int" scope="param">z</Var>
                </plusExpr>
              </returnStatement>
            </body>
          </compoundStatement>
        </body>
      </functionDefinition>
    </Decl_CXXRecord>
  </globalDeclarations>
</XcodeProgram>

初期化子リストの実装 (2016/02/18)

初期化子リストをfunctionDefinition要素中に表示する処理を実装した。 次のコードを

class A {
  int x, y, z;
  A(int a): x(a * a), y(a + a), z(0) {}
};

次のように変換する。

<?xml version="1.0" encoding="UTF-8"?>
<XcodeProgram source="/home/hnagamin/Documents/ClangXcodeML/src/initializer_list.cpp" language="C" time="2016-02-24 18:28:11">
  <typeTable>
    <pointerType type="Pointer0" ref="int"/>
    <classType type="Class0">
      <symbols>
        <id type="int">
          <name>x</name>
        </id>
        <id type="int">
          <name>y</name>
        </id>
        <id type="int">
          <name>z</name>
        </id>
        <id type="Function0" sclass="extern_def"/>
      </symbols>
    </classType>
    <functionType type="Function0" return_type="void">
      <params>
        <name type="int">a</name>
      </params>
    </functionType>
  </typeTable>
  <globalSymbols/>
  <globalDeclarations>
    <Decl_CXXRecord>
      <id access="private" type="int">
        <name>x</name>
      </id>
      <id access="private" type="int">
        <name>y</name>
      </id>
      <id access="private" type="int">
        <name>z</name>
      </id>
      <functionDefinition access="private">
        <constructor/>
        <symbols>
          <id type="int" sclass="param">
            <name>a</name>
          </id>
        </symbols>
        <params>
          <name type="int">a</name>
        </params>
        <constructorInitializerList>
          <constructorInitializer>
            <mulExpr type="int">
              <Var type="int" scope="param">a</Var>
              <Var type="int" scope="param">a</Var>
            </mulExpr>
          </constructorInitializer>
          <constructorInitializer>
            <plusExpr type="int">
              <Var type="int" scope="param">a</Var>
              <Var type="int" scope="param">a</Var>
            </plusExpr>
          </constructorInitializer>
          <constructorInitializer>
            <intConstant type="int">0</intConstant>
          </constructorInitializer>
        </constructorInitializerList>
        <body>
          <compoundStatement>
            <symbols/>
            <declarations/>
          </compoundStatement>
        </body>
      </functionDefinition>
    </Decl_CXXRecord>
  </globalDeclarations>
</XcodeProgram>

課題

初期化子リストの各メンバ名をどう表示するか考える必要がある。

<constructorInitializer>
  <name>x</name>
  <body>
    <mulExpr type="int">
      <Var type="int" scope="param">a</Var>
      <Var type="int" scope="param">a</Var>
    </mulExpr>
  </body>
</constructorInitializer>

などとしても良いかもしれない。

演算子オーバーロードの実装 (2016/02/18)

5.3 functionDefinition要素 に従い演算子オーバーロードを扱う処理を実装した。 次のコードを

class A {
  int value;
  public:
  int operator*() {
    return value;
  }
  A operator*(A other);
};

A operator*(int k, A x);

次のように変換する。

<?xml version="1.0" encoding="UTF-8"?>
<XcodeProgram source="/home/hnagamin/Documents/ClangXcodeML/src/operator.cc" language="C" time="2016-02-19 20:21:28">
  <typeTable>
    <pointerType type="Pointer0" ref="Class0"/>
    <classType type="Class0">
      <symbols>
        <id type="int">
          <name>value</name>
        </id>
        <id type="Function0" sclass="extern_def"/>
        <id type="Function1" sclass="extern_def"/>
      </symbols>
    </classType>
    <functionType type="Function0" return_type="int">
      <params/>
    </functionType>
    <functionType type="Function1" return_type="Class0">
      <params>
        <name type="Class0">other</name>
      </params>
    </functionType>
    <functionType type="Function2" return_type="Class0">
      <params>
        <name type="int">k</name>
        <name type="Class0">x</name>
      </params>
    </functionType>
  </typeTable>
  <globalSymbols>
    <id type="Function2" sclass="extern_def"/>
  </globalSymbols>
  <globalDeclarations>
    <Decl_CXXRecord>
      <id access="private" type="int">
        <name>value</name>
      </id>
      <Decl_AccessSpec access="public"/>
      <functionDefinition access="public">
        <operator>pointerRef</operator>                 <!-- ここ -->
        <symbols/>
        <params/>
        <body>
          <compoundStatement>
            <symbols/>
            <declarations/>
            <body>
              <returnStatement>
                <memberRef type="int" member="value">
                  <Stmt_CXXThisExprClass/>
                </memberRef>
              </returnStatement>
            </body>
          </compoundStatement>
        </body>
      </functionDefinition>
      <functionDecl access="public">
        <operator>mulExpr</operator>
      </functionDecl>
    </Decl_CXXRecord>
    <functionDecl>
      <operator>mulExpr</operator>
    </functionDecl>
  </globalDeclarations>
</XcodeProgram>

コミット 046250df55c52cce827efa98e6dfb942acc25dd9 を参照せよ。

課題

ユーザー定義リテラル

ユーザー定義リテラルはC++11で導入された機能である。これを用いると、例えば

for (int i : 10_times) {        // _timesというユーザー定義リテラルが使われている
  std::cout << i << std::endl;
}

ユーザー定義リテラルで整数のRange-based for

のようなコードを書くことができる。 優先度が低いと判断したため実装しなかった。コミット 1b7cf0950d4a7f1703f5b1493a86edff4639eaea も参照せよ。

operator要素の内容

5.3.1 operator要素 では以下の演算子名が定義されていない。()内に現在の実装における仮の演算子名を示す。

  • -> (arrowExpr)
  • ->* (arrowStarExpr)
  • () (callExpr)
  • [] (subScriptExpr)
  • 単項* (pointerRef)
  • 単項& (varAddr)
  • 単項+ (unaryPlusExpr)

キャスト演算子のオーバーロード

5.3.1 operator要素 ではキャスト演算子に関する言及がない。 functionDefinition要素の子要素として新たにcastOperator要素を定義することを提案する。

functionDecl要素の子要素

5.5 functionDecl要素は子要素としてname要素だけをもつが、functionDefinition要素との対称性を考慮して operator要素、constructor要素、destructor要素も子要素にもてる方が良い。

これらは例えば以下のコードで必要となる:

class Rational {
  public:
    Rational(int denom, int numer);                             // コンストラクタの宣言
    ~Rational();                                                // デストラクタの宣言
  private:
    int denominator, numerator;
};

Rational operator*(const Rational &lhs, const Rational &rhs);   // 演算子オーバーロードの宣言

inheritedFrom要素の実装 (2016/02/24)

3.9.1 inheritedFrom要素 (C++) に従い実装した。 typeTableとglobalDeclarationsの該当する場所に基本クラスの情報を出力する。 virtual基本クラスのとき、値が"1"のis_virtual属性をもつ。 派生時のアクセス指定子に基づくaccess属性をもつ。

次のコードを

class A {};
class B {};
class C : virtual public A, public B {};

次のように変換する。

<?xml version="1.0" encoding="UTF-8"?>
<XcodeProgram source="/home/hnagamin/Documents/ClangXcodeML/src/inheritedFrom.cc" language="C" time="2016-02-24 20:41:30">
  <typeTable>
    <classType type="Class0">
      <symbols/>
    </classType>
    <classType type="Class1">
      <symbols/>
    </classType>
    <classType type="Class2">
      <inheritedFrom>                       <!-- ここ -->
        <typeName ref="Class0"/>
        <typeName ref="Class1"/>
      </inheritedFrom>
      <symbols/>
    </classType>
  </typeTable>
  <globalSymbols/>
  <globalDeclarations>
    <Decl_CXXRecord/>
    <Decl_CXXRecord/>
    <Decl_CXXRecord>
      <inheritedFrom>                       <!-- ここ -->
        <typeName ref="Class0" access="public" is_virtual="1"/>
        <typeName ref="Class1" access="public"/>
      </inheritedFrom>
    </Decl_CXXRecord>
  </globalDeclarations>
</XcodeProgram>

次のコミットも参照せよ。

  • f30ef47486ea2d36fe6daf0a9bf50a78784b5e84
  • 74315e385fc6bfc47cecf4aa39f3861ec206644e
Clone this wiki locally