Studying note of GCC-3.4.6 source (134)

来源:互联网 发布:刘路造假事件知乎 编辑:程序博客网 时间:2024/05/21 17:16

5.12.5.2.2.2.1.3.1.           Instantiatebase class – substituting argument for parameter

The base classmay depends on template parameter as our example here. So to instantiate thederived class, it first needs instantiate its base classes appropriately. Herewe display the intermediate tree of “SmallObject” in below again for convience.“SmallObject” has single base class – “ThreadingModel” which defaults to“SingleThreaded”, and “SmallObject” is declared within namespace “Loki”.

(Clickhere for open)

figure 115:intermediate tree for “SmallObject”

In instantiate_class_template,at line 5320, patternis the node of RECORD_TYPE at top in the figure; and pinfo at line 5400 is that pointedby binfofield of pattern.Then at line 5425, namespace “Loki” is made as the current binding context. Soat line 5439, the first argument for tsubst is the node ofBOUND_TEMPLATE_TEMPLATE_PARM, and the second argument args is the tree_vec in red inbelow figure.

(Clickhere for open)

figure 116:intermediate tree for the VAR_DECL

 

6681   static tree

6682   tsubst (tree t,tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

6685  

6686     if (t == NULL_TREE || t == error_mark_node

6687        || t == integer_type_node

6688        || t == void_type_node

6689        || t == char_type_node

6690        || t == unknown_type_node

6691        || TREE_CODE (t) == NAMESPACE_DECL)

6692       return t;

6693  

6694     if(TREE_CODE (t) == IDENTIFIER_NODE)

6695      type = IDENTIFIER_TYPE_VALUE (t);

6696    else

6697       type = TREE_TYPE (t);

6698  

6699     my_friendly_assert (type !=unknown_type_node, 20030716);

6700  

6701     if (type && TREE_CODE (t) !=FUNCTION_DECL

6702        && TREE_CODE (t) != TYPENAME_TYPE

6703        && TREE_CODE (t) != TEMPLATE_DECL

6704        && TREE_CODE (t) != IDENTIFIER_NODE

6705        && TREE_CODE (t) != FUNCTION_TYPE

6706         && TREE_CODE (t) != METHOD_TYPE)

6707       type = tsubst (type, args, complain,in_decl);

6708     if (type == error_mark_node)

6709       returnerror_mark_node;

6710  

6711     if (DECL_P (t))

6712       returntsubst_decl (t, args, type, complain);

6713  

6714     switch(TREE_CODE (t))

6715     {

         

6776       caseTEMPLATE_TYPE_PARM:

6777       caseTEMPLATE_TEMPLATE_PARM:

6778       caseBOUND_TEMPLATE_TEMPLATE_PARM:

6779       caseTEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785         r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) ==TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6790        {

6791          idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795        {

6796          idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802           tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             returnerror_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

6812             if (TREE_CODE (t) ==TEMPLATE_TYPE_PARM)

6813             {

6814               my_friendly_assert (TYPE_P (arg),0);

6815               returncp_build_qualified_type_real

6816                       (arg, cp_type_quals (arg) |cp_type_quals (t),

6817                        complain |tf_ignore_bad_quals);

6818             }

6819             else if (TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6820             {

6821               /* We areprocessing a type constructed from

6822                 a templatetemplate parameter.  */

6823               tree argvec = tsubst (TYPE_TI_ARGS(t),

6824                                args, complain, in_decl);

6825               if (argvec == error_mark_node)

6826                 returnerror_mark_node;

 

As trefers to the node of BOUND_TEMPLATE_TEMPALTE_PARM, at line 6791 idx is0, and levelis 1; argat line 6806 then points to the node of TEMPLATE_DECL of “SingleThreaded”. Alsonotice that at line 6823, the first argument of tsubst “TYPE_TI_ARGS (t)”for our example refers to the tree_vec containing 2 elements in the firstfigure in this section [Its definition is: (TI_ARGS(TYPE_TEMPLATE_INFO (NODE)))].

 

6681   static tree

6682   tsubst (tree t,tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

        ...

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

       

6714     switch(TREE_CODE (t))

6715     {

         

6950     caseTREE_VEC:

6951       if (type != NULL_TREE)

6952       {

             

6970       }

6971

6972       /* Otherwise,a vector of template arguments.  */

6973       return tsubst_template_args (t, args, complain,in_decl);

          

7304    }

7305 }

 

Here argument t stands for the parameters of the template,while argsrepresents the arguments at instantiation. As semantic check should be taken atpoint of instantiation for template, tsubst_template_args verifies if thearguments are compatible with the parameters. Now t points to node in red asbelow figure.

t1

5744   static tree

5745   tsubst_template_args (tree t, tree args,tsubst_flags_t complain, tree in_decl)              in pt.c

5746   {

5747    int len = TREE_VEC_LENGTH (t);

5748     int need_new = 0, i;

5749     tree *elts = alloca (len * sizeof (tree));

5750    

5751     for (i = 0; i < len; i++)

5752     {

5753      tree orig_arg = TREE_VEC_ELT (t, i);

5754       tree new_arg;

5756  

5757       if (TREE_CODE (orig_arg) == TREE_VEC)

5758         new_arg = tsubst_template_args (orig_arg,args, complain, in_decl);

5759       else

5760         new_arg = tsubst_template_arg(orig_arg, args, complain, in_decl);

5761        

5762       if (new_arg == error_mark_node)

5763         returnerror_mark_node;

5764  

5765       elts[i] = new_arg;

5766       if (new_arg != orig_arg)

5767         need_new = 1;

5768     }

5769    

5770     if (!need_new)

5771       return t;

5772  

5773     t = make_tree_vec (len);

5774     for (i = 0; i< len; i++)

5775       TREE_VEC_ELT (t, i) = elts[i];

5776    

5777     return t;

5778   }

 

See that the first element in t is a tree_vec, which are the parameters forouter template. This tree_vec (the first element) and the second element as theparameter of the inner template both are processed by tsubst_template_arg. In thefunction, for all candidates, TYPE_P returns zero as they are not node oftypes. See that the arguments of t and args in tsubst_expr are the same as those in tsubst_template_arg.

 

7822   static tree

7823   tsubst_expr (treet, tree args, tsubst_flags_t complain, tree in_decl)                            in pt.c

7824   {

7825     tree stmt, tmp;

7826     tsubst_flags_t stmt_expr

7827       = complain & (tf_stmt_expr_cmpd |tf_stmt_expr_body);

7828  

7829     complain ^= stmt_expr;

7830     if (t == NULL_TREE || t == error_mark_node)

7831       return t;

7832  

7833     if (!STATEMENT_CODE_P (TREE_CODE (t)))

7834       returntsubst_copy_and_build (t, args, complain, in_decl,

7835                                /*function_p=*/false);

       

8156   }

 

Here all template arguments are not of statement, so tsubst_copy_and_buildis always invoked.

 

8179   tree

8180   tsubst_copy_and_build(tree t,                                                                         in pt.c

8181                    tree args,

8182                   tsubst_flags_t complain,

8183                    treein_decl,

8184                    boolfunction_p)

8185   {

8186     #define RECUR(NODE) /

8187     tsubst_copy_and_build (NODE, args, complain,in_decl, /*function_p=*/false)

8188

8189    tree op1;

8190

8191     if (t == NULL_TREE || t == error_mark_node)

8192     returnt;

8193  

8194     switch(TREE_CODE (t))

8195     {

        

8693       default:

8694         return tsubst_copy(t, args, complain, in_decl);

8695     }

8696

8697   #undef RECUR

8698   }

 

For the outer template parameters, the first isTEMPLATE_TEMPALTE_PARM, the second and the third both are TEMPLATE_PARM_INDEX;and the parameter of the inner template is the TEMPLATE_TYPE_PARM. All thesenodes are processed by tsubst_copy.

 

7449   static tree

7450   tsubst_copy (treet, tree args, tsubst_flags_t complain, tree in_decl)                    in pt.c

7451   {

7452     enumtree_code code;

7453     tree r;

7454  

7455     if (t == NULL_TREE || t == error_mark_node)

7456       return t;

7457  

7458    code = TREE_CODE (t);

7469  

7460     switch (code)

7461     {

         

7767       caseRECORD_TYPE:

7768       caseUNION_TYPE:

7769       caseENUMERAL_TYPE:

7770       caseINTEGER_TYPE:

7771       caseTEMPLATE_TYPE_PARM:

7772       caseTEMPLATE_TEMPLATE_PARM:

7773       caseBOUND_TEMPLATE_TEMPLATE_PARM:

7774       caseTEMPLATE_PARM_INDEX:

7775       casePOINTER_TYPE:

7776       caseREFERENCE_TYPE:

7777       caseOFFSET_TYPE:

7778       caseFUNCTION_TYPE:

7779       case METHOD_TYPE:

7780       caseARRAY_TYPE:

7781       caseTYPENAME_TYPE:

7782       caseUNBOUND_CLASS_TEMPLATE:

7783       caseTYPEOF_TYPE:

7784       caseTYPE_DECL:

7785         returntsubst (t, args, complain, in_decl);

         

7816     }

7817   }

 

Again for all nodes, tsubst is invoked. And remember that t refersto the template parameters and args holds the template arguments.

 

6681   static tree

6682   tsubst (tree t,tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684    tree type, r;

6685

6686   if (t== NULL_TREE || t == error_mark_node

6687     || t == integer_type_node

6688     || t == void_type_node

6689     || t == char_type_node

6690      || t == unknown_type_node

6691     || TREE_CODE (t) == NAMESPACE_DECL)

6692      return t;

6693

6694     if(TREE_CODE (t) == IDENTIFIER_NODE)

6695      type = IDENTIFIER_TYPE_VALUE (t);

6696    else

6697      type = TREE_TYPE (t);

6698  

6699     my_friendly_assert (type !=unknown_type_node, 20030716);

6700  

6701     if (type && TREE_CODE (t) !=FUNCTION_DECL

6702       && TREE_CODE (t) != TYPENAME_TYPE

6703       && TREE_CODE (t) != TEMPLATE_DECL

6704       && TREE_CODE (t) != IDENTIFIER_NODE

6705       && TREE_CODE (t) != FUNCTION_TYPE

6706        && TREE_CODE (t) != METHOD_TYPE)

6707       type = tsubst (type, args, complain,in_decl);

6708     if (type == error_mark_node)

6709       returnerror_mark_node;

6710  

6711     if (DECL_P (t))

6712       returntsubst_decl (t, args, type, complain);

6713  

6714     switch(TREE_CODE (t))

6715     {

         

6776       caseTEMPLATE_TYPE_PARM:

6777       caseTEMPLATE_TEMPLATE_PARM:

6778       caseBOUND_TEMPLATE_TEMPLATE_PARM:

6779       caseTEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785         r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) ==TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6790        {

6791          idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795        {

6796          idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802           tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             returnerror_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

6812             if (TREE_CODE (t) ==TEMPLATE_TYPE_PARM)

6813             {

                 

6818             }

6819             else if (TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6820             {

                 

6843             }

6844             else

6845               /*TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */

6846               returnarg;

6847           }

6848         }

           

6907       }

         

7304     }

7305   }

 

Node of TEMPLATE_TEMPLATE_PRAM has null type field. And idx and level atline 6791 are set according to the associated TEMPLATE_PARM_INDEX node as 0 and1 respectively. At line 6806 arg points to the TEMPALTE_DECL of“SingleThreaded”. When returning this node back to tsubst_template_arg, uses_template_parmsat line 5713 returns zero for this node as it is not dependent one. And thisnode is returned further.

The secondparameter of the outer template is the node of TEMPLATE_PARM_INDEX in belowfigure. While argat line 6806 refers to the INTEGER_CST of 4096 in the rear figure; and it is returned at line6846 also.

(Clickhere for open)

Similar is the third parameter for the outer template, which isomitted in previous section, as it very resembles the second one. For the innertemplate, the parameter is the node of TEMPLATE_TYPE_PARM in below figure.

t2

The level recorded by the associatedTEMPLATE_PARM_INDEX in the figure is 2 while level indicated by args is1; following code will be executed in tsubst for this node.

 

6681   static tree

6682   tsubst (tree t,tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

       

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

6714     switch(TREE_CODE (t))

6715     {

         

6776       case TEMPLATE_TYPE_PARM:

6777       caseTEMPLATE_TEMPLATE_PARM:

6778       caseBOUND_TEMPLATE_TEMPLATE_PARM:

6779       caseTEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785         r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) ==TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6790        {

6791          idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795        {

6796          idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802           tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             returnerror_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

               

6847           }

6848         }

6849         else

6850           abort ();

6851  

6852         if (level == 1)

6853           /* This canhappen during the attempted tsubst'ing in

6854             unify. This means thatwe don't yet have any information

6855             about the templateparameter in question.  */

6856           returnt;

6857  

6858         /* If we gethere, we must have been looking at a parm for a

6859           more deeply nestedtemplate. Make a new version of this

6860           template parameter, but with a lowerlevel.  */

6861         switch(TREE_CODE (t))

6862         {

6863           caseTEMPLATE_TYPE_PARM:

6864           caseTEMPLATE_TEMPLATE_PARM:

6865           caseBOUND_TEMPLATE_TEMPLATE_PARM:

6866             if (cp_type_quals (t))

6867             {

                 

6873             }

6874             else

6875             {

6876               r = copy_type (t);

6877               TEMPLATE_TYPE_PARM_INDEX (r)

6878                 = reduce_template_parm_level(TEMPLATE_TYPE_PARM_INDEX (t),

6879                                           r,levels);

6880               TYPE_STUB_DECL (r)= TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);

6881               TYPE_MAIN_VARIANT (r) = r;

6882               TYPE_POINTER_TO (r) = NULL_TREE;

6883               TYPE_REFERENCE_TO (r) = NULL_TREE;

6884  

6885               if (TREE_CODE (t) ==BOUND_TEMPLATE_TEMPLATE_PARM)

6886               {

                   

6894               }

6895             }

6896             break;

6897  

6898           caseTEMPLATE_PARM_INDEX:

6899             r = reduce_template_parm_level (t,type, levels);

6900             break;

6901          

6902           default:

6903             abort ();

6904         }

6905  

6906         return r;

6907       }

         

7304     }

7305   }

 

Above at line 6878, TEMPLATE_TYPE_PARM_INDEX fetches the node in valuefield of the node of TEMPLATE_TYPE_PARM, which is the node ofTEMPLATE_PARM_INDEX.

 

2128   static tree

2129   reduce_template_parm_level (tree index,tree type, int levels)                              in pt.c

2130   {

2131     if (TEMPLATE_PARM_DESCENDANTS (index) ==NULL_TREE

2132        || (TEMPLATE_PARM_LEVEL(TEMPLATE_PARM_DESCENDANTS (index))

2133           != TEMPLATE_PARM_LEVEL (index) -levels))

2134     {

2135       tree orig_decl = TEMPLATE_PARM_DECL (index);

2136       tree decl, t;

2137        

2138       decl = build_decl(TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);

2139       TREE_CONSTANT (decl) = TREE_CONSTANT(orig_decl);

2140       TREE_READONLY (decl) = TREE_READONLY(orig_decl);

2141       DECL_ARTIFICIAL (decl) = 1;

2142       SET_DECL_TEMPLATE_PARM_P (decl);

2143        

2144       t = build_template_parm_index(TEMPLATE_PARM_IDX (index),

2145                                 TEMPLATE_PARM_LEVEL(index) - levels,

2146                                TEMPLATE_PARM_ORIG_LEVEL (index),

2147                                 decl, type);

2148      TEMPLATE_PARM_DESCENDANTS (index) = t;

2149  

2150       /* Templatetemplate parameters need this.  */

2151       DECL_TEMPLATE_PARMS (decl)

2152         = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL(index));

2153     }

2154  

2155     returnTEMPLATE_PARM_DESCENDANTS (index);

2156   }

 

