Studying note of GCC-3.4.6 source (108)

来源:互联网 发布:淘宝定贝排名在线查询 编辑:程序博客网 时间:2024/05/21 14:46

5.12.3.2.1.2.1.1.1.           Prepare databefore function handling

Next, it prepares structure for expanding statements within thebody. Notice that argument t in begin_stmt_tree refers to the address offield DECL_SAVED_TREE of the RESULT_DECL.

 

67      void

68      begin_stmt_tree (tree *t)                                                                   inc-semantics.c

69      {

70        /*We create a trivial EXPR_STMT so that last_tree is never NULL in

71          whatfollows. We remove the extraneous statement in

72         finish_stmt_tree.  */

73        *t = build_nt (EXPR_STMT,void_zero_node);

74        last_tree= *t;

75        last_expr_type = NULL_TREE;

76        last_expr_filename =input_filename;

77      }

 

The chain of statements must be ended by a fake EXPR_STMT beforeprocessing. And this EXPR_STMT will be removed when the process finished.Above, last_* are macros accessing relevant fields of the binding scope.

 

300    #define last_tree (current_stmt_tree()->x_last_stmt)                            inc-common.h

 

316    stmt_tree

317    current_stmt_tree (void)                                                                   insemantics.c

318    {

319      return(cfun

320            ? &cfun->language->base.x_stmt_tree

321            : &scope_chain->x_stmt_tree);

322    }

 

Now, as it is handling method, cfun is already allocated in allocate_struct_function atline 10360 in start_function.So here, we see what cfun looks like.

 

6434   void

6435   allocate_struct_function (tree fndecl)                                                         infunction.c

6436   {

6437     tree result;

6438  

6439     cfun = ggc_alloc_cleared (sizeof (structfunction));

6440  

6441     max_parm_reg =LAST_VIRTUAL_REGISTER + 1;

6442  

6443     cfun->stack_alignment_needed =STACK_BOUNDARY;

6444     cfun->preferred_stack_boundary =STACK_BOUNDARY;

6445  

6446     current_function_funcdef_no= funcdef_no++;

6447  

6448     cfun->function_frequency =FUNCTION_FREQUENCY_NORMAL;

6449  

6450     init_stmt_for_function ();

6451     init_eh_for_function ();

6452  

6453     (*lang_hooks.function.init) (cfun);

6454     if (init_machine_status)

6455       cfun->machine = (*init_machine_status) ();

6456  

6457     if (fndecl == NULL)

6458       return;

6459  

6460     DECL_SAVED_INSNS (fndecl) = cfun;

6461     cfun->decl = fndecl;

6462  

6463     result = DECL_RESULT(fndecl);

6464     if (aggregate_value_p(result, fndecl))

6465     {

6466   #ifdef PCC_STATIC_STRUCT_RETURN

6467      current_function_returns_pcc_struct = 1;

6468   #endif

6469      current_function_returns_struct = 1;

6470     }

6471  

6472    current_function_returns_pointer = POINTER_TYPE_P (TREE_TYPE (result));

6473  

6474    current_function_needs_context

6475       = (decl_function_context (current_function_decl) != 0

6476          && ! DECL_NO_STATIC_CHAIN (current_function_decl));

6477   }

 

Refer to section Evaluate cost forarithmatic operatoins – Create dummy function context for some details. Forthe invocation, the argument fndecl points to the node FUNCTION_DECL. Above, init_stmt_for_functionand init_eh_for_functionjust create instance of stmt_status and eh_status for cfun.

Then at line 6453, for C++ front-end, cxx_push_function_context isregistered into function.initwithinlang_hooks. It initializes the variables used during compilation ofa C++ function.

 

11290 void

11291 cxx_push_function_context (struct function * f)                                                indecl.c

