次は declarator 。型に対して後置される修飾子がこちらに含まれるというのは前に述べた通り。その部分を無視すると、 '(' の後に parmlist_or_identifiers と来ている。 identifiers をいきなり書くのは K&R 記法で、普通は parmlist の方が来るのだろう。大部慣れてきたので今度はいきなりダンプデータを読んでみる。
/* declarator.c */ void func(int int_variable) {}
これがコード。ダンプデータは
start_function = { declspecs = @1 tree_list valu: @2 @2 identifier_node strg: void lngt: 4 declarator = @1 call_expr fn : @2 args: @3 @2 identifier_node strg: func lngt: 4 @3 tree_list purp: @4 chan: @5 @4 parm_decl name: @6 type: @7 scpe: @8 srcp: declarator.c:2 chan: @9 argt: @7 size: @10 algn: 32 used: 0 @5 tree_list valu: @7 chan: @11 @6 identifier_node strg: int_variable lngt: 12 @7 integer_type name: @12 size: @10 algn: 32 prec: 32 min : @13 max : @14 @8 translation_unit_decl srcp::0 @9 parm_decl name: @15 type: @16 scpe: @8 srcp: declarator.c:2 argt: @16 size: @17 algn: 8 used: 0 @10 integer_cst type: @18 low : 32 @11 tree_list valu: @16 chan: @19 @12 type_decl name: @20 type: @7 scpe: @8 srcp: :0 chan: @21 @13 integer_cst type: @7 high: -1 low : -2147483648 @14 integer_cst type: @7 low : 2147483647 @15 identifier_node strg: char_variable lngt: 13 @16 integer_type name: @21 size: @17 algn: 8 prec: 8 min : @22 max : @23 @17 integer_cst type: @18 low : 8 @18 integer_type name: @24 size: @25 algn: 64 prec: 36 unsigned min : @26 max : @27 @19 tree_list valu: @28 @20 identifier_node strg: int lngt: 3 @21 type_decl name: @29 type: @16 scpe: @8 srcp: :0 chan: @30 @22 integer_cst type: @16 high: -1 low : -128 @23 integer_cst type: @16 low : 127 @24 identifier_node strg: bit_size_type lngt: 13 @25 integer_cst type: @18 low : 64 @26 integer_cst type: @18 low : 0 @27 integer_cst type: @18 high: 15 low : -1 @28 void_type name: @31 algn: 8 @29 identifier_node strg: char lngt: 4 @30 type_decl name: @32 type: @33 scpe: @8 srcp: :0 chan: @34 @31 type_decl name: @35 type: @28 scpe: @8 srcp: :0 chan: @36 @32 identifier_node strg: long int lngt: 8 @33 integer_type name: @30 size: @10 algn: 32 prec: 32 min : @37 max : @38 @34 type_decl name: @39 type: @40 scpe: @8 srcp: :0 chan: @41 @35 identifier_node strg: void lngt: 4
まだ長々と続くが、
@3 の purpose を見ると @4 => @9 と chain する。 @4 に含まれている情報は多いが、 name には int_variable という識別子名、 type には int という型名が入っていて、 @9 の name は char_variable で type は char という型名、ちゃんとパースできている。
@3 の chain は purpose に含まれている情報なのであまり意味が無いように感じられるが、これが何故かはとりあえず意味解析の段階まで保留 (@@@)。ここに限らず、 tree をこのように構成した理由というのは意味解析も見ないとわからないと考えられる。
実際に木を作るのは parmlist_or_identifiers からいくらか辿って parms のあたり。
parms: firstparm { push_parm_decl ($1); } | parms ',' parm { push_parm_decl ($3); } ;
push_parm_decl は push_decl に入り、 push_decl は長かったが、ようするに current_function_decl グローバル変数に push してくれるようだ。
さて、個々のパラメータだが、今回の場合、 parm の最初のものがマッチするはず。
parm: declspecs_ts setspecs parm_declarator maybe_attribute { $$ = build_tree_list (build_tree_list (current_declspecs, $3), chainon ($4, all_prefix_attributes)); POP_DECLSPEC_STACK; }
attribute は気にする必要は無いだろう。 build_tree_list は明解だ。パラメータリストに tree_list を使用する場合のコメントも付記されている。
/* Return a newly created TREE_LIST node whose purpose and value fields are PARM and VALUE. */ tree build_tree_list (tree parm, tree value) { tree t = make_node (TREE_LIST); TREE_PURPOSE (t) = parm; TREE_VALUE (t) = value; return t; }
先に見たダンプもこれでだいたい理解できたはずだ。