5.12.3.2.1.1.3.1. 解析默认构造函数
类似于类“SingleThreaded”解析其成员,依次调用cp_parser_class_specifier,cp_parser_member_specification_opt,cp_parser_member_declaration,cp_parser_decl_specifier_seq,在下面的代码片段中按照构造函数解析这个decl-specifier。
cp_parser_decl_specifier_seq (continue)
6741 /* Constructors are a special case. The `S' in `S()' is not a
6742 decl-specifier; it is the beginning of the declarator. */
6743 constructor_p = (!decl_spec
6744 && constructor_possible_p
6745 && cp_parser_constructor_declarator_p (parser,
6746 friend_p));
在6744行,constructor_possible_p是parser的in_declarator_p域取反。该域在解析声明符期间为true。
14161 static bool
14162 cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) in parser.c
14163 {
14164 bool constructor_p;
14165 tree type_decl = NULL_TREE;
14166 bool nested_name_p;
14167 cp_token *next_token;
14168
14169 /* The common case is that this is not a constructor declarator, so
14170 try to avoid doing lots of work if at all possible. It's not
14171 valid declare a constructor at function scope. */
14172 if (at_function_scope_p ())
14173 return false;
14174 /* And only certain tokens can begin a constructor declarator. */
14175 next_token = cp_lexer_peek_token (parser->lexer);
14176 if (next_token->type != CPP_NAME
14177 && next_token->type != CPP_SCOPE
14178 && next_token->type != CPP_NESTED_NAME_SPECIFIER
14179 && next_token->type != CPP_TEMPLATE_ID)
14180 return false;
14181
14182 /* Parse tentatively; we are going to roll back all of the tokens
14183 consumed here. */
14184 cp_parser_parse_tentatively (parser);
14185 /* Assume that we are looking at a constructor declarator. */
14186 constructor_p = true;
14187
14188 /* Look for the optional `::' operator. */
14189 cp_parser_global_scope_opt (parser,
14190 /*current_scope_valid_p=*/false);
14191 /* Look for the nested-name-specifier. */
14192 nested_name_p
14193 = (cp_parser_nested_name_specifier_opt (parser,
14194 /*typename_keyword_p=*/false,
14195 /*check_dependency_p=*/false,
14196 /*type_p=*/false,
14197 /*is_declaration=*/false)
14198 != NULL_TREE);
14199 /* Outside of a class-specifier, there must be a
14200 nested-name-specifier. */
14201 if (!nested_name_p &&
14202 (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
14203 || friend_p))
14204 constructor_p = false;
14205 /* If we still think that this might be a constructor-declarator,
14206 look for a class-name. */
14207 if (constructor_p)
14208 {
14209 /* If we have:
14210
14211 template <typename T> struct S { S(); };
14212 template <typename T> S<T>::S ();
14213
14214 we must recognize that the nested `S' names a class.
14215 Similarly, for:
14216
14217 template <typename T> S<T>::S<T> ();
14218
14219 we must recognize that the nested `S' names a template. */
14220 type_decl = cp_parser_class_name (parser,
14221 /*typename_keyword_p=*/false,
14222 /*template_keyword_p=*/false,
14223 /*type_p=*/false,
14224 /*check_dependency_p=*/false,
14225 /*class_head_p=*/false,
14226 /*is_declaration=*/false);
14227 /* If there was no class-name, then this is not a constructor. */
14228 constructor_p = !cp_parser_error_occurred (parser);
14229 }
注意到上面14217行的注释中给出的例子,对于例子“template <typename T> S<T>::S();”“template <typename T> S<T>::”部分是nested-name-specifier,函数cp_parser_class_name 确定“S”是否代表类名;如果不是,cp_parser_error_occurred将返回非0值。而由cp_parser_class_name返回的type_decl是代表该类的TYPE_DECL。我们在后面来看名字查找的过程。
cp_parser_constructor_declarator_p (continue)
14231 /* If we're still considering a constructor, we have to see a `(',
14232 to begin the parameter-declaration-clause, followed by either a
14233 `)', an `...', or a decl-specifier. We need to check for a
14234 type-specifier to avoid being fooled into thinking that:
14235
14236 S::S (f) (int);
14237
14238 is a constructor. (It is actually a function named `f' that
14239 takes one parameter (of type `int') and returns a value of type
14240 `S::S'. */
14241 if (constructor_p
14242 && cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
14243 {
14244 if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
14245 && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
14246 /* A parameter declaration begins with a decl-specifier,
14247 which is either the "attribute" keyword, a storage class
14248 specifier, or (usually) a type-specifier. */
14249 && !cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)
14250 && !cp_parser_storage_class_specifier_opt (parser))
14251 {
…
14298 }
14299 }
14300 else
14301 constructor_p = false;
14302 /* We did not really want to consume any tokens. */
14303 cp_parser_abort_tentative_parse (parser);
14304
14305 return constructor_p;
14306 }
接着,当cp_parser_constructor_declarator_p返回到cp_parser_decl_specifier_seq时,decl_spec保持为NULL。因此执行下面的代码。
cp_parser_decl_specifier_seq (continue)
6807 /* If we still do not have a DECL_SPEC, then there are no more
6808 decl-specifiers. */
6809 if (!decl_spec)
6810 {
6811 /* Issue an error message, unless the entire construct was
6812 optional. */
6813 if (!(flags & CP_PARSER_FLAGS_OPTIONAL))
6814 {
6815 cp_parser_error (parser, "expected decl specifier");
6816 return error_mark_node;
6817 }
6818
6819 break;
6820 }
注意到在调用该函数时,flags是CP_PARSER_FLAGS_OPTIONAL,它表示构造函数是可选的。在6819行,将跳出WHILE循环,并且返回NULL,因为构造函数是声明符(declarator)而不是decl-specifier。
5.12.3.2.1.1.3.4.1. 解析声明符
因为构造函数或析构函数是声明符,如果我们写下正确的构造函数或析构函数,我们将进入12603行的ELSE块,开始按照声明符来解析构造函数。
在一个可选的decl-specifier-seq后,跟着一列声明符。每个声明符仅包含一个declarator-id,它命名了所声明的标识符。出现在一个declarator-id中的unqualified-id应该是一个简单的标识符,除了某些特殊函数的声明及模板特化或偏特化的声明。一个declarator-id不应该是被修饰的(qualified),除非是在类定义体外的成员函数或静态数据成员的定义,或是在其名字空间外的变量或函数的定义及显式具现,或是在其名字空间外先前所声明的一个显式特化的定义,或是为另一个类或名字空间成员的友元函数的声明。当该declarator-id具有修饰时,该声明应该援引一个先前所声明的成员,该成员属于该修饰符所引用的名字空间或类,并且该成员不能由using声明引入,该using声明在该declarator-id的nested-name-specifie部分所限定的类或名字空间域中。[注意:如果修饰符是全局域::的解析操作符(resolution operator),该declarator-id援引声明在全局名字空间的名字。]
一个auto,static,extern,register,mutable,friend,inline,virtual或typedef说明符直接应用到每个在init-declarator-list中的declarator-id;每个declarator-id的类型依赖于该decl-specifier-seq及其声明符。
因此,一个特定标识符的声明具有形式:“T D”,其中T是一个decl-specifier-seq,而D是一个声明符。下面是一个确定由这样一个声明中所包含的declarator-id所指定的类型的递归过程。
首先,该decl-specifier-seq确定了一个类型。在声明T D中,decl-specifier-seq T确定了类型“T”。[例如:在声明int unsigned i;中,类型指示符int unsigned确定了类型“unsigned int”]
声明T D,其中D是一个未加修饰(unadorned)的标识符,该标识符的类型是“T”。
声明T D,其中D具有形式“( D1 )”,其中所包含的declarator-id的类型,与声明T D1中所包含的declarator-id的类型相同。
括号不改变嵌入的(embedded)declarator-id的类型,但它们可以改变复杂声明符的绑定。
cp_parser_member_declaration (continue)
12508 /* Check for an invalid type-name. */
12509 if (cp_parser_diagnose_invalid_type_name (parser))
12510 return;
12511 /* If there is no declarator, then the decl-specifier-seq should
12512 specify a type. */
12513 if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
12514 {
…
12602 }
12603 else
12604 {
12605 /* See if these declarations will be friends. */
12606 friend_p = cp_parser_friend_p (decl_specifiers);
12607
12608 /* Keep going until we hit the `;' at the end of the
12609 declaration. */
12610 while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
12611 {
12612 tree attributes = NULL_TREE;
12613 tree first_attribute;
12614
12615 /* Peek at the next token. */
12616 token = cp_lexer_peek_token (parser->lexer);
12617
12618 /* Check for a bitfield declaration. */
12619 if (token->type == CPP_COLON
12620 || (token->type == CPP_NAME
12621 && cp_lexer_peek_nth_token (parser->lexer, 2)->type
12622 == CPP_COLON))
12623 {
…
12657 }
12658 else
12659 {
12660 tree declarator;
12661 tree initializer;
12662 tree asm_specification;
12663 int ctor_dtor_or_conv_p;
12664
12665 /* Parse the declarator. */
12666 declarator
12667 = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
12668 &ctor_dtor_or_conv_p,
12669 /*parenthesized_p=*/NULL,
12670 /*member_p=*/true);
在我们的例子中,上面的decl_specifiers是NULL(即,没有decl-specifier-seq部分)。那么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 {
…
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 }
Declarator及abstract-declarator的语法如下:
declarator
├ ptr-operator declarator
├ direct-declarator
GNU Ext ├ attributes [opt] ptr-operator declarator
GNU Ext Ⅼ attributes [opt] director-declarator
abstract-declarator
├ ptr-operator abstract-declarator [opt]
├ direct-abstract-declarator
GNU Ext ├ attributes [opt] ptr-operator abstract-declarator [opt]
GNU Ext Ⅼ attributes [opt] direct-abstract-declarator
声明符可以是一个标识符,例如:“int j;”,或者direct- declarator,例如:“int (*pf)()”(跟在int后面的符号构成了一个direct-declarator,int本身是type-specifier);或者abstract- declarator,例如:“int (*)()”(跟在int后面的符号构成一个abstract-declarator,int本身是type-specifier,它们放在一起形成type-id)。
这里ptr-operator部分不出现。在10287行,cp_parser_ptr_operator使得在10291行的测试失败。
10378 static tree
10379 cp_parser_direct_declarator (cp_parser* parser, in parser.c
10380 cp_parser_declarator_kind dcl_kind,
10381 int* ctor_dtor_or_conv_p,
10382 bool member_p)
10383 {
10384 cp_token *token;
10385 tree declarator = NULL_TREE;
10386 tree scope = NULL_TREE;
10387 bool saved_default_arg_ok_p = parser->default_arg_ok_p;
10388 bool saved_in_declarator_p = parser->in_declarator_p;
10389 bool first = true;
10390 bool pop_p = false;
10391
10392 while (true)
10393 {
10394 /* Peek at the next token. */
10395 token = cp_lexer_peek_token (parser->lexer);
10396 if (token->type == CPP_OPEN_PAREN)
10397 {
…
10537 }
10538 else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
10539 && token->type == CPP_OPEN_SQUARE)
10540 {
…
10577 }
10578 else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
10579 {
10580 /* Parse a declarator-id */
10581 if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
10582 cp_parser_parse_tentatively (parser);
10583 declarator = cp_parser_declarator_id (parser);
10584 if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
10585 {
…
10593 }
10594
10595 if (declarator == error_mark_node)
10596 break;
10597
10598 if (TREE_CODE (declarator) == SCOPE_REF
10599 && !current_scope ())
10600 {
…
10636 }
注意到dcl_kind是CP_PARSER_DECLARATOR_NAMED,而第一次进入WHILE块时,first是true。亦即,如果第一个符号是CPP_NAME,应该表示是一个declarator-id。
10882 static tree
10883 cp_parser_declarator_id (cp_parser* parser) in parser.c
10884 {
10885 tree id_expression;
10886
10887 /* The expression must be an id-expression. Assume that qualified
10888 names are the names of types so that:
10889
10890 template <class T>
10891 int S<T>::R::i = 3;
10892
10893 will work; we must treat `S<T>::R' as the name of a type.
10894 Similarly, assume that qualified names are templates, where
10895 required, so that:
10896
10897 template <class T>
10898 int S<T>::R<T>::i = 3;
10899
10900 will work, too. */
10901 id_expression = cp_parser_id_expression (parser,
10902 /*template_keyword_p=*/false,
10903 /*check_dependency_p=*/false,
10904 /*template_p=*/NULL,
10905 /*declarator_p=*/true);
10906 /* If the name was qualified, create a SCOPE_REF to represent
10907 that. */
10908 if (parser->scope && id_expression != error_mark_node)
10909 {
10910 id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
10911 parser->scope = NULL_TREE;
10912 }
10913
10914 return id_expression;
10915 }
declarator-id
├ ::[opt] nested-name-specifier [opt] type-name
Ⅼ id-expression ├ class-name
├ unqualified-id | ├ identifier
Ⅼ qualifier-id | Ⅼ template-id
├ :: identifier ├ enum-name --- identifier
├ :: operator-function-id Ⅼ typedef-name --- identifier
├ :: [opt] nested-name-specifier [opt] template [opt] unqualified-id
Ⅼ :: template-id
Ⅼ template-name <template-argument-list [opt]>
Ⅼ identifier ├ template-argument-list, template-argument
Ⅼ template-argument
├ assignment-expression
├ type-id
Ⅼ id-expression
从这个语法树,可以看到id-expression可能与其他规则中的declarator-id共享相同的前缀“::[opt] nested-name-specifier [opt]”。另外,id-expresion与type-name的多个规则重叠。看到前端首先尝试按id-expression来解析declarator-id。
unqualified-id
├ identifier
├ operator-function-id
├ conversion-function-id
├ template-id
Ⅼ ~class-name
2685 static tree
2686 cp_parser_id_expression (cp_parser *parser, in parser.c
2687 bool template_keyword_p,
2688 bool check_dependency_p,
2689 bool *template_p,
2690 bool declarator_p)
2691 {
2692 bool global_scope_p;
2693 bool nested_name_specifier_p;
2694
2695 /* Assume the `template' keyword was not used. */
2696 if (template_p)
2697 *template_p = false;
2698
2699 /* Look for the optional `::' operator. */
2700 global_scope_p
2701 = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
2702 != NULL_TREE);
2703 /* Look for the optional nested-name-specifier. */
2704 nested_name_specifier_p
2705 = (cp_parser_nested_name_specifier_opt (parser,
2706 /*typename_keyword_p=*/false,
2707 check_dependency_p,
2708 /*type_p=*/false,
2709 declarator_p)
2710 != NULL_TREE);
2711 /* If there is a nested-name-specifier, then we are looking at
2712 the first qualified-id production. */
2713 if (nested_name_specifier_p)
2714 {
…
2740 }
2741 /* Otherwise, if we are in global scope, then we are looking at one
2742 of the other qualified-id productions. */
2743 else if (global_scope_p)
2744 {
…
2787 }
2788 else
2789 return cp_parser_unqualified_id (parser, template_keyword_p,
2790 /*check_dependency_p=*/true,
2791 declarator_p);
2792 }
对于例子中的构造函数,这个unqualifier-id是一个简单的标识符。
2816 static tree
2817 cp_parser_unqualified_id (cp_parser* parser, in parser.c
2818 bool template_keyword_p,
2819 bool check_dependency_p,
2820 bool declarator_p)
2821 {
2822 cp_token *token;
2823
2824 /* Peek at the next token. */
2825 token = cp_lexer_peek_token (parser->lexer);
2826
2827 switch (token->type)
2828 {
2829 case CPP_NAME:
2830 {
2831 tree id;
2832
2833 /* We don't know yet whether or not this will be a
2834 template-id. */
2835 cp_parser_parse_tentatively (parser);
2836 /* Try a template-id. */
2837 id = cp_parser_template_id (parser, template_keyword_p,
2838 check_dependency_p,
2839 declarator_p);
2840 /* If it worked, we're done. */
2841 if (cp_parser_parse_definitely (parser))
2842 return id;
2843 /* Otherwise, it's an ordinary identifier. */
2844 return cp_parser_identifier (parser);
2845 }
…
3033 }
3034 }
在10583行,标识符“Lock”作为声明符取入declarator中。注意到在下面的10640行,ctor_dtor_or_conv_p是一个指针,现在它指向在cp_parser_member_declaration中12668行的变量ctor_dtor_or_conv_p。因为我们现在在类“Lock”中,满足10643行的条件。
cp_parser_direct_declarator (continue)
10638 /* Check to see whether the declarator-id names a constructor,
10639 destructor, or conversion. */
10640 if (declarator && ctor_dtor_or_conv_p
10641 && ((TREE_CODE (declarator) == SCOPE_REF
10642 && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
10643 || (TREE_CODE (declarator) != SCOPE_REF
10644 && at_class_scope_p ())))
10645 {
10646 tree unqualified_name;
10647 tree class_type;
10648
10649 /* Get the unqualified part of the name. */
10650 if (TREE_CODE (declarator) == SCOPE_REF)
10651 {
10652 class_type = TREE_OPERAND (declarator, 0);
10653 unqualified_name = TREE_OPERAND (declarator, 1);
10654 }
10655 else
10656 {
10657 class_type = current_class_type;
10658 unqualified_name = declarator;
10659 }
10660
10661 /* See if it names ctor, dtor or conv. */
10662 if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
10663 || IDENTIFIER_TYPENAME_P (unqualified_name)
10664 || constructor_name_p (unqualified_name, class_type)
10665 || (TREE_CODE (unqualified_name) == TYPE_DECL
10666 && same_type_p (TREE_TYPE (unqualified_name),
10667 class_type)))
10668 *ctor_dtor_or_conv_p = -1;
10669 }
10670
10671 handle_declarator:;
10672 scope = get_scope_of_declarator (declarator);
10673 if (scope)
10674 /* Any names that appear after the declarator-id for a
10675 member are looked up in the containing scope. */
10676 pop_p = push_scope (scope);
10677 parser->in_declarator_p = true;
10678 if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
10679 || (declarator
10680 && (TREE_CODE (declarator) == SCOPE_REF
10681 || TREE_CODE (declarator) == IDENTIFIER_NODE)))
10682 /* Default args are only allowed on function
10683 declarations. */
10684 parser->default_arg_ok_p = saved_default_arg_ok_p;
10685 else
10686 parser->default_arg_ok_p = false;
10687
10688 first = false;
10689 }
10690 /* We're done. */
10691 else
10692 break;
10693 }
10694
10695 /* For an abstract declarator, we might wind up with nothing at this
10696 point. That's an error; the declarator is not optional. */
10697 if (!declarator)
10698 cp_parser_error (parser, "expected declarator");
10699
10700 /* If we entered a scope, we must exit it now. */
10701 if (pop_p)
10702 pop_scope (scope);
10703
10704 parser->default_arg_ok_p = saved_default_arg_ok_p;
10705 parser->in_declarator_p = saved_in_declarator_p;
10706
10707 return declarator;
10708 }
在这里ctor_dtor_or_conv_p用于检测构造函数,析构函数或转换操作符。如果该声明符是一个名字,它被设置为-1,如果是一个函数则是+1,否则就被设置为0。因此在10668行,ctor_dtor_or_conv_p被设置为-1。
进一步的,如果获得的声明符是SCOPE_REF,它指出了其后符号的绑定作用域,在处理后续符号之前,需要使得这个域成为当前作用域。在10672行,函数get_scope_of_declarator 检查是否有任何一个这样的域能从declarator获取,如果有,该函数返回相应的树节点。
注意在10677行的赋值,因为我们已经见到声明符,设置parser中的标记in_declarator_p来表明这个事实。这个标记将影响声明符后续符号的解析过程。对于我们的例子“Lock() {}”,“Lock”后面的符号是“(”。它将回到10392行的WHILE循环,并执行下面的代码。注意这里的member_p是true。
cp_parser_direct_declarator (continue)
10392 while (true)
10393 {
10394 /* Peek at the next token. */
10395 token = cp_lexer_peek_token (parser->lexer);
10396 if (token->type == CPP_OPEN_PAREN)
10397 {
10398 /* This is either a parameter-declaration-clause, or a
10399 parenthesized declarator. When we know we are parsing a
10400 named declarator, it must be a parenthesized declarator
10401 if FIRST is true. For instance, `(int)' is a
10402 parameter-declaration-clause, with an omitted
10403 direct-abstract-declarator. But `((*))', is a
10404 parenthesized abstract declarator. Finally, when T is a
10405 template parameter `(T)' is a
10406 parameter-declaration-clause, and not a parenthesized
10407 named declarator.
10408
10409 We first try and parse a parameter-declaration-clause,
10410 and then try a nested declarator (if FIRST is true).
10411
10412 It is not an error for it not to be a
10413 parameter-declaration-clause, even when FIRST is
10414 false. Consider,
10415
10416 int i (int);
10417 int i (3);
10418
10419 The first is the declaration of a function while the
10420 second is a the definition of a variable, including its
10421 initializer.
10422
10423 Having seen only the parenthesis, we cannot know which of
10424 these two alternatives should be selected. Even more
10425 complex are examples like:
10426
10427 int i (int (a));
10428 int i (int (3));
10429
10430 The former is a function-declaration; the latter is a
10431 variable initialization.
10432
10433 Thus again, we try a parameter-declaration-clause, and if
10434 that fails, we back out and return. */
10435
10436 if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
10437 {
10438 tree params;
10439 unsigned saved_num_template_parameter_lists;
10440
10441 /* In a member-declarator, the only valid interpretation
10442 of a parenthesis is the start of a
10443 parameter-declaration-clause. (It is invalid to
10444 initialize a static data member with a parenthesized
10445 initializer; only the "=" form of initialization is
10446 permitted.) */
10447 if (!member_p)
10448 cp_parser_parse_tentatively (parser);
10449
10450 /* Consume the `('. */
10451 cp_lexer_consume_token (parser->lexer);
10452 if (first)
10453 {
10454 /* If this is going to be an abstract declarator, we're
10455 in a declarator and we can't have default args. */
10456 parser->default_arg_ok_p = false;
10457 parser->in_declarator_p = true;
10458 }
10459
10460 /* Inside the function parameter list, surrounding
10461 template-parameter-lists do not apply. */
10462 saved_num_template_parameter_lists
10463 = parser->num_template_parameter_lists;
10464 parser->num_template_parameter_lists = 0;
10465
10466 /* Parse the parameter-declaration-clause. */
10467 params = cp_parser_parameter_declaration_clause (parser);
10468
10469 parser->num_template_parameter_lists
10470 = saved_num_template_parameter_lists;
10471
10472 /* If all went well, parse the cv-qualifier-seq and the
10473 exception-specification. */
10474 if (member_p || cp_parser_parse_definitely (parser))
10475 {
10476 tree cv_qualifiers;
10477 tree exception_specification;
10478
10479 if (ctor_dtor_or_conv_p)
10480 *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
10481 first = false;
10482 /* Consume the `)'. */
10483 cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
10484
10485 /* Parse the cv-qualifier-seq. */
10486 cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
10487 /* And the exception-specification. */
10488 exception_specification
10489 = cp_parser_exception_specification_opt (parser);
10490
10491 /* Create the function-declarator. */
10492 declarator = make_call_declarator (declarator,
10493 params,
10494 cv_qualifiers,
10495 exception_specification);
10496 /* Any subsequent parameter lists are to do with
10497 return type, so are not those of the declared
10498 function. */
10499 parser->default_arg_ok_p = false;
10500
10501 /* Repeat the main loop. */
10502 continue;
10503 }
10504 }
看到后面的符号中没有参数,cv-qualifier-seq及exception-specification出现,仅执行make_call_declarator。
121 tree
122 make_call_declarator (tree target, tree parms, tree cv_qualifiers, in lex.c
123 tree exception_specification)
124 {
125 target = build_nt (CALL_EXPR, target,
126 tree_cons (parms, cv_qualifiers, NULL_TREE),
127 /* The third operand is really RTL. We
128 shouldn't put anything there. */
129 NULL_TREE);
130 CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification;
131 return target;
132 }
通过这个函数,为声明符创建了树节点CALL_EXPR。那么返回到cp_parser_declarator进一步把它连同可能出现的属性封装入另一个tree_list节点。当返回到cp_parser_member_declaration时,如下的节点将得到创建。
(点此打开)
图67:类“Lock”构造函数的CALL_EXPR