11292 {

11293   structlanguage_function *p

11294     = ggc_alloc_cleared (sizeof (structlanguage_function));

11295   f->language = p;

11296

11297   /*Whenever we start a new function, we destroy temporaries in the

11298     usualway.  */

11299   current_stmt_tree()->stmts_are_full_exprs_p = 1;

11300

11301   if (f->decl)

11302   {

11303     tree fn = f->decl;

11304

11305     if(DECL_SAVED_FUNCTION_DATA (fn))

11306     {

11307       /*If we already parsed this function, and we're just expanding it

11308        now, restore saved state.  */

11309       *cp_function_chain = *DECL_SAVED_FUNCTION_DATA(fn);

11310

11311       /*If we decided that we didn't want to inline this function,

11312        make sure the back-end knows that. */

11313       if(!current_function_cannot_inline)

11314        current_function_cannot_inline = cp_function_chain->cannot_inline;

11315

11316       /* We don't need the saved data anymore.Unless this is an inline

11317        function; we need the named return value info for

11318        cp_copy_res_decl_for_inlining.  */

11319       if (! DECL_INLINE (fn))

11320        DECL_SAVED_FUNCTION_DATA (fn) = NULL;

11321     }

11322   }

11323 }

 

Below cp_function_chainreturns field languageof cfun.

 

802  #define cp_function_chain (cfun->language)                                                        in cp-tree.h

 

Then DECL_SAVED_FUNCTION_DATA returns the address of saved_language_functionfor the FUNCTION_DECL, which is filled when finishes parsing the function. However,if DECL_SAVED_FUNCTION_DATA is not null, it means there is an error of functionredefinition. In fact, argument f is cfun created at line 6439, which doesn’tsatisfy condition at line 11301, so for C++, code from line 11302 to 11320 won’tbe run (in current version, it is the only point to invoke cxx_push_function_context).To record status of function for the C++ language, below structure is defined.

 

771    struct language_function GTY(())                                                              in cp-tree.h

772    {

773      structc_language_function base;

774   

775      tree x_dtor_label;

776      tree x_current_class_ptr;

777      tree x_current_class_ref;

778      tree x_eh_spec_block;

779      tree x_in_charge_parm;

780      tree x_vtt_parm;

781      tree x_return_value;

782   

783      int returns_value;

784      int returns_null;

785      int returns_abnormally;

786      int in_function_try_handler;

787      int in_base_initializer;

788   

789      /*True if this function can throw an exception. */

790      BOOL_BITFIELD can_throw : 1;

791   

792      structnamed_label_use_list *x_named_label_uses;

793      structnamed_label_list *x_named_labels;

794      structcp_binding_level *bindings;

795      varray_type x_local_names;

796   

797      constchar *cannot_inline;

798    };

 

As C++ accommendates grammar of C, the structure containsc_language_function to hold status of C relevant. And other fields are for C++solely.

 

289    struct c_language_function GTY(()) {                                                        inc-common.h

290      /*While we are parsing the function, this contains information

291        aboutthe statement-tree that we are building. */

292      structstmt_tree_s x_stmt_tree;

293      /*The stack of SCOPE_STMTs for the current function.  */

294      tree x_scope_stmt_stack;

295    };

 

Also, generating code for different machine must take thecharacteristic of machine into account, and this information should be usedduring instruction emission for the machine.

 

11911 static struct machine_function *

11912 ix86_init_machine_status (void)                                                               ini386.c

11913 {

11914   structmachine_function *f;

11915

11916   f = ggc_alloc_cleared (sizeof (structmachine_function));

11917   f->use_fast_prologue_epilogue_nregs= -1;

11918

11919   returnf;

11920 }

 

See that machine_function defined for x86 machine will record thesnapshot of the machine at point executing the function.

 

3167   struct machine_function GTY(())                                                               in i386.h

3168   {

3169     structstack_local_entry *stack_locals;

3170     constchar *some_ld_name;

3171     int save_varrargs_registers;

3172     int accesses_prev_frame;

3173     int optimize_mode_switching;

3174     /*Set by ix86_compute_frame_layout and used by prologue/epilogue expander to

3175      determine the style used.  */

3176     intuse_fast_prologue_epilogue;

3177     /*Number of saved registers USE_FAST_PROLOGUE_EPILOGUE has been computed

3178      for.  */

3179     intuse_fast_prologue_epilogue_nregs;

3180   };

 

Below stmt_tree_s is used to store the statements within infunction. See that at line 73 in begin_stmt_tree, x_last_stmt will be the chain ofEXPR_STMT.

 

