您的位置:首页 > 编程语言

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
(它极像我们之前看到的类方法的解析)。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: