Studying note of GCC-3.4.6 source (134)

5.12.5.2.2.2.1.3.1.            Instantiate base class – substituting argument for parameter

The base class may depends on template parameter as our example here. So to instantiate the derived class, it first needs instantiate its base classes appropriately. Here we 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”.

(Click here for open )

figure 115 : intermediate tree for “SmallObject”

In instantiate_class_template , at line 5320, pattern is the node of RECORD_TYPE at top in the figure; and pinfo at line 5400 is that pointed by binfo field of pattern . Then at line 5425, namespace “Loki” is made as the current binding context. So at line 5439, the first argument for tsubst is the node of BOUND_TEMPLATE_TEMPLATE_PARM, and the second argument args is the tree_vec in red in below figure.

(Click here 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       return error_mark_node;

6710  

6711     if (DECL_P (t))

6712       return tsubst_decl (t, args, type, complain);

6713  

6714     switch (TREE_CODE (t))

6715     {

         

6776       case TEMPLATE_TYPE_PARM:

6777       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_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             return error_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               return cp_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 are processing a type constructed from

6822                 a template template parameter.  */

6823               tree argvec = tsubst (TYPE_TI_ARGS (t),

6824                                 args, complain, in_decl);

6825               if (argvec == error_mark_node)

6826                 return error_mark_node;

 

As t refers to the node of BOUND_TEMPLATE_TEMPALTE_PARM, at line 6791 idx is 0, and level is 1; arg at line 6806 then points to the node of TEMPLATE_DECL of “SingleThreaded”. Also notice 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 first figure 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      case TREE_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 args represents the arguments at instantiation. As semantic check should be taken at point of instantiation for template, tsubst_template_args verifies if the arguments are compatible with the parameters. Now t points to node in red as below 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         return error_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 for outer template. This tree_vec (the first element) and the second element as the parameter of the inner template both are processed by tsubst_template_arg . In the function, for all candidates, TYPE_P returns zero as they are not node of types. 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 (tree t, 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       return tsubst_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_build is always invoked.

 

8179   tree

8180   tsubst_copy_and_build (tree t,                                                                         in pt.c

8181                     tree args,

8182                     tsubst_flags_t complain,

8183                     tree in_decl,

8184                     bool function_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      return t;

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 is TEMPLATE_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 these nodes are processed by tsubst_copy .

 

7449   static tree

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

7451   {

7452     enum tree_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       case RECORD_TYPE:

7768       case UNION_TYPE:

7769       case ENUMERAL_TYPE:

7770       case INTEGER_TYPE:

7771       case TEMPLATE_TYPE_PARM:

7772       case TEMPLATE_TEMPLATE_PARM:

7773       case BOUND_TEMPLATE_TEMPLATE_PARM:

7774       case TEMPLATE_PARM_INDEX:

7775       case POINTER_TYPE:

7776       case REFERENCE_TYPE:

7777       case OFFSET_TYPE:

7778       case FUNCTION_TYPE:

7779       case METHOD_TYPE:

7780       case ARRAY_TYPE:

7781       case TYPENAME_TYPE:

7782       case UNBOUND_CLASS_TEMPLATE:

7783       case TYPEOF_TYPE:

7784       case TYPE_DECL:

7785         return tsubst (t, args, complain, in_decl);

         

7816     }

7817   }

 

Again for all nodes, tsubst is invoked. And remember that t refers to 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       return error_mark_node;

6710  

6711     if (DECL_P (t))

6712       return tsubst_decl (t, args, type, complain);

6713  

6714     switch (TREE_CODE (t))

6715     {

         

6776       case TEMPLATE_TYPE_PARM:

6777       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_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             return error_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               return arg;

6847           }

6848         }

           

6907       }

         

7304     }

7305   }

 

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

The second parameter of the outer template is the node of TEMPLATE_PARM_INDEX in below figure. While arg at line 6806 refers to the INTEGER_CST of 4096 in the rear figure; and it is returned at line 6846 also.

(Click here for open )

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

Studying note of GCC-3.4.6 source (134)_第1张图片

The level recorded by the associated TEMPLATE_PARM_INDEX in the figure is 2 while level indicated by args is 1; 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       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_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             return error_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

               

6847           }

6848         }

6849         else

6850           abort ();

6851  

6852         if (level == 1)

6853           /* This can happen during the attempted tsubst'ing in

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

6855             about the template parameter in question.  */

6856           return t;

6857  

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

