GCC-3.4.6源代码学习笔记(128)
2010-11-26 13:01
537 查看
5.12.5.
第三个例子
现在我们已经有了“SmallObject
”的定义,那么我们使用下面的“
main
”函数来使用这个类,从中看一下将会产生怎样的中间树。
using
namespace Loki;
int main ()
{
SmallObject<>
object_;
return
1;
}
5.12.5.1.
using
指示
假定这个“main
”函数在另一个源文件中,它也构成一个编译单元,因此解析器由以下调用开始,
cp_parser_translation_unit
à
cp_parser_declaration_seq_opt
,其中的
WHILE
循环将依次处理语句。
对于第一个是
using
指示的语句,调用栈进一步延伸,从
cp_parser_declaration
à
cp_parser_block_declaration
à
cp_parser_using_directive
à
parse_using_directive
à
do_using_directive
。
3350
void
3351
do_using_directive
(tree namespace)
in name-lookup.c
3352
{
3353
if (namespace == error_mark_node)
3354
return
;
3355
3356
my_friendly_assert (TREE_CODE (namespace) ==
NAMESPACE_DECL, 20050830);
3357
3358
if (building_stmt_tree ())
3359
add_stmt (build_stmt (USING_STMT,
namespace));
3360
namespace =
ORIGINAL_NAMESPACE
(namespace);
3361
3362
if (!toplevel_bindings_p ())
3363
push_using_directive (namespace);
3364
else
3365
/* direct usage */
3366
add_using_namespace
(
current_namespace
,
namespace, 0);
3367
}
如果
building_stmt_tree
是非
0
值,表示正在为函数、块等结构产生语句,那么
using
指示将有
USING_STMT
为之生成。这里的实参
namespace
是相应的
NAMESPACE_DECL
。在
3362
行,如果最里层的有效非类作用域是一个名字空间(
using
指示不允许在类域中使用,但可以用在其方法作用域中),
toplevel_bindings_p
返回非
0
值。例如:
namespace
A {
int i;
}
class
B {
int func() {
using
namespace A;
return
i;
}
};
对于用在名字空间域的那些
using
指示,在对应于该名字空间作用域的
NAMESPACE_DECL
节点中,域
DECL_NAMESPACE_USING
将是一个
tree_list
,通过
add_using_namespace
用来把这些
using
指示串接起来。
3275
static
void
3276
add_using_namespace
(tree user, tree
used, bool indirect)
in name-lookup.c
3277
{
3278
tree t;
3279
timevar_push (TV_NAME_LOOKUP);
3280
/* Using oneself is
a no-op.
*/
3281
if (user == used)
3282
{
3283
timevar_pop (TV_NAME_LOOKUP);
3284
return
;
3285
}
3286
my_friendly_assert (TREE_CODE (user) ==
NAMESPACE_DECL, 380);
3287
my_friendly_assert (TREE_CODE (used) ==
NAMESPACE_DECL, 380);
3288
/* Check if we
already have this.
*/
3290
t = purpose_member (used,
DECL_NAMESPACE_USING (user));
3291
if (t != NULL_TREE)
3292
{
3293
if (!indirect)
3294
/* Promote to
direct usage.
*/
3295
TREE_INDIRECT_USING (t) = 0;
3296
timevar_pop (TV_NAME_LOOKUP);
3297
return
;
3298
}
3299
3300
/* Add used to the
user's using list.
*/
3301
DECL_NAMESPACE_USING (user)
3302
= tree_cons
(used,
namespace_ancestor
(user, used),
3303
DECL_NAMESPACE_USING (user));
3304
3305
TREE_INDIRECT_USING (DECL_NAMESPACE_USING
(user)) = indirect;
3306
3307
/* Add user to the
used's users list.
*/
3308
DECL_NAMESPACE_USERS (used)
3309
= tree_cons
(user,
0, DECL_NAMESPACE_USERS (used));
3310
3311
/* Recursively add
all namespaces used.
*/
3312
for
(t =
DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
3313
/* indirect usage
*/
3314
add_using_namespace
(user, TREE_PURPOSE (t), 1);
3315
3316
/* Tell everyone
using us about the new used namespaces.
*/
3317
for
(t =
DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
3318
add_using_namespace
(TREE_PURPOSE (t), used, 1);
3319
timevar_pop (TV_NAME_LOOKUP);
3320
}
在
5.12.4.1.1.2.1.3.2.
其他名字
一节中,我们看到
using
指示的使用必须不能混淆名字空间的层次,在名字查找时,前端将严格按照其层次进行搜寻。
add_using_namespace
需要记录必要的层次信息。这里
namespace_ancestor
找出
ns1
及
ns2
最接近的公共祖先。看到所有的名字空间都有相同的公共祖先——全局名字空间。(关于
add_using_namespace
生成的这个列表的使用,参考
lookup_using_namespace
)。
3194
static
tree
3195
namespace_ancestor
(tree ns1, tree ns2)
in name-lookup.c
3196
{
3197
timevar_push (TV_NAME_LOOKUP);
3198
if (is_ancestor
(ns1, ns2))
3199
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
ns1);
3200
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
3201
namespace_ancestor
(CP_DECL_CONTEXT (ns1),
ns2));
3202
}
这里参数
root
是当前名字空间,而
child
是由
using
指示指定的名字空间。那么
is_ancestor
持续地从
child
开始获取上下文,直到找到
root
或离开这棵树。对于前一种情形,
root
是
child
的祖先,并且函数返回非
0
值;反之,函数返回
0
。
2502
bool
2503
is_ancestor
(tree root, tree child)
in name-lookup.c
2504
{
2505
my_friendly_assert ((TREE_CODE (root) ==
NAMESPACE_DECL
2506
|| TREE_CODE (root) ==
FUNCTION_DECL
2507
|| CLASS_TYPE_P (root)),
20030307);
2508
my_friendly_assert ((TREE_CODE (child) ==
NAMESPACE_DECL
2509
|| CLASS_TYPE_P (child)),
2510
20030307);
2511
2512
/* The global
namespace encloses everything.
*/
2513
if (root == global_namespace
)
2514
return
true;
2515
2516
while
(true)
2517
{
2518
/* If we've run
out of scopes, stop.
*/
2519
if (!child)
2520
return
false;
2521
/* If we've
reached the ROOT, it encloses CHILD.
*/
2522
if (root == child)
2523
return
true;
2524
/* Go out one level.
*/
2525
if (TYPE_P (child))
2526
child = TYPE_NAME (child);
2527
child = DECL_CONTEXT (child);
2528
}
2529
}
那么对于我们的例子,全局名字空间在其
DECL_NAMESPACE_USERS
域串接了“
Loki
”。
5.12.5.2.
Main()
的定义
5.12.5.2.1.函数定义
–
声明符部分
对于
main
函数,
cp_parser_declaration
又一次调用
cp_parser_block_declaration
à
cp_parser_simple_declaration
。在我们的上下文中,参数
function_definition_allowed_p
是
true
,这表示我们同时把一个函数定义(
function-definition
)识别作简单声明(
simple-declaration
)。
block-declaration
的语法如下:
block-declaration:
simple-declaration | asm-definition |
namespace-alias-definition | using-declaration |
using-directive
GNU
Extension:
block-declaration: __extension__
block-declaration |
label-declaration
6370
static
void
6371
cp_parser_block_declaration
(cp_parser
*parser,
in parser.c
6372
bool
statement_p)
6373
{
6374
cp_token *token1;
6375
int saved_pedantic;
6376
6377
/* Check for the
`__extension__' keyword.
*/
6378
if (cp_parser_extension_opt (parser,
&saved_pedantic))
6379
{
…
6386
}
6387
6388
/* Peek at the next
token to figure out which kind of declaration is
6389
present.
*/
6390
token1 = cp_lexer_peek_token
(parser->lexer);
6391
6392
/* If the next
keyword is `asm', we have an asm-definition.
*/
6393
if (token1->keyword == RID_ASM)
6394
{
…
6398
}
6399
/* If the next
keyword is `namespace', we have a
6400
namespace-alias-definition.
*/
6401
else if (token1->keyword == RID_NAMESPACE)
6402
cp_parser_namespace_alias_definition
(parser);
6403
/* If the next
keyword is `using', we have either a
6404
using-declaration or a
using-directive.
*/
6405
else if (token1->keyword == RID_USING)
6406
{
…
6419
}
6420
/* If the next
keyword is `__label__' we have a label declaration.
*/
6421
else if (token1->keyword == RID_LABEL)
6422
{
…
6426
}
6427
/* Anything else must
be a simple-declaration.
*/
6428
else
6429
cp_parser_simple_declaration
(parser, !statement_p);
6430
}
simple-declaration
的语法是:
simple-declaration:
decl-specifier-seq [opt] init-declarator-list
[opt] ;
init-declarator-list:
init-declarator | init-declarator-list ,
init-declarator
看到
simple-declaration
可能被包含在一个
block-declaraition
中,而该
block-declaraition
则可能在一个函数域或类方法域中,其中要求访问控制,因此期望一个新的延迟访问实例。而在
6475
行的
stop_deferring_access_checks
防止加入更多由
perform_or_defer_access_check
检查的延迟访问控制,不过对于
decl-specifier-seq
及
init-declarator-list
访问检查都是需要的,因此稍后将通过
resume_deferring_access_checks
重新开始检查。
6444
static
void
6445
cp_parser_simple_declaration
(cp_parser*
parser,
in parser.c
6446
bool function_definition_allowed_p)
6447
{
6448
tree decl_specifiers;
6449
tree attributes;
6450
int declares_class_or_enum;
6451
bool saw_declarator;
6452
6453
/* Defer access
checks until we know what is being declared; the
6454
checks for names appearing in
the decl-specifier-seq should be
6455
done as if we were in the
scope of the thing being declared.
*/
6456
push_deferring_access_checks
(dk_deferred);
6457
6458
/* Parse the
decl-specifier-seq. We have to keep track of whether
6459
or not the decl-specifier-seq
declares a named class or
6460
enumeration type, since that
is the only case in which the
6461
init-declarator-list is
allowed to be empty.
6462
6463
[dcl.dcl]
6464
6465
I
n a simple-declaration, the optional
init-declarator-list can be
6466
omitted only when declaring a
class or enumeration, that is when
6467
the decl-specifier-seq
contains either a class-specifier, an
6468
elaborated-type-specifier, or
an enum-specifier.
*/
6469
decl_specifiers
6470
= cp_parser_decl_specifier_seq (parser,
6471
CP_PARSER_FLAGS_OPTIONAL,
6472
&attributes,
6473
&declares_class_or_enum);
6474
/* We no longer
need to defer access checks.
*/
6475
stop_deferring_access_checks ();
6476
6477
/* In a block
scope, a valid declaration must always have a
6478
decl-specifier-seq. By not
trying to parse declarators, we can
6479
resolve the
declaration/expression ambiguity more quickly.
*/
6480
if (!function_definition_allowed_p &&
!decl_specifiers)
6481
{
6482
cp_parser_error (parser, "expected
declaration");
6483
goto
done;
6484
}
6485
6486
/* If the next two
tokens are both identifiers, the code is
6487
erroneous. The usual cause of
this situation is code like:
6488
6489
T t;
6490
6491
where "T" should
name a type -- but does not.
*/
6492
if (cp_parser_diagnose_invalid_type_name
(parser))
6493
{
6494
/* If parsing
tentatively, we should commit; we really are
6495
looking at a
declaration.
*/
6496
cp_parser_commit_to_tentative_parse
(parser);
6497
/* Give up.
*/
6498
goto
done;
6499
}
我们前面已经看到,
cp_parser_decl_specifier_seq
将解析函数的返回类型;那么在这里
decl_specifiers
是一个
tree_list
,其中的
TREE_VALUE
域指向
integer_type_node
节点。注意一个函数定义可能没有返回类型(它默认为
int
)。
1950
static
bool
1951
cp_parser_diagnose_invalid_type_name
(cp_parser *parser)
in parser.c
1952
{
1953
/* If the next two
tokens are both identifiers, the code is
1954
erroneous. The usual cause of
this situation is code like:
1955
1956
T t;
1957
1958
where "T" should
name a type -- but does not.
*/
1959
if (cp_lexer_next_token_is
(parser->lexer, CPP_NAME)
1960
&& cp_lexer_peek_nth_token
(parser->lexer, 2)->type
== CPP_NAME)
1961
{
1962
tree name;
1963
1964
/* If parsing
tentatively, we should commit; we really are
1965
looking at a
declaration.
*/
1966
/* Consume the first
identifier.
*/
1967
name = cp_lexer_consume_token
(parser->lexer)->value;
1968
/* Issue an error
message.
*/
1969
error ("`%s' does not name a
type", IDENTIFIER_POINTER (name));
1970
/* If we're in a
template class, it's possible that the user was
1971
referring to a type from a
base class. For example:
1972
1973
template <typename T>
struct A { typedef T X; };
1974
template <typename T>
struct B : public A<T> { X x; };
1975
1976
The user should have said
"typename A<T>::X".
*/
1977
if (processing_template_decl
&& current_class_type
)
1978
{
1979
tree b;
1980
1981
for
(b =
TREE_CHAIN (TYPE_BINFO (current_class_type
));
1982
b;
1983
b = TREE_CHAIN (b))
1984
{
1985
tree base_type = BINFO_TYPE (b);
1986
if (CLASS_TYPE_P (base_type)
1987
&& dependent_type_p
(base_type))
1988
{
1989
tree field;
1990
/* Go from
a particular instantiation of the
1991
template (which will
have an empty TYPE_FIELDs),
1992
to the main
version.
*/
1993
base_type =
CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type);
1994
for
(field = TYPE_FIELDS (base_type);
1995
field;
1996
field = TREE_CHAIN (field))
1997
if (TREE_CODE (field) == TYPE_DECL
1998
&& DECL_NAME (field) ==
name)
1999
{
2000
error ("(perhaps `typename
%T::%s' was intended)",
2001
BINFO_TYPE (b),
IDENTIFIER_POINTER (name));
2002
break
;
2003
}
2004
if (field)
2005
break
;
2006
}
2007
}
2008
}
2009
/* Skip to the end
of the declaration; there's no point in
2010
trying to process it.
*/
2011
cp_parser_skip_to_end_of_statement
(parser);
2012
2013
return
true;
2014
}
2015
2016
return
false;
2017
}
作为正确的形式,
decl-specifier-seq
的核心部分应该命名一个类型。通过名字查找规则找到的该类型将被返回给
decl-specifiers
;而如果没有找到适合的类型,这个符号保持为标识符,那么
cp_parser_diagnose_invalid_type_name
诊断这个错误情况,并给出诊断消息。
cp_parser_simple_declaration
(continue)
6501
/* If we have seen
at least one decl-specifier, and the next token
6502
is not a parenthesis, then we
must be looking at a declaration.
6503
(After "int (" we
might be looking at a functional cast.)
*/
6504
if (decl_specifiers
6505
&& cp_lexer_next_token_is_not
(parser->lexer, CPP_OPEN_PAREN))
6506
cp_parser_commit_to_tentative_parse
(parser);
6507
6508
/* Keep going until
we hit the `;' at the end of the simple
6509
declaration.
*/
6510
saw_declarator = false;
6511
while
(cp_lexer_next_token_is_not (parser->lexer,
6512
CPP_SEMICOLON))
6513
{
6514
cp_token *token;
6515
bool function_definition_p;
6516
tree decl;
6517
6518
saw_declarator = true;
6519
/* Parse the
init-declarator.
*/
6520
decl = cp_parser_init_declarator
(parser, decl_specifiers, attributes,
6521
function_definition_allowed_p,
6522
/*member_p=*/
false,
6523
declares_class_or_enum,
6524
&function_definition_p);
6525
/* If an error
occurred while parsing tentatively, exit quickly.
6526
(That usually happens when
in the body of a function; each
6527
statement is treated as a
declaration-statement until proven
6528
otherwise.)
*/
6529
if (cp_parser_error_occurred (parser))
6530
goto
done;
6531
/* Handle
function definitions specially.
*/
6532
if (function_definition_p)
6533
{
6534
/* If the next
token is a `,', then we are probably
6535
processing something like:
6536
6537
void f() {}, *p;
6538
6539
which is erroneous.
*/
6540
if (cp_lexer_next_token_is
(parser->lexer, CPP_COMMA))
6541
error ("mixing declarations and
function-definitions is forbidden");
6542
/* Otherwise,
we're done with the list of declarators.
*/
6543
else
6544
{
6545
pop_deferring_access_checks ();
6546
return
;
6547
}
6548
}
…
6580
}
…
6593
/* Consume the
`;'.
*/
6594
cp_parser_require (parser, CPP_SEMICOLON,
"`;'");
6595
6596
done:
6597
pop_deferring_access_checks ();
6598
}
注意到参数
declares_class_or_enum
是
0
,因为该
type-specifier
不是
class-specifier
,
enum-specifier
,也不是
elaborated-type-specifier
。
init-declarator
的内容包括:
init-declarator:
declarator initializer [opt]
function-definition:
decl-specifier-seq [opt] declarator
ctor-initializer [opt] function-body
decl-specifier-seq [opt] declarator
function-try-block
GNU
Extension:
init-declarator:
declarator asm-specification [opt]
attributes [opt] initializer [opt]
function-definition:
__extension__
function-definition
注意
ctor-initializer
仅用于构造函数中。
9933
static
tree
9934
cp_parser_init_declarator
(cp_parser*
parser,
in parser.c
9935
tree decl_specifiers,
9936
tree prefix_attributes,
9937
bool
function_definition_allowed_p,
9938
bool member_p,
9939
int
declares_class_or_enum,
9940
bool*
function_definition_p)
9941
{
9942
cp_token *token;
9943
tree declarator;
9944
tree attributes;
9945
tree asm_specification;
9946
tree initializer;
9947
tree decl = NULL_TREE;
9948
tree scope;
9949
bool is_initialized;
9950
bool is_parenthesized_init;
9951
bool is_non_constant_init;
9952
int ctor_dtor_or_conv_p;
9953
bool friend_p;
9954
bool pop_p = false;
9955
9956
/* Assume that this
is not the declarator for a function
9957
definition.
*/
9958
if (function_definition_p)
9959
*function_definition_p = false;
9960
9961
/* Defer access
checks while parsing the declarator; we cannot know
9962
what names are accessible
until we know what is being
9963
declared.
*/
9964
resume_deferring_access_checks ();
9965
9966
/* Parse the declarator.
*/
9967
declarator
9968
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
9969
&ctor_dtor_or_conv_p,
9970
/*parenthesized_p=*/
NULL,
9971
/*member_p=*/
false);
9972
/* Gather up the
deferred checks.
*/
9973
stop_deferring_access_checks ();
“
main ()
”部分是声明符,其中包括作为
declarator-id
的“
main
”,而“
()
”是参数列表。那么在
cp_parser_declarator
中,
cp_parser_direct_declarator
迭代其主
WHILE
循环
2
次。在第一次中调用:
cp_parser_declarator_id
à
cp_parser_id_expression
à
cp_parser_identifier
返回“
main
”的
IDENTIFIER_NODE
。第二次中调用:
cp_parser_parameter_declaration_clause
返回空参数列表对应的
void_list_node
。然后
make_call_declarator
把这个
declarator-id
及
parameter-list
组合成一个如下图的
CALL_EXPR
(它极像我们之前看到的类方法的解析)。
![](http://hi.csdn.net/attachment/201011/26/4457637_1290747622rcRK.jpg)
相关文章推荐
- GCC-3.4.6源代码学习笔记(97)
- GCC-3.4.6源代码学习笔记(47)
- GCC-3.4.6源代码学习笔记(98)
- GCC-3.4.6源代码学习笔记(68)
- GCC-3.4.6源代码学习笔记(149)
- GCC-3.4.6源代码学习笔记(21)
- GCC-3.4.6源代码学习笔记(121)
- GCC-3.4.6源代码学习笔记(86)
- GCC-3.4.6源代码学习笔记(165)
- GCC-3.4.6源代码学习笔记(139-续2)
- GCC-3.4.6源代码学习笔记(35)
- GCC-3.4.6源代码学习笔记(69)
- GCC-3.4.6源代码学习笔记(19续)
- GCC-3.4.6源代码学习笔记(130)
- GCC-3.4.6源代码学习笔记(175)
- GCC-3.4.6源代码学习笔记(159)
- GCC-3.4.6源代码学习笔记(180)
- GCC-3.4.6源代码学习笔记(26)
- GCC-3.4.6源代码学习笔记(57)
- GCC-3.4.6源代码学习笔记(26续2)