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

GCC-3.4.6源代码学习笔记 (102)

2010-09-16 11:50 423 查看
5.12.3.2.1.1.3.5.


解析其它构造函数


在解析了默认构造函数后,我们回到
cp_parser_member_specification_opt

,它开始解析下一个构造函数:
Lock(const
Host&) {}

这是一个很有趣的构造函数,因为它的参数是类模板的模板参数。既然我们已经看过解析默认构造函数的过程,在这里我们只看不同的部分。

5.12.3.2.1.1.3.5.1.


解析参数


对于这个构造函数,它具有参数,因此在
10467
行,在
cp_parser_direct_declarator

里,该参数由
cp_parser_parameter_declaration_clause

来解析。

11026

static
tree

11027

cp_parser_parameter_declaration_clause

(cp_parser* parser)

in parser.c

11028

{

11029

tree parameters;

11030

cp_token *token;

11031

bool ellipsis_p;

11032

11033

/*
Peek at the next token.
*/

11034

token = cp_lexer_peek_token
(parser->lexer);

11035

/*
Check for trivial parameter-declaration-clauses.
*/

11036

if (token->type ==
CPP_ELLIPSIS)

11037

{

11038

/*
Consume the `...' token.
*/

11039

cp_lexer_consume_token
(parser->lexer);

11040

return
NULL_TREE;

11041

}

11042

else if (token->type ==
CPP_CLOSE_PAREN)

11043

/* There are no parameters.
*/

11044

{

11045

#ifndef
NO_IMPLICIT_EXTERN_C

11046

if (in_system_header
&& current_class_type == NULL

11047

&& current_lang_name
== lang_name_c)

11048

return
NULL_TREE;

11049

else

11050

#endif

11051

return
void_list_node;

11052

}

11053

/*
Check for `(void)', too, which is a special case.
*/

11054

else if (token->keyword
== RID_VOID

11055

&&
(cp_lexer_peek_nth_token (parser->lexer, 2)->type

11056

==
CPP_CLOSE_PAREN))

11057

{

11058

/*
Consume the `void' token.

*/

11059

cp_lexer_consume_token (parser->lexer);

11060

/*
There are no parameters.
*/

11061

return
void_list_node;

11062

}

11063

11064

/*
Parse the parameter-declaration-list.

*/

11065

parameters =
cp_parser_parameter_declaration_list

(parser);

11066

/*
If a parse error occurred while parsing the

11067

parameter-declaration-list, then the entire

11068

parameter-declaration-clause is erroneous.
*/

11069

if (parameters ==
error_mark_node)

11070

return
error_mark_node;

所有的参数都将由
cp_parser_parameter_declaration_list

通过
tree_list
节点串接起来。

11109

static
tree

11110

cp_parser_parameter_declaration_list

(cp_parser* parser)

in parser.c

11111

{

11112

tree parameters = NULL_TREE;

11113

11114

/*
Look for more parameters.
*/

11115

while
(true)

11116

{

11117

tree parameter;

11118

bool parenthesized_p;

11119

/*
Parse the parameter.
*/

11120

parameter

11121

=
cp_parser_parameter_declaration

(parser,

11122

/*template_parm_p=*/
false,

11123

&parenthesized_p);

11124

11125

/* If a parse error occurred parsing the
parameter declaration,

11126

then
the entire parameter-declaration-list is erroneous.
*/

11127

if (parameter ==
error_mark_node)

11128

{

11129

parameters =
error_mark_node;

11130

break
;

11131

}

11132

/* Add the new parameter to the list.
*/

11133

TREE_CHAIN (parameter) =
parameters;

11134

parameters = parameter;

11135

11136

/* Peek at the next token.
*/

11137

if (cp_lexer_next_token_is
(parser->lexer,
CPP_CLOSE_PAREN)

11138

|| cp_lexer_next_token_is
(parser->lexer,
CPP_ELLIPSIS))

11139

/*
The parameter-declaration-list is complete.

*/

11140

break
;



11187

}

11188

11189

/*
We built up the list in reverse order; straighten it out now.
*/

11190

return
nreverse (parameters);

11191

}

由上可见,串中的每个节点都是由
cp_parser_parameter_declaration

准备的。

11215

static
tree

11216

cp_parser_parameter_declaration

(cp_parser *parser,

in parser.c

11217

bool
template_parm_p,

11218

bool *parenthesized_p)

11219

{

11220

int declares_class_or_enum;

11221

bool
greater_than_is_operator_p;

11222

tree decl_specifiers;

11223

tree attributes;

11224

tree declarator;

11225

tree default_argument;

11226

tree parameter;

11227

cp_token *token;

11228

const
char *saved_message;

11229

11230

/*
In a template parameter, `>' is not an operator.

11231

11232

[temp.param]

11233

11234

When
parsing a default template-argument for a non-type

11235

template-parameter, the first non-nested `>' is taken as the end

11236

of the
template parameter-list rather than a greater-than

11237

operator.
*/

11238

greater_than_is_operator_p =
!template_parm_p;

11239

11240

/*
Type definitions may not appear in parameter types.

*/

11241

saved_message = parser->type_definition_forbidden_message;

11242

parser->type_definition_forbidden_message

11243

= "types may not be
defined in parameter types";

11244

11245

/*
Parse the declaration-specifiers.
*/

11246

decl_specifiers

11247

=
cp_parser_decl_specifier_seq
(parser,

11248

CP_PARSER_FLAGS_NONE,

11249

&attributes,

11250

&declares_class_or_enum);

11251

/*
If an error occurred, there's no reason to attempt to parse the

11252

rest
of the declaration.
*/

11253

if (cp_parser_error_occurred
(parser))

11254

{

11255

parser->type_definition_forbidden_message = saved_message;

11256

return
error_mark_node;

11257

}


const Host

是一个
decl-specifier-seq
。那么
cp_parser_decl_specifier_seq

通过重复调用
cp_parser_type_specifier

不停地解析这个序列。在第一次调用中对于关键字
const

返回了“
const
”的唯一节点;而在第二次调用中,通过下列的调用栈:
cp_parser_type_specifier

à

cp_parser_simple_type_specifier

à

cp_parser_type_name

à

cp_parser_class_name

à

cp_parser_identifier


cp_parser_lookup_name

à

lookup_name_real

,找出“
Host
”的
TYPE_DECL
节点。

cp_parser_parameter_declaration_clause (continue)

11259

/*
Peek at the next token.
*/

11260

token = cp_lexer_peek_token
(parser->lexer);

11261

/*
If the next token is a `)', `,', `=', `>', or `...', then there

11262

is no
declarator.
*/

11263

if (token->type ==
CPP_CLOSE_PAREN

11264

|| token->type ==
CPP_COMMA

11265

|| token->type ==
CPP_EQ

11266

|| token->type ==
CPP_ELLIPSIS

11267

|| token->type ==
CPP_GREATER)

11268

{

11269

declarator = NULL_TREE;

11270

if (parenthesized_p)

11271

*parenthesized_p =
false;

11272

}

11273

/*
Otherwise, there should be a declarator.

*/

11274

else

11275

{

11276

bool
saved_default_arg_ok_p = parser->default_arg_ok_p;

11277

parser->default_arg_ok_p = false;

11278

11279

/*
After seeing a decl-specifier-seq, if the next token is not a

11280

"(", there is no possibility that the code is a valid

11281

expression. Therefore, if parsing tentatively, we commit at

11282

this
point.
*/

11283

if
(!parser->in_template_argument_list_p

11284

/* In an expression context, having seen:

11285

11286

(int((char ...

11287

11288

we cannot be sure whether we are looking at a

11289

function-type (taking a "char" as a parameter) or a cast

11290

of some object of type "char" to "int".
*/

11291

&& !parser->in_type_id_in_expr_p

11292

&&
cp_parser_parsing_tentatively (parser)

11293

&&
!cp_parser_committed_to_tentative_parse (parser)

11294

&&
cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))

11295

cp_parser_commit_to_tentative_parse
(parser);

11296

/* Parse the declarator.

*/

11297

declarator =
cp_parser_declarator

(parser,

11298

CP_PARSER_DECLARATOR_EITHER,

11299

/*ctor_dtor_or_conv_p=*/
NULL,

11300

parenthesized_p,

11301

/*member_p=*/
false);

11302

parser->default_arg_ok_p
= saved_default_arg_ok_p;

11303

/*
After the declarator, allow more attributes.

*/

11304

attributes = chainon (attributes, cp_parser_attributes_opt (parser));

11305

}

随后的符号“
&
”是声明符。因此在
11297
行,
cp_parser_declarator

被调用。注意到参数
dcl_kind


CP_PARSER_DECLARATOR_EITHER
,它表示声明符(
declarator
)或者抽象声明符(
abstract-declarator
)都可以。事实上,“
&
”是一个抽象声明符,因为它不代表任何标识符的名字。

10259

static
tree

10260

cp_parser_declarator (cp_parser* parser,
in parser.c

10261

cp_parser_declarator_kind
dcl_kind,

10262

int*
ctor_dtor_or_conv_p,

10263

bool* parenthesized_p,

10264

bool
member_p)

10265

{

10266

cp_token *token;

10267

tree declarator;

10268

enum
tree_code code;

10269

tree cv_qualifier_seq;

10270

tree class_type;

10271

tree attributes = NULL_TREE;

10272

10273

/*
Assume this is not a constructor, destructor, or type-conversion

10274

operator.
*/

10275

if (ctor_dtor_or_conv_p)

10276

*ctor_dtor_or_conv_p = 0;

10277

10278

if
(cp_parser_allow_gnu_extensions_p (parser))

10279

attributes = cp_parser_attributes_opt
(parser);

10280

10281

/*
Peek at the next token.
*/

10282

token = cp_lexer_peek_token
(parser->lexer);

10283

10284

/*
Check for the ptr-operator production.

*/

10285

cp_parser_parse_tentatively
(parser);

10286

/*
Parse the ptr-operator.
*/

10287

code =
cp_parser_ptr_operator

(parser,

10288

&class_type,

10289

&cv_qualifier_seq);

10290

/*
If that worked, then we have a ptr-operator.

*/

10291

if (cp_parser_parse_definitely
(parser))

10292

{

10293

/* If a ptr-operator was found, then this
declarator was not

10294

parenthesized.
*/

10295

if (parenthesized_p)

10296

*parenthesized_p = true;

10297

/*
The dependent declarator is optional if we are parsing an

10298

abstract-declarator.
*/

10299

if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)

10300

cp_parser_parse_tentatively
(parser);

10301

10302

/*
Parse the dependent declarator.
*/

10303

declarator = cp_parser_declarator
(parser, dcl_kind,

10304

/*ctor_dtor_or_conv_p=*/
NULL,

10305

/*parenthesized_p=*/
NULL,

10306

/*member_p=*/
false);

10307

10308

/* If we are parsing an abstract-declarator,
we must handle the

10309

case
where the dependent declarator is absent.

*/

10310

if (dcl_kind !=
CP_PARSER_DECLARATOR_NAMED

10311

&& !
cp_parser_parse_definitely

(parser))

10312

declarator = NULL_TREE;

10313

10314

/* Build the representation of the
ptr-operator.
*/

10315

if (code == INDIRECT_REF)

10316

declarator =
make_pointer_declarator (cv_qualifier_seq,

10317

declarator);

10318

else

10319

declarator =
make_reference_declarator

(cv_qualifier_seq,

10320

declarator);

10321

/*
Handle the pointer-to-member case.
*/

10322

if (class_type)

10323

declarator = build_nt
(SCOPE_REF, class_type, declarator);

10324

}

10325

/*
Everything else is a direct-declarator.

*/

10326

else

10327

{

10328

if (parenthesized_p)

10329

*parenthesized_p = cp_lexer_next_token_is
(parser->lexer,

10330

CPP_OPEN_PAREN);

10331

declarator = cp_parser_direct_declarator
(parser,
dcl_kind,

10332

ctor_dtor_or_conv_p,

10333

member_p);

10334

}

10335

10336

if (attributes &&
declarator != error_mark_node)

10337

declarator = tree_cons
(attributes, declarator, NULL_TREE);

10338

10339

return
declarator;

10340

}

