GCC-3.4.6源代码学习笔记 (100 续)
2010-09-10 11:45
381 查看
grokdeclarator (continue)
8163
{
8164
tree decl;
8165
8166
if (decl_context == PARM)
8167
{
8168
decl =
cp_build_parm_decl (declarator, type);
8169
8170
bad_specifiers (decl,
"parameter", virtualp, quals != NULL_TREE,
8171
inlinep,
friendp, raises != NULL_TREE);
8172
}
8173
else if (decl_context ==
FIELD)
8174
{
8175
/*
The C99 flexible array extension.
*/
8176
if (!staticp &&
TREE_CODE (type) == ARRAY_TYPE
8177
&& TYPE_DOMAIN
(type) == NULL_TREE)
8178
{
8179
tree itype =
compute_array_index_type (dname, integer_zero_node);
8180
type = build_cplus_array_type
(TREE_TYPE (type), itype);
8181
}
8182
8183
if (type ==
error_mark_node)
8184
{
8185
/* Happens when declaring arrays of sizes which
8186
are error_mark_node, for example.
*/
8187
decl = NULL_TREE;
8188
}
8189
else if (in_namespace
&& !friendp)
8190
{
8191
/* Something like struct S { int N::j; };
*/
8192
error ("invalid
use of `::'");
8193
decl = NULL_TREE;
8194
}
8195
else if (TREE_CODE
(type) == FUNCTION_TYPE)
8196
{
8197
int publicp = 0;
8198
tree function_context;
8199
8200
/* We catch the others as conflicts with the builtin
8201
typedefs.
*/
8202
if (friendp &&
declarator == ridpointers
[(int)
RID_SIGNED])
8203
{
8204
error
("function `%D' cannot be declared friend",
8205
declarator);
8206
friendp = 0;
8207
}
8208
8209
if (friendp == 0)
8210
{
8211
if (ctype == NULL_TREE)
8212
ctype = current_class_type
;
8213
8214
if (ctype ==
NULL_TREE)
8215
{
8216
error ("can't
make `%D' into a method -- not in a class",
8217
declarator);
8218
return
void_type_node;
8219
}
8220
8221
/*
``A union may [ ... ] not [ have ] virtual functions.''
8222
ARM 9.5 */
8223
if (virtualp
&& TREE_CODE (ctype) == UNION_TYPE)
8224
{
8225
error
("function `%D' declared virtual inside a union",
8226
declarator);
8227
return
void_type_node;
8228
}
8229
8230
if
(NEW_DELETE_OPNAME_P (declarator))
8231
{
8232
if (virtualp)
8233
{
8234
error ("`%D' cannot be declared
virtual, since it is always static",
8235
declarator);
8236
virtualp = 0;
8237
}
8238
}
8239
else if (staticp
< 2)
8240
type = build_method_type_directly
(ctype,
8241
TREE_TYPE (type),
8242
TYPE_ARG_TYPES (type));
8243
}
8244
8245
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the
node.
*/
8246
function_context =
(ctype != NULL_TREE) ?
8247
decl_function_context
(TYPE_MAIN_DECL
(ctype)) : NULL_TREE;
8248
publicp = (! friendp
|| ! staticp)
8249
&&
function_context == NULL_TREE;
8250
decl = grokfndecl
(ctype, type,
8251
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
8252
?
declarator : dname,
8253
parms,
8254
declarator,
8255
virtualp, flags, quals, raises,
8256
friendp
? -1 : 0, friendp, publicp, inlinep,
8257
funcdef_flag, template_count, in_namespace);
8258
if (decl == NULL_TREE)
8259
return
decl;
8260
#if
0
8261
/* This clobbers the attrs stored in `decl' from
`attrlist'.
*/
8262
/* The decl and setting of decl_attr is also turned off.
*/
8263
decl =
build_decl_attribute_variant (decl, decl_attr);
8264
#endif
在中间树中,该类的非静态方法应该是
METHOD_TYPE
。对于方法,正如我们所了解的,
this
是隐含的参数指向这个方法所要操纵的对象。下面的
build_pointer_type
则是创建这个隐含的
this
。注意到,作为副作用,在
7601
行所构建的
FUNCTION_TYPE
节点被丢弃(它将随后被
GC
回收)。
3902
tree
3903
build_method_type_directly
(tree basetype,
in
tree.c
3904
tree
rettype,
3905
tree
argtypes)
3906
{
3907
tree t;
3908
tree ptype;
3909
int hashcode;
3910
3911
/*
Make a node of the sort we want.
*/
3912
t = make_node
(METHOD_TYPE);
3913
3914
TYPE_METHOD_BASETYPE (t) =
TYPE_MAIN_VARIANT (basetype);
3915
TREE_TYPE (t) = rettype;
3916
ptype = build_pointer_type
(basetype);
3917
3918
/*
The actual arglist for this function includes a "hidden" argument
3919
which
is "this". Put it into the list of argument types.
*/
3920
argtypes = tree_cons
(NULL_TREE, ptype, argtypes);
3921
TYPE_ARG_TYPES (t) =
argtypes;
3922
3923
/*
If we already have such a type, use the old one and free this one.
3924
Note
that it also frees up the above cons cell if found.
*/
3925
hashcode = TYPE_HASH
(basetype) + TYPE_HASH (rettype) +
3926
type_hash_list (argtypes);
3927
3928
t = type_hash_canon
(hashcode, t);
3929
3930
if (!COMPLETE_TYPE_P (t))
3931
layout_type
(t);
3932
3933
return
t;
3934
}
在
8247
行,如果
decl
的封闭(
enclosing
)域不是
FUNCTION_DECL
,
decl_funtion_context
返回
NULL_TREE
,否则就是这个
FUNCTION_DECL
。而现在
decl
是
current_class_type
,它是结构体“
Lock
”的
TYPE_DECL
。
4392
tree
4393
decl_function_context
(tree decl)
in
tree.c
4394
{
4395
tree context;
4396
4397
if (TREE_CODE (decl) ==
ERROR_MARK)
4398
return
0;
4399
4400
if (TREE_CODE (decl) ==
SAVE_EXPR)
4401
context =
SAVE_EXPR_CONTEXT (decl);
4402
4403
/*
C++ virtual functions use DECL_CONTEXT for the class of the vtable
4404
where
we look up the function at runtime. Such functions always take
4405
a
first argument of type 'pointer to real context'.
4406
4407
C++
should really be fixed to use DECL_CONTEXT for the real context,
4408
and
use something else for the "virtual context".
*/
4409
else if (TREE_CODE (decl) ==
FUNCTION_DECL && DECL_VINDEX (decl))
4410
context
4411
= TYPE_MAIN_VARIANT
4412
(TREE_TYPE
(TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
4413
else
4414
context = DECL_CONTEXT
(decl);
4415
4416
while
(context && TREE_CODE (context) != FUNCTION_DECL)
4417
{
4418
if (TREE_CODE (context) ==
BLOCK)
4419
context =
BLOCK_SUPERCONTEXT (context);
4420
else
4421
context = get_containing_scope
(context);
4422
}
4423
4424
return
context;
4425
}
而在进入封闭域栈时,除了
*_DECL
可能还会遇到
*_TYPE
,通过
get_containing_scope
获取相应的封闭上下文。
4383
tree
4384
get_containing_scope
(tree t)
in
tree.c
4385
{
4386
return
(TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT
(t));
4387
}
结果在
8248
行,
publicp
是
1
,它表示该声明的可见性仅取决于包含它的类。
那么对于
8250
行
grokfndecl
的调用,其参数的值为:
ctype
(
current_class_type
),
type
(在
8240
行的
METHOD_TYPE
节点),
parms
(
NULL_TREE
),
virtualp
(
0
),
flags
(
NO_SPECIAL
),
quals
(
NULL_TREE
),
raises
(
NULL_TREE
),
check
(
0
),
friendp
(
0
),
publicp
(
1
),
inlinep
(
0
),
funcdef_flag
(
-1
),
template_count
(
0
),
in_namespace
(
NULL_TREE)
。
5582
static
tree
5583
grokfndecl
(tree ctype,
in
decl.c
5584
tree type,
5585
tree declarator,
5586
tree parms,
5587
tree orig_declarator,
5588
int virtualp,
5589
enum
overload_flags
flags,
5590
tree quals,
5591
tree raises,
5592
int check,
5593
int friendp,
5594
int publicp,
5595
int inlinep,
5596
int funcdef_flag,
5597
int template_count,
5598
tree in_namespace)
5599
{
5600
tree decl;
5601
int staticp = ctype
&& TREE_CODE (type) == FUNCTION_TYPE;
5602
int has_default_arg = 0;
5603
tree t;
5604
5605
if (raises)
5606
type =
build_exception_variant (type, raises);
5607
5608
decl =
build_lang_decl
(FUNCTION_DECL, declarator, type);
5609
DECL_ARGUMENTS (decl) =
parms;
5610
/*
Propagate volatile out from type to decl.
*/
5611
if (TYPE_VOLATILE (type))
5612
TREE_THIS_VOLATILE (decl)
= 1;
5613
5614
/*
If this decl has namespace scope, set that up.
*/
5615
if (in_namespace)
5616
set_decl_namespace (decl,
in_namespace, friendp);
5617
else if (!ctype)
5618
DECL_CONTEXT (decl) =
FROB_CONTEXT (current_namespace);
5619
5620
/*
`main' and builtins have implicit 'C' linkage.
*/
5621
if ((MAIN_NAME_P
(declarator)
5622
|| (IDENTIFIER_LENGTH
(declarator) > 10
5623
&& IDENTIFIER_POINTER
(declarator)[0] == '_'
5624
&&
IDENTIFIER_POINTER (declarator)[1] == '_'
5625
&& strncmp
(IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
5626
&&
current_lang_name == lang_name_cplusplus
5627
&& ctype ==
NULL_TREE
5628
/* NULL_TREE means global namespace.
*/
5629
&& DECL_CONTEXT
(decl) == NULL_TREE)
5630
SET_DECL_LANGUAGE (decl,
lang_c);
5631
5632
/*
Should probably propagate const out from type to decl I bet (mrs).
*/
5633
if (staticp)
5634
{
5635
DECL_STATIC_FUNCTION_P
(decl) = 1;
5636
DECL_CONTEXT (decl) =
ctype;
5637
}
5638
5639
if (ctype)
5640
DECL_CONTEXT (decl) =
ctype;
5641
5642
if (ctype == NULL_TREE
&& DECL_MAIN_P (decl))
5643
{
5644
if
(processing_template_decl)
5645
error ("cannot
declare `::main' to be a template");
5646
if (inlinep)
5647
error ("cannot
declare `::main' to be inline");
5648
if (!publicp)
5649
error ("cannot
declare `::main' to be static");
5650
if (!same_type_p
(TREE_TYPE (TREE_TYPE (decl)),
5651
integer_type_node))
5652
error ("`main' must
return `int'");
5653
inlinep = 0;
5654
publicp = 1;
5655
}
5656
5657
/*
Members of anonymous types and local classes have no linkage; make
5658
them
internal.
*/
5659
/*
FIXME what if it gets a name from typedef?
*/
5660
if (ctype &&
(TYPE_ANONYMOUS_P (ctype)
5661
|| decl_function_context
(TYPE_MAIN_DECL (ctype))))
5662
publicp = 0;
5663
5664
if (publicp)
5665
{
5666
/*
[basic.link]: A name with no linkage (notably, the name of a class
5667
or enumeration declared in a local scope)
shall not be used to
5668
declare an entity with linkage.
5669
5670
Only check this for public decls for now. See
core 319, 389.
*/
5671
t = no_linkage_check
(TREE_TYPE (decl));
5672
if (t)
5673
{
5674
if (TYPE_ANONYMOUS_P
(t))
5675
{
5676
if (DECL_EXTERN_C_P
(decl))
5677
/*
Allow this; it's pretty common in C.
*/;
5678
else
5679
{
5680
pedwarn
("non-local function `%#D' uses anonymous type",
5681
decl);
5682
if
(DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
5683
cp_pedwarn_at
("/
5684
`%#D' does not refer to the
unqualified type, so it is not used for linkage",
5685
TYPE_NAME (t));
5686
}
5687
}
5688
else
5689
pedwarn
("non-local function `%#D' uses local type `%T'",
5690
decl, t);
5691
}
5692
}
5693
5694
TREE_PUBLIC (decl) =
publicp;
5695
if (! publicp)
5696
{
5697
DECL_INTERFACE_KNOWN
(decl) = 1;
5698
DECL_NOT_REALLY_EXTERN
(decl) = 1;
5699
}
5700
5701
/*
If the declaration was declared inline, mark it as such.
*/
5702
if (inlinep)
5703
DECL_DECLARED_INLINE_P
(decl) = 1;
5704
/*
We inline functions that are explicitly declared inline, or, when
5705
the
user explicitly asks us to, all functions.
*/
5706
if (DECL_DECLARED_INLINE_P
(decl)
5707
|| (flag_inline_trees ==
2 && !DECL_INLINE (decl) && funcdef_flag))
5708
DECL_INLINE (decl) = 1;
5709
5710
DECL_EXTERNAL (decl) = 1;
5711
if (quals != NULL_TREE && TREE_CODE
(type) == FUNCTION_TYPE)
5712
{
5713
error ("%smember
function `%D' cannot have `%T' method qualifier",
5714
(ctype ?
"static " : "non-"), decl, TREE_VALUE (quals));
5715
quals = NULL_TREE;
5716
}
5717
5718
if (IDENTIFIER_OPNAME_P
(DECL_NAME (decl)))
5719
grok_op_properties (decl, /*complain=*/
true);
5720
5721
if (ctype && decl_function_context
(decl))
5722
DECL_NO_STATIC_CHAIN
(decl) = 1;
5723
5724
for
(t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t =
TREE_CHAIN (t))
5725
if (TREE_PURPOSE (t)
5726
&& TREE_CODE
(TREE_PURPOSE (t)) == DEFAULT_ARG)
5727
{
5728
has_default_arg = 1;
5729
break
;
5730
}
5731
5732
if (friendp
5733
&& TREE_CODE
(orig_declarator) == TEMPLATE_ID_EXPR)
5734
{
...
5786
}
5787
5788
if (funcdef_flag)
5789
/* Make the
init_value nonzero so pushdecl knows this is not
5790
tentative.
error_mark_node is replaced later with the BLOCK.
*/
5791
DECL_INITIAL (decl) = error_mark_node;
5792
5793
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p
(decl))
5794
TREE_NOTHROW (decl) = 1;
5795
5796
/* Caller will do the rest of this.
*/
5797
if (check < 0)
5798
return
decl;
5799
5800
if (flags == NO_SPECIAL && ctype
&& constructor_name_p (declarator, ctype))
5801
DECL_CONSTRUCTOR_P (decl) = 1;
5802
5803
/* Function gets
the ugly name, field gets the nice one. This call
5804
may change the
type of the function (because of default
5805
parameters)!
*/
5806
if (ctype != NULL_TREE)
5807
grokclassfn
(ctype, decl, flags, quals);
在调用
grokclassfn
之前,中间树对应的部分如下。
(
点此打开
)
图
68
:“
Lock
”构造函数的
FUNCTION_DECL
—第一步
虽然已经创建了
METHOD_TYPE
节点,但它可能不完全是所要求的,因为这个类型节点没有考虑限定词及属性。而且那个隐含的
this
参数应该是一个指针常量。
303
void
304
grokclassfn
(tree ctype, tree function, enum
overload_flags flags, tree quals)
in decl2.c
305
{
306
tree fn_name = DECL_NAME
(function);
307
int this_quals =
TYPE_UNQUALIFIED;
308
309
/*
Even within an `extern "C"' block, members get C++ linkage.
See
310
[dcl.link] for details.
*/
311
SET_DECL_LANGUAGE (function,
lang_cplusplus);
312
313
if (fn_name == NULL_TREE)
314
{
315
error ("name missing
for member function");
316
fn_name = get_identifier
("<anonymous>");
317
DECL_NAME (function) =
fn_name;
318
}
319
320
if (quals)
321
this_quals =
grok_method_quals (ctype, function, quals);
322
323
if (TREE_CODE (TREE_TYPE
(function)) == METHOD_TYPE)
324
{
325
/*
Must add the class instance variable up front.
*/
326
/*
Right now we just make this a pointer.
But later
327
we may wish to make it special.
*/
328
tree type = TREE_VALUE
(TYPE_ARG_TYPES (TREE_TYPE (function)));
329
tree qual_type;
330
tree parm;
331
332
/*
The `this' parameter is implicitly `const'; it cannot be
333
assigned to.
*/
334
this_quals |=
TYPE_QUAL_CONST;
335
qual_type =
cp_build_qualified_type (type, this_quals);
336
parm = build_artificial_parm
(this_identifier,
qual_type);
337
c_apply_type_quals_to_decl
(this_quals, parm);
338
TREE_CHAIN (parm) =
DECL_ARGUMENTS (function);
339
DECL_ARGUMENTS (function)
= parm;
340
}
341
342
DECL_CONTEXT (function) =
ctype;
343
344
if (flags == DTOR_FLAG)
345
DECL_DESTRUCTOR_P
(function) = 1;
346
347
if (flags == DTOR_FLAG ||
DECL_CONSTRUCTOR_P (function))
348
maybe_retrofit_in_chrg
(function);
349
}
上面的参数
function
是先前所创建的
FUNCTION_DECL
节点。而
TREE_TYPE
从这个节点返回对应的
METHOD_TYPE
节点。虽然已经为类构建了
this
指针,不过这个隐含的参数应该是一个指针常量—其引用对象不能更换(这个非常量指针也是需要的,作为非限定类型,前端要求它出现在限定类型链表的头部)。因此
cp_build_qualified_type
从非限定类型构建要求的限定类型。
196
tree
197
build_artificial_parm
(tree name, tree type)
in
decl2.c
198
{
199
tree parm = cp_build_parm_decl
(name, type);
200
DECL_ARTIFICIAL (parm) = 1;
201
/*
All our artificial parms are implicitly `const'; they cannot be
202
avsigned
to.
*/
203
TREE_READONLY (parm) = 1;
204
return
parm;
205
}
同样注意在
336
行,
this_identifier
是表示
this
指针的全局标识符(它仅是名字“
this
”)。
182
tree
183
cp_build_parm_decl
(tree name, tree type)
in
decl2.c
184
{
185
tree parm =
build_decl
(PARM_DECL, name, type);
186
/*
DECL_ARG_TYPE is only used by the back end and the back end never
187
sees
templates.
*/
188
if (!processing_template_decl
)
189
DECL_ARG_TYPE (parm) = type_passed_as
(type);
190
return
parm;
191
}
在这里,
processing_template_decl
仍然为非
0
值,因为我们还在一个类模板里(
class
“
SingleThreaded
”),因此仅创建了
PARM_DECL
节点,但没有进一步的处理。同样当从
grokclassfn
返回,
maybe_retrofit_in_chrg
不做任何事,因为
processing_template_decl
是非
0
值。现在中间树看起来就像:
(
点此打开
)
图
69
:“
Lock
”构造函数的
FUNCTION_DECL
—第二步
下面,对于普通的模板声明(即,非具现,非特化),函数
check_explicit_specialization
不做实质的事情。
grokfndecl (continue)
5809
decl =
check_explicit_specialization (orig_declarator, decl,
5810
template_count,
5811
2 * (funcdef_flag != 0) +
5812
4 * (friendp != 0));
5813
if (decl == error_mark_node)
5814
return
NULL_TREE;
5815
5816
if (ctype != NULL_TREE
5817
&& (!
TYPE_FOR_JAVA (ctype) || check_java_method (decl))
5818
&& check)
5819
{
…
5865
}
5866
5867
if (DECL_CONSTRUCTOR_P
(decl) && !grok_ctor_properties (ctype, decl))
5868
return
NULL_TREE;
5869
5870
if (ctype == NULL_TREE ||
check)
5871
return
decl;
5872
5873
if (virtualp)
5874
DECL_VIRTUAL_P (decl) = 1;
5875
5876
return
decl;
5877
}
在离开
grokfndecl
之前,还需要一些检查。对于构造函数,它不能是
X(X)
的形式,因为如果不慎对自己赋值将导致无限递归。在
5867
行,
grok_ctor_properties
进行这个检查。
grokdeclarator (continue)
8266
/* [class.conv.ctor]
8267
8268
A constructor declared without the
function-specifier
8269
explicit that can be called with a single
parameter
8270
specifies
a conversion from the type of its first
8271
parameter to the type of its class. Such
a constructor
8272
is called a converting constructor.
*/
8273
if (explicitp == 2)
8274
DECL_NONCONVERTING_P
(decl) = 1;
8275
else if
(DECL_CONSTRUCTOR_P (decl))
8276
{
8277
/* The constructor can be called with exactly one
8278
parameter if there is at least one parameter,
and
8279
any
subsequent parameters have default arguments.
8280
Ignore any compiler-added parms.
*/
8281
tree arg_types =
FUNCTION_FIRST_USER_PARMTYPE (decl);
8282
8283
if (arg_types ==
void_list_node
8284
|| (arg_types
8285
&&
TREE_CHAIN (arg_types)
8286
&&
TREE_CHAIN (arg_types) != void_list_node
8287
&&
!TREE_PURPOSE (TREE_CHAIN (arg_types))))
8288
DECL_NONCONVERTING_P
(decl) = 1;
8289
}
8290
}
…
8548
}
8549
8550
my_friendly_assert
(!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
8551
8552
/*
Record `register' declaration for warnings on &
8553
and
in case doing stupid register allocation.
*/
8554
8555
if (RIDBIT_SETP
(RID_REGISTER, specbits))
8556
DECL_REGISTER (decl) =
1;
8557
8558
if (RIDBIT_SETP
(RID_EXTERN, specbits))
8559
DECL_THIS_EXTERN (decl)
= 1;
8560
8561
if (RIDBIT_SETP
(RID_STATIC, specbits))
8562
DECL_THIS_STATIC (decl)
= 1;
8563
8564
/*
Record constancy and volatility. There's no need to do this
8565
when
processing a template; we'll do this for the instantiated
8566
declaration based on the type of DECL.
*/
8567
if (!processing_template_decl
)
8568
c_apply_type_quals_to_decl (type_quals, decl);
8569
8570
return
decl;
8571
}
8572
}
我们知道,带有参数的构造函数可以被用作转换操作符,除非它被声明为“
explict
”。而且只有构造函数可被声明为“
explicit
”,如果
explicitp
为
2
,则表示其使用没问题。能用作转换构造函数的构造函数必须带有至少一个参数,而且除第一个参数外,其他参数需要具有缺省值。
现在我们已经构建了方法的树节点,但其设置尚未完成。因此在
start_method
的余下部分,它为构造函数完成节点的设置。注意
fndecl
是由
grokdeclarator
构建的
FUNCTION_DECL
节点。
start_method (continue)
11051
if (fndecl ==
error_mark_node)
11052
return
error_mark_node;
11053
11054
if (fndecl == NULL ||
TREE_CODE (fndecl) != FUNCTION_DECL)
11055
{
11056
error ("invalid
member function declaration");
11057
return
error_mark_node;
11058
}
11059
11060
if (attrlist)
11061
cplus_decl_attributes
(&fndecl, attrlist, 0);
11062
11063
/*
Pass friends other than inline friend functions back.
*/
11064
if (fndecl ==
void_type_node)
11065
return
fndecl;
11066
11067
if (DECL_IN_AGGR_P (fndecl))
11068
{
11069
if (IDENTIFIER_ERROR_LOCUS
(DECL_ASSEMBLER_NAME (fndecl)) != current_class_type
)
11070
{
11071
if (DECL_CONTEXT
(fndecl)
11072
&& TREE_CODE(
DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
11073
error ("`%D' is
already defined in class `%T'", fndecl,
11074
DECL_CONTEXT
(fndecl));
11075
}
11076
return
void_type_node;
11077
}
11078
11079
check_template_shadow
(fndecl);
11080
11081
DECL_DECLARED_INLINE_P
(fndecl) = 1;
11082
if (flag_default_inline)
11083
DECL_INLINE (fndecl) = 1;
11084
11085
/*
We process method specializations in finish_struct_1.
*/
11086
if (processing_template_decl
&&
!DECL_TEMPLATE_SPECIALIZATION (fndecl))
11087
{
11088
fndecl = push_template_decl
(fndecl);
11089
if (fndecl ==
error_mark_node)
11090
return
fndecl;
11091
}
11092
11093
if (! DECL_FRIEND_P
(fndecl))
11094
{
11095
if (TREE_CHAIN (fndecl))
11096
{
11097
fndecl = copy_node
(fndecl);
11098
TREE_CHAIN (fndecl) =
NULL_TREE;
11099
}
11100
grok_special_member_properties
(fndecl);
11101
}
11102
11103
cp_finish_decl (fndecl,
NULL_TREE, NULL_TREE, 0);
11104
11105
/*
Make a place for the parms.
*/
11106
begin_scope
(sk_function_parms, fndecl);
11107
11108
DECL_IN_AGGR_P (fndecl) = 1;
11109
return
fndecl;
11110
}
因为我们仍然在类模板中,所以它需要检查该声明符是否会屏蔽模板参数。在
15224
行的
DECL_TEMPLATE_SPECIALIZATION
检查
DECL_USE_TEMPLATE
域是否等于
2
(这表示显式特化)。毫无疑问,在这里,这个构造函数也被视为一个模板声明,因为它被包含在一个类模板中。在前面的章节中我们多次看过
push_template_decl
,注意到因为不是直接包含在域
sk_template_parms
中,在
push_template_decl_real
的局部变量
primary
是
false
。当从
push_template_decl
返回时,中间树加入了以下的节点。
(
点此打开
)
图
70
:“
Lock
”构造函数的
FUNCTION_DECL
—第三步
在成功地创建了相应的
TEMPLATE_DECL
并把它加入到上下文环境中,包含类节点的某些标记需要相应地设置。
8900
void grok_special_member_properties
(tree decl)
in
decl.c
8901
{
8902
if
(!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
8903
; /*
Not special.
*/
8904
else if (DECL_CONSTRUCTOR_P
(decl))
8905
{
8906
int ctor = copy_fn_p
(decl);
8907
8908
if (ctor > 0)
8909
{
8910
/*
[class.copy]
8911
8912
A non-template constructor for class X is a
copy
8913
constructor if its first parameter is of
type X&, const
8914
X&, volatile X& or const volatile
X&, and either there
8915
are no other parameters or else all other
parameters have
8916
default arguments.
*/
8917
TYPE_HAS_INIT_REF
(DECL_CONTEXT (decl)) = 1;
8918
if (ctor > 1)
8919
TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
8920
}
8921
else if (sufficient_parms_p
(FUNCTION_FIRST_USER_PARMTYPE
(decl)))
8922
TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
8923
}
8924
else if
(DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
8925
{
…
8942
}
8943
}
上面在
8906
行,
copy_fn_p
检查
decl
是否是拷贝构造函数或赋值操作符,如果它都不是,则返回
0
。那么
FUNCTION_FIRST_USER_PARMTYPE
获取第一个非人造的参数(也即跳过参数
const this*
)。
983
#define
FUNCTION_FIRST_USER_PARMTYPE
(NODE) /
in cp-tree.h
984
skip_artificial_parms_for
((NODE),
TYPE_ARG_TYPES (TREE_TYPE (NODE)))
上面的图清除地解释了
skip_artificial_parms_for
的行为。注意到只有从虚基类派生的类,
DECL_HAS_IN_CHARGE_PARM_P
及
DECL_HAS_VTT_PARM_P
才可能返回非
0
值。
1061
tree
1062
skip_artificial_parms_for
(tree fn, tree list)
in
method.c
1063
{
1064
if
(DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
1065
list = TREE_CHAIN (list);
1066
else
1067
return
list;
1068
1069
if
(DECL_HAS_IN_CHARGE_PARM_P (fn))
1070
list = TREE_CHAIN (list);
1071
if (DECL_HAS_VTT_PARM_P
(fn))
1072
list = TREE_CHAIN (list);
1073
return
list;
1074
}
注意,非可变参数的
FUNCTION_DECL
的参数链表必须由
void_list_node
结尾。
398
bool
399
sufficient_parms_p
(tree parmlist)
in
call.c
400
{
401
for
(; parmlist && parmlist != void_list_node;
402
parmlist = TREE_CHAIN
(parmlist))
403
if (!TREE_PURPOSE
(parmlist))
404
return
false;
405
return
true;
406
}
然后在
start_method
中,
cp_finish_decl
通过向节点中置入行号及初始值(如果有的话)完成对声明的处理。不过,因为在类模板中,该函数仅设置了
FUNCTION_DECL
节点的标记
DECL_INITIALIZED_IN_CLASS_P
。
另外,在
15244
行,
begin_scope
使得
FUNCTION_DECL
成为了当前的作用域(绑定域)。在这一步,中间树看起来如下:
(
点此打开
)
图
71
:“
Lock
”构造函数的
FUNCTION_DECL
—完成
8163
{
8164
tree decl;
8165
8166
if (decl_context == PARM)
8167
{
8168
decl =
cp_build_parm_decl (declarator, type);
8169
8170
bad_specifiers (decl,
"parameter", virtualp, quals != NULL_TREE,
8171
inlinep,
friendp, raises != NULL_TREE);
8172
}
8173
else if (decl_context ==
FIELD)
8174
{
8175
/*
The C99 flexible array extension.
*/
8176
if (!staticp &&
TREE_CODE (type) == ARRAY_TYPE
8177
&& TYPE_DOMAIN
(type) == NULL_TREE)
8178
{
8179
tree itype =
compute_array_index_type (dname, integer_zero_node);
8180
type = build_cplus_array_type
(TREE_TYPE (type), itype);
8181
}
8182
8183
if (type ==
error_mark_node)
8184
{
8185
/* Happens when declaring arrays of sizes which
8186
are error_mark_node, for example.
*/
8187
decl = NULL_TREE;
8188
}
8189
else if (in_namespace
&& !friendp)
8190
{
8191
/* Something like struct S { int N::j; };
*/
8192
error ("invalid
use of `::'");
8193
decl = NULL_TREE;
8194
}
8195
else if (TREE_CODE
(type) == FUNCTION_TYPE)
8196
{
8197
int publicp = 0;
8198
tree function_context;
8199
8200
/* We catch the others as conflicts with the builtin
8201
typedefs.
*/
8202
if (friendp &&
declarator == ridpointers
[(int)
RID_SIGNED])
8203
{
8204
error
("function `%D' cannot be declared friend",
8205
declarator);
8206
friendp = 0;
8207
}
8208
8209
if (friendp == 0)
8210
{
8211
if (ctype == NULL_TREE)
8212
ctype = current_class_type
;
8213
8214
if (ctype ==
NULL_TREE)
8215
{
8216
error ("can't
make `%D' into a method -- not in a class",
8217
declarator);
8218
return
void_type_node;
8219
}
8220
8221
/*
``A union may [ ... ] not [ have ] virtual functions.''
8222
ARM 9.5 */
8223
if (virtualp
&& TREE_CODE (ctype) == UNION_TYPE)
8224
{
8225
error
("function `%D' declared virtual inside a union",
8226
declarator);
8227
return
void_type_node;
8228
}
8229
8230
if
(NEW_DELETE_OPNAME_P (declarator))
8231
{
8232
if (virtualp)
8233
{
8234
error ("`%D' cannot be declared
virtual, since it is always static",
8235
declarator);
8236
virtualp = 0;
8237
}
8238
}
8239
else if (staticp
< 2)
8240
type = build_method_type_directly
(ctype,
8241
TREE_TYPE (type),
8242
TYPE_ARG_TYPES (type));
8243
}
8244
8245
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the
node.
*/
8246
function_context =
(ctype != NULL_TREE) ?
8247
decl_function_context
(TYPE_MAIN_DECL
(ctype)) : NULL_TREE;
8248
publicp = (! friendp
|| ! staticp)
8249
&&
function_context == NULL_TREE;
8250
decl = grokfndecl
(ctype, type,
8251
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
8252
?
declarator : dname,
8253
parms,
8254
declarator,
8255
virtualp, flags, quals, raises,
8256
friendp
? -1 : 0, friendp, publicp, inlinep,
8257
funcdef_flag, template_count, in_namespace);
8258
if (decl == NULL_TREE)
8259
return
decl;
8260
#if
0
8261
/* This clobbers the attrs stored in `decl' from
`attrlist'.
*/
8262
/* The decl and setting of decl_attr is also turned off.
*/
8263
decl =
build_decl_attribute_variant (decl, decl_attr);
8264
#endif
在中间树中,该类的非静态方法应该是
METHOD_TYPE
。对于方法,正如我们所了解的,
this
是隐含的参数指向这个方法所要操纵的对象。下面的
build_pointer_type
则是创建这个隐含的
this
。注意到,作为副作用,在
7601
行所构建的
FUNCTION_TYPE
节点被丢弃(它将随后被
GC
回收)。
3902
tree
3903
build_method_type_directly
(tree basetype,
in
tree.c
3904
tree
rettype,
3905
tree
argtypes)
3906
{
3907
tree t;
3908
tree ptype;
3909
int hashcode;
3910
3911
/*
Make a node of the sort we want.
*/
3912
t = make_node
(METHOD_TYPE);
3913
3914
TYPE_METHOD_BASETYPE (t) =
TYPE_MAIN_VARIANT (basetype);
3915
TREE_TYPE (t) = rettype;
3916
ptype = build_pointer_type
(basetype);
3917
3918
/*
The actual arglist for this function includes a "hidden" argument
3919
which
is "this". Put it into the list of argument types.
*/
3920
argtypes = tree_cons
(NULL_TREE, ptype, argtypes);
3921
TYPE_ARG_TYPES (t) =
argtypes;
3922
3923
/*
If we already have such a type, use the old one and free this one.
3924
Note
that it also frees up the above cons cell if found.
*/
3925
hashcode = TYPE_HASH
(basetype) + TYPE_HASH (rettype) +
3926
type_hash_list (argtypes);
3927
3928
t = type_hash_canon
(hashcode, t);
3929
3930
if (!COMPLETE_TYPE_P (t))
3931
layout_type
(t);
3932
3933
return
t;
3934
}
在
8247
行,如果
decl
的封闭(
enclosing
)域不是
FUNCTION_DECL
,
decl_funtion_context
返回
NULL_TREE
,否则就是这个
FUNCTION_DECL
。而现在
decl
是
current_class_type
,它是结构体“
Lock
”的
TYPE_DECL
。
4392
tree
4393
decl_function_context
(tree decl)
in
tree.c
4394
{
4395
tree context;
4396
4397
if (TREE_CODE (decl) ==
ERROR_MARK)
4398
return
0;
4399
4400
if (TREE_CODE (decl) ==
SAVE_EXPR)
4401
context =
SAVE_EXPR_CONTEXT (decl);
4402
4403
/*
C++ virtual functions use DECL_CONTEXT for the class of the vtable
4404
where
we look up the function at runtime. Such functions always take
4405
a
first argument of type 'pointer to real context'.
4406
4407
C++
should really be fixed to use DECL_CONTEXT for the real context,
4408
and
use something else for the "virtual context".
*/
4409
else if (TREE_CODE (decl) ==
FUNCTION_DECL && DECL_VINDEX (decl))
4410
context
4411
= TYPE_MAIN_VARIANT
4412
(TREE_TYPE
(TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
4413
else
4414
context = DECL_CONTEXT
(decl);
4415
4416
while
(context && TREE_CODE (context) != FUNCTION_DECL)
4417
{
4418
if (TREE_CODE (context) ==
BLOCK)
4419
context =
BLOCK_SUPERCONTEXT (context);
4420
else
4421
context = get_containing_scope
(context);
4422
}
4423
4424
return
context;
4425
}
而在进入封闭域栈时,除了
*_DECL
可能还会遇到
*_TYPE
,通过
get_containing_scope
获取相应的封闭上下文。
4383
tree
4384
get_containing_scope
(tree t)
in
tree.c
4385
{
4386
return
(TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT
(t));
4387
}
结果在
8248
行,
publicp
是
1
,它表示该声明的可见性仅取决于包含它的类。
那么对于
8250
行
grokfndecl
的调用,其参数的值为:
ctype
(
current_class_type
),
type
(在
8240
行的
METHOD_TYPE
节点),
parms
(
NULL_TREE
),
virtualp
(
0
),
flags
(
NO_SPECIAL
),
quals
(
NULL_TREE
),
raises
(
NULL_TREE
),
check
(
0
),
friendp
(
0
),
publicp
(
1
),
inlinep
(
0
),
funcdef_flag
(
-1
),
template_count
(
0
),
in_namespace
(
NULL_TREE)
。
5582
static
tree
5583
grokfndecl
(tree ctype,
in
decl.c
5584
tree type,
5585
tree declarator,
5586
tree parms,
5587
tree orig_declarator,
5588
int virtualp,
5589
enum
overload_flags
flags,
5590
tree quals,
5591
tree raises,
5592
int check,
5593
int friendp,
5594
int publicp,
5595
int inlinep,
5596
int funcdef_flag,
5597
int template_count,
5598
tree in_namespace)
5599
{
5600
tree decl;
5601
int staticp = ctype
&& TREE_CODE (type) == FUNCTION_TYPE;
5602
int has_default_arg = 0;
5603
tree t;
5604
5605
if (raises)
5606
type =
build_exception_variant (type, raises);
5607
5608
decl =
build_lang_decl
(FUNCTION_DECL, declarator, type);
5609
DECL_ARGUMENTS (decl) =
parms;
5610
/*
Propagate volatile out from type to decl.
*/
5611
if (TYPE_VOLATILE (type))
5612
TREE_THIS_VOLATILE (decl)
= 1;
5613
5614
/*
If this decl has namespace scope, set that up.
*/
5615
if (in_namespace)
5616
set_decl_namespace (decl,
in_namespace, friendp);
5617
else if (!ctype)
5618
DECL_CONTEXT (decl) =
FROB_CONTEXT (current_namespace);
5619
5620
/*
`main' and builtins have implicit 'C' linkage.
*/
5621
if ((MAIN_NAME_P
(declarator)
5622
|| (IDENTIFIER_LENGTH
(declarator) > 10
5623
&& IDENTIFIER_POINTER
(declarator)[0] == '_'
5624
&&
IDENTIFIER_POINTER (declarator)[1] == '_'
5625
&& strncmp
(IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
5626
&&
current_lang_name == lang_name_cplusplus
5627
&& ctype ==
NULL_TREE
5628
/* NULL_TREE means global namespace.
*/
5629
&& DECL_CONTEXT
(decl) == NULL_TREE)
5630
SET_DECL_LANGUAGE (decl,
lang_c);
5631
5632
/*
Should probably propagate const out from type to decl I bet (mrs).
*/
5633
if (staticp)
5634
{
5635
DECL_STATIC_FUNCTION_P
(decl) = 1;
5636
DECL_CONTEXT (decl) =
ctype;
5637
}
5638
5639
if (ctype)
5640
DECL_CONTEXT (decl) =
ctype;
5641
5642
if (ctype == NULL_TREE
&& DECL_MAIN_P (decl))
5643
{
5644
if
(processing_template_decl)
5645
error ("cannot
declare `::main' to be a template");
5646
if (inlinep)
5647
error ("cannot
declare `::main' to be inline");
5648
if (!publicp)
5649
error ("cannot
declare `::main' to be static");
5650
if (!same_type_p
(TREE_TYPE (TREE_TYPE (decl)),
5651
integer_type_node))
5652
error ("`main' must
return `int'");
5653
inlinep = 0;
5654
publicp = 1;
5655
}
5656
5657
/*
Members of anonymous types and local classes have no linkage; make
5658
them
internal.
*/
5659
/*
FIXME what if it gets a name from typedef?
*/
5660
if (ctype &&
(TYPE_ANONYMOUS_P (ctype)
5661
|| decl_function_context
(TYPE_MAIN_DECL (ctype))))
5662
publicp = 0;
5663
5664
if (publicp)
5665
{
5666
/*
[basic.link]: A name with no linkage (notably, the name of a class
5667
or enumeration declared in a local scope)
shall not be used to
5668
declare an entity with linkage.
5669
5670
Only check this for public decls for now. See
core 319, 389.
*/
5671
t = no_linkage_check
(TREE_TYPE (decl));
5672
if (t)
5673
{
5674
if (TYPE_ANONYMOUS_P
(t))
5675
{
5676
if (DECL_EXTERN_C_P
(decl))
5677
/*
Allow this; it's pretty common in C.
*/;
5678
else
5679
{
5680
pedwarn
("non-local function `%#D' uses anonymous type",
5681
decl);
5682
if
(DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
5683
cp_pedwarn_at
("/
5684
`%#D' does not refer to the
unqualified type, so it is not used for linkage",
5685
TYPE_NAME (t));
5686
}
5687
}
5688
else
5689
pedwarn
("non-local function `%#D' uses local type `%T'",
5690
decl, t);
5691
}
5692
}
5693
5694
TREE_PUBLIC (decl) =
publicp;
5695
if (! publicp)
5696
{
5697
DECL_INTERFACE_KNOWN
(decl) = 1;
5698
DECL_NOT_REALLY_EXTERN
(decl) = 1;
5699
}
5700
5701
/*
If the declaration was declared inline, mark it as such.
*/
5702
if (inlinep)
5703
DECL_DECLARED_INLINE_P
(decl) = 1;
5704
/*
We inline functions that are explicitly declared inline, or, when
5705
the
user explicitly asks us to, all functions.
*/
5706
if (DECL_DECLARED_INLINE_P
(decl)
5707
|| (flag_inline_trees ==
2 && !DECL_INLINE (decl) && funcdef_flag))
5708
DECL_INLINE (decl) = 1;
5709
5710
DECL_EXTERNAL (decl) = 1;
5711
if (quals != NULL_TREE && TREE_CODE
(type) == FUNCTION_TYPE)
5712
{
5713
error ("%smember
function `%D' cannot have `%T' method qualifier",
5714
(ctype ?
"static " : "non-"), decl, TREE_VALUE (quals));
5715
quals = NULL_TREE;
5716
}
5717
5718
if (IDENTIFIER_OPNAME_P
(DECL_NAME (decl)))
5719
grok_op_properties (decl, /*complain=*/
true);
5720
5721
if (ctype && decl_function_context
(decl))
5722
DECL_NO_STATIC_CHAIN
(decl) = 1;
5723
5724
for
(t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t =
TREE_CHAIN (t))
5725
if (TREE_PURPOSE (t)
5726
&& TREE_CODE
(TREE_PURPOSE (t)) == DEFAULT_ARG)
5727
{
5728
has_default_arg = 1;
5729
break
;
5730
}
5731
5732
if (friendp
5733
&& TREE_CODE
(orig_declarator) == TEMPLATE_ID_EXPR)
5734
{
...
5786
}
5787
5788
if (funcdef_flag)
5789
/* Make the
init_value nonzero so pushdecl knows this is not
5790
tentative.
error_mark_node is replaced later with the BLOCK.
*/
5791
DECL_INITIAL (decl) = error_mark_node;
5792
5793
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p
(decl))
5794
TREE_NOTHROW (decl) = 1;
5795
5796
/* Caller will do the rest of this.
*/
5797
if (check < 0)
5798
return
decl;
5799
5800
if (flags == NO_SPECIAL && ctype
&& constructor_name_p (declarator, ctype))
5801
DECL_CONSTRUCTOR_P (decl) = 1;
5802
5803
/* Function gets
the ugly name, field gets the nice one. This call
5804
may change the
type of the function (because of default
5805
parameters)!
*/
5806
if (ctype != NULL_TREE)
5807
grokclassfn
(ctype, decl, flags, quals);
在调用
grokclassfn
之前,中间树对应的部分如下。
(
点此打开
)
图
68
:“
Lock
”构造函数的
FUNCTION_DECL
—第一步
虽然已经创建了
METHOD_TYPE
节点,但它可能不完全是所要求的,因为这个类型节点没有考虑限定词及属性。而且那个隐含的
this
参数应该是一个指针常量。
303
void
304
grokclassfn
(tree ctype, tree function, enum
overload_flags flags, tree quals)
in decl2.c
305
{
306
tree fn_name = DECL_NAME
(function);
307
int this_quals =
TYPE_UNQUALIFIED;
308
309
/*
Even within an `extern "C"' block, members get C++ linkage.
See
310
[dcl.link] for details.
*/
311
SET_DECL_LANGUAGE (function,
lang_cplusplus);
312
313
if (fn_name == NULL_TREE)
314
{
315
error ("name missing
for member function");
316
fn_name = get_identifier
("<anonymous>");
317
DECL_NAME (function) =
fn_name;
318
}
319
320
if (quals)
321
this_quals =
grok_method_quals (ctype, function, quals);
322
323
if (TREE_CODE (TREE_TYPE
(function)) == METHOD_TYPE)
324
{
325
/*
Must add the class instance variable up front.
*/
326
/*
Right now we just make this a pointer.
But later
327
we may wish to make it special.
*/
328
tree type = TREE_VALUE
(TYPE_ARG_TYPES (TREE_TYPE (function)));
329
tree qual_type;
330
tree parm;
331
332
/*
The `this' parameter is implicitly `const'; it cannot be
333
assigned to.
*/
334
this_quals |=
TYPE_QUAL_CONST;
335
qual_type =
cp_build_qualified_type (type, this_quals);
336
parm = build_artificial_parm
(this_identifier,
qual_type);
337
c_apply_type_quals_to_decl
(this_quals, parm);
338
TREE_CHAIN (parm) =
DECL_ARGUMENTS (function);
339
DECL_ARGUMENTS (function)
= parm;
340
}
341
342
DECL_CONTEXT (function) =
ctype;
343
344
if (flags == DTOR_FLAG)
345
DECL_DESTRUCTOR_P
(function) = 1;
346
347
if (flags == DTOR_FLAG ||
DECL_CONSTRUCTOR_P (function))
348
maybe_retrofit_in_chrg
(function);
349
}
上面的参数
function
是先前所创建的
FUNCTION_DECL
节点。而
TREE_TYPE
从这个节点返回对应的
METHOD_TYPE
节点。虽然已经为类构建了
this
指针,不过这个隐含的参数应该是一个指针常量—其引用对象不能更换(这个非常量指针也是需要的,作为非限定类型,前端要求它出现在限定类型链表的头部)。因此
cp_build_qualified_type
从非限定类型构建要求的限定类型。
196
tree
197
build_artificial_parm
(tree name, tree type)
in
decl2.c
198
{
199
tree parm = cp_build_parm_decl
(name, type);
200
DECL_ARTIFICIAL (parm) = 1;
201
/*
All our artificial parms are implicitly `const'; they cannot be
202
avsigned
to.
*/
203
TREE_READONLY (parm) = 1;
204
return
parm;
205
}
同样注意在
336
行,
this_identifier
是表示
this
指针的全局标识符(它仅是名字“
this
”)。
182
tree
183
cp_build_parm_decl
(tree name, tree type)
in
decl2.c
184
{
185
tree parm =
build_decl
(PARM_DECL, name, type);
186
/*
DECL_ARG_TYPE is only used by the back end and the back end never
187
sees
templates.
*/
188
if (!processing_template_decl
)
189
DECL_ARG_TYPE (parm) = type_passed_as
(type);
190
return
parm;
191
}
在这里,
processing_template_decl
仍然为非
0
值,因为我们还在一个类模板里(
class
“
SingleThreaded
”),因此仅创建了
PARM_DECL
节点,但没有进一步的处理。同样当从
grokclassfn
返回,
maybe_retrofit_in_chrg
不做任何事,因为
processing_template_decl
是非
0
值。现在中间树看起来就像:
(
点此打开
)
图
69
:“
Lock
”构造函数的
FUNCTION_DECL
—第二步
下面,对于普通的模板声明(即,非具现,非特化),函数
check_explicit_specialization
不做实质的事情。
grokfndecl (continue)
5809
decl =
check_explicit_specialization (orig_declarator, decl,
5810
template_count,
5811
2 * (funcdef_flag != 0) +
5812
4 * (friendp != 0));
5813
if (decl == error_mark_node)
5814
return
NULL_TREE;
5815
5816
if (ctype != NULL_TREE
5817
&& (!
TYPE_FOR_JAVA (ctype) || check_java_method (decl))
5818
&& check)
5819
{
…
5865
}
5866
5867
if (DECL_CONSTRUCTOR_P
(decl) && !grok_ctor_properties (ctype, decl))
5868
return
NULL_TREE;
5869
5870
if (ctype == NULL_TREE ||
check)
5871
return
decl;
5872
5873
if (virtualp)
5874
DECL_VIRTUAL_P (decl) = 1;
5875
5876
return
decl;
5877
}
在离开
grokfndecl
之前,还需要一些检查。对于构造函数,它不能是
X(X)
的形式,因为如果不慎对自己赋值将导致无限递归。在
5867
行,
grok_ctor_properties
进行这个检查。
grokdeclarator (continue)
8266
/* [class.conv.ctor]
8267
8268
A constructor declared without the
function-specifier
8269
explicit that can be called with a single
parameter
8270
specifies
a conversion from the type of its first
8271
parameter to the type of its class. Such
a constructor
8272
is called a converting constructor.
*/
8273
if (explicitp == 2)
8274
DECL_NONCONVERTING_P
(decl) = 1;
8275
else if
(DECL_CONSTRUCTOR_P (decl))
8276
{
8277
/* The constructor can be called with exactly one
8278
parameter if there is at least one parameter,
and
8279
any
subsequent parameters have default arguments.
8280
Ignore any compiler-added parms.
*/
8281
tree arg_types =
FUNCTION_FIRST_USER_PARMTYPE (decl);
8282
8283
if (arg_types ==
void_list_node
8284
|| (arg_types
8285
&&
TREE_CHAIN (arg_types)
8286
&&
TREE_CHAIN (arg_types) != void_list_node
8287
&&
!TREE_PURPOSE (TREE_CHAIN (arg_types))))
8288
DECL_NONCONVERTING_P
(decl) = 1;
8289
}
8290
}
…
8548
}
8549
8550
my_friendly_assert
(!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
8551
8552
/*
Record `register' declaration for warnings on &
8553
and
in case doing stupid register allocation.
*/
8554
8555
if (RIDBIT_SETP
(RID_REGISTER, specbits))
8556
DECL_REGISTER (decl) =
1;
8557
8558
if (RIDBIT_SETP
(RID_EXTERN, specbits))
8559
DECL_THIS_EXTERN (decl)
= 1;
8560
8561
if (RIDBIT_SETP
(RID_STATIC, specbits))
8562
DECL_THIS_STATIC (decl)
= 1;
8563
8564
/*
Record constancy and volatility. There's no need to do this
8565
when
processing a template; we'll do this for the instantiated
8566
declaration based on the type of DECL.
*/
8567
if (!processing_template_decl
)
8568
c_apply_type_quals_to_decl (type_quals, decl);
8569
8570
return
decl;
8571
}
8572
}
我们知道,带有参数的构造函数可以被用作转换操作符,除非它被声明为“
explict
”。而且只有构造函数可被声明为“
explicit
”,如果
explicitp
为
2
,则表示其使用没问题。能用作转换构造函数的构造函数必须带有至少一个参数,而且除第一个参数外,其他参数需要具有缺省值。
现在我们已经构建了方法的树节点,但其设置尚未完成。因此在
start_method
的余下部分,它为构造函数完成节点的设置。注意
fndecl
是由
grokdeclarator
构建的
FUNCTION_DECL
节点。
start_method (continue)
11051
if (fndecl ==
error_mark_node)
11052
return
error_mark_node;
11053
11054
if (fndecl == NULL ||
TREE_CODE (fndecl) != FUNCTION_DECL)
11055
{
11056
error ("invalid
member function declaration");
11057
return
error_mark_node;
11058
}
11059
11060
if (attrlist)
11061
cplus_decl_attributes
(&fndecl, attrlist, 0);
11062
11063
/*
Pass friends other than inline friend functions back.
*/
11064
if (fndecl ==
void_type_node)
11065
return
fndecl;
11066
11067
if (DECL_IN_AGGR_P (fndecl))
11068
{
11069
if (IDENTIFIER_ERROR_LOCUS
(DECL_ASSEMBLER_NAME (fndecl)) != current_class_type
)
11070
{
11071
if (DECL_CONTEXT
(fndecl)
11072
&& TREE_CODE(
DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
11073
error ("`%D' is
already defined in class `%T'", fndecl,
11074
DECL_CONTEXT
(fndecl));
11075
}
11076
return
void_type_node;
11077
}
11078
11079
check_template_shadow
(fndecl);
11080
11081
DECL_DECLARED_INLINE_P
(fndecl) = 1;
11082
if (flag_default_inline)
11083
DECL_INLINE (fndecl) = 1;
11084
11085
/*
We process method specializations in finish_struct_1.
*/
11086
if (processing_template_decl
&&
!DECL_TEMPLATE_SPECIALIZATION (fndecl))
11087
{
11088
fndecl = push_template_decl
(fndecl);
11089
if (fndecl ==
error_mark_node)
11090
return
fndecl;
11091
}
11092
11093
if (! DECL_FRIEND_P
(fndecl))
11094
{
11095
if (TREE_CHAIN (fndecl))
11096
{
11097
fndecl = copy_node
(fndecl);
11098
TREE_CHAIN (fndecl) =
NULL_TREE;
11099
}
11100
grok_special_member_properties
(fndecl);
11101
}
11102
11103
cp_finish_decl (fndecl,
NULL_TREE, NULL_TREE, 0);
11104
11105
/*
Make a place for the parms.
*/
11106
begin_scope
(sk_function_parms, fndecl);
11107
11108
DECL_IN_AGGR_P (fndecl) = 1;
11109
return
fndecl;
11110
}
因为我们仍然在类模板中,所以它需要检查该声明符是否会屏蔽模板参数。在
15224
行的
DECL_TEMPLATE_SPECIALIZATION
检查
DECL_USE_TEMPLATE
域是否等于
2
(这表示显式特化)。毫无疑问,在这里,这个构造函数也被视为一个模板声明,因为它被包含在一个类模板中。在前面的章节中我们多次看过
push_template_decl
,注意到因为不是直接包含在域
sk_template_parms
中,在
push_template_decl_real
的局部变量
primary
是
false
。当从
push_template_decl
返回时,中间树加入了以下的节点。
(
点此打开
)
图
70
:“
Lock
”构造函数的
FUNCTION_DECL
—第三步
在成功地创建了相应的
TEMPLATE_DECL
并把它加入到上下文环境中,包含类节点的某些标记需要相应地设置。
8900
void grok_special_member_properties
(tree decl)
in
decl.c
8901
{
8902
if
(!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
8903
; /*
Not special.
*/
8904
else if (DECL_CONSTRUCTOR_P
(decl))
8905
{
8906
int ctor = copy_fn_p
(decl);
8907
8908
if (ctor > 0)
8909
{
8910
/*
[class.copy]
8911
8912
A non-template constructor for class X is a
copy
8913
constructor if its first parameter is of
type X&, const
8914
X&, volatile X& or const volatile
X&, and either there
8915
are no other parameters or else all other
parameters have
8916
default arguments.
*/
8917
TYPE_HAS_INIT_REF
(DECL_CONTEXT (decl)) = 1;
8918
if (ctor > 1)
8919
TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
8920
}
8921
else if (sufficient_parms_p
(FUNCTION_FIRST_USER_PARMTYPE
(decl)))
8922
TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
8923
}
8924
else if
(DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
8925
{
…
8942
}
8943
}
上面在
8906
行,
copy_fn_p
检查
decl
是否是拷贝构造函数或赋值操作符,如果它都不是,则返回
0
。那么
FUNCTION_FIRST_USER_PARMTYPE
获取第一个非人造的参数(也即跳过参数
const this*
)。
983
#define
FUNCTION_FIRST_USER_PARMTYPE
(NODE) /
in cp-tree.h
984
skip_artificial_parms_for
((NODE),
TYPE_ARG_TYPES (TREE_TYPE (NODE)))
上面的图清除地解释了
skip_artificial_parms_for
的行为。注意到只有从虚基类派生的类,
DECL_HAS_IN_CHARGE_PARM_P
及
DECL_HAS_VTT_PARM_P
才可能返回非
0
值。
1061
tree
1062
skip_artificial_parms_for
(tree fn, tree list)
in
method.c
1063
{
1064
if
(DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
1065
list = TREE_CHAIN (list);
1066
else
1067
return
list;
1068
1069
if
(DECL_HAS_IN_CHARGE_PARM_P (fn))
1070
list = TREE_CHAIN (list);
1071
if (DECL_HAS_VTT_PARM_P
(fn))
1072
list = TREE_CHAIN (list);
1073
return
list;
1074
}
注意,非可变参数的
FUNCTION_DECL
的参数链表必须由
void_list_node
结尾。
398
bool
399
sufficient_parms_p
(tree parmlist)
in
call.c
400
{
401
for
(; parmlist && parmlist != void_list_node;
402
parmlist = TREE_CHAIN
(parmlist))
403
if (!TREE_PURPOSE
(parmlist))
404
return
false;
405
return
true;
406
}
然后在
start_method
中,
cp_finish_decl
通过向节点中置入行号及初始值(如果有的话)完成对声明的处理。不过,因为在类模板中,该函数仅设置了
FUNCTION_DECL
节点的标记
DECL_INITIALIZED_IN_CLASS_P
。
另外,在
15244
行,
begin_scope
使得
FUNCTION_DECL
成为了当前的作用域(绑定域)。在这一步,中间树看起来如下:
(
点此打开
)
图
71
:“
Lock
”构造函数的
FUNCTION_DECL
—完成
相关文章推荐
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记(19续)
- GCC-3.4.6源代码学习笔记(51)
- GCC-3.4.6源代码学习笔记(125)
- GCC-3.4.6源代码学习笔记(24续)
- GCC-3.4.6源代码学习笔记(44)
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(161)
- GCC-3.4.6源代码学习笔记(112)
- GCC-3.4.6源代码学习笔记(10续3)
- GCC-3.4.6源代码学习笔记(60)
- GCC-3.4.6源代码学习笔记(13)
- GCC-3.4.6源代码学习笔记(141)
- GCC-3.4.6源代码学习笔记(49)
- GCC-3.4.6源代码学习笔记(48续)
- GCC-3.4.6源代码学习笔记(146)
- GCC-3.4.6源代码学习笔记(174)
- GCC-3.4.6源代码学习笔记(131)
- GCC-3.4.6源代码学习笔记(120)
- GCC-3.4.6源代码学习笔记 (104)