Studying note of GCC-3.4.6 source (99)

5.12.3.2.1.1.3.4.    Parse default constructor

Following the similar path of class “SingleThreaded” to parse its member, with call stack of cp_parser_class_specifier, cp_parser_member_specification_opt, cp_parser_member_declaration, cp_parser_decl_specifier_seq, it comes to parse the decl-specifier as constructor with following code snippet.

 

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));

 

At line 6744, constructor_possible_p is the reverse of in_declarator_p slot in parser which is true during parsing declarator.

 

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   }

 

Notice the example given in the comment above 14217, for the example “template <typename T> S<T>::S();” the part “template <typename T> S<T>::” is the nested-name-specifier, routine cp_parser_class_name tells whether “S” stands for class-name or not; cp_parser_error_occurred will return non-zero if it is not. And type_decl returned by cp_parser_class_name is the TYPE_DECL representing the class. We will see the details of name-lookup in later.

 

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 }

 

Further, when cp_parser_constructor_declarator_p returns cp_parser_decl_specifier_seq, decl_spec remains as NULL. And then following code is executed:

 

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     }

 

Notice that at invocation of the function, flags is CP_PARSER_FLAGS_OPTIONAL which indicates constructor is optional. It will break out the WHILE loop at line 6819 and returns NULL as constrcutor is declarator instead of decl-specifier.

5.12.3.2.1.1.3.4.1.            Parse declarator

As constructor or destructor is declarator, if we write correct constructor or destructor, it should enter ELSE block at line 12603, and begins parsing the constructor as declarator.

A list of declarators appears after an optional decl-specifier-seq. Each declarator contains exactly one declarator-id; it names the identifier that is declared. An unqualified-id occurring in a declarator-id shall be a simple identifier except for the declaration of some special functions and for the declaration of template specializations or partial specializations. A declarator-id shall not be qualified except for the definition of a member function or static data member outside of its class, the definition or explicit instantiation of a function or variable member of a namespace outside of its namespace, or the definition of a previously declared explicit specialization outside of its namespace, or the declaration of a friend function that is a member of another class or namespace. When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers, and the member shall not have been introduced by a using declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id. [Note: if the qualifier is the global :: scope resolution operator, the declarator-id refers to a name declared in the global namespace scope. ]

An auto, static, extern, register, mutable, friend, inline, virtual, or typedef specifier applies directly to each declarator-id in a init-declarator-list; the type specified for each declarator-id depends on both the decl-specifier-seq and its declarator.

Thus, a declaration of a particular identifier has the form: “T D”, where T is a decl-specifier-seq and D is a declarator. Following is a recursive procedure for determining the type specified for the contained declarator-id by such a declaration.

First, the decl-specifier-seq determines a type. In a declaration T D, the decl-specifier-seq T determines the type “T.” [Example: in the declaration int unsigned i; the type specifiers int unsigned determine the type “unsigned int”]

In a declarationT D where D is an unadorned identifier the type of this identifier is “T”.

In a declarationT D where D has the form “( D1 )”, the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration: T D1

Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.

 

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);

 

In our example, decl_specifiers above is NULL (e.g., decl-specifier-seq part is absent). Then the declarator part is parsed by below function.

 

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 }

 

The grammar of declarator and abstract-declarator are given below.

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

The declarator can be an identifier, for example: int j; or direct-declarator, for example: int (*pf)() (tokens following int forms a direct-declarator, int itself is type-specifier); or abstract- declarator, for example: int (*)() (tokens following int forms an abstract-declarator, int itself is type-specifier, and putting tegother they form type-id).

Here ptr-operator is absent. At line 10287 cp_parser_ptr_operator makes test at line 10291 fail.

 

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       }

 

Notice that dcl_kind used is CP_PARSER_DECLARATOR_NAMED; and first is true for first entering the WHILE block. That is, if first token is CPP_NAME, it should indicate a 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

From the syntax tree, it can see that id-expression may share the same prefix “::[opt] nested-name-specifier [opt]” with the other rule of declarator-id. Further id-expression and type-name overlap in several rules. See that the front-end first tries declarator-id as id-expression.

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 }

 

For the constructor of the example, unqualifier-id is the simple identifier.

 

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   }

 

It gets the identifier “Lock” as declarator into declarator at line 10583. Notice that below at line 10640, ctor_dtor_or_conv_p is a pointer and now it refers to variable ctor_dtor_or_conv_p at line 12668 in cp_parser_member_declaration. As we currently within class “Lock”, it satisfies the condition at line 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 }

 

Here ctor_dtor_or_conv_p is used to detect constructor, destructor or conversion operators. It is set to -1 if the declarator is a name, and +1 if it is a function. Otherwise it is set to zero. So at line 10668, ctor_dtor_or_conv_p is set as -1.

Further if declarator gotten is SCOPE_REF, it specifies the binding scope for following tokens; it must make this scope into current one before handling the coming tokens. At line 10672, routine get_scope_of_declarator just sees if any such scope can be retrieved from declarator, if soo, the function returns the corresponding tree node.

Note the assignment at line 10677, as we just saw the declarator, it sets the flag in_declarator_p in parser to indicate the fact. This flag will affect the parsing procedure of following tokens of declarator. For our example “Lock() {}”, the next token of “Lock” is “(“. It loops back the WHILE loop at line 10392 and executes following code. Note member_p here is 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       }

 

See that no parameter presents and no cv-qualifier-seq and exception-specification follows, just make_call_declarator is executed.

 

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    }

 

By this function, tree node of CALL_EXPR is created for declarator. Then returns back cp_parser_declarator further wraps it with another tree_list with possible attributes. In fact, we will have following node created when returns back cp_parser_member_declaration.

(Click here for open)

Figure 67: CALL_EXPR for ctor of class “Lock”

 

你可能感兴趣的:(tree,token,Constructor,nested,attributes,destructor)