259    struct stmt_tree_s GTY(()) {                                                              inc-common.h

260      /*The last statement added to the tree.  */

261      tree x_last_stmt;

262      /*The type of the last expression statement. (This information is

263        neededto implement the statement-expression extension.)  */

264      tree x_last_expr_type;

265      /*The last filename we recorded.  */

266      constchar *x_last_expr_filename;

267      /*In C++, Nonzero if we should treat statements as full

268       expressions. In particular, this variable is no-zero if at the

269        end ofa statement we should destroy any temporaries created

270        during that statement. Similarly, if, at theend of a block, we

271        shoulddestroy any local variables in this block. Normally, this

272       variable is nonzero, since those are the normal semantics of

273        C++.

274   

275       However, in order to represent aggregate initialization code as

276        treestructure, we use statement-expressions. The statements

277        withinthe statement expression should not result in cleanups

278        beingrun until the entire enclosing statement is complete.

279   

280        Thisflag has no effect in C.  */

281      int stmts_are_full_exprs_p;

282    };

283   

284    typedef struct stmt_tree_s *stmt_tree;

 

Then at line 6460 in allocate_struct_function, DECL_SAVED_INSNSpoints to cfun.See that when handling next function, cfun will be recreated at line 6439, andDECL_SAVED_INSNS will be the solely reference to this function instance.

Further, if the function returns aggregate type, more code needs begenerated to pass address instead, and certain optimization may be applied. Forexample:

struct A { … };

A func() { return A(); }

int main() {

  A a = func();

}

An opportunity of optimization is to make func to manipulate adirectly.

In short, function returning aggregate type needs speciallyhandling, here find out them by aggregate_value_p which we will see later.

 

start_function (continue)

 

10373   /*Let the user know we're compiling this function.  */

10374   announce_function (decl1);

10375

10376   /*Record the decl so that the function name is defined.

10377     If wealready have a decl for this name, and it is a FUNCTION_DECL,

10378     usethe old decl.  */

10379   if (!processing_template_decl &&!(flags & SF_PRE_PARSED))

10380   {

         

10405   }

10406

10407   /*Reset these in case the call to pushdecl changed them.  */

10408   current_function_decl = decl1;

10409   cfun->decl = decl1;

10410

10411  /*If we are (erroneously) defining a function that we have already

10412    defined before, wipe out what we knew before.  */

10413   if (!DECL_PENDING_INLINE_P(decl1))

10414     DECL_SAVED_FUNCTION_DATA(decl1) = NULL;

10415

10416   if (ctype &&!doing_friend && !DECL_STATIC_FUNCTION_P (decl1))

10417   {

10418     /*We know that this was set up by `grokclassfn'. We do not

10419       wait until `store_parm_decls', since evilparse errors may

10420       never get us to that point. Here we keep theconsistency

10421       between `current_class_type' and`current_class_ptr'.  */

10422     tree t = DECL_ARGUMENTS(decl1);

10423

10424     my_friendly_assert (t !=NULL_TREE && TREE_CODE (t) == PARM_DECL,

10425                      162);

10426     my_friendly_assert(TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE,

10427                     19990811);

10428

10429    cp_function_chain->x_current_class_ref

10430       = build_indirect_ref (t, NULL);

10431    cp_function_chain->x_current_class_ptr = t;

10432

10433     /* Constructors anddestructors need to know whether they're "in

10434       charge" of initializing virtual baseclasses.  */

10435     t = TREE_CHAIN (t);

10436     if(DECL_HAS_IN_CHARGE_PARM_P (decl1))

10437     {

10438       current_in_charge_parm = t;

10439       t = TREE_CHAIN (t);

10440     }

10441     if (DECL_HAS_VTT_PARM_P(decl1))

10442     {

10443       if (DECL_NAME (t) != vtt_parm_identifier)

10444         abort ();

10445       current_vtt_parm = t;

10446     }

10447   }

 

