您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (134)

2010-12-25 13:47 405 查看
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
)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: