GCC-3.4.6源代码学习笔记 (102)

5.12.3.2.1.1.3.5.    解析其它构造函数

在解析了默认构造函数后,我们回到 cp_parser_member_specification_opt ,它开始解析下一个构造函数: Lock(const Host&) {}

这是一个很有趣的构造函数,因为它的参数是类模板的模板参数。既然我们已经看过解析默认构造函数的过程,在这里我们只看不同的部分。

5.12.3.2.1.1.3.5.1.            解析参数

对于这个构造函数,它具有参数,因此在 10467 行,在 cp_parser_direct_declarator 里,该参数由 cp_parser_parameter_declaration_clause 来解析。

 

11026 static tree

11027 cp_parser_parameter_declaration_clause (cp_parser* parser)                        in parser.c

11028 {

11029   tree parameters;

11030   cp_token *token;

11031   bool ellipsis_p;

11032

11033   /* Peek at the next token.  */

11034   token = cp_lexer_peek_token (parser->lexer);

11035   /* Check for trivial parameter-declaration-clauses.  */

11036   if (token->type == CPP_ELLIPSIS)

11037   {

11038     /* Consume the `...' token.  */

11039     cp_lexer_consume_token (parser->lexer);

11040     return NULL_TREE;

11041   }

11042   else if (token->type == CPP_CLOSE_PAREN)

11043      /* There are no parameters.  */

11044   {

11045 #ifndef NO_IMPLICIT_EXTERN_C

11046     if (in_system_header && current_class_type == NULL

11047         && current_lang_name == lang_name_c)

11048       return NULL_TREE;

11049     else

11050 #endif

11051       return void_list_node;

11052   }

11053   /* Check for `(void)', too, which is a special case.  */

11054   else if (token->keyword == RID_VOID

11055         && (cp_lexer_peek_nth_token (parser->lexer, 2)->type

11056              == CPP_CLOSE_PAREN))

11057   {

11058     /* Consume the `void' token.  */

11059     cp_lexer_consume_token (parser->lexer);

11060     /* There are no parameters.  */

11061     return void_list_node;

11062   }

11063  

11064   /* Parse the parameter-declaration-list.  */

11065   parameters = cp_parser_parameter_declaration_list (parser);

11066   /* If a parse error occurred while parsing the

11067     parameter-declaration-list, then the entire

11068     parameter-declaration-clause is erroneous.  */

11069   if (parameters == error_mark_node)

11070     return error_mark_node;

 

所有的参数都将由 cp_parser_parameter_declaration_list 通过 tree_list 节点串接起来。

 

11109 static tree

11110  cp_parser_parameter_declaration_list (cp_parser* parser)                            in parser.c

11111  {

11112    tree parameters = NULL_TREE;

11113 

11114    /* Look for more parameters.  */

11115    while (true)

11116    {

11117      tree parameter;

11118      bool parenthesized_p;

11119      /* Parse the parameter.  */

11120      parameter

11121          = cp_parser_parameter_declaration (parser,

11122                                       /*template_parm_p=*/ false,

11123                                       &parenthesized_p);

11124

11125      /* If a parse error occurred parsing the parameter declaration,

11126       then the entire parameter-declaration-list is erroneous.  */

11127     if (parameter == error_mark_node)

11128     {

11129       parameters = error_mark_node;

11130       break ;

11131     }

11132      /* Add the new parameter to the list.  */

11133     TREE_CHAIN (parameter) = parameters;

11134     parameters = parameter;

11135

11136      /* Peek at the next token.  */

11137     if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)

11138        || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))

11139       /* The parameter-declaration-list is complete.  */

11140       break ;

          …

11187   }

11188

11189   /* We built up the list in reverse order; straighten it out now.  */

11190   return nreverse (parameters);

11191 }

 

由上可见,串中的每个节点都是由 cp_parser_parameter_declaration 准备的。

 

11215 static tree

11216 cp_parser_parameter_declaration (cp_parser *parser,                                   in parser.c

11217                             bool template_parm_p,

11218                             bool *parenthesized_p)