A newTEMPLATE_PARM_INDEX is created with decreased level to indicate the instantiationof the inner template parameter. And this node is chained as the immediatedescendant of the orginial TEMPLATE_PARM_INDEX node.

t4

Then at line 6823 intsubst,argveccreated by the nested tsubst for parameters in the node ofBOUND_TEMPLATE_TEMPLATE_PARM is shown in below figure.

(Clickhere for open)

Continue in the tsubsthandling the node of BOUND_TEMPLATE_TEMPLATE_PARM; remember that argbelow refers to TEMPLATE_DECL of “SingleThreaded” in the below figure. As nowwe are instantiating the outer template, it is the precondition to instantiatethe inner template first. It is done implicitly by lookup_template_class below.

 

tsubst (continue)

 

6828               /* We canget a TEMPLATE_TEMPLATE_PARM here when

6829                 we are resolvingnested-types in the signature of

6830                 a memberfunction templates.

6831                 Otherwise ARG is aTEMPLATE_DECL and is the real

6832                 template to beinstantiated.  */

6833               if (TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM)

6834                 arg = TYPE_NAME (arg);

6835  

6836               r = lookup_template_class (arg,

6837                                     argvec,in_decl,

6838                                     DECL_CONTEXT(arg),

6839                                     /*entering_scope=*/0,

6840                                     complain);

