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

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 newly declared entry in the symbol table. If we're

10096     processing a declaration in a class-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 only be 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 object declared as __attribute__((deprecated)) suppresses

3690       warnings of uses of other deprecated 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       return error_mark_node;

3703  

3704     type = TREE_TYPE (decl);

3705  

3706     if (type == error_mark_node)

3707       return error_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 the object's

3715         namespace.  */

3716       push_decl_namespace (context);

3717     }

3718  

3719     /* We are only interested 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                enum decl_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     int explicit_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     enum tree_code innermost_code = ERROR_MARK;

6487     int bitfield = 0;

6488   #if 0

6489     /* See the code below that used this.  */

6490     tree decl_attr = NULL_TREE;

6491   #endif

6492  

6493     /* Keep track of what sort of function is being processed

6494       so that we can warn about default return values, or explicit

6495       return values which do not match 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 a declarator for the name being declared

6519       and get it as a string, for an error 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            case IDENTIFIER_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 the decl specs and record which ones appear.

6829       Some typespecs are defined as built-in typenames.

6830       Others, the ones that are modifiers of other types,

6831       are represented by bits in SPECBITS: set the bits for

6832       the modifiers that appear. Storage class keywords are also in SPECBITS.

6833  

6834       If there is a typedef name or a type, store the type in TYPE.

6835       This includes builtin typedefs such 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' is mentioned twice.

6841  

6842       For C++, constructors and destructors 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 parse errors slip through. For example,

6850         `int class;' is not caught by 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 entire declaration is itself tagged as deprecated then

6858         suppress reports of deprecated 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         goto found;

6946       }

6947       if (type)

6948         error ("two or more data types in declaration of `%s'", name);

6949       else if (TREE_CODE (id) == IDENTIFIER_NODE)

6950       {

           

6960       }

6961       else if (id != error_mark_node)

6962         /* Can't change CLASS nodes into RECORD nodes here!  */

6963         type = id;

6964  

6965   found: ;

6966     }

6967  

6968   #if 0

6969     /* See the code below 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 out the structure of the declarator proper.

7340       Descend through it, creating more complex types, until we reach

7341       the declared identifier (or NULL_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 a variable.  */

8518  

8519         /* An uninitialized 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 stupid register 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       /* Record constancy 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 the type of DECL.  */

8567       if (!processing_template_decl)

8568         c_apply_type_quals_to_decl (type_quals, decl);

8569  

8570       return decl;

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 the scope in which to place the variable, but remember

5903       whether or not that scope was explicitly 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 need DECL_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 we don't have any

5940         way to recover whether or not 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 class context, static means one per class,

5951       public access, and static storage.  */

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), and absence 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 top level, 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 mere warning is sure to result in improper semantics

5979           at runtime. Don't bother to allow this to compile.  */

5980         error ("thread-local storage not supported 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 a local scope) shall not be used to

5987         declare an entity with linkage.

5988  

5989         Only check this for public decls for now.  */

5990       tree t = no_linkage_check (TREE_TYPE (decl));

5991       if (t)

5992       {

5993         if (TYPE_ANONYMOUS_P (t))

5994           /* Ignore for now; `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 this declaration 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       return error_mark_node;

3839  

3840   #if ! defined ( ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)

3841     /* Tell the back-end to use or not use .common as appropriate. If we say

3842       -fconserve-space, we want this to 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 (tree x)                                                                               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        /* Template parameters have no context; they are not X::T even

579          when declared within a class or namespace.  */

580        ;

581      else

582      {

583        if (current_function_decl && x != current_function_decl

584           /* A local declaration for a function doesn't constitute

585             nesting.  */

586           && TREE_CODE (x) != FUNCTION_DECL

587           /* A local declaration for an `extern' variable is in the

588             scope of the current 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 this decl was explicitly namespace-qualified, look it

616          up in its namespace 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 is new in its binding level.

829          Install the new declaration and return it.  */

830        if (namespace_bindings_p ())

831        {

           

872        }

873        else

874        {

875          /* Here to install 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            /* Because push_local_binding will hook X on to the

883              current_binding_level's name list, we don't want to

884              do that again 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 in SCOPE.  */

10113   if (scope)

10114     pop_p = push_scope (scope);

10115

10116   /* Perform deferred access 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 entity being declared is a function, pretend that we

10123       are in its scope. If it is a `friend', it may have access to

10124       things that would not otherwise be accessible.  */

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 the access control checks for the declarator and the

10132       the decl-specifiers.  */

10133     perform_deferred_access_checks ();

10134

10135     /* Restore the saved value.  */

10136     if (TREE_CODE (decl) == FUNCTION_DECL)

10137       current_function_decl = saved_current_function_decl;

10138   }

10139

10140   /* Parse the initializer.  */

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                     /* If the initializer is in parentheses, then this is

10185                     a direct-initialization, which means that an

10186                     `explicit' constructor is OK. Otherwise, an

10187                     `explicit' constructor cannot be used.  */

10188                  ((is_parenthesized_init || !is_initialized)

10189                  ? 0 : LOOKUP_ONLYCONVERTING));

10190

10191   /* Remember whether or 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 执行延迟访问检查的时机。看到访问控制检查失败不会停止解析器。

 

你可能感兴趣的:(function,tree,processing,deprecated,binding,attributes)