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-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 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_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 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_p是false。那么对于这个例子,仅有的操作由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的代码。因为我们正要退出类的作用域,因此参数functionbody是0;而keep是0,则使得没有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_NODE的bindings域绑定了该名字与该作用域中的声明。在退出该作用域时,毫无疑问需要移除这些绑定。这样才可以安全地撤到上一级作用域。
- GCC-3.4.6源代码学习笔记(113)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记 (102)
- GCC-3.4.6源代码学习笔记 (103)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记 (105)
- GCC-3.4.6源代码学习笔记 (106)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(2)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(4)
- GCC-3.4.6源代码学习笔记(5)
- GCC-3.4.6源代码学习笔记(7)
- GCC-3.4.6源代码学习笔记(8)
- Studying note of GCC-3.4.6 source (112)
- c#中的interface abstract与virtual
- 将文本文件插入Oracle表中
- 安装freeradius步骤(freeradius 2.1.9+oracle 10g+ubuntu10.4)
- 重新开工啦
- GCC-3.4.6源代码学习笔记(113)
- arg_separator.output
- 使用response.getWriter().write() 乱码问题
- Studying note of GCC-3.4.6 source (113)
- 一步步学shader系列(1):环境光照(Ambient light)
- linux下automake用法(转)
- IrrCompileConfig.h
- video4linux(v4l)使用摄像头的实例基础教程与体会
- Message List