6841               returncp_build_qualified_type_real

6842                        (r, TYPE_QUALS (t),complain);

6843             }

6844             else

6845               /*TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */

6846               returnarg;

6847           }

6848         }

6849         else

6850           abort ();

 

So atinvocation of lookup_template_class,argument dlis the TEMPLATE_DECL in red in below figure, and arglist is the argvec in tusbst above, and contextis the scope of “Loki”.

(Clickhere for open)

 

4133   tree

4134   lookup_template_class(tree d1,                                                                              in pt.c

4135                       tree arglist,

4136                       tree in_decl,

4137                       tree context,

4138                       int entering_scope,

4139                       tsubst_flags_t complain)

4140   {

4141     tree template = NULL_TREE, parmlist;

4142     tree t;

4143    

4144     timevar_push (TV_NAME_LOOKUP);

4145    

4146     if (TREE_CODE (d1) == IDENTIFIER_NODE)

4147     {

         

4162     }

4163     else if (TREE_CODE (d1) == TYPE_DECL&& IS_AGGR_TYPE (TREE_TYPE (d1)))

4164     {

         

4177     }

4178     else if (TREE_CODE (d1) == ENUMERAL_TYPE

4179           || (TYPE_P (d1) && IS_AGGR_TYPE(d1)))

4180     {

         

4183     }

4184     else if (TREE_CODE (d1) == TEMPLATE_DECL

4185           && TREE_CODE(DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)

4186     {

4187       template = d1;

4188       d1 = DECL_NAME (template);

4189       context = DECL_CONTEXT (template);

4190     }

       

4219     complain &= ~tf_user;

4220    

4221     if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))