ptr-operator
具有以下的语法。它代表或者有、或者没有
cv-qualifier
部分的直接(引用)或间接(指针)的引用。因此
cp_parser_ptr_operator

的返回值是
ADDR_EXPR
或者
INDIRECT_REF


ptr-operator




*

cv-qualifier-seq


[opt]

|



cv-qualifier


cv-qualifier-seq [opt]


&


const

|



volatile

|



__restrict__

GNU Ext


::[opt]

nested-name-specifier * cv-qualifier-seq [opt]

GNU Ext

&

cv-qualifier-seq [opt]

10729

static
enum
tree_code

10730

cp_parser_ptr_operator

(cp_parser* parser,
in
parser.c

10731

tree*
type,

10732

tree*
cv_qualifier_seq)

10733

{

10734

enum
tree_code code = ERROR_MARK;

10735

cp_token *token;

10736

10737

/*
Assume that it's not a pointer-to-member.

*/

10738

*type = NULL_TREE;

10739

/*
And that there are no cv-qualifiers.
*/

10740

*cv_qualifier_seq =
NULL_TREE;

10741

10742

/*
Peek at the next token.
*/

10743

token = cp_lexer_peek_token
(parser->lexer);

10744

/*
If it's a `*' or `&' we have a pointer or reference.
*/

10745

if (token->type ==
CPP_MULT || token->type == CPP_AND)

10746

{

10747

/*
Remember which ptr-operator we were processing.

*/

10748

code = (token->type ==
CPP_AND ? ADDR_EXPR : INDIRECT_REF);

10749

10750

/*
Consume the `*' or `&'.

*/

10751

cp_lexer_consume_token

(parser->lexer);

10752

10753

/* A `*' can be followed by a
cv-qualifier-seq, and so can a

10754

`&', if we are allowing GNU extensions. (The only qualifier

10755

that
can legally appear after `&' is `restrict', but that is

10756

enforced during semantic analysis.

*/

10757

if (code == INDIRECT_REF

10758

|| cp_parser_allow_gnu_extensions_p
(parser))

10759

*cv_qualifier_seq =
cp_parser_cv_qualifier_seq_opt

(parser);

10760

}

10761

else

10762

{

10763

/* Try the pointer-to-member case.
*/

10764

cp_parser_parse_tentatively
(parser);

10765

/*
Look for the optional `::' operator.
*/

10766

cp_parser_global_scope_opt

(parser,

10767

/*current_scope_valid_p=*/
false);

10768

/*
Look for the nested-name specifier.
*/

10769

cp_parser_nested_name_specifier
(parser,

10770

/*typename_keyword_p=*/
false,

10771

/*check_dependency_p=*/
true,

10772

/*type_p=*/
false,

10773

/*is_declaration=*/
false);

10774

/*
If we found it, and the next token is a `*', then we are

10775

indeed looking at a pointer-to-member operator.
*/

10776

if
(!cp_parser_error_occurred (parser)

10777

&& cp_parser_require
(parser, CPP_MULT,
"`*'"))

10778

{

10779

/* The type of which the member is a member is
given by the

10780

current SCOPE.
*/

10781

*type = parser->scope;

10782

/*
The next name will not be qualified.
*/

10783

parser->scope =
NULL_TREE;

10784

parser->qualifying_scope = NULL_TREE;

10785

parser->object_scope
= NULL_TREE;

10786

/* Indicate that the `*' operator was
used.
*/

10787

code = INDIRECT_REF;

10788

/*
Look for the optional cv-qualifier-seq.

*/

10789

*cv_qualifier_seq =
cp_parser_cv_qualifier_seq_opt

(parser);

10790

}

10791

/*
If that didn't work we don't have a ptr-operator.
*/

10792

if (!cp_parser_parse_definitely
(parser))

10793

cp_parser_error (parser,
"expected ptr-operator");

10794

}

10795

10796

return
code;

10797

}

