概述
5.12.4.2.3. Process base class
5.12.4.2.3.1. Parse base-clause
Tokens after “SmallObject” are “: public ThreadingModel<SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >”, which indicates the base class “SmallObject” derives from. Review the rule of class-head again in below.
class-head:
class-key identifier [opt] base-clause [opt]
class-key nested-name-specifier identifier base-clause [opt]
class-key nested-name-specifier [opt] template-id base-clause [opt]
If nested-name-specifier is found, below variable nested_name_specifier will point to the tree object of it. And no doubt, it constructs a context that the base class should be visible within. Then at line 12330 below, if nested_name_specifier is not null, it should be make as current binding scope by push_scope .
cp_parser_class_head (continue)
12317 /* Indicate whether this class was declared as a `class' or as a
12318 `struct'. */
12319 if (TREE_CODE (type) == RECORD_TYPE)
12320 CLASSTYPE_DECLARED_CLASS (type) = (class_key == class_type);
12321 cp_parser_check_class_key (class_key, type);
12322
12323 /* Enter the scope containing the class; the names of base classes
12324 should be looked up in that context. For example, given:
12325
12326 struct A { struct B {}; struct C; };
12327 struct A::C : B {};
12328
12329 is valid. */
12330 if (nested_name_specifier)
12331 pop_p = push_scope (nested_name_specifier);
12332 /* Now, look for the base-clause. */
12333 token = cp_lexer_peek_token (parser->lexer);
12334 if (token->type == CPP_COLON)
12335 {
12336 tree bases;
12337
12338 /* Get the list of base-classes. */
12339 bases = cp_parser_base_clause (parser);
12340 /* Process them. */
12341 xref_basetypes (type, bases);
12342 }
12343 /* Leave the scope given by the nested-name-specifier. We will
12344 enter the class scope itself while processing the members. */
12345 if (pop_p)
12346 pop_scope (nested_name_specifier);
12347
12348 done:
12349 if (invalid_explicit_specialization_p)
12350 {
12351 end_specialization ();
12352 --parser->num_template_parameter_lists;
12353 }
12354 *attributes_p = attributes;
12355 return type;
12356 }
In fact, the part leading by “:” is called base-clause according to the grammar, it obeys following rules:
base-clause:
: base-specifier-list
base-specifier-list:
base-specifier
base-specifier-list , base-specifier
Obviously, if base-specifier-list contains more than one base-specifier, it corresponds to multiple-derivation. And these bases will be chained after variable bases in below function.
12900 static tree
12901 cp_parser_base_clause (cp_parser* parser) in parser.c
12902 {
12903 tree bases = NULL_TREE;
12904
12905 /* Look for the `:' that begins the list. */
12906 cp_parser_require (parser, CPP_COLON, "`:'");
12907
12908 /* Scan the base-specifier-list. */
12909 while (true)
12910 {
12911 cp_token *token;
12912 tree base;
12913
12914 /* Look for the base-specifier. */
12915 base = cp_parser_base_specifier (parser);
12916 /* Add BASE to the front of the list. */
12917 if (base != error_mark_node)
12918 {
12919 TREE_CHAIN (base) = bases;
12920 bases = base;
12921 }
12922 /* Peek at the next token. */
12923 token = cp_lexer_peek_token (parser->lexer);
12924 /* If it's not a comma, then the list is complete. */
12925 if (token->type != CPP_COMMA)
12926 break ;
12927 /* Consume the `,'. */
12928 cp_lexer_consume_token (parser->lexer);
12929 }
12930
12931 /* PARSER->SCOPE may still be non-NULL at this point, if the last
12932 base class had a qualified name. However, the next name that
12933 appears is certainly not qualified. */
12934 parser->scope = NULL_TREE;
12935 parser->qualifying_scope = NULL_TREE;
12936 parser->object_scope = NULL_TREE;
12937
12938 return nreverse (bases);
12939 }
The part base-specifier describes from which to derive and by how. So its rules are obvious.
base-specifier:
:: [opt] nested-name-specifier [opt] class-name
virtual access-specifier [opt] :: [opt] nested-name-specifier [opt] class-name
access-specifier virtual [opt] :: [opt] nested-name-specifier [opt] class-name
12955 static tree
12956 cp_parser_base_specifier (cp_parser* parser) in parser.c
12957 {
12958 cp_token *token;
12959 bool done = false;
12960 bool virtual_p = false;
12961 bool duplicate_virtual_error_issued_p = false;
12962 bool duplicate_access_error_issued_p = false;
12963 bool class_scope_p, template_p;
12964 tree access = access_default_node;
12965 tree type;
12966
12967 /* Process the optional `virtual' and `access-specifier'. */
12968 while (!done)
12969 {
12970 /* Peek at the next token. */
12971 token = cp_lexer_peek_token (parser->lexer);
12972 /* Process `virtual'. */
12973 switch (token->keyword)
12974 {
12975 case RID_VIRTUAL:
12976 /* If `virtual' appears more than once, issue an error. */
12977 if (virtual_p && !duplicate_virtual_error_issued_p)
12978 {
12979 cp_parser_error (parser,
12980 "`virtual' specified more than once in base-specified");
12981 duplicate_virtual_error_issued_p = true;
12982 }
12983
12984 virtual_p = true;
12985
12986 /* Consume the `virtual' token. */
12987 cp_lexer_consume_token (parser->lexer);
12988
12989 break ;
12990
12991 case RID_PUBLIC:
12992 case RID_PROTECTED:
12993 case RID_PRIVATE:
12994 /* If more than one access specifier appears, issue an
12995 error. */
12996 if (access != access_default_node
12997 && !duplicate_access_error_issued_p)
12998 {
12999 cp_parser_error (parser,
13000 "more than one access specifier in base-specified");
13001 duplicate_access_error_issued_p = true;
13002 }
13003
13004 access = ridpointers [(int) token->keyword];
13005
13006 /* Consume the access-specifier. */
13007 cp_lexer_consume_token (parser->lexer);
13008
13009 break ;
13010
13011 default :
13012 done = true;
13013 break ;
13014 }
13015 }
13016 /* It is not uncommon to see programs mechanically, errouneously, use
13017 the 'typename' keyword to denote (dependent) qualified types
13018 as base classes. */
13019 if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
13020 {
13021 if (!processing_template_decl)
13022 error ("keyword `typename' not allowed outside of templates");
13023 else
13024 error ("keyword `typename' not allowed in this context "
13025 "(the base class is implicitly a type)");
13026 cp_lexer_consume_token (parser->lexer);
13027 }
13028
13029 /* Look for the optional `::' operator. */
13030 cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/ false);
13031 /* Look for the nested-name-specifier. The simplest way to
13032 implement:
13033
13034 [temp.res]
13035
13036 The keyword `typename' is not permitted in a base-specifier or
13037 mem-initializer; in these contexts a qualified name that
13038 depends on a template-parameter is implicitly assumed to be a
13039 type name.
13040
13041 is to pretend that we have seen the `typename' keyword at this
13042 point. */
13043 cp_parser_nested_name_specifier_opt (parser,
13044 /*typename_keyword_p=*/ true,
13045 /*check_dependency_p=*/ true,
13046 /*type_p=*/ true,
13047 /*is_declaration=*/ true);
13048 /* If the base class is given by a qualified name, assume that names
13049 we see are type names or templates, as appropriate. */
13050 class_scope_p = (parser->scope && TYPE_P (parser->scope));
13051 template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
13052
13053 /* Finally, look for the class-name. */
13054 type = cp_parser_class_name (parser,
13055 class_scope_p,
13056 template_p,
13057 /*type_p=*/ true,
13058 /*check_dependency_p=*/ true,
13059 /*class_head_p=*/ false,
13060 /*is_declaration=*/ true);
13061
13062 if (type == error_mark_node)
13063 return error_mark_node;
13064
13065 return finish_base_specifier (TREE_TYPE (type), access, virtual_p);
13066 }
Above, cp_parser_nested_name_specifier_opt will set scope field of parser with present nested-name-specifier if any, which in turn will affect the rearching result of class-name look-up. At line 13051, cp_parser_optional_template_keyword checks if keyword “template” is present, if present and the nested-name-specifier indicates a class-scope, it is an explicit hint of name of template. For our case, template_p is false. The detail of class-name look-up is given before.
In brief decription, class “ThreadingModel” has been declared, in cp_parser_template_name at line 8212, cp_parser_lookup_name returns the corresponding TEMPLATE_DECL. The template argument “SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize>” is a template-id again. Thus this time goes through cp_parser_enclosed_template_argument_list , cp_parser_template_argument_list , cp_parser_template_argument , cp_parser_id_expression , cp_parser_unqualified_id , cp_parser_template_id , again in cp_parser_template_name at the same line 8212, TEMPLATE_DECL of “SmallObject” is found (as the class tag has been handled), then next in cp_parser_template_id at line 7899, cp_parser_enclosed_template_argument_list is recursed.
5.12.4.2.3.1.1. The inner template-id
And this time “ThreadingModel” is a type-id parsed by call-stack: cp_parser_type_id , cp_parser_type_specifier_seq , cp_parser_type_specifier , cp_parser_simple_type_specifier , cp_parser_type_name , in cp_parser_class_name at line 11795, again cp_parser_lookup_name returns the TEMPLATE_DECL associated, and in cp_parser_maybe_treat_template_as_class at line 11812, corresponding TYPE_DECL is retrieved from result field of the TEMPLATE_DECL. Then at line 10947 in cp_parser_type_id , groktypename returns the corresponding node of TEMPLATE_TEMPLATE_PARM from type field of the TYPE_DECL.
Next both “chunkSize” and “maxSmallObjectSize” are id-expression degraded from assignment-expression. Both IDENTIFIER_NODEs are returned. Then at line 7994 in cp_parser_template_id , as template is TEMPLATE_DECL, the template-id needs be created by finish_template_type as below.
cp_parser_template_id
7991 /* Build a representation of the specialization. */
7992 if (TREE_CODE (template) == IDENTIFIER_NODE)
7993 template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
7994 else if (DECL_CLASS_TEMPLATE_P (template)
7995 || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
7996 template_id
7997 = finish_template_type (template, arguments,
7998 cp_lexer_next_token_is (parser->lexer,
7999 CPP_SCOPE));
Here arguments is the list of template-argument in form of tree_vec as below.
2222 tree
2223 finish_template_type (tree name, tree args, int entering_scope) in semantics.c
2224 {
2225 tree decl;
2226
2227 decl = lookup_template_class (name, args,
2228 NULL_TREE, NULL_TREE, entering_scope,
2229 tf_error | tf_warning | tf_user);
2230 if (decl != error_mark_node)
2231 decl = TYPE_STUB_DECL (decl);
2232
2233 return decl;
2234 }
Also argument name refers to the TEMPLATE_DECL of “SmallObject” shown in below. We expect to see this tree after class “SmallObject” has its class tag processed, and notice that the last parameter “std::size_t maxSmallObjectSize” is left out to make the figure not to be too large, as we can see parameter almost the same “std::size_t chunkSize”.
(Click here for open )
Figure 110 : SmallObject after class tag handled
And for this time invocation, arguments in_decl , context are NULL, and entering_scope is 0.
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 {
4148 if (IDENTIFIER_VALUE (d1)
4149 && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
4150 template = IDENTIFIER_VALUE (d1);
4151 else
4152 {
4153 if (context)
4154 push_decl_namespace (context);
4155 template = lookup_name (d1, /*prefer_type=*/ 0);
4156 template = maybe_get_template_decl_from_type_decl (template);
4157 if (context)
4158 pop_decl_namespace ();
4159 }
4160 if (template)
4161 context = DECL_CONTEXT (template);
4162 }
4163 else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
4164 {
4165 tree type = TREE_TYPE (d1);
4166
4167 /* If we are declaring a constructor, say A<T>::A<T>, we will get
4168 an implicit typename for the second A. Deal with it. */
4169 if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
4170 type = TREE_TYPE (type);
4171
4172 if (CLASSTYPE_TEMPLATE_INFO (type))
4173 {
4174 template = CLASSTYPE_TI_TEMPLATE (type);
4175 d1 = DECL_NAME (template);
4176 }
4177 }
4178 else if (TREE_CODE (d1) == ENUMERAL_TYPE
4179 || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
4180 {
4181 template = TYPE_TI_TEMPLATE (d1);
4182 d1 = DECL_NAME (template);
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 }
4191
4192 /* With something like `template <class T> class X class X { ... };'
4193 we could end up with D1 having nothing but an IDENTIFIER_VALUE.
4194 We don't want to do that, but we have to deal with the situation,
4195 so let's give them some syntax errors to chew on instead of a
4196 crash. Alternatively D1 might not be a template type at all. */
4197 if (! template)
4198 {
4199 if (complain & tf_error)
4200 error ("`%T' is not a template", d1);
4201 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
4202 }
4203
4204 if (TREE_CODE (template) != TEMPLATE_DECL
4205 /* Make sure it's a user visible template, if it was named by
4206 the user. */
4207 || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
4208 && !PRIMARY_TEMPLATE_P (template)))
4209 {
4210 if (complain & tf_error)
4211 {
4212 error ("non-template type `%T' used as a template", d1);
4213 if (in_decl)
4214 cp_error_at ("for template declaration `%D'", in_decl);
4215 }
4216 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
4217 }
4218
4219 complain &= ~tf_user;
Above template is updated at line 4187 as the TEMPLATE_DECL of “SmallObject” and dl is updated to corresponding IDENTIFIER_NODE, and context is NULL. And also template_type below is set to the node of TEMPLATE_TEMPLATE_PARM; then most_general_template at line 4271 returns the most-general declaration for the template (for our case, the template is the most general form). Traversing the arguments of the template in above figure, it gets parm_depth of 1, and arg_depth of 1 (arglist is the arguments shown in figure above).
Indicated their names, arg_depth corresponds to the depth of arguments of the template-id, while parm_depth is the depth of parameters of the template declaration. Case for both values unmatched is shown by the example:
template <class T> struct S1 {
template <class U> struct S2 {};
};
In the definition of S2, the argument-list is “U”, but the full definition (if defining outside S1) is: template <class T> template <U> struct S1<T>::S2
It is what the parser expects! It must fill in the missing argument “T”. However, we are not in this trouble, we can skip it and go ahead.
lookup_template_class (continue)
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 {
4278 /* We've been given an incomplete set of template arguments.
4279 For example, given:
4280
4281 template <class T> struct S1 {
4282 template <class U> struct S2 {};
4283 template <class U> struct S2<U*> {};
4284 };
4285
4286 we will be called with an ARGLIST of `U*', but the
4287 TEMPLATE will be `template <class T> template
4288 <class U> struct S1<T>::S2'. We must fill in the missing
4289 arguments. */
4290 arglist
4291 = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
4292 arglist);
4293 arg_depth = TMPL_ARGS_DEPTH (arglist);
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);
After adding the extra arguments appropriately, arg_depth should equate to parm_depth , and case of parm_depth larger than 1 means handling member class template. It is not our fate here. At line 4347, INNERMOST_TEMPLATE_PARMS just returns the TREE_VEC node in above figure SmallObject after processing class tag , and INNERMOST_TEMPLATE_ARGS returns the arglist in whole.
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);
3820
3821 if (nargs > nparms
3822 || (nargs < nparms
3823 && require_all_arguments
3824 && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
3825 {
3826 if (complain & tf_error)
3827 {
3828 error ("wrong number of template arguments (%d, should be %d)",
3829 nargs, nparms);
3830
3831 if (in_decl)
3832 cp_error_at ("provided for `%D'", in_decl);
3833 }
3834
3835 return error_mark_node;
3836 }
Above at line 3818, NUM_TMPL_ARGS returns the TREE_VEC_LENGTH of the vector. See that at this step, the length of arguments must be no larger than the length of parameters. For our declaration, the length of arguments is 3 and is the same as the length of parameters. Now nparms holds this length.
coerce_template_parms (continue)
3838 new_inner_args = make_tree_vec (nparms);
3839 new_args = add_outermost_template_args (args, new_inner_args);
The case of number parameters larger than number of arguments, involves using default arguments. These default arguments must be added in by add_outermost_template_args .
538 static tree
539 add_outermost_template_args (tree args, tree extra_args) in pt.c
540 {
541 tree new_args;
542
543 /* If there are more levels of EXTRA_ARGS than there are ARGS,
544 something very fishy is going on. */
545 my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
546 0);
547
548 /* If *all* the new arguments will be the EXTRA_ARGS, just return
549 them. */
550 if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
551 return extra_args;
552
553 /* For the moment, we make ARGS look like it contains fewer levels. */
554 TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
555
556 new_args = add_to_template_args (args, extra_args);
557
558 /* Now, we restore ARGS to its full dimensions. */
559 TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);
560
561 return new_args;
562 }
For cases no using default arguments add_outermost_template_args does nothing but returns new_inner_args to new_args . Now parms is the TREE_VEC node in above figure SmallObject after processing class tag ; so for first element, parm points to below node.
coerce_template_parms (continue)
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 }
In this invocation, argument parm is the TEMPLATE_DECL of “ThreadingModel”, arg also refers to this node. Above as nargs equates naprms , arg is fetched from inner_args .
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);
3649
3650 if (TREE_CODE (arg) == TREE_LIST
3651 && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
3652 {
3653 /* The template argument was the name of some
3654 member function. That's usually
3655 invalid, but static members are OK. In any
3656 case, grab the underlying fields/functions
3657 and issue an error later if required. */
3658 arg = TREE_VALUE (arg);
3659 TREE_TYPE (arg) = unknown_type_node;
3660 }
3661
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;
Obviously, at this point, we have requires_tmpl_type (1), requires_type (1), is_tmpl_type (1), is_type (1). Among these variables, we can see that requires_tmpl_type is the subset of requires_type , and so is is_tmpl_type and is_type . Any inconsistency should be an error!
convert_template_arguments (continue)
3678 if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
3679 && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
3680 {
3681 pedwarn ("to refer to a type member of a template parameter, use `typename %E'", arg);
3682
3683 arg = make_typename_type (TREE_OPERAND (arg, 0),
3684 TREE_OPERAND (arg, 1),
3685 complain & tf_error);
3686 is_type = 1;
3687 }
3688 if (is_type != requires_type)
3689 {
3690 if (in_decl)
3691 {
3692 if (complain & tf_error)
3693 {
3694 error ("type/value mismatch at argument %d in template parameter list for `%D'",
3695 i + 1, in_decl);
3696 if (is_type)
3697 error (" expected a constant of type `%T', got `%T'",
3698 TREE_TYPE (parm),
3699 (is_tmpl_type ? DECL_NAME (arg) : arg));
3700 else if (requires_tmpl_type)
3701 error (" expected a class template, got `%E'", arg);
3702 else
3703 error (" expected a type, got `%E'", arg);
3704 }
3705 }
3706 return error_mark_node;
3707 }
3708 if (is_tmpl_type ^ requires_tmpl_type)
3709 {
3710 if (in_decl && (complain & tf_error))
3711 {
3712 error ("type/value mismatch at argument %d in template parameter list for `%D'",
3713 i + 1, in_decl);
3714 if (is_tmpl_type)
3715 error (" expected a type, got `%T'", DECL_NAME (arg));
3716 else
3717 error (" expected a class template, got `%T'", arg);
3718 }
3719 return error_mark_node;
3720 }
3721
3722 if (is_type)
3723 {
3724 if (requires_tmpl_type)
3725 {
3726 if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
3727 /* The number of argument required is not known yet.
3728 Just accept it for now. */
3729 val = TREE_TYPE (arg);
3730 else
3731 {
3732 tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
3733 tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
3734
3735 if (coerce_template_template_parms (parmparm, argparm,
3736 complain, in_decl,
3737 inner_args))
3738 {
3739 val = arg;
3740
3741 /* TEMPLATE_TEMPLATE_PARM node is preferred over
3742 TEMPLATE_DECL. */
3743 if (val != error_mark_node
3744 && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
3745 val = TREE_TYPE (val);
3746 }
3747 else
3748 {
3749 if (in_decl && (complain & tf_error))
3750 {
3751 error ("type/value mismatch at argument %d in template parameter list for `%D'",
3752 i + 1, in_decl);
3753 error (" expected a template of type `%D', got `%D'", parm, arg);
3754 }
3755
3756 val = error_mark_node;
3757 }
3758 }
3759 }
3760 else
3761 val = groktypename (arg);
3762 }
3763 else
3764 {
…
3790 }
3791
3792 return val;
3793 }
5.12.4.2.3.1.1.1. The template-template argument
As parm and arg refer to the same TEMPALTE_DECL, then parmparm and argparm both point to TREE_VEC in below figure comes from the TEMPLATE_DECL of “ThreadingModel”.
(Click here for open )
3559 static int
3560 coerce_template_template_parms (tree parm_parms, in pt.c
3561 tree arg_parms,
3562 tsubst_flags_t complain,
3563 tree in_decl,
3564 tree outer_args)
3565 {
3566 int nparms, nargs, i;
3567 tree parm, arg;
3568
3569 my_friendly_assert (TREE_CODE (parm_parms) == TREE_VEC, 0);
3570 my_friendly_assert (TREE_CODE (arg_parms) == TREE_VEC, 0);
3571
3572 nparms = TREE_VEC_LENGTH (parm_parms);
3573 nargs = TREE_VEC_LENGTH (arg_parms);
3574
3575 /* The rule here is opposite of coerce_template_parms. */
3576 if (nargs < nparms
3577 || (nargs > nparms
3578 && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE))
3579 return 0;
3580
3581 for (i = 0; i < nparms; ++i)
3582 {
3583 parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
3584 arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
3585
3586 if (arg == NULL_TREE || arg == error_mark_node
3587 || parm == NULL_TREE || parm == error_mark_node)
3588 return 0;
3589
3590 if (TREE_CODE (arg) != TREE_CODE (parm))
3591 return 0;
3592
3593 switch (TREE_CODE (parm))
3594 {
3595 case TYPE_DECL:
3596 break ;
3597
3598 case TEMPLATE_DECL:
3599 /* We encounter instantiations of templates like
3600 template <template <template <class> class> class TT>
3601 class C; */
3602 {
3603 tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
3604 tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
3605
3606 if (!coerce_template_template_parms
3607 (parmparm, argparm, complain, in_decl, outer_args))
3608 return 0;
3609 }
3610 break ;
3611
3612 case PARM_DECL:
3613 /* The tsubst call is used to handle cases such as
3614 template <class T, template <T> class TT> class D;
3615 i.e. the parameter list of TT depends on earlier parameters. */
3616 if (!same_type_p
3617 (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
3618 TREE_TYPE (arg)))
3619 return 0;
3620 break ;
3621
3622 default :
3623 abort ();
3624 }
3625 }
3626 return 1;
3627 }
The exactly matching types of parm_parms and arg_parms make the function returns 1. This function, besides validates template template argument and template template parameter, will fills up default argument.
Then at line 3745, in coerce_template_arguments , val is updated to the node of TEMPLATE_TEMPLATE_PARM in above figure. And this node in turn is placed into the first element of new_inner_args .
5.12.4.2.3.1.1.2. The non-type argument
For the second argument, the argument arg of coerce_template_arguments is the IDENTIFIER_NODE of “chunkSize”, and parm is the node referred by the value field in red in below figure.
(Click here for open )
convert_template_arguments (continue)
3763 else
3764 {
3765 tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
3766
3767 if (invalid_nontype_parm_type_p (t, complain))
3768 return error_mark_node;
3769
3770 if (!uses_template_parms (arg) && !uses_template_parms (t))
3771 /* We used to call digest_init here. However, digest_init
3772 will report errors, which we don't want when complain
3773 is zero. More importantly, digest_init will try too
3774 hard to convert things: for example, `0' should not be
3775 converted to pointer type at this point according to
3776 the standard. Accepting this is not merely an
3777 extension, since deciding whether or not these
3778 conversions can occur is part of determining which
3779 function template to call, or whether a given explicit
3780 argument specification is valid. */
3781 val = convert_nontype_argument (t, arg);
3782 else
3783 val = arg;
3784
3785 if (val == NULL_TREE)
3786 val = error_mark_node;
3787 else if (val == error_mark_node && (complain & tf_error))
3788 error ("could not convert template argument `%E' to `%T'",
3789 arg, t);
3790 }
3791
3792 return val;
3793 }
If the parameter is the dependent type (argument is an instance of it), or the argument is the dependent value, don’t attempt to fold the argument. Routine uses_template_parms can tell us if argument t depends upon template parameter.
4795 int
4796 uses_template_parms (tree t) in pt.c
4797 {
4798 bool dependent_p;
4799 int saved_processing_template_decl;
4800
4801 saved_processing_template_decl = processing_template_decl;
4802 if (!saved_processing_template_decl)
4803 processing_template_decl = 1;
4804 if (TYPE_P (t))
4805 dependent_p = dependent_type_p (t);
4806 else if (TREE_CODE (t) == TREE_VEC)
4807 dependent_p = any_dependent_template_arguments_p (t);
4808 else if (TREE_CODE (t) == TREE_LIST)
4809 dependent_p = (uses_template_parms (TREE_VALUE (t))
4810 || uses_template_parms (TREE_CHAIN (t)));
4811 else if (TREE_CODE (t) == TYPE_DECL)
4812 dependent_p = dependent_type_p (TREE_TYPE (t));
4813 else if (DECL_P (t)
4814 || EXPR_P (t)
4815 || TREE_CODE (t) == TEMPLATE_PARM_INDEX
4816 || TREE_CODE (t) == OVERLOAD
4817 || TREE_CODE (t) == BASELINK
4818 || TREE_CODE (t) == IDENTIFIER_NODE
4819 || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
4820 dependent_p = ( type_dependent_expression_p (t)
4821 || value_dependent_expression_p (t));
4822 else if (t == error_mark_node)
4823 dependent_p = false;
4824 else
4825 abort ();
4826 processing_template_decl = saved_processing_template_decl;
4827
4828 return dependent_p;
4829 }
In our example, in template-id “ThreadingModel< SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >”, argument “ThreadingModel” in the part “SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize>” is the one depends on template parameter.
最后
以上就是鲜艳滑板为你收集整理的Studying note of GCC-3.4.6 source (125)的全部内容,希望文章能够帮你解决Studying note of GCC-3.4.6 source (125)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复