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

来源:互联网 发布:floor php 编辑:程序博客网 时间:2024/06/06 13:58

5.12.3.2.1.2.2.         闭合类定义

expand_or_defer_fn à cp_parser_late_parsing_for_member à cp_parser_late_parsing_for_memberà cp_parser_class_specifier à cp_parser_type_specifierà cp_parser_decl_specifier_seq返回至cp_parser_single_declaration,将执行下面的代码。

 

cp_parser_single_declaration (continue)

 

14549   /*Check for the declaration of a template class. */

14550   if (declares_class_or_enum)

14551   {

14552     if (cp_parser_declares_only_class_p(parser))

14553     {

14554       decl = shadow_tag (decl_specifiers);

14555       if (decl)

14556         decl = TYPE_NAME(decl);

14557       else

14558         decl = error_mark_node;

14559     }

14560   }

14561   /*If it's not a template class, try for a template function. If

14562     thenext token is a `;', then this declaration does not declare

14563    anything. But, if there were errors in the decl-specifiers, then

14564     theerror might well have come from an attempted class-specifier.

14565     Inthat case, there's no need to warn about a missing declarator.  */

14566   if (!decl

14567       &&(cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)

14568           || !value_member (error_mark_node,decl_specifiers)))

14569     decl = cp_parser_init_declarator (parser,

14570                               decl_specifiers,

14571                               attributes,

14572                               /*function_definition_allowed_p=*/true,

14573                               member_p,

14574                               declares_class_or_enum,

14575                               &function_definition_p);

14576

14577   pop_deferring_access_checks ();

14578

14579   /*Clear any current qualification; whatever comes next is the start

14580     ofsomething new.  */

14581   parser->scope =NULL_TREE;

14582   parser->qualifying_scope= NULL_TREE;

14583   parser->object_scope =NULL_TREE;

14584   /*Look for a trailing `;' after the declaration. */

14585   if (!function_definition_p

14586       && (decl ==error_mark_node

14587            ||!cp_parser_require (parser, CPP_SEMICOLON, "`;'")))

14588    cp_parser_skip_to_end_of_block_or_statement (parser);

14589

14590   returndecl;

14591 }

 

我们已经看过,declares_class_or_enum可被设置为以下标记的按位与的结果:

1: decl-specifiers之一是一个elaborated-type-specifier(即一个类型声明)

2: decl-specifiers之一是一个enum-specifierclass-specifier(即一个类型定义)

因此如果declares_class_or_enum不是0,需要进一步看这是否为类定义。如果是,将执行一些安全检查,这些检查与前面章节中对嵌套类所执行的检查相仿。

因为现在只是完成了“decl-specifier-seq[opt]init-declarator [opt];”中decl-specifier-seq部分,函数cp_parser_declares_only_class_p用于确认是否出现声明符。

 

15029 static bool

15030 cp_parser_declares_only_class_p (cp_parser *parser)                                   in parser.c

15031 {

15032   /*If the next token is a `;' or a `,' then there is no

15033    declarator.  */

15034   return(cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)

15035        || cp_lexer_next_token_is (parser->lexer,CPP_COMMA));

15036 }

 

如果没有声明符,这只能是类型声明。这需要确认。

 

3608   tree

3609   shadow_tag (tree declspecs)                                                                             in decl.c

3610   {

3611     tree t = check_tag_decl (declspecs);

3612  

3613     if (!t)

3614       returnNULL_TREE;

3615  

3616    maybe_process_partial_specialization (t);

3617  

3618     /*This is where the variables in an anonymous union are

3619      declared. An anonymous union declaration looks like:

3620       union{ ... } ;

3621      because there is no declarator after the union, the parser

3622       sendsthat declaration here.  */

3623     if (ANON_AGGR_TYPE_P (t))

3624     {

3625       fixup_anonymous_aggr (t);

3626  

3627       if (TYPE_FIELDS (t))

3628       {

3629         tree decl =grokdeclarator (NULL_TREE, declspecs, NORMAL,0,

3630                              NULL);

3631         finish_anon_union(decl);

3632       }

3633     }

3634  

3635     returnt;

3636   }

 