11219 {

11220   int declares_class_or_enum;

11221   bool greater_than_is_operator_p;

11222   tree decl_specifiers;

11223   tree attributes;

11224   tree declarator;

11225   tree default_argument;

11226   tree parameter;

11227   cp_token *token;

11228   const char *saved_message;

11229

11230   /* In a template parameter, `>' is not an operator.

11231

11232       [temp.param]

11233

11234     When parsing a default template-argument for a non-type

11235     template-parameter, the first non-nested `>' is taken as the end

11236     of the template parameter-list rather than a greater-than

11237     operator.  */

11238   greater_than_is_operator_p = !template_parm_p;

11239

11240   /* Type definitions may not appear in parameter types.  */

11241   saved_message = parser->type_definition_forbidden_message;

11242   parser->type_definition_forbidden_message

11243      = "types may not be defined in parameter types";

11244

11245   /* Parse the declaration-specifiers.  */

11246   decl_specifiers

11247     = cp_parser_decl_specifier_seq (parser,

11248                               CP_PARSER_FLAGS_NONE,

11249                               &attributes,

11250                               &declares_class_or_enum);

11251   /* If an error occurred, there's no reason to attempt to parse the

11252     rest of the declaration.  */

11253   if (cp_parser_error_occurred (parser))

11254   {

11255     parser->type_definition_forbidden_message = saved_message;

11256     return error_mark_node;

11257   }

 

const Host 是一个 decl-specifier-seq 。那么 cp_parser_decl_specifier_seq 通过重复调用 cp_parser_type_specifier 不停地解析这个序列。在第一次调用中对于关键字 const 返回了“ const ”的唯一节点;而在第二次调用中,通过下列的调用栈: cp_parser_type_specifier à cp_parser_simple_type_specifier à cp_parser_type_name à cp_parser_class_name à cp_parser_identifier cp_parser_lookup_name à lookup_name_real ,找出“ Host ”的 TYPE_DECL 节点。

 

cp_parser_parameter_declaration_clause (continue)

 

11259   /* Peek at the next token.  */

11260   token = cp_lexer_peek_token (parser->lexer);

11261   /* If the next token is a `)', `,', `=', `>', or `...', then there

11262     is no declarator.  */

11263   if (token->type == CPP_CLOSE_PAREN

11264       || token->type == CPP_COMMA

11265       || token->type == CPP_EQ

11266       || token->type == CPP_ELLIPSIS

11267       || token->type == CPP_GREATER)

11268   {

11269     declarator = NULL_TREE;

11270     if (parenthesized_p)

11271       *parenthesized_p = false;

11272   }

11273   /* Otherwise, there should be a declarator.  */

11274   else

11275   {

11276     bool saved_default_arg_ok_p = parser->default_arg_ok_p;

11277     parser->default_arg_ok_p = false;

11278  

11279     /* After seeing a decl-specifier-seq, if the next token is not a

11280       "(", there is no possibility that the code is a valid

11281       expression. Therefore, if parsing tentatively, we commit at

11282       this point.  */

11283     if (!parser->in_template_argument_list_p

11284         /* In an expression context, having seen:

11285

11286             (int((char ...

11287

11288            we cannot be sure whether we are looking at a

11289            function-type (taking a "char" as a parameter) or a cast

11290            of some object of type "char" to "int".  */

11291          && !parser->in_type_id_in_expr_p

11292          && cp_parser_parsing_tentatively (parser)

11293          && !cp_parser_committed_to_tentative_parse (parser)

11294          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))

11295       cp_parser_commit_to_tentative_parse (parser);

11296      /* Parse the declarator.  */

11297     declarator = cp_parser_declarator (parser,

11298                                 CP_PARSER_DECLARATOR_EITHER,

11299                                  /*ctor_dtor_or_conv_p=*/ NULL,

11300                                 parenthesized_p,

11301                                 /*member_p=*/ false);

11302     parser->default_arg_ok_p = saved_default_arg_ok_p;

11303     /* After the declarator, allow more attributes.  */

11304     attributes = chainon (attributes, cp_parser_attributes_opt (parser));

11305   }

 

随后的符号“ & ”是声明符。因此在 11297 行, cp_parser_declarator 被调用。注意到参数 dcl_kind CP_PARSER_DECLARATOR_EITHER ,它表示声明符( declarator )或者抽象声明符( abstract-declarator )都可以。事实上,“ & ”是一个抽象声明符,因为它不代表任何标识符的名字。

 

10259 static tree

10260 cp_parser_declarator (cp_parser* parser,                                                    in parser.c

10261                   cp_parser_declarator_kind dcl_kind,

10262                   int* ctor_dtor_or_conv_p,

10263                   bool* parenthesized_p,

10264                   bool member_p)

