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

5.12.3.2.1.1.3.1.    解析默认构造函数

类似于类“SingleThreaded”解析其成员,依次调用cp_parser_class_specifiercp_parser_member_specification_optcp_parser_member_declarationcp_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_pparserin_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     }

 

注意到在调用该函数时,flagsCP_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-idnested-name-specifie部分所限定的类或名字空间域中。[注意:如果修饰符是全局域::的解析操作符(resolution operator),该declarator-id援引声明在全局名字空间的名字。]

一个autostaticexternregistermutablefriendinlinevirtualtypedef说明符直接应用到每个在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的类型相同。

括号不改变嵌入的(embeddeddeclarator-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_specifiersNULL(即,没有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 }

 

Declaratorabstract-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-declaratorint本身是type-specifier);或者abstract- declarator,例如:“int (*)()”(跟在int后面的符号构成一个abstract-declaratorint本身是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_kindCP_PARSER_DECLARATOR_NAMED,而第一次进入WHILE块时,firsttrue。亦即,如果第一个符号是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-expresiontype-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_declaration12668行的变量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_ptrue

 

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-seqexception-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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值