Above at line 10374, announce_function just prints out the messageabout going to compile the function. At line 10416, if ctype is not NULL, it ensures thatit is processing method. And if the method is not static, then DECL_ARGUMENTSat line 10422 returns “const this*”. To tell out method from function and forquick accessing the “this” instance, it is better to save the reference andpointer within the function structure. That is why we see x_current_class_refand x_current_class_ptrat line 10429 and 10431.

 

2082   tree

2083   build_indirect_ref (tree ptr, const char *errorstring)                                          in typeck.c

2084   {

2085     tree pointer, type;

2086  

2087     if (ptr == error_mark_node)

2088       returnerror_mark_node;

2089  

2090     if (ptr ==current_class_ptr)

2091       returncurrent_class_ref;

2092  

2093     pointer = (TREE_CODE(TREE_TYPE (ptr)) == REFERENCE_TYPE

2094             ? ptr : decay_conversion (ptr));

2095     type = TREE_TYPE (pointer);

2096  

2097     if (TYPE_PTR_P (type) ||TREE_CODE (type) == REFERENCE_TYPE)

2098     {

2099       /*[expr.unary.op]

2100       

2101          Ifthe type of the expression is "pointer to T," the type

2102          ofthe result is "T."  

2103  

2104          Wemust use the canonical variant because certain parts of

2105          theback end, like fold, do pointer comparisons between

2106         types.  */

2107       tree t =canonical_type_variant (TREE_TYPE (type));

2108  

2109       if (VOID_TYPE_P (t))

2110       {

2111         /*A pointer to incomplete type (other than cv void) can be

2112          dereferenced [expr.unary.op]/1  */

2113         error ("`%T' is nota pointer-to-object type", type);

2114         returnerror_mark_node;

2115       }

2116       else if (TREE_CODE(pointer) == ADDR_EXPR

2117             &&same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))

2118         /*The POINTER was something like `&x'. We simplify `*&x' to

2119          `x'.  */

2120         returnTREE_OPERAND (pointer, 0);

2121       else

2122       {

2123         tree ref = build1 (INDIRECT_REF, t, pointer);

2124  

2125         /*We *must* set TREE_READONLY when dereferencing a pointer to const,

2126           sothat we get the proper error message if the result is used

2127           toassign to. Also, &* is supposed to be a no-op.  */

2128         TREE_READONLY (ref) =CP_TYPE_CONST_P (t);

2129         TREE_THIS_VOLATILE (ref)= CP_TYPE_VOLATILE_P (t);

2130         TREE_SIDE_EFFECTS (ref)

2131             =(TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));

2132         returnref;

2133       }

2134     }

2135     /*`pointer' won't be an error_mark_node if we were given a

2136       pointer to member, so it's cool to check for this here.  */

2137     else if(TYPE_PTR_TO_MEMBER_P (type))

2138       error ("invalid useof `%s' on pointer to member", errorstring);

2139     else if (pointer != error_mark_node)

2140     {

2141       if (errorstring)

2142          error ("invalidtype argument of `%s'", errorstring);

2143       else

2144         error ("invalid type argument");

2145     }

2146     returnerror_mark_node;

2147   }

 

Above at line 2094, decay_conversion does nothing but justreturns ptr- the node of PARM_DECL of “const this*”. And at line 2107, canonical_type_variantis just a simple wrapper of cp_build_qualified_type to createcv-qualifier qualified type

 

start_function (continue)

 

10449   if (DECL_INTERFACE_KNOWN(decl1))

10450   {

10451     tree ctx =decl_function_context (decl1);

10452

10453     if (DECL_NOT_REALLY_EXTERN(decl1))

10454       DECL_EXTERNAL (decl1) =0;

10455

10456     if (ctx != NULL_TREE&& DECL_DECLARED_INLINE_P (ctx)

10457       && TREE_PUBLIC (ctx))

10458      /*This is a function in a local class in an extern inline

10459        function. */

10460      comdat_linkage (decl1);

10461   }

10462   /*If this function belongs to an interface, it is public.

10463     If itbelongs to someone else's interface, it is also external.

10464     Thisonly affects inlines and template instantiations.  */

10465   else if (interface_unknown== 0

10466         && ! DECL_TEMPLATE_INSTANTIATION(decl1))