10265 {

10266   cp_token *token;

10267   tree declarator;

10268   enum tree_code code;

10269   tree cv_qualifier_seq;

10270   tree class_type;

10271   tree attributes = NULL_TREE;

10272

10273   /* Assume this is not a constructor, destructor, or type-conversion

10274     operator.  */

10275   if (ctor_dtor_or_conv_p)

10276     *ctor_dtor_or_conv_p = 0;

10277

10278   if (cp_parser_allow_gnu_extensions_p (parser))

10279     attributes = cp_parser_attributes_opt (parser);

10280  

10281   /* Peek at the next token.  */

10282   token = cp_lexer_peek_token (parser->lexer);

10283  

10284   /* Check for the ptr-operator production.  */

10285   cp_parser_parse_tentatively (parser);

10286   /* Parse the ptr-operator.  */

10287   code = cp_parser_ptr_operator (parser,

10288                            &class_type,

10289                             &cv_qualifier_seq);

10290   /* If that worked, then we have a ptr-operator.  */

10291   if (cp_parser_parse_definitely (parser))

10292   {

10293      /* If a ptr-operator was found, then this declarator was not

10294       parenthesized.  */

10295     if (parenthesized_p)

10296       *parenthesized_p = true;

10297     /* The dependent declarator is optional if we are parsing an

10298       abstract-declarator.  */

10299     if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)

10300       cp_parser_parse_tentatively (parser);

10301

10302     /* Parse the dependent declarator.  */

10303     declarator = cp_parser_declarator (parser, dcl_kind,

10304                                 /*ctor_dtor_or_conv_p=*/ NULL,

10305                                 /*parenthesized_p=*/ NULL,

10306                                 /*member_p=*/ false);

10307

10308      /* If we are parsing an abstract-declarator, we must handle the

10309       case where the dependent declarator is absent.  */

10310     if (dcl_kind != CP_PARSER_DECLARATOR_NAMED

10311         && ! cp_parser_parse_definitely (parser))

10312       declarator = NULL_TREE;

10313     

10314      /* Build the representation of the ptr-operator.  */

10315     if (code == INDIRECT_REF)

10316       declarator = make_pointer_declarator (cv_qualifier_seq,

10317                                       declarator);

10318     else

10319       declarator = make_reference_declarator (cv_qualifier_seq,

10320                                        declarator);

10321     /* Handle the pointer-to-member case.  */

10322     if (class_type)

10323       declarator = build_nt (SCOPE_REF, class_type, declarator);

10324   }

10325   /* Everything else is a direct-declarator.  */

10326   else

10327   {

10328     if (parenthesized_p)

10329       *parenthesized_p = cp_lexer_next_token_is (parser->lexer,

10330                                            CPP_OPEN_PAREN);

10331     declarator = cp_parser_direct_declarator (parser, dcl_kind,

10332                                       ctor_dtor_or_conv_p,

10333                                       member_p);

10334   }

10335

10336   if (attributes && declarator != error_mark_node)

10337     declarator = tree_cons (attributes, declarator, NULL_TREE);

10338  

10339   return declarator;

10340 }

 

ptr-operator 具有以下的语法。它代表或者有、或者没有 cv-qualifier 部分的直接(引用)或间接(指针)的引用。因此 cp_parser_ptr_operator 的返回值是 ADDR_EXPR 或者 INDIRECT_REF

ptr-operator

* cv-qualifier-seq [opt]

|       cv-qualifier cv-qualifier-seq [opt]

&      const

|          volatile

|         __restrict__ GNU Ext

::[opt] nested-name-specifier * cv-qualifier-seq [opt]

GNU Ext & cv-qualifier-seq [opt]

 

10729 static enum tree_code

10730 cp_parser_ptr_operator (cp_parser* parser,                                                in parser.c

10731                     tree* type,

10732                     tree* cv_qualifier_seq)

10733 {

10734   enum tree_code code = ERROR_MARK;

10735   cp_token *token;

10736

10737   /* Assume that it's not a pointer-to-member.  */

10738   *type = NULL_TREE;

10739   /* And that there are no cv-qualifiers.  */

10740   *cv_qualifier_seq = NULL_TREE;

10741

10742   /* Peek at the next token.  */

10743   token = cp_lexer_peek_token (parser->lexer);

10744   /* If it's a `*' or `&' we have a pointer or reference.  */

10745   if (token->type == CPP_MULT || token->type == CPP_AND)

10746   {

10747     /* Remember which ptr-operator we were processing.  */

10748     code = (token->type == CPP_AND ? ADDR_EXPR : INDIRECT_REF);

10749

10750     /* Consume the `*' or `&'.  */

10751     cp_lexer_consume_token (parser->lexer);

10752

10753      /* A `*' can be followed by a cv-qualifier-seq, and so can a

10754       `&', if we are allowing GNU extensions. (The only qualifier

10755       that can legally appear after `&' is `restrict', but that is

10756       enforced during semantic analysis.  */

10757     if (code == INDIRECT_REF

10758        || cp_parser_allow_gnu_extensions_p (parser))

10759       *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);

10760   }

10761   else