4222     {

         

4259     }

4260     else

4261     {

4262       tree template_type = TREE_TYPE (template);

4263       tree gen_tmpl;

4264       tree type_decl;

4265       tree found = NULL_TREE;

4266       tree *tp;

4267       int arg_depth;

4268       int parm_depth;

4269       int is_partial_instantiation;

4270  

4271       gen_tmpl = most_general_template(template);

4272       parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);

4273       parm_depth = TMPL_PARMS_DEPTH (parmlist);

4274       arg_depth = TMPL_ARGS_DEPTH (arglist);

4275  

4276       if (arg_depth == 1 && parm_depth> 1)

4277     {

           

4294       }

4295

4296       /* Now we shouldhave enough arguments.  */

4297       my_friendly_assert (parm_depth == arg_depth,0);

4298     

4299       /* From here on,we're only interested in the most general

4300         template. */

4301       template = gen_tmpl;

4302  

4303       /* Calculate theBOUND_ARGS. These will be the args that are

4304         actually tsubst'd into thedefinition to create the

4305         instantiation.  */

4306       if (parm_depth > 1)

4307       {

           

4344       }

4345       else

4346         arglist

4347             = coerce_template_parms(INNERMOST_TEMPLATE_PARMS (parmlist),

4348                                   INNERMOST_TEMPLATE_ARGS(arglist),

4349                                   template,

4350                                   complain, /*require_all_args=*/1);