10467   {

10468     if (DECL_DECLARED_INLINE_P(decl1)

10469        || DECL_TEMPLATE_INSTANTIATION (decl1)

10470        || processing_template_decl)

10471     {

10472       DECL_EXTERNAL (decl1)

10473              = (interface_only

10474                 ||(DECL_DECLARED_INLINE_P (decl1)

10475                   && ! flag_implement_inlines

10476                   && !DECL_VINDEX (decl1)));

10477

10478       /* For WIN32 wealso want to put these in linkonce sections. */

10479       maybe_make_one_only (decl1);

10480     }

10481     else

10482       DECL_EXTERNAL (decl1) =0;

10483     DECL_NOT_REALLY_EXTERN(decl1) = 0;

10484     DECL_INTERFACE_KNOWN(decl1) = 1;

10485   }

10486   else if (interface_unknown&& interface_only

10487         && ! DECL_TEMPLATE_INSTANTIATION(decl1))

10488   {

10489     /*If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma

10490       interface, we will have interface_only set butnot

10491       interface_known. In that case, we don't wantto use the normal

10492       heuristics because someone will supply a#pragma implementation

10493       elsewhere, and deducing it here would producea conflict.  */

10494     comdat_linkage (decl1);

10495     DECL_EXTERNAL (decl1) = 0;

10496     DECL_INTERFACE_KNOWN(decl1) = 1;

10497     DECL_DEFER_OUTPUT (decl1)= 1;

10498   }

10499   else

10500   {

10501     /*This is a definition, not a reference.

10502       Soclear DECL_EXTERNAL.  */

10503     DECL_EXTERNAL (decl1) = 0;

10504

10505     if((DECL_DECLARED_INLINE_P (decl1)

10506          || DECL_TEMPLATE_INSTANTIATION (decl1))

10507        && ! DECL_INTERFACE_KNOWN (decl1)

10508        /* Don't try todefer nested functions for now.  */

10509        && ! decl_function_context (decl1))

10510       DECL_DEFER_OUTPUT (decl1)= 1;

10511     else

10512       DECL_INTERFACE_KNOWN(decl1) = 1;

10513   }

 

Refers to section #pragmainterface & #pragma implementation for the details. For our example,without specifying “#pragma interface” and “#pragma implementation”, conditionat line 10499 is satisfied.

5.12.3.2.1.2.1.1.2.           Push functionscope

Before exitting the routine, it should push the scope of the functioninto effect. Notice that sk_function_parms specifies that the scopecontaining function parameters.

 

start_function (continue)

 

10515   begin_scope (sk_function_parms, decl1);

10516

10517   ++function_depth;

10518

10519   if (DECL_DESTRUCTOR_P(decl1))

10520   {

10521     dtor_label = build_decl(LABEL_DECL, NULL_TREE, NULL_TREE);

10522     DECL_CONTEXT (dtor_label)= current_function_decl;

10523   }

10524

10525   start_fname_decls();

10526  

10527   store_parm_decls(current_function_parms);

10528

10529   return1;

10530 }

 

Then the front-end needs setup following identifers, [6] gives thedetails:

5.43 Function Names asStrings

GCC provides three magic variables which hold the name of thecurrent function, as a string. The first of these is __func__, which is part ofthe C99 standard:

The identifier __func__ is implicitly declared by the translator asif, immediately following the opening brace of each function definition, thedeclaration

static constchar __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosingfunction. This name is the unadorned name of the function.

__FUNCTION__ is another name for __func__. Older versions of GCCrecognize only this name. However, it is not standardized. For maximumportability, we recommend you use __func__, but provide a fallback definitionwith the preprocessor:

#if __STDC_VERSION__ <199901L

# if __GNUC__ >= 2

# define __func____FUNCTION__

# else

# define __func__"<unknown>"

# endif

#endif

In C, __PRETTY_FUNCTION__ is yet another name for __func__. However,in C++, __RETTY_FUNCTION__ contains the type signature of the function as wellas its bare name. For example, this program:

extern "C" {

extern int printf (char*, ...);

}

class a {

public:

void sub (int i)

{

printf ("__FUNCTION__ = %s/n", __FUNCTION__);

printf ("__PRETTY_FUNCTION__ = %s/n",__PRETTY_FUNCTION__);

}

};