回到
cp_parser_declarator

,这个函数根据
cp_parser_ptr_operator

返回的节点码构建对应的树节点。不过,注意到在“
&
”后面没有跟着标识符,参数
target


NULL
,它对应于该声明符(它在
cp_parser_declarator


10312
行设置)。

113

tree

114

make_reference_declarator

(tree cv_qualifiers, tree target)
in
lex.c

115

{

116

target = build_nt
(ADDR_EXPR, target);

117

TREE_TYPE (target) =
cv_qualifiers;

118

return
target;

119

}

接下来处理可能的缺省参数,幸运的是,这里没有使用缺省参数。

cp_parser_parameter_declaration (continue)

11307

/*
The restriction on defining new types applies only to the type

11308

of the
parameter, not to the default argument.

*/

11309

parser->type_definition_forbidden_message = saved_message;

11310

11311

/*
If the next token is `=', then process a default argument.
*/

11312

if (cp_lexer_next_token_is
(parser->lexer,
CPP_EQ))

11313

{



11441

}

11442

else

11443

default_argument =
NULL_TREE;

11444

11445

/*
Create the representation of the parameter.

*/

11446

if (attributes)

11447

decl_specifiers = tree_cons
(attributes, NULL_TREE, decl_specifiers);

11448

parameter = build_tree_list
(default_argument,

11449

build_tree_list (decl_specifiers,

11450

declarator));

