Studying note of GCC-3.4.6 source (102)

5.12.3.2.1.1.3.5.    Parse other constructors

After parsing the default constructor, it returns back cp_parser_member_specification_opt , it begins parsing next constructor: Lock(const Host&) {}

It is a very interesting one, as its parameter is that of template parameter of the containing template class. As we have seen the procedure of parsing default constructor, here we just need to see those different.

5.12.3.2.1.1.3.5.1.            Parse parameter

For the constructor, it contains parameter, so at line 10467, in cp_parser_direct_declarator , the parameter is parsed by 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;

 

All parameters will be chained in node of tree_list by cp_parser_parameter_declaration_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 }

 

From above, every node of the chain is prepared by 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” is the decl-specifier-seq. Then cp_parser_decl_specifier_seq repeatly parses the sequence by cp_parser_type_specifier , and in first time for keyword const the unique node of “const” is returned; in second time, with following call stack 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 , the TYPE_DECL node of “Host” is found.

 

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   }

 

Token “&” follows is a declarator instead. So at line 11297, cp_parser_declarator is invoked. Notice that parameter dcl_kind is CP_PARSER_DECLARATOR_EITHER which means declarator or abstract-declarator is acceptible. In fact “&” is an abstract-declarator which hasn’t the name of identifier.

 

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 }

 

The ptr-operator has following grammar. It indicates direct (reference) or indirect (pointer) reference with/without cv-qualifier. So the returned value of cp_parser_ptr_operator is the tree code of ADDR_EXPR or 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 }

 

Back cp_parser_declarator , the function creates corresponding tree node according to the tree code returned by cp_parser_ptr_operator . However, notice that no identifier follows “&”, argument target is NULL for the declarator (it is set at line 10312 in cp_parser_declarator ).

 

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     }

 

Following handles the possible default argument, lucky it is not used here.

 

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 }

 

Finally, assemble all parts tegother, it gets a quite complex tree for the argument.

 

(Click here for open )

Figure 74 : Parameter for the constructor

 

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 }

 

At last finish_parmlist sets the needed flags of the nodes for the parameters.

 

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   }

 

Notice that information about ellipsis parameter (…) is contained within the head node of the chain. So the intermediate tree looks like:

(Click here for open )

Figure 75 : Finish preparing parameter for the constructor

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (102))