int

main (void)

{

a ax;

ax.sub (0);

return 0;

}

gives this output:

__FUNCTION__ =sub

__PRETTY_FUNCTION__= void a::sub(int)

These identifiers are not preprocessor macros. In GCC 3.3 andearlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as stringliterals; they could be used to initialize char arrays, and they could beconcatenated with other string literals. GCC 3.4 and later treat them asvariables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ havealways been variables.

 

991    void

992    start_fname_decls (void)                                                                   in c-common.c

993    {

994      unsigned ix;

995      tree saved = NULL_TREE;

996   

997      for(ix = 0; fname_vars[ix].decl;ix++)

998      {

999        tree decl = *fname_vars[ix].decl;

1000  

1001       if (decl)

1002       {

1003         saved = tree_cons (decl,build_int_2 (ix, 0), saved);

1004         *fname_vars[ix].decl = NULL_TREE;

1005       }

1006     }

1007     if (saved ||saved_function_name_decls)

1008       /*Normally they'll have been NULL, so only push if we've got a

1009        stack, or they are non-NULL.  */

1010       saved_function_name_decls= tree_cons (saved, NULL_TREE,

1011                                       saved_function_name_decls);

1012   }

 

As mentioned above, __func__, ___FUNCTION__ and __PRETTY_FUNCTION__are all implmented as identifiers after v3.4. Struct fname_var_t carries theinformation of these identifiers.

 

689    struct fname_var_t                                                                            in c-common.c

690    {

691      tree *const decl;      /* pointer to the VAR_DECL. */

692      constunsigned rid;  /*RID number for the identifier.  */

693      constint pretty;       /*How pretty is it? */

694    };

695   

696    /* The three ways of getting then name of thecurrent function.  */

697   

698    const struct fname_var_t fname_vars[]=

699    {

700      /*C99 compliant __func__, must be first. */

701      {&c99_function_name_decl_node,RID_C99_FUNCTION_NAME, 0},

702      /*GCC __FUNCTION__ compliant.  */

703     {&function_name_decl_node, RID_FUNCTION_NAME, 0},

704      /*GCC __PRETTY_FUNCTION__ compliant.  */

705     {&pretty_function_name_decl_node, RID_PRETTY_FUNCTION_NAME, 1},

706     {NULL, 0, 0},

707    };

 

Of course, these identifiers must be global visible and unique, sothey are in fact declared within c_global_trees, and with associated RID tagmarked as a special token (like reserved words) recognized by parser. Note thatc99_function_name_decl_node,function_name_decl_node,pretty_function_name_decl_nodeare more like placeholder. They are all null pointer.

So see that at line 1004 in start_fname_decl, if decl of fname_vars is non-null, which meansusing __func__ etc in the caller function, then at time entering the calleefunction, it should be cached within global stack of saved_function_name_decls. And whenexitting from the callee function, the cached decl would be restored to make itusablein the rest of caller function.

When the function scope becomes the current_binding_level, it needs topush the parameters into the scope so later name-lookup can find out the properitem. Now current_function_parmsrefers to the chain of the parameters of the function.

 

10538 static void

10539 store_parm_decls (tree current_function_parms)                                         indecl.c