上面的check_tag_decl返回了所声明的类型(*_TYPE类型的节点),或者NULL如果不是声明类型的话。这个值进而又被shadow_tag返回。那么在cp_parser_single_declaration14556行,decl所指向的就是对应的TYPE_DECL节点。而在14566行,若declNULL,表明这不是类型声明,因为cp_parser_single_declaration只被cp_parser_explicit_specializationcp_parser_template_declaration_after_export所调用(这里是后者),那么剩下的可能就是模板函数,由14569行的cp_parser_init_declarator来解析之。

cp_parser_single_declaration回到cp_parser_template_declaration_after_export

 

cp_parser_template_declaration_after_export(continue)

 

14461   else

14462   {

14463     decl = cp_parser_single_declaration (parser,

14464                                  member_p,

14465                                  &friend_p);

14466

14467     /*If this is a member template declaration, let the front

14468       endknow.  */

14469     if (member_p &&!friend_p && decl)

14470     {

14471       if (TREE_CODE (decl) ==TYPE_DECL)

14472        cp_parser_check_access_in_redeclaration (decl);

14473

14474       decl =finish_member_template_decl (decl);

14475     }

14476     else if (friend_p&& decl && TREE_CODE (decl) == TYPE_DECL)

14477       make_friend_class (current_class_type,TREE_TYPE (decl),

14478                       /*complain=*/true);

14479   }

14480   /*We are done with the current parameter list. */

14481  --parser->num_template_parameter_lists;

14482

14483   /*Finish up.  */

14484   finish_template_decl (parameter_list);

14485

14486   /*Register member declarations.  */

14487   if (member_p &&!friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))

14488     finish_member_declaration(decl);

14489

14490   /*If DECL is a function template, we must return to parse it later.

14491     (Eventhough there is no definition, there might be default

14492    arguments that need handling.)  */

14493   if (member_p && decl

14494      && (TREE_CODE(decl) == FUNCTION_DECL

14495          ||DECL_FUNCTION_TEMPLATE_P (decl)))

14496     TREE_VALUE(parser->unparsed_functions_queues)

14497              = tree_cons (NULL_TREE, decl,

14498                        TREE_VALUE (parser->unparsed_functions_queues));

14499 }

 

上面,对于我们作为例子的模板声明,它不是一个类成员,因此参数member_pfalse。那么对于这个例子,仅有的操作由finish_template_decl完成。

 

2208   void

2209   finish_template_decl (tree parms)                                                      insemantics.c

2210   {

2211     if (parms)

2212       end_template_decl ();

2213     else

2214       end_specialization ();

2215   }

 

参数parms提取自“<…>”,因此如果它是NULL,它一定是一个特化。

 

2279   void

2280   end_template_decl (void)                                                                                inpt.c

2281   {

2282     reset_specialization ();

2283  

2284     if (!processing_template_decl)

2285       return;

2286  

2287     /*This matches the pushlevel in begin_template_parm_list.  */

2288     finish_scope();

2289  

2290     --processing_template_decl;

2291     current_template_parms = TREE_CHAIN(current_template_parms);

2292   }

 

在完成目标声明解析时,意味着我们到达了其作用域的边界。这个作用域也是由finish_scope来关闭。并且要记住把正在处理模板声明的数目减一。参考图:嵌套模参数的布局,上面在2291行,current_template_parms的域TREE_CHAIN指向封闭模板(containing template)的目标参数,如果存在的话。

 

354    void

355    finish_scope (void)                                                                                         indecl.c

356    {

357      poplevel (0, 0, 0);

358    }

 

为了方便起见,在下面我们重新显示poplevel的代码。因为我们正要退出类的作用域,因此参数functionbody0;而keep0,则使得没有BLOCK节点为该域中的声明而构建。

 

423    tree

424    poplevel (int keep, int reverse, int functionbody)                                               indecl.c

