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

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     the next token is a `;', then this declaration does not declare

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

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

14565     In that 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     of something 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   return decl;

14591 }

 

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

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

2: decl-specifiers 之一是一个 enum-specifier class-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       return NULL_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       sends that 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     return t;

3636   }

 

上面的 check_tag_decl 返回了所声明的类型( *_TYPE 类型的节点),或者 NULL 如果不是声明类型的话。这个值进而又被 shadow_tag 返回。那么在 cp_parser_single_declaration 14556 行, decl 所指向的就是对应的 TYPE_DECL 节点。而在 14566 行,若 decl NULL ,表明这不是类型声明,因为 cp_parser_single_declaration 只被 cp_parser_explicit_specialization cp_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       end know.  */

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     (Even though 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_p false 。那么对于这个例子,仅有的操作由 finish_template_decl 完成。

 

2208   void

2209   finish_template_decl (tree parms)                                                      in semantics.c

2210   {

2211     if (parms)

2212       end_template_decl ();

2213     else

2214       end_specialization ();

2215   }

 

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

 

2279   void

2280   end_template_decl (void)                                                                                in pt.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)                                                                                         in decl.c

356    {

357      poplevel (0, 0, 0);

358    }

 

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

 

423    tree

424    poplevel (int keep, int reverse, int functionbody)                                               in decl.c

425    {

426      tree link;

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

428        Put it into 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        But parameter 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        if they 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        warn about 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 if this level is a function body,

535        create a 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 a for-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        that we 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_NODE bindings 域绑定了该名字与该作用域中的声明。在退出该作用域时,毫无疑问需要移除这些绑定。这样才可以安全地撤到上一级作用域。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值