4351  

4352       if (arglist == error_mark_node)

4353         /* We wereunable to bind the arguments.  */

4354         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);

 

Above parmlistis the tree_list pointed by arguments field of the TEMPLATE_DECL of“SingleThreaded”. So argument parms below is the tree_vec referred by valuefield of this tree_list; it is the parameters in the declaration.INNERMOST_TEMPLATE_ARGS following accesses the second element of the argvecabove – the argument for inner template.

 

3805   static tree

3806   coerce_template_parms(tree parms,                                                                       in pt.c

3807                      tree args,

3808                       tree in_decl,

3809                       tsubst_flags_t complain,

3810                       int require_all_arguments)

3811   {

3812     int nparms, nargs, i, lost = 0;

3813     tree inner_args;

3814     tree new_args;

3815     tree new_inner_args;

3816  

3817     inner_args = INNERMOST_TEMPLATE_ARGS (args);

3818     nargs = inner_args ? NUM_TMPL_ARGS(inner_args) : 0;

3819     nparms = TREE_VEC_LENGTH (parms);

       

3838     new_inner_args = make_tree_vec (nparms);

3839     new_args = add_outermost_template_args (args,new_inner_args);

3840     for (i = 0; i < nparms; i++)

3841     {

3842       tree arg;

3843       tree parm;

3844  

3845       /* Get the Ithtemplate parameter.  */

3846       parm = TREE_VEC_ELT (parms, i);

3847  

3848       /* Calculate theIth argument.  */

3849       if (i < nargs)

3850        arg = TREE_VEC_ELT (inner_args, i);

3851       else if (require_all_arguments)

3852         /* There must be a default arg in thiscase.  */

3853         arg = tsubst_template_arg (TREE_PURPOSE(parm), new_args,

3854                               complain, in_decl);

3855       else

3856         break;

3857        

3858       my_friendly_assert (arg, 20030727);

3859       if (arg == error_mark_node)

3860         error ("template argument %d isinvalid", i + 1);

3861       else

3862         arg = convert_template_argument(TREE_VALUE (parm),

3863                                     arg,new_args, complain, i,

3864                                     in_decl);

3865        

3866       if (arg == error_mark_node)

3867         lost++;

3868       TREE_VEC_ELT (new_inner_args, i) = arg;

3869     }

3870  

3871     if (lost)

3872       returnerror_mark_node;

3873  

3874     returnnew_inner_args;

3875   }

 