11451

11452

return
parameter;

11453

}

最后,把各部分组合起来,对于构造函数的参数,它是一棵相当复杂的树。


点此打开




74

:构造函数的参数

cp_parser_parameter_declaration_clause (continue)

11072

/*
Peek at the next token.
*/

11073

token = cp_lexer_peek_token
(parser->lexer);

11074

/*
If it's a `,', the clause should terminate with an ellipsis.
*/

11075

if (token->type ==
CPP_COMMA)

11076

{

11077

/*
Consume the `,'.
*/

11078

cp_lexer_consume_token
(parser->lexer);

11079

/*
Expect an ellipsis.
*/

11080

ellipsis_p

11081

= (cp_parser_require
(parser, CPP_ELLIPSIS, "`...'") != NULL);

11082

}

11083

/*
It might also be `...' if the optional trailing `,' was

11084

omitted.
*/

11085

else if (token->type ==
CPP_ELLIPSIS)

11086

{

11087

/*
Consume the `...' token.
*/

11088

cp_lexer_consume_token
(parser->lexer);

11089

/*
And remember that we saw it.

*/

11090

ellipsis_p = true;

11091

}

11092

else

11093

ellipsis_p = false;

11094

11095

/*
Finish the parameter list.
*/

11096

return
finish_parmlist
(parameters, ellipsis_p);

11097

}

最终,
finish_parmlist

为参数的节点设置需要的标记。

1994

tree

1995

finish_parmlist

(tree parms, int ellipsis)

in semantics.c

1996

{

1997

if (parms)

1998

{

1999

/*
We mark the PARMS as a parmlist so that declarator processing can

2000

disambiguate certain constructs.

*/

2001

TREE_PARMLIST (parms) = 1;

2002

/*
We do not append void_list_node here, but leave it to grokparms

2003

to
do that.
*/

2004

PARMLIST_ELLIPSIS_P
(parms) = ellipsis;

2005

}

2006

return
parms;

2007

}

注意到关于省略号参数(

)的信息保存在链的头一个节点中。因此中间树看起来就像:


点此打开




75

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