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.
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.
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 )