As both parms and args are tree_vec of size 1, add_outermost_template_argsat line 3839 does nothing. Further at line 3850, arg points to the new createdTEMPLATE_TYPE_PARM node.

 

3636   static tree

3637   convert_template_argument(tree parm,                                                            in pt.c

3638                           tree arg,

3639                           tree args,

3640                           tsubst_flags_tcomplain,

3641                           int i,

3642                           tree in_decl)

3643   {

3644     tree val;

3645     tree inner_args;

3646     int is_type, requires_type, is_tmpl_type,requires_tmpl_type;

3647    

3648     inner_args = INNERMOST_TEMPLATE_ARGS (args);

       

3662     requires_tmpl_type = TREE_CODE (parm) ==TEMPLATE_DECL;

3663     requires_type = (TREE_CODE (parm) ==TYPE_DECL

3664                   || requires_tmpl_type);

3665  

3666     is_tmpl_type = ((TREE_CODE (arg) ==TEMPLATE_DECL

3667                    &&TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)

3668                  || TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM

3669                  || TREE_CODE (arg) ==UNBOUND_CLASS_TEMPLATE);

3670    

3671     if (is_tmpl_type

3672        && (TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM

3673             || TREE_CODE (arg) ==UNBOUND_CLASS_TEMPLATE))

3674       arg= TYPE_STUB_DECL (arg);

3675  

3676     is_type = TYPE_P (arg) || is_tmpl_type;

       

3722     if (is_type)

3723     {

3724       if (requires_tmpl_type)

3725      {

           

3759      }

3760      else

3761        val = groktypename (arg);

3762     }

3763    else

3764     {

         

3790     }

3791  

3792     return val;

3793   }

 

Node of TEMPLATE_TYPE_PARM is regarded as type, so is_typeat line 3676 is true as TYPE_P returns true for arg. Following at line 3761, as arg isnot a tree_list, groktypename just returns argback. Note that argis placed into arglistat line 4347 in lookup_template_class.

 

lookup_template_class (continue)

 

4356       /* In the scopeof a template class, explicit references to the

4357         template class refer to thetype of the template, not any

4358         instantiation of it. Forexample, in:

4359       

4360         template <class T> class C { voidf(C<T>); }

4361  

4362         the `C<T>' is just thesame as `C'. Outside of the

4363         class, however, such areference is an instantiation.  */

4364       if (comp_template_args(TYPE_TI_ARGS (template_type),

4365                            arglist))

4366       {

4367         found = template_type;

4368         

4369         if (!entering_scope &&PRIMARY_TEMPLATE_P (template))

4370         {

4371           tree ctx;

4372             

4373           for(ctx = current_class_type;

4374               ctx && TREE_CODE (ctx) !=NAMESPACE_DECL;

4375               ctx = (TYPE_P (ctx)

4376                     ? TYPE_CONTEXT (ctx)

4377                     : DECL_CONTEXT (ctx)))

4378             if (TYPE_P (ctx) && same_type_p(ctx, template_type))

4379               gotofound_ctx;

4380             

4381           /* We're notin the scope of the class, so the

4382             TEMPLATE_TYPE is not thetype we want after all.  */

4383           found = NULL_TREE;

4384       found_ctx:;

4385         }

4386       }

