Studying note of GCC-3.4.6 source (102)

来源:互联网 发布:太平洋证券炒股软件 编辑:程序博客网 时间:2024/05/16 18:20

5.12.3.2.1.1.3.5.   Parseother constructors

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

It is a very interesting one, as its parameter is that of templateparameter of the containing template class. As we have seen the procedure ofparsing 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     returnNULL_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       returnNULL_TREE;

11049     else

11050 #endif

11051       returnvoid_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     returnvoid_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     returnerror_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 theparameter declaration,

11126       thenthe 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   returnnreverse (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                             booltemplate_parm_p,

11218                            bool *parenthesized_p)

11219 {

11220   int declares_class_or_enum;

11221   boolgreater_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   constchar *saved_message;

11229

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

11231

11232      [temp.param]

11233

11234     Whenparsing a default template-argument for a non-type

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

11236     of thetemplate 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 bedefined 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     restof the declaration.  */

11253   if (cp_parser_error_occurred(parser))

11254   {

11255    parser->type_definition_forbidden_message = saved_message;

11256     returnerror_mark_node;

11257   }

 

“const Host” is the decl-specifier-seq. Then cp_parser_decl_specifier_seqrepeatly parses the sequence by cp_parser_type_specifier, and in first timefor keyword constthe unique node of “const” is returned; in second time, with following callstack 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 nodeclarator.  */

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     boolsaved_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       thispoint.  */

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_kindis CP_PARSER_DECLARATOR_EITHER which means declarator or abstract-declarator isacceptible. In fact “&” is an abstract-declarator which hasn’t the name ofidentifier.

 

10259 static tree

10260 cp_parser_declarator (cp_parser* parser,                                                    inparser.c

10261                   cp_parser_declarator_kinddcl_kind,

10262                   int*ctor_dtor_or_conv_p,

10263                   bool*parenthesized_p,

10264                   boolmember_p)

10265 {

10266   cp_token *token;

10267  tree declarator;

10268   enumtree_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 thisdeclarator 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       casewhere 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 theptr-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   returndeclarator;

10340 }

 

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

10731                     tree*type,

10732                     tree*cv_qualifier_seq)

10733 {

10734   enumtree_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 acv-qualifier-seq, and so can a

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

10755       thatcan 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 isgiven 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 wasused.  */

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   returncode;

10797 }

 

Back cp_parser_declarator, the function createscorresponding tree node according to the tree code returned by cp_parser_ptr_operator.However, notice that no identifier follows “&”, argument targetis 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)                                  inlex.c

115     {

116       target = build_nt (ADDR_EXPR,target);

117       TREE_TYPE (target) =cv_qualifiers;

118       returntarget;

119     }

 

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

 

cp_parser_parameter_declaration (continue)

 

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

11308     of theparameter, 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   returnparameter;

11453 }

 

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

 

(Clickhere 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   returnfinish_parmlist (parameters, ellipsis_p);

11097 }

 

At last finish_parmlist sets the needed flags of thenodes 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         todo that.  */

2004       PARMLIST_ELLIPSIS_P (parms)= ellipsis;

2005     }

2006     returnparms;

2007   }

 

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

(Clickhere for open)

Figure 75: Finish preparing parameter for the constructor

 

原创粉丝点击