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