10540 {

10541   tree fndecl = current_function_decl;

10542   tree parm;

10543

10544   /*This is a chain of any other decls that came in among the parm

10545    declarations. If a parm is declared with enum {foo, bar} x;

10546     thenCONST_DECLs for foo and bar are put here. */

10547   tree nonparms = NULL_TREE;

10548

10549   if (current_function_parms)

10550   {

10551     /*This case is when the function was defined with an ANSI prototype.

10552       Theparms already have decls, so we need not do anything here

10553      except record them as in effect

10554       andcomplain if any redundant old-style parm decls were written.  */

10555

10556     tree specparms =current_function_parms;

10557     tree next;

10558

10559     /*Must clear this because it might contain TYPE_DECLs declared

10560       atclass level.  */

10561     current_binding_level->names = NULL;

10562

10563     /*If we're doing semantic analysis, then we'll call pushdecl

10564         for each of these. We must do them inreverse order so that

10565       theyend in the correct forward order.  */

10566     specparms = nreverse(specparms);

10567

10568     for(parm = specparms; parm; parm = next)

10569     {

10570       next = TREE_CHAIN(parm);

10571       if (TREE_CODE (parm) ==PARM_DECL)

10572       {

10573         if (DECL_NAME (parm)== NULL_TREE

10574            || TREE_CODE (parm)!= VOID_TYPE)

10575           pushdecl (parm);

10576         else

10577           error("parameter `%D' declared void", parm);

10578       }

10579       else

10580       {

10581         /* If we find an enum constant or a type tag,

10582          put it aside for the moment.  */

10583         TREE_CHAIN (parm) = NULL_TREE;

10584         nonparms = chainon(nonparms, parm);

10585       }

10586     }

10587

10588     /*Get the decls in their original chain order and record in the

10589      function. This is all and only the PARM_DECLs that were

10590      pushed into scope by the loop above. */

10591     DECL_ARGUMENTS (fndecl) = getdecls ();

10592   }

10593   else

10594     DECL_ARGUMENTS (fndecl) =NULL_TREE;

10595

10596   /*Now store the final chain of decls for the arguments

10597     as thedecl-chain of the current lexical scope.

10598     Putthe enumerators in as well, at the front so that

10599    DECL_ARGUMENTS is not modified. */

10600   current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl));

10601

10602   /*Do the starting of the exception specifications, if we have any.  */

10603   if (flag_exceptions && ! processing_template_decl

10604       && flag_enforce_eh_specs

10605       &&TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))

10606     current_eh_spec_block =begin_eh_spec_block ();

10607 }

 

Here at line 10573 and 10574, validates the parameters again, if theparameter is valid, pushes it into the function scope by our old friend pushdecl.And at this point current_function_decl refers to the FUNCTION_DECL of themethod. For every parameter, pushdecl is invoked in reverse order. So forfirst invocation, the PARM_DECL of “const Host&” is nameless.

 

566    tree

567    pushdecl (tree x)                                                                                     inname-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          whendeclared 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;

593   

594        /*If this is the declaration for a namespace-scope function,

595          but thedeclaration itself is in a local scope, mark the

596         declaration.  */

597        if (TREE_CODE (x) ==FUNCTION_DECL

598           &&DECL_NAMESPACE_SCOPE_P (x)

599           && current_function_decl

600           && x != current_function_decl)

601          DECL_LOCAL_FUNCTION_P(x) = 1;

602      }

603   

604      name = DECL_NAME (x);

605      if (name)

606      {

         

1007     }

1008  

1009     if (need_new_binding)

1010       add_decl_to_level (x,

1011                      DECL_NAMESPACE_SCOPE_P (x)

1012                       ?NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))

1013                       : current_binding_level);

1014  

1015     POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, x);

1016   }

 

As theparameter is nameless, so no cxx_binding node is created for the parameter butjust records it in names field of the FUNCTION_DECL.

(Clickhere for open)

Figure 92:pushing PARM_DECL of const Host&

For our case, last parameter handled is “const this*”, which hasname of “this”. No doubt, “this” has an associated IDNETIFIER_NODE, and it isneeded to be bound with the scope. For convience, we post the related code ofpushdecl again at below. Can see pushing named parameters is not different thanpushing other node of DECL.

 

566    tree

567    pushdecl (tree x)                                                                                     inname-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          whendeclared 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;

593   

594        /*If this is the declaration for a namespace-scope function,

595          butthe declaration itself is in a local scope, mark the

596         declaration.  */

597        if (TREE_CODE (x) ==FUNCTION_DECL

598           &&DECL_NAMESPACE_SCOPE_P (x)

599           && current_function_decl

600           && x != current_function_decl)

601          DECL_LOCAL_FUNCTION_P(x) = 1;

602      }

603   

604      name = DECL_NAME (x);

605      if (name)