425    {

426      tree link;

427      /*The chain of decls was accumulated in reverse order.

428        Put itinto forward order, just for cleanliness. */

429      tree decls;

430      int tmp = functionbody;

431      int real_functionbody;

432      tree subblocks;

433      tree block = NULL_TREE;

434     tree decl;

435      int leaving_for_scope;

436      scope_kind kind;

       

454      if (current_binding_level->keep)

455        keep = 1;

       

493      /*Get the decls in the order they were written.

494       Usually current_binding_level->names is in reverse order.

495        Butparameter decls were previously put in forward order.  */

496   

497      if (reverse)

498       current_binding_level->names

499          = decls = nreverse(current_binding_level->names);

500      else

501        decls =current_binding_level->names;

502   

503      /*Output any nested inline functions within this block

504        ifthey weren't already output.  */

505      for(decl = decls; decl; decl = TREE_CHAIN (decl))

506        if (TREE_CODE (decl) ==FUNCTION_DECL

507           && !TREE_ASM_WRITTEN (decl)

508           && DECL_INITIAL(decl) != NULL_TREE

509           &&TREE_ADDRESSABLE (decl)

510           &&decl_function_context (decl) == current_function_decl)

511         {

           

523        }

524   

525      /*When not in function-at-a-time mode, expand_end_bindings will

526        warnabout unused variables. But, in function-at-a-time mode

527       expand_end_bindings is not passed the list of variables in the

528       current scope, and therefore no warning is emitted. So, we

529       explicitly warn here.  */

530      if (!processing_template_decl)

531       warn_about_unused_variables (getdecls ());

532   

533      /*If there were any declarations or structure tags in that level,

534        or ifthis level is a function body,

535        createa BLOCK to record them for the life of this function.  */

536      block = NULL_TREE;

      

550      /*We still support the old for-scope rules, whereby the variables

551        in afor-init statement were in scope after the for-statement

552        ended.We only use the new rules if flag_new_for_scope is

553       nonzero.  */

554      leaving_for_scope

555        =current_binding_level->kind == sk_for && flag_new_for_scope == 1;

556   

557      /*Remove declarations for all the DECLs in this level.  */

558      for(link = decls; link; link = TREE_CHAIN (link))

559      {

560        if (leaving_for_scope&& TREE_CODE (link) == VAR_DECL

561           && DECL_NAME(link))

562        {

           

619        }

620        else

621        {

622          /*Remove the binding.  */

623          decl = link;

624          if (TREE_CODE (decl) ==TREE_LIST)

625            decl = TREE_VALUE(decl);

626          if (DECL_P (decl))

627            pop_binding(DECL_NAME (decl), decl);

628          else if (TREE_CODE(decl) == OVERLOAD)

629            pop_binding(DECL_NAME (OVL_FUNCTION (decl)), decl);

630          else

631            abort ();

632        }

633      }

634   

635      /*Remove declarations for any `for' variables from inner scopes

636        thatwe kept around.  */

637      for(link = current_binding_level->dead_vars_from_for;

638          link; link = TREE_CHAIN(link))

639        pop_binding(DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));

640   

641      /*Restore the IDENTIFIER_TYPE_VALUEs.  */

642      for(link = current_binding_level->type_shadowed;

643          link; link = TREE_CHAIN(link))

644        SET_IDENTIFIER_TYPE_VALUE(TREE_PURPOSE (link), TREE_VALUE (link));

645   

646      /*Restore the IDENTIFIER_LABEL_VALUEs for local labels.  */

647      for(link = current_binding_level->shadowed_labels;

648          link;

649          link = TREE_CHAIN(link))

650        pop_label (TREE_VALUE(link), TREE_PURPOSE (link));

       

682      kind =current_binding_level->kind;

683   

684      leave_scope();

       

722      POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, block);

723    }

 

因为对应于作用域的cxx_scope对象的names域记录了在其中的所有声明,并且对应的IDENTIFIER_NODEbindings域绑定了该名字与该作用域中的声明。在退出该作用域时,毫无疑问需要移除这些绑定。这样才可以安全地撤到上一级作用域。