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
:完成对构造函数参数的准备
解析其它构造函数
在解析了默认构造函数后,我们回到
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
:完成对构造函数参数的准备
相关文章推荐
- GCC-3.4.6源代码学习笔记(129 续)
- GCC-3.4.6源代码学习笔记(143)
- GCC-3.4.6源代码学习笔记(35)
- GCC-3.4.6源代码学习笔记(147-续2)
- GCC-3.4.6源代码学习笔记(132)
- GCC-3.4.6源代码学习笔记(78)
- GCC-3.4.6源代码学习笔记(44)
- GCC-3.4.6源代码学习笔记(26)
- GCC-3.4.6源代码学习笔记(163)
- GCC-3.4.6源代码学习笔记(110)
- GCC-3.4.6源代码学习笔记(26续2)
- GCC-3.4.6源代码学习笔记(139-续1)
- GCC-3.4.6源代码学习笔记(140)
- GCC-3.4.6源代码学习笔记(59)
- GCC-3.4.6源代码学习笔记(116)
- GCC-3.4.6源代码学习笔记(95)
- GCC-3.4.6源代码学习笔记(96)
- GCC-3.4.6源代码学习笔记(19续)
- GCC-3.4.6源代码学习笔记(21)
- GCC-3.4.6源代码学习笔记(133)