606      {

607        intdifferent_binding_level = 0;

608   

609        if (TREE_CODE (x) == FUNCTION_DECL ||DECL_FUNCTION_TEMPLATE_P (x))

610          check_default_args (x);

611    

612        if (TREE_CODE (name) ==TEMPLATE_ID_EXPR)

613          name = TREE_OPERAND(name, 0);

614   

615        /*In case this decl was explicitly namespace-qualified, look it

616          upin 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);

          ...

743        check_template_shadow (x);

          ...

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               /* Becausepush_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          }

            ...

898          if (oldlocal)

899          {

900            tree d = oldlocal;

901   

902            while (oldlocal

903                  &&TREE_CODE (oldlocal) == VAR_DECL

904                  &&DECL_DEAD_FOR_LOCAL (oldlocal))

905              oldlocal =DECL_SHADOWED_FOR_VAR (oldlocal);

906   

907            if (oldlocal ==NULL_TREE)

908              oldlocal = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (d));

909          }

910   

911           /*If this is an extern function declaration, see if we

912           have a global definition or declaration for the function.  */

913          if (oldlocal ==NULL_TREE

914             &&DECL_EXTERNAL (x)

915             && oldglobal!= NULL_TREE

916             && TREE_CODE(x) == FUNCTION_DECL

917             && TREE_CODE(oldglobal) == FUNCTION_DECL)

918          {

             

927          }

928          /* If we have a local external declaration,

929           and no file-scope declaration has yet been seen,

930           then if we later have a file-scope decl it must not be static.  */

931          if (oldlocal ==NULL_TREE

932             && oldglobal== NULL_TREE

933             &&DECL_EXTERNAL (x)

934             &&TREE_PUBLIC (x))

935            TREE_PUBLIC (name) =1;

936   

937          /*Warn if shadowing an argument at the top level of the body.  */

938          if (oldlocal !=NULL_TREE && !DECL_EXTERNAL (x)

939             /* Inline declsshadow nothing.  */

940             &&!DECL_FROM_INLINE (x)

941             && TREE_CODE(oldlocal) == PARM_DECL

942             /* Don't check the `this' parameter.  */

943             &&!DECL_ARTIFICIAL (oldlocal))

944          {

             

971          }

972   

973          /*Maybe warn if shadowing something else. */

974          else if (warn_shadow&& !DECL_EXTERNAL (x)

975                /* No shadow warnings for internally generated vars.  */

976                && !DECL_ARTIFICIAL (x)

977                /* No shadow warnings for vars made for inlining.  */

978                && !DECL_FROM_INLINE (x))

979          {

             

1002         }

1003       }

1004  

1005       if (TREE_CODE (x) ==VAR_DECL)

1006         maybe_register_incomplete_var (x);

1007     }

1008  

1009     if (need_new_binding)

1010       add_decl_to_level (x,

1011                      DECL_NAMESPACE_SCOPE_P (x)

1012                       ? NAMESPACE_LEVEL(CP_DECL_CONTEXT (x))

1013                       :current_binding_level);

1014  

1015     POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, x);

1016   }

 

Above at line 881, push_local_binding creates the cxx_bindingnode and binds the IDENTIFIER_NODE with its scope by this node. When theidentifier appears in more than once in the source, it needs to check anypossible danger introduced. Above at line 876, IDENTIFIER_VALUE returns thelast declaration within non-namespace scope, IDENTIFIER_NAMESPACE_VALUE returns the lastdeclaration within the innermost effective namespace scope. Then at line 902,the WHILE loop skips variabledeclared within local block (i.e, FORblock). If no non-namespace non-local declaration is found, at line 908, oldlocal will get the declaration within namespace scope. Parameter “constthis*” is front-end generated argument with DECL_ARTIFICIAL flag set. Next, itupdates arguments field of the FUNCTION_DECL to names bound within the scope bygetdecls.

 

1533   tree

1534   getdecls (void)                                                                                  in name-lookup.c

1535   {

1536     returncurrent_binding_level->names;

1537   }

 

Then we willget following figure. Note, in PARM_DECL node, “this” represents the matchingIDENTIFIER_NODE. Connection from “this” to cxx_binding indicates IDENTIFIER_BINDING.

(Clickhere for open)

Figure 93:pushing PARM_DECL of “const this*”