gcc - yyparse (declarator)

次は 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       

まだ長々と続くが、 なので無視する。 @1 で args は @3 だと示され、 @3 は @5 => @11 => @19 と chain する。 @5 は辿っていくと int 、 @11 は char 、 @19 は void を示している。 void はデリミタだろうか。

@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;
}

先に見たダンプもこれでだいたい理解できたはずだ。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h