10762   {

10763      /* Try the pointer-to-member case.  */

10764     cp_parser_parse_tentatively (parser);

10765     /* Look for the optional `::' operator.  */

10766     cp_parser_global_scope_opt (parser,

10767                              /*current_scope_valid_p=*/ false);

10768     /* Look for the nested-name specifier.  */

10769     cp_parser_nested_name_specifier (parser,

10770                                 /*typename_keyword_p=*/ false,

10771                                 /*check_dependency_p=*/ true,

10772                                  /*type_p=*/ false,

10773                                 /*is_declaration=*/ false);

10774     /* If we found it, and the next token is a `*', then we are

10775       indeed looking at a pointer-to-member operator.  */

10776     if (!cp_parser_error_occurred (parser)

10777        && cp_parser_require (parser, CPP_MULT, "`*'"))

10778     {

10779        /* The type of which the member is a member is given by the

10780         current SCOPE.  */

10781       *type = parser->scope;

10782       /* The next name will not be qualified.  */

10783       parser->scope = NULL_TREE;

10784       parser->qualifying_scope = NULL_TREE;

10785       parser->object_scope = NULL_TREE;

10786        /* Indicate that the `*' operator was used.  */

10787       code = INDIRECT_REF;

10788       /* Look for the optional cv-qualifier-seq.  */

10789       *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);

10790     }

10791     /* If that didn't work we don't have a ptr-operator.  */

10792     if (!cp_parser_parse_definitely (parser))

10793       cp_parser_error (parser, "expected ptr-operator");

10794   }

10795

10796   return code;

10797 }

 

回到 cp_parser_declarator ,这个函数根据 cp_parser_ptr_operator 返回的节点码构建对应的树节点。不过,注意到在“ & ”后面没有跟着标识符,参数 target NULL ,它对应于该声明符(它在 cp_parser_declarator 10312 行设置)。

 

113     tree

114     make_reference_declarator (tree cv_qualifiers, tree target)                                  in lex.c

115     {

116       target = build_nt (ADDR_EXPR, target);

117       TREE_TYPE (target) = cv_qualifiers;

118       return target;

119     }

 

接下来处理可能的缺省参数,幸运的是,这里没有使用缺省参数。

 

cp_parser_parameter_declaration (continue)

 

11307   /* The restriction on defining new types applies only to the type

11308     of the parameter, not to the default argument.  */

11309   parser->type_definition_forbidden_message = saved_message;

11310

11311   /* If the next token is `=', then process a default argument.  */

11312   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))

11313   {

          …

11441   }

11442   else

11443     default_argument = NULL_TREE;

11444  

11445   /* Create the representation of the parameter.  */

11446   if (attributes)

11447     decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);

11448   parameter = build_tree_list (default_argument,

11449                          build_tree_list (decl_specifiers,

11450                                       declarator));

11451

11452   return parameter;

11453 }

 

最后,把各部分组合起来,对于构造函数的参数,它是一棵相当复杂的树。

点此打开

74 :构造函数的参数

 

cp_parser_parameter_declaration_clause (continue)

 

11072   /* Peek at the next token.  */

11073   token = cp_lexer_peek_token (parser->lexer);

11074   /* If it's a `,', the clause should terminate with an ellipsis.  */

11075   if (token->type == CPP_COMMA)

11076   {

11077     /* Consume the `,'.  */

11078     cp_lexer_consume_token (parser->lexer);

11079     /* Expect an ellipsis.  */

11080     ellipsis_p

11081         = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL);

11082   }

11083   /* It might also be `...' if the optional trailing `,' was

11084     omitted.  */

11085   else if (token->type == CPP_ELLIPSIS)

11086   {

11087     /* Consume the `...' token.  */

11088     cp_lexer_consume_token (parser->lexer);

11089     /* And remember that we saw it.  */

11090     ellipsis_p = true;

11091   }

11092   else

11093     ellipsis_p = false;

11094

11095   /* Finish the parameter list.  */

11096   return finish_parmlist (parameters, ellipsis_p);

11097 }

 

最终, finish_parmlist 为参数的节点设置需要的标记。

 

1994   tree

1995   finish_parmlist (tree parms, int ellipsis)                                              in semantics.c

1996   {

1997     if (parms)

1998     {

1999       /* We mark the PARMS as a parmlist so that declarator processing can

2000         disambiguate certain constructs.  */

2001       TREE_PARMLIST (parms) = 1;

2002       /* We do not append void_list_node here, but leave it to grokparms

2003         to do that.  */

2004       PARMLIST_ELLIPSIS_P (parms) = ellipsis;

2005     }

2006     return parms;

2007   }

 

注意到关于省略号参数( )的信息保存在链的头一个节点中。因此中间树看起来就像:

点此打开

75 :完成对构造函数参数的准备

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值