GCC-3.4.6源代码学习笔记(132)
来源:互联网 发布:中国移动网络摄影机 编辑:程序博客网 时间:2024/06/06 03:45
5.12.5.2.2.2.1.2. 构建VAR_DECL
接下来在cp_parser_simple_declaration中,调用cp_parser_init_declarator来解析声明符部分。调用栈cp_parser_declarator à cp_parser_direct_declarator à cp_parser_declarator_idà cp_parser_id_expression à cp_parser_unqualified_idà cp_parser_identifier,为“object_”构建了一个IDENTIFIER_NODE。接着在cp_parser_init_declarator中,以下代码片段将被执行。
cp_parser_init_declarator (continue)
10095 /* Enter the newlydeclared entry in the symbol table. If we're
10096 processing a declaration in aclass-specifier, we wait until
10097 after processing the initializer. */
10098 if (!member_p)
10099 {
10100 if(parser->in_unbraced_linkage_specification_p)
10101 {
10102 decl_specifiers = tree_cons(error_mark_node,
10103 get_identifier("extern"),
10104 decl_specifiers);
10105 have_extern_spec = false;
10106 }
10107 decl = start_decl(declarator, decl_specifiers,
10108 is_initialized, attributes,prefix_attributes);
10109 }
“SmallObject<> object_”是一个变量声明。一个新的树节点需要在中间树中创建来代表这个实体。在这次调用中,实参intialized是false,attributes及prefix_attributes都是NULL。
3670 tree
3671 start_decl (tree declarator, in decl.c
3672 tree declspecs,
3673 int initialized,
3674 tree attributes,
3675 tree prefix_attributes)
3676 {
3677 tree decl;
3678 tree type, tem;
3679 tree context;
3680
3681 /* This should onlybe done once on the top most decl. */
3682 if (have_extern_spec)
3683 {
3684 declspecs = tree_cons (NULL_TREE,get_identifier ("extern"),
3685 declspecs);
3686 have_extern_spec = false;
3687 }
3688
3689 /* An objectdeclared as __attribute__((deprecated)) suppresses
3690 warnings of uses of otherdeprecated items. */
3691 if (lookup_attribute ("deprecated",attributes))
3692 deprecated_state = DEPRECATED_SUPPRESS;
3693
3694 attributes = chainon (attributes,prefix_attributes);
3695
3696 decl = grokdeclarator (declarator, declspecs,NORMAL,initialized,
3697 &attributes);
3698
3699 deprecated_state = DEPRECATED_NORMAL;
3700
3701 if (decl == NULL_TREE || TREE_CODE (decl) ==VOID_TYPE)
3702 returnerror_mark_node;
3703
3704 type = TREE_TYPE (decl);
3705
3706 if (type == error_mark_node)
3707 returnerror_mark_node;
3708
3709 context = DECL_CONTEXT (decl);
3710
3711 if (initialized && context &&TREE_CODE (context) == NAMESPACE_DECL
3712 && context != current_namespace&& TREE_CODE (decl) == VAR_DECL)
3713 {
3714 /* When parsing the initializer, lookup should use theobject's
3715 namespace. */
3716 push_decl_namespace (context);
3717 }
3718
3719 /* We are onlyinterested in class contexts, later. */
3720 if (context && TREE_CODE (context) ==NAMESPACE_DECL)
3721 context = NULL_TREE;
作为声明的一种,期望的是某种DECL节点,因此需要grokdeclarator分析decl-specifiers及声明符部分来构成这个节点。
6462 tree
6463 grokdeclarator(tree declarator, in decl.c
6464 tree declspecs,
6465 enumdecl_context decl_context,
6466 int initialized,
6467 tree* attrlist)
6468 {
6469 RID_BIT_TYPE specbits;
6470 int nclasses = 0;
6471 tree spec;
6472 tree type = NULL_TREE;
6473 int longlong = 0;
6474 int type_quals;
6475 int virtualp, explicitp, friendp, inlinep,staticp;
6476 intexplicit_int = 0;
6477 int explicit_char = 0;
6478 int defaulted_int = 0;
6479 int extern_langp = 0;
6480 tree dependant_name = NULL_TREE;
6481
6482 tree typedef_decl = NULL_TREE;
6483 const char*name;
6484 tree typedef_type = NULL_TREE;
6485 int funcdef_flag = 0;
6486 enumtree_code innermost_code = ERROR_MARK;
6487 int bitfield = 0;
6488 #if 0
6489 /* See the codebelow that used this. */
6490 tree decl_attr = NULL_TREE;
6491 #endif
6492
6493 /* Keep track ofwhat sort of function is being processed
6494 so that we can warn aboutdefault return values, or explicit
6495 return values which do notmatch prescribed defaults. */
6496 special_function_kind sfk = sfk_none;
6497
6498 tree dname = NULL_TREE;
6499 tree ctype = current_class_type;
6500 tree ctor_return_type = NULL_TREE;
6501 enum overload_flags flags = NO_SPECIAL;
6502 tree quals = NULL_TREE;
6503 tree raises = NULL_TREE;
6504 int template_count = 0;
6505 tree in_namespace = NULL_TREE;
6506 tree returned_attrs = NULL_TREE;
6507 tree scope = NULL_TREE;
6508 tree parms = NULL_TREE;
6509
6510 RIDBIT_RESET_ALL (specbits);
6511 if (decl_context == FUNCDEF)
6512 funcdef_flag = 1, decl_context = NORMAL;
6513 else if (decl_context == MEMFUNCDEF)
6514 funcdef_flag = -1, decl_context = FIELD;
6515 else if (decl_context == BITFIELD)
6516 bitfield = 1, decl_context = FIELD;
6517
6518 /* Look inside adeclarator for the name being declared
6519 and get it as a string, for anerror message. */
6520 {
6521 tree *next = &declarator;
6522 tree decl;
6523 name = NULL;
6524
6525 while (next&& *next)
6526 {
6527 decl = *next;
6528 switch (TREE_CODE(decl))
6529 {
…
6629 caseIDENTIFIER_NODE:
6630 if (TREE_CODE (decl) == IDENTIFIER_NODE)
6631 dname = decl;
6632
6633 next =0;
6634
6635 if (C_IS_RESERVED_WORD (dname))
6636 {
…
6640 }
6641 else if (!IDENTIFIER_TYPENAME_P (dname))
6642 name = IDENTIFIER_POINTER (dname);
…
6654 break;
6655
6656 }
6657 }
6658 }
…
6828 /* Look through thedecl specs and record which ones appear.
6829 Some typespecs are defined asbuilt-in typenames.
6830 Others, the ones that aremodifiers of other types,
6831 are represented by bits inSPECBITS: set the bits for
6832 the modifiers that appear.Storage class keywords are also in SPECBITS.
6833
6834 If there is a typedef name ora type, store the type in TYPE.
6835 This includes builtin typedefssuch as `int'.
6836
6837 Set EXPLICIT_INT if the type is`int' or `char' and did not
6838 come from a user typedef.
6839
6840 Set LONGLONG if `long' ismentioned twice.
6841
6842 For C++, constructors anddestructors have their own fast treatment. */
6843
6844 for (spec =declspecs; spec; spec = TREE_CHAIN (spec))
6845 {
6846 int i;
6847 tree id;
6848
6849 /* Certain parseerrors slip through. For example,
6850 `int class;' is not caughtby the parser. Try
6851 weakly to recover here. */
6852 if (TREE_CODE (spec) != TREE_LIST)
6853 return 0;
6854
6855 id = TREE_VALUE (spec);
6856
6857 /* If the entiredeclaration is itself tagged as deprecated then
6858 suppress reports ofdeprecated items. */
6859 if (!adding_implicit_members && id &&TREE_DEPRECATED (id))
6860 {
6861 if (deprecated_state != DEPRECATED_SUPPRESS)
6862 warn_deprecated_use (id);
6863 }
6864
6865 if (TREE_CODE (id) == IDENTIFIER_NODE)
6866 {
…
6933 }
6934 else if (TREE_CODE (id) == TYPE_DECL)
6935 {
6936 if (type)
6937 error ("multiple declarations `%T'and `%T'", type,
6938 TREE_TYPE (id));
6939 else
6940 {
6941 type = TREE_TYPE (id);
6942 TREE_VALUE (spec) = type;
6943 typedef_decl = id;
6944 }
6945 gotofound;
6946 }
6947 if (type)
6948 error ("two or more data types indeclaration of `%s'", name);
6949 else if (TREE_CODE (id) == IDENTIFIER_NODE)
6950 {
…
6960 }
6961 else if (id != error_mark_node)
6962 /* Can't changeCLASS nodes into RECORD nodes here! */
6963 type = id;
6964
6965 found: ;
6966 }
6967
6968 #if 0
6969 /* See the codebelow that used this. */
6970 if (typedef_decl)
6971 decl_attr = DECL_ATTRIBUTES (typedef_decl);
6972 #endif
6973 typedef_type = type;
…
7019 ctype = NULL_TREE;
…
7337 scope = get_scope_of_declarator (declarator);
7338
7339 /* Now figure outthe structure of the declarator proper.
7340 Descend through it, creatingmore complex types, until we reach
7341 the declared identifier (orNULL_TREE, in an abstract declarator). */
7342
7343 while(declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
7344 && TREE_CODE (declarator) !=TEMPLATE_ID_EXPR)
7345 {
…
7840 }
…
8163 {
8164 tree decl;
8165
8166 if (decl_context == PARM)
8167 {
…
8172 }
8173 else if (decl_context == FIELD)
8174 {
…
8427 }
8428 else if (TREE_CODE (type) == FUNCTION_TYPE
8429 || TREE_CODE (type) == METHOD_TYPE)
8430 {
…
8514 }
8515 else
8516 {
8517 /* It's avariable. */
8518
8519 /* Anuninitialized decl with `extern' is a reference. */
8520 decl = grokvardecl(type, declarator, &specbits,
8521 initialized,
8522 (type_quals &TYPE_QUAL_CONST) != 0,
8523 ctype ? ctype :in_namespace);
8524 bad_specifiers(decl, "variable", virtualp, quals != NULL_TREE,
8525 inlinep, friendp, raises !=NULL_TREE);
8526
8527 if (ctype)
8528 {
…
8547 }
8548 }
8549
8550 my_friendly_assert (!RIDBIT_SETP(RID_MUTABLE, specbits), 19990927);
8551
8552 /* Record`register' declaration for warnings on &
8553 and in case doing stupidregister allocation. */
8554
8555 if (RIDBIT_SETP (RID_REGISTER, specbits))
8556 DECL_REGISTER (decl) = 1;
8557
8558 if (RIDBIT_SETP (RID_EXTERN, specbits))
8559 DECL_THIS_EXTERN (decl) = 1;
8560
8561 if (RIDBIT_SETP (RID_STATIC, specbits))
8562 DECL_THIS_STATIC (decl) = 1;
8563
8564 /* Recordconstancy and volatility. There's no need to do this
8565 when processing a template;we'll do this for the instantiated
8566 declaration based on thetype of DECL. */
8567 if (!processing_template_decl)
8568 c_apply_type_quals_to_decl (type_quals, decl);
8569
8570 returndecl;
8571 }
8572 }
在上面的代码中,显然6525行的WHILE块验证声明符部分;而6844行的FOR块验证并提前对应的type-specifier。注意到在6941行,type指向上一节中所构建的RECORD_TYPE。
接着type及declarator将被组合起来由grokvardecl来构成期望的VAR_DECL。注意到对于我们的情形,在调用期间,参数scope是NULL,constp是false,initialized是false,而specbits_in包含了0。
5885 static tree
5886 grokvardecl (tree type, in decl.c
5887 tree name,
5888 RID_BIT_TYPE * specbits_in,
5889 int initialized,
5890 int constp,
5891 tree scope)
5892 {
5893 tree decl;
5894 tree explicit_scope;
5895 RID_BIT_TYPE specbits;
5896
5897 my_friendly_assert (!name || TREE_CODE (name)== IDENTIFIER_NODE,
5898 20020808);
5899
5900 specbits = *specbits_in;
5901
5902 /* Compute thescope in which to place the variable, but remember
5903 whether or not that scope wasexplicitly specified by the user. */
5904 explicit_scope = scope;
5905 if (!scope)
5906 {
5907 /* An explicit"extern" specifier indicates a namespace-scope
5908 variable. */
5909 if (RIDBIT_SETP (RID_EXTERN, specbits))
5910 scope = current_namespace;
5911 else if (!at_function_scope_p ())
5912 {
5913 scope = current_scope ();
5914 if (!scope)
5915 scope = current_namespace;
5916 }
5917 }
5918
5919 if (scope
5920 && (/*If the variable is a namespace-scope variable declared in a
5921 template, we needDECL_LANG_SPECIFIC. */
5922 (TREE_CODE (scope) == NAMESPACE_DECL&& processing_template_decl)
5923 /*Similarly for namespace-scope variables with language linkage
5924 other than C++. */
5925 || (TREE_CODE (scope) ==NAMESPACE_DECL
5926 && current_lang_name !=lang_name_cplusplus)
5927 /*Similarly for static data members. */
5928 || TYPE_P (scope)))
5929 decl = build_lang_decl (VAR_DECL, name,type);
5930 else
5931 decl = build_decl(VAR_DECL, name, type);
5932
5933 if (explicit_scope && TREE_CODE(explicit_scope) == NAMESPACE_DECL)
5934 set_decl_namespace (decl, explicit_scope,0);
5935 else
5936 DECL_CONTEXT (decl) = scope;
5937
5938 if (name && scope && current_lang_name!= lang_name_c)
5939 /* We can't mangle lazily here because wedon't have any
5940 way to recover whether ornot a variable was `extern
5941 "C"' later. */
5942 mangle_decl (decl);
5943
5944 if (RIDBIT_SETP (RID_EXTERN, specbits))
5945 {
5946 DECL_THIS_EXTERN (decl) = 1;
5947 DECL_EXTERNAL (decl) = !initialized;
5948 }
5949
5950 /* In classcontext, static means one per class,
5951 public access, and staticstorage. */
5952 if (DECL_CLASS_SCOPE_P (decl))
5953 {
5954 TREE_PUBLIC (decl) = 1;
5955 TREE_STATIC (decl) = 1;
5956 DECL_EXTERNAL (decl) = 0;
5957 }
5958 /* At top level,either `static' or no s.c.makes a definition
5959 (perhaps tentative), andabsence of `static' makes it public. */
5960 else if (toplevel_bindings_p ())
5961 {
5962 TREE_PUBLIC (decl) = (RIDBIT_NOTSETP(RID_STATIC, specbits)
5963 &&(DECL_THIS_EXTERN (decl) || ! constp));
5964 TREE_STATIC (decl) = ! DECL_EXTERNAL(decl);
5965 }
5966 /* Not at toplevel, only `static' makes a static definition. */
5967 else
5968 {
5969 TREE_STATIC (decl) = !! RIDBIT_SETP(RID_STATIC, specbits);
5970 TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
5971 }
5972
5973 if (RIDBIT_SETP (RID_THREAD, specbits))
5974 {
5975 if (targetm.have_tls)
5976 DECL_THREAD_LOCAL (decl) = 1;
5977 else
5978 /* A merewarning is sure to result in improper semantics
5979 at runtime. Don't botherto allow this to compile. */
5980 error ("thread-local storage notsupported for this target");
5981 }
5982
5983 if (TREE_PUBLIC (decl))
5984 {
5985 /* [basic.link]:A name with no linkage (notably, the name of a class
5986 or enumeration declared in alocal scope) shall not be used to
5987 declare an entity withlinkage.
5988
5989 Only check this for publicdecls for now. */
5990 tree t = no_linkage_check (TREE_TYPE(decl));
5991 if (t)
5992 {
5993 if (TYPE_ANONYMOUS_P (t))
5994 /* Ignore fornow; `enum { foo } e' is pretty common. */;
5995 else
5996 pedwarn ("non-local variable `%#D'uses local type `%T'",
5997 decl, t);
5998 }
5999 }
6000
6001 return decl;
6002 }
在这一步之后,我们得到下图中的VAR_DECL。看到该节点的context域是NULL,因为我们不在类作用域中。
(点此打开)
start_decl (continue)
3832 /* Enter thisdeclaration into the symbol table. */
3833 tem = maybe_push_decl (decl);
3834
3835 if (processing_template_decl)
3836 tem = push_template_decl (tem);
3837 if (tem == error_mark_node)
3838 returnerror_mark_node;
3839
3840 #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
3841 /* Tell theback-end to use or not use .common as appropriate. If we say
3842 -fconserve-space, we want thisto save .data space, at the expense of
3843 wrong semantics. If we say-fno-conserve-space, we want this to
3844 produce errors about redefs;to do this we force variables into the
3845 data segment. */
3846 DECL_COMMON (tem) = ((TREE_CODE (tem) !=VAR_DECL
3847 ||!DECL_THREAD_LOCAL (tem))
3848 && (flag_conserve_space|| ! TREE_PUBLIC (tem)));
3849 #endif
3850
3851 if (! processing_template_decl)
3852 start_decl_1 (tem);
3853
3854 return tem;
3855 }
作为一个context域为NULL 的VAR_DECL节点, maybe_push_decl为 decl调用pushdecl。而对于我们的例子,在3852行的start_decl_1不做任何事。
566 tree
567 pushdecl (treex) in name-lookup.c
568 {
569 tree t;
570 tree name;
571 int need_new_binding;
572
573 timevar_push (TV_NAME_LOOKUP);
574
575 need_new_binding = 1;
576
577 if (DECL_TEMPLATE_PARM_P (x))
578 /* Templateparameters have no context; they are not X::T even
579 when declaredwithin a class or namespace. */
580 ;
581 else
582 {
583 if (current_function_decl && x != current_function_decl
584 /* A localdeclaration for a function doesn't constitute
585 nesting. */
586 && TREE_CODE (x) !=FUNCTION_DECL
587 /* A localdeclaration for an `extern' variable is in the
588 scope of thecurrent namespace, not the current
589 function. */
590 && !(TREE_CODE (x) == VAR_DECL&& DECL_EXTERNAL (x))
591 && !DECL_CONTEXT (x))
592 DECL_CONTEXT (x) = current_function_decl;
…
602 }
603
604 name = DECL_NAME (x);
605 if (name)
606 {
607 int different_binding_level = 0;
…
615 /* In case thisdecl was explicitly namespace-qualified, look it
616 up in itsnamespace context. */
617 if (DECL_NAMESPACE_SCOPE_P (x) &&namespace_bindings_p ())
618 t = namespace_binding (name, DECL_CONTEXT(x));
619 else
620 t = lookup_name_current_level (name);
…
828 /* This name isnew in its binding level.
829 Install the newdeclaration and return it. */
830 if (namespace_bindings_p())
831 {
…
872 }
873 else
874 {
875 /* Here toinstall a non-global value. */
876 tree oldlocal = IDENTIFIER_VALUE (name);
877 tree oldglobal =IDENTIFIER_NAMESPACE_VALUE (name);
878
879 if (need_new_binding)
880 {
881 push_local_binding (name, x, 0);
882 /* Becausepush_local_binding will hook X on to the
883 current_binding_level's name list, we don't want to
884 do thatagain below. */
885 need_new_binding = 0;
886 }
…
1003 }
1004
1005 if (TREE_CODE (x) == VAR_DECL)
1006 maybe_register_incomplete_var (x);
1007 }
…
1015 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
1016 }
我们已经多次看过pushdecl;再次我们在上面给出该函数得到执行部分的代码。看到在1006行的maybe_register_incomplete_var对非外部的VAR_DECL不做处理。在退出start_decl时,我们得到如下的中间树。
(点此打开)
cp_parser_init_declarator (continue)
10111 /* Enter the SCOPE.That way unqualified names appearing in the
10112 initializer will be looked up inSCOPE. */
10113 if (scope)
10114 pop_p = push_scope (scope);
10115
10116 /* Perform deferredaccess control checks, now that we know in which
10117 SCOPE the declared entity resides. */
10118 if (!member_p && decl)
10119 {
10120 tree saved_current_function_decl =NULL_TREE;
10121
10122 /* If the entitybeing declared is a function, pretend that we
10123 are in its scope. If it is a `friend', itmay have access to
10124 things that would not otherwise beaccessible. */
10125 if (TREE_CODE (decl) == FUNCTION_DECL)
10126 {
10127 saved_current_function_decl = current_function_decl;
10128 current_function_decl = decl;
10129 }
10130
10131 /* Perform theaccess control checks for the declarator and the
10132 the decl-specifiers. */
10133 perform_deferred_access_checks();
10134
10135 /* Restore the savedvalue. */
10136 if (TREE_CODE (decl) == FUNCTION_DECL)
10137 current_function_decl =saved_current_function_decl;
10138 }
10139
10140 /* Parse theinitializer. */
10141 if (is_initialized)
10142 initializer = cp_parser_initializer(parser,
10143 &is_parenthesized_init,
10144 &is_non_constant_init);
10145 else
10146 {
10147 initializer = NULL_TREE;
10148 is_parenthesized_init = false;
10149 is_non_constant_init = true;
10150 }
…
10178 /* Finish processing the declaration. But,skip friend
10179 declarations. */
10180 if (!friend_p && decl)
10181 cp_finish_decl(decl,
10182 initializer,
10183 asm_specification,
10184 /* Ifthe initializer is in parentheses, then this is
10185 a direct-initialization, which means that an
10186 `explicit' constructor is OK.Otherwise, an
10187 `explicit' constructorcannot be used. */
10188 ((is_parenthesized_init ||!is_initialized)
10189 ? 0 : LOOKUP_ONLYCONVERTING));
10190
10191 /* Remember whetheror not variables were initialized by
10192 constant-expressions. */
10193 if (decl && TREE_CODE (decl) ==VAR_DECL
10194 && is_initialized &&!is_non_constant_init)
10195 DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(decl) = true;
10196
10197 return decl;
10198 }
注意到在为template-id及VAR_DECL构建了节点之后,正是为相关声明符及decl-specifier执行延迟访问检查的时机。看到访问控制检查失败不会停止解析器。
- GCC-3.4.6源代码学习笔记(132)
- 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)
- 小悲剧
- setsockopt
- ifconfig配置
- MessageBox 按钮内容修改
- [Android]仿通讯录ListView小例子
- GCC-3.4.6源代码学习笔记(132)
- 关于单点登录的一点想法
- 错误解决:附加SQL Server 2000/2005数据库 5118错误 摘自红色黑客联盟(www.7747.net) 原文:http://www.7747.net/Article/201006/51336.html
- Studying note of GCC-3.4.6 source (132)
- 不适合当一名开发人员的10种迹象
- Visual Studio 2008 使用技巧
- Source Insight经典教程
- 一个Axis2 + eclipse开发Web服务的例子SayHi
- 人性的经典2