6859           more deeply nested template. Make a new version of this

6860            template parameter, but with a lower level.  */

6861         switch (TREE_CODE (t))

6862         {

6863           case TEMPLATE_TYPE_PARM:

6864           case TEMPLATE_TEMPLATE_PARM:

6865           case BOUND_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           case TEMPLATE_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 value field of the node of TEMPLATE_TYPE_PARM, which is the node of TEMPLATE_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       /* Template template parameters need this.  */

2151       DECL_TEMPLATE_PARMS (decl)

2152         = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));

2153     }

2154  

2155     return TEMPLATE_PARM_DESCENDANTS (index);

2156   }

 

A new TEMPLATE_PARM_INDEX is created with decreased level to indicate the instantiation of the inner template parameter. And this node is chained as the immediate descendant of the orginial TEMPLATE_PARM_INDEX node.

Then at line 6823 in tsubst , argvec created by the nested tsubst for parameters in the node of BOUND_TEMPLATE_TEMPLATE_PARM is shown in below figure.

(Click here for open )

Continue in the tsubst handling the node of BOUND_TEMPLATE_TEMPLATE_PARM; remember that arg below refers to TEMPLATE_DECL of “SingleThreaded” in the below figure. As now we are instantiating the outer template, it is the precondition to instantiate the inner template first. It is done implicitly by lookup_template_class below.

 

tsubst (continue)

 

6828               /* We can get a TEMPLATE_TEMPLATE_PARM here when

6829                 we are resolving nested-types in the signature of

6830                 a member function templates.

6831                 Otherwise ARG is a TEMPLATE_DECL and is the real

6832                 template to be instantiated.  */

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               return cp_build_qualified_type_real

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

6843             }

6844             else

6845               /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.  */

6846               return arg;

6847           }

6848         }

6849         else

6850           abort ();

 

So at invocation of lookup_template_class , argument dl is the TEMPLATE_DECL in red in below figure, and arglist is the argvec in tusbst above, and context is the scope of “Loki”.

(Click here 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 should have 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 the BOUND_ARGS. These will be the args that are

4304         actually tsubst'd into the definition 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 were unable to bind the arguments.  */

4354         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

 

Above parmlist is the tree_list pointed by arguments field of the TEMPLATE_DECL of “SingleThreaded”. So argument parms below is the tree_vec referred by value field of this tree_list; it is the parameters in the declaration. INNERMOST_TEMPLATE_ARGS following accesses the second element of the argvec above – 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 Ith template parameter.  */

3846       parm = TREE_VEC_ELT (parms, i);

3847  

3848       /* Calculate the Ith 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 this case.  */

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 is invalid", i + 1);

3861       else

3862         arg = convert_template_argument (TREE_VALUE (parm),

3863                                     arg, new_args, complain, i,

3864                                     i n_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       return error_mark_node;

3873  

3874     return new_inner_args;

3875   }

 

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

 

3636   static tree

3637   convert_template_argument (tree parm,                                                            in pt.c

3638                           tree arg,

3639                           tree args,

3640                           tsubst_flags_t complain,

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_type at line 3676 is true as TYPE_P returns true for arg . Following at line 3761, as arg is not a tree_list, groktypename just returns arg back. Note that arg is placed into arglist at line 4347 in lookup_template_class .

 

lookup_template_class (continue)

 

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

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

4358         instantiation of it. For example, in:

4359       

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

4361  

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

4363         class, however, such a reference 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               goto found_ctx;

4380             

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

4382             TEMPLATE_TYPE is not the type 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 the type.  */

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 local class. 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 called start_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 the template information. We have to figure out which

4485         template is the immediate parent if this is a full

4486         instantiation.  */

4487       if (parm_depth == 1 || is_partial_instantiation

4488          || !PRIMARY_TEMPLATE_P (template))

4489         /* This case is easy; 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 the type has been registered on the instantiations

4554           list, we set up the enumerators. Because the enumeration

4555           constants may involve the enumeration type itself, we make

4556           sure to register the type first, and then create the

4557           constants. That way, doing tsubst_expr for the enumeration

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

4559          the instantiation and exit above.  */

4560         tsubst_enum (template_type, t, arglist);

4561  

4562       /* Reset the name of 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 type makes use of template parameters, the

4568           code that generates debugging 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 that its argument is the same as arglist , we are not within class context (current_class_type is NULL), we have to abondon this found RECORD_TYPE.

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

(Click here for open )

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (134))