4387       if (found)

4388         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,found);

        

4431       context = tsubst (DECL_CONTEXT (template),arglist,

4432                     complain, in_decl);

4433       if (!context)

4434         context = global_namespace;

4435  

4436       /* Create thetype.  */

4437       if (TREE_CODE (template_type) ==ENUMERAL_TYPE)

4438       {

           

4450       }

4451       else

4452       {

4453         t = make_aggr_type(TREE_CODE (template_type));

4454         CLASSTYPE_DECLARED_CLASS (t)

4455              = CLASSTYPE_DECLARED_CLASS(template_type);

4456         SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);

4457         TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA(template_type);

4458  

4459         /* A localclass. Make sure the decl gets registered properly.  */

4460         if (context == current_function_decl)

4461           pushtag (DECL_NAME (template), t, 0);

4462       }

4463  

4464       /* If we calledstart_enum or pushtag above, this information

4465         will already be set up.  */

4466       if (!TYPE_NAME (t))

4467       {

4468         TYPE_CONTEXT (t) = FROB_CONTEXT(context);

4469         

4470         type_decl = create_implicit_typedef (DECL_NAME(template), t);

4471         DECL_CONTEXT (type_decl) = TYPE_CONTEXT(t);

4472        TYPE_STUB_DECL (t) = type_decl;

4473         DECL_SOURCE_LOCATION (type_decl)

4474            = DECL_SOURCE_LOCATION (TYPE_STUB_DECL(template_type));

4475       }

4476       else

4477         type_decl = TYPE_NAME (t);

4478  

4479       TREE_PRIVATE (type_decl)

4480          = TREE_PRIVATE (TYPE_STUB_DECL(template_type));

4481       TREE_PROTECTED (type_decl)

4482          = TREE_PROTECTED (TYPE_STUB_DECL(template_type));

4483  

4484       /* Set up thetemplate information. We have to figure out which

4485         template is the immediateparent if this is a full

4486         instantiation.  */

4487       if (parm_depth == 1 ||is_partial_instantiation

4488          || !PRIMARY_TEMPLATE_P (template))

4489         /* This case iseasy; there are no member templates involved. */

4490         found = template;

4491       else

4492       {

           

4544       }

4545  

4546       SET_TYPE_TEMPLATE_INFO (t, tree_cons(found, arglist, NULL_TREE)); 

4547       DECL_TEMPLATE_INSTANTIATIONS (template)

4548          = tree_cons (arglist, t,

4549                     DECL_TEMPLATE_INSTANTIATIONS(template));

4550  

4551       if (TREE_CODE (t) == ENUMERAL_TYPE

4552          && !is_partial_instantiation)

4553         /* Now that thetype has been registered on the instantiations

4554           list, we set up theenumerators. Because the enumeration

4555           constants may involve theenumeration type itself, we make

4556           sure to register the typefirst, and then create the

4557           constants. That way, doingtsubst_expr for the enumeration

4558           constants won't result inrecursive calls here; we'll find

4559          the instantiation and exitabove.  */

4560         tsubst_enum (template_type, t, arglist);

4561  

4562       /* Reset the nameof the type, now that CLASSTYPE_TEMPLATE_INFO

4563         is set up.  */

4564       if (TREE_CODE (t) != ENUMERAL_TYPE)

4565         DECL_NAME (type_decl) =classtype_mangled_name (t);

4566       if (is_partial_instantiation)

4567         /* If the typemakes use of template parameters, the

4568           code that generatesdebugging information will crash.  */

4569         DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;

4570  

4571       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);

4572     }

4573     timevar_pop (TV_NAME_LOOKUP);

4574   }

 

Notice that template_type is the node of RECORD_TYPE of“SingleThreaded”, though comp_template_args at line 4364 finds thatits argument is the same as arglist, we are not within class context (current_class_typeis NULL), we have to abondon this found RECORD_TYPE.

Next contextis NAMESPACE_DECL of “Loki”, tsubst at line 4431 does nothing but returnsthis node. The code following is to create the RECORD_TYPE and associated nodesfor the base class instantiation. So following nodes are created. At last thenode of RECORD_TYPE is returned in instantiate_class_template at line 5439.

(Clickhere for open)

 

原创粉丝点击