Studying note of GCC-3.4.6 source (128)

5.12.5.      The third example

Now we have definition of “SmallObject”, we use following “main” function to use this class, and see what’s immediate tree will be created.

using namespace Loki;

int main ()

{

SmallObject<> object_;

return 1;
}

5.12.5.1.              The using directive

Assuming that this “main” function lies in a separate source, which is a translation-unit, so the parser begins with following calls, cp_parser_translation_unit à cp_parser_declaration_seq_opt , in which the WHILE loop will process statements in turn.

For first statement of the using-directive, the call stack further goes down from cp_parser_declaration à cp_parser_block_declaration à cp_parser_using_directive à parse_using_directive à do_using_directive .

 

3350   void

3351   do_using_directive (tree namespace)                                                         in name-lookup.c

3352   {

3353     if (namespace == error_mark_node)

3354       return ;

3355  

3356     my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 20050830);

3357  

3358     if (building_stmt_tree ())

3359       add_stmt (build_stmt (USING_STMT, namespace));

3360     namespace = ORIGINAL_NAMESPACE (namespace);

3361  

3362     if (!toplevel_bindings_p ())

3363       push_using_directive (namespace);

3364     else

3365        /* direct usage */

3366       add_using_namespace ( current_namespace , namespace, 0);

3367   }

 

If building_stmt_tree is nonzero, it means we are generating statements for function, block etc, so the using-directive should have USING_STMT generated for. Here argument namespace is the associated NAMESPACE_DECL. At line 3362, toplevel_bindings_p returns nonzero if the innermost effective non-class binding scope is a namespace (using-directive is not allowed within class scope but can in method scope). For example:

namespace A {

    int i;

}

class B {

    int func() {

        using namespace A;

        return i;

    }

};

For those using-directives under namespace scope, in the NAMESPACE_DECL node for the namespace scope, field DECL_NAMESPACE_USING will be a tree_list to chain the using-directives tegother by add_using_namespace .

 

3275   static void

3276   add_using_namespace (tree user, tree used, bool indirect)                     in name-lookup.c

3277   {

3278     tree t;

3279     timevar_push (TV_NAME_LOOKUP);

3280     /* Using oneself is a no-op.  */

3281     if (user == used)

3282     {

3283       timevar_pop (TV_NAME_LOOKUP);

3284       return ;

3285     }

3286     my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);

3287     my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);

3288     /* Check if we already have this.  */

3290     t = purpose_member (used, DECL_NAMESPACE_USING (user));

3291     if (t != NULL_TREE)

3292     {

3293       if (!indirect)

3294         /* Promote to direct usage.  */

3295         TREE_INDIRECT_USING (t) = 0;

3296       timevar_pop (TV_NAME_LOOKUP);

3297       return ;

3298     }

3299  

3300     /* Add used to the user's using list.  */

3301     DECL_NAMESPACE_USING (user)

3302       = tree_cons (used, namespace_ancestor (user, used),

3303               DECL_NAMESPACE_USING (user));

3304  

3305     TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;

3306  

3307     /* Add user to the used's users list.  */

3308     DECL_NAMESPACE_USERS (used)

3309       = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));

3310  

3311     /* Recursively add all namespaces used.  */

3312     for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))

3313       /* indirect usage */

3314       add_using_namespace (user, TREE_PURPOSE (t), 1);

3315  

3316     /* Tell everyone using us about the new used namespaces.  */

3317     for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))

3318       add_using_namespace (TREE_PURPOSE (t), used, 1);

3319     timevar_pop (TV_NAME_LOOKUP);

3320   }

 

In section 5.12.4.1.1.2.1.3.2. Other names , see that using-directive shouldn’t garble the namespaces’ level, and at name-lookup, the front-end will do the search according to the level strictly. add_using_namespace needs record necessary information. Here namespace_ancestor finds out the closet common ancestor of ns1 and ns2. Notice that all namespace scopes have same ancient ancestor – global namespace. (For the using of the list grown here, refers to routine lookup_using_namespace ).

 

3194   static tree

3195   namespace_ancestor (tree ns1, tree ns2)                                             in name-lookup.c

3196   {

3197     timevar_push (TV_NAME_LOOKUP);

3198     if (is_ancestor (ns1, ns2))

3199       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);

3200     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,

3201                             namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));

3202   }

 

Here argument root is current namespace scope, and child is the namespace specified by the using-directive. Then is_ancestor continuously to retrieve the context starting at child till finds out root or exhausts the tree. For the previous case, root is the ancestor of child , and the routine returns nonzero value; otherwise it returns zero.

 

2502   bool

2503   is_ancestor (tree root, tree child)                                                               in name-lookup.c

2504   {

2505     my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL

2506                      || TREE_CODE (root) == FUNCTION_DECL

2507                      || CLASS_TYPE_P (root)), 20030307);

2508     my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL

2509                       || CLASS_TYPE_P (child)),

2510                       20030307);

2511    

2512     /* The global namespace encloses everything.  */

2513     if (root == global_namespace )

2514       return true;

2515  

2516     while (true)

2517     {

2518       /* If we've run out of scopes, stop.  */

2519       if (!child)

2520         return false;

2521       /* If we've reached the ROOT, it encloses CHILD.  */

2522       if (root == child)

2523         return true;

2524        /* Go out one level.  */

2525       if (TYPE_P (child))

2526         child = TYPE_NAME (child);

2527       child = DECL_CONTEXT (child);

2528     }

2529   }

 

So for our example, global namespace chains “Loki” in its DECL_NAMESPACE_USERS field.

5.12.5.2.              Main () definition

5.12.5.2.1.        Function-definition – declaractor part

For the main function, cp_parser_declaration again invokes cp_parser_block_declaration à cp_parser_simple_declaration . Under our context, argument function_definition_allowed_p is true which means we also recognize a function-definition as a simple-declaration.

The grammar of block-declaration is:

block-declaration:

     simple-declaration | asm-definition | namespace-alias-definition | using-declaration |

     using-directive 

GNU Extension:

   block-declaration: __extension__ block-declaration | label-declaration

 

6370   static void

6371   cp_parser_block_declaration (cp_parser *parser,                                        in parser.c

6372                           bool      statement_p)

6373   {

6374     cp_token *token1;

6375     int saved_pedantic;

6376  

6377     /* Check for the `__extension__' keyword.  */

6378     if (cp_parser_extension_opt (parser, &saved_pedantic))

6379     {

         

6386     }

6387  

6388     /* Peek at the next token to figure out which kind of declaration is

6389        present.  */

6390     token1 = cp_lexer_peek_token (parser->lexer);

6391  

6392     /* If the next keyword is `asm', we have an asm-definition.  */

6393     if (token1->keyword == RID_ASM)

6394     {

         

6398     }

6399     /* If the next keyword is `namespace', we have a

6400       namespace-alias-definition.  */

6401     else if (token1->keyword == RID_NAMESPACE)

6402       cp_parser_namespace_alias_definition (parser);

6403     /* If the next keyword is `using', we have either a

6404       using-declaration or a using-directive.  */

6405     else if (token1->keyword == RID_USING)

6406     {

         

6419     }

6420     /* If the next keyword is `__label__' we have a label declaration.  */

6421     else if (token1->keyword == RID_LABEL)

6422     {

         

6426     }

6427     /* Anything else must be a simple-declaration.  */

6428     else

6429       cp_parser_simple_declaration (parser, !statement_p);

6430   }

 

Grammar for simple-declaration is:

simple-declaration:

     decl-specifier-seq [opt] init-declarator-list [opt] ; 

init-declarator-list:

     init-declarator | init-declarator-list , init-declarator

See simple-declaration may lie in a block-declaraition which in turn may within a function scope or class-method scope, which requires access control, so a new deferred access control instance is expected. And stop_deferring_access_checks at line 6475 prevents adding more deferred access check by perform_or_defer_access_check , but access checking is required for both decl-specifier-seq and init-declarator-list, so for the later one it will resume the checking by resume_deferring_access_checks .

 

6444   static void

6445   cp_parser_simple_declaration (cp_parser* parser,                                       in parser.c

6446                            bool function_definition_allowed_p)

6447   {

6448     tree decl_specifiers;

6449     tree attributes;

6450     int declares_class_or_enum;

6451     bool saw_declarator;

6452  

6453     /* Defer access checks until we know what is being declared; the

6454       checks for names appearing in the decl-specifier-seq should be

6455       done as if we were in the scope of the thing being declared.  */

6456     push_deferring_access_checks (dk_deferred);

6457  

6458     /* Parse the decl-specifier-seq. We have to keep track of whether

6459       or not the decl-specifier-seq declares a named class or

6460       enumeration type, since that is the only case in which the

6461       init-declarator-list is allowed to be empty. 

6462  

6463       [dcl.dcl]

6464  

6465       I n a simple-declaration, the optional init-declarator-list can be

6466       omitted only when declaring a class or enumeration, that is when

6467       the decl-specifier-seq contains either a class-specifier, an

6468       elaborated-type-specifier, or an enum-specifier.  */

6469     decl_specifiers

6470       = cp_parser_decl_specifier_seq (parser,

6471                                 CP_PARSER_FLAGS_OPTIONAL,

6472                                 &attributes,

6473                                  &declares_class_or_enum);

6474     /* We no longer need to defer access checks.  */

6475     stop_deferring_access_checks ();

6476  

6477     /* In a block scope, a valid declaration must always have a

6478       decl-specifier-seq. By not trying to parse declarators, we can

6479       resolve the declaration/expression ambiguity more quickly.  */

6480     if (!function_definition_allowed_p && !decl_specifiers)

6481     {

6482       cp_parser_error (parser, "expected declaration");

6483       goto done;

6484     }

6485  

6486     /* If the next two tokens are both identifiers, the code is

6487       erroneous. The usual cause of this situation is code like:

6488  

6489         T t;

6490  

6491       where "T" should name a type -- but does not.  */

6492     if (cp_parser_diagnose_invalid_type_name (parser))

6493     {

6494       /* If parsing tentatively, we should commit; we really are

6495         looking at a declaration.  */

6496       cp_parser_commit_to_tentative_parse (parser);

6497       /* Give up.  */

6498       goto done;

6499     }

 

As we see before, cp_parser_decl_specifier_seq will parse the return type of the function; so here decl_specifiers is a tree_list with TREE_VALUE field referring to the node of integer_type_node . Note that a function-definition may haven’t return type (it defaults to int).

 

1950   static bool

1951   cp_parser_diagnose_invalid_type_name (cp_parser *parser)                        in parser.c

1952   {

1953     /* If the next two tokens are both identifiers, the code is

1954       erroneous. The usual cause of this situation is code like:

1955  

1956       T t;

1957  

1958       where "T" should name a type -- but does not.  */

1959     if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)

1960        && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)

1961     {

1962       tree name;

1963  

1964       /* If parsing tentatively, we should commit; we really are

1965         looking at a declaration.  */

1966       /* Consume the first identifier.  */

1967       name = cp_lexer_consume_token (parser->lexer)->value;

1968       /* Issue an error message.  */

1969       error ("`%s' does not name a type", IDENTIFIER_POINTER (name));

1970       /* If we're in a template class, it's possible that the user was

1971         referring to a type from a base class. For example:

1972  

1973         template <typename T> struct A { typedef T X; };

1974         template <typename T> struct B : public A<T> { X x; };

1975  

1976          The user should have said "typename A<T>::X".  */

1977       if (processing_template_decl && current_class_type )

1978       {

1979         tree b;

1980  

1981         for (b = TREE_CHAIN (TYPE_BINFO (current_class_type ));

1982             b;

1983             b = TREE_CHAIN (b))

1984         {

1985           tree base_type = BINFO_TYPE (b);

1986           if (CLASS_TYPE_P (base_type)

1987              && dependent_type_p (base_type))

1988            {

1989             tree field;

1990             /* Go from a particular instantiation of the

1991               template (which will have an empty TYPE_FIELDs),

1992               to the main version.  */

1993             base_type = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type);

1994             for (field = TYPE_FIELDS (base_type);

1995                 field;

1996                 field = TREE_CHAIN (field))

1997               if (TREE_CODE (field) == TYPE_DECL

1998                  && DECL_NAME (field) == name)

1999                {

2000                 error ("(perhaps `typename %T::%s' was intended)",

2001                      BINFO_TYPE (b), IDENTIFIER_POINTER (name));

2002                 break ;

2003               }

2004               if (field)

2005                 break ;

2006            }

2007         }

2008       }

2009       /* Skip to the end of the declaration; there's no point in

2010         trying to process it.  */

2011       cp_parser_skip_to_end_of_statement (parser);

2012        

2013       return true;

2014     }

2015  

2016     return false;

2017   }

 

Being proper form, the core part of decl-specifier-seq should name a type. That type found following name-lookup rule will be returned to decl-specifiers ; and if no appropriate type is found, this token stays as identifier, and cp_parser_diagnose_invalid_type_name diagnoses this error case, and gives out diagnostic message.

 

cp_parser_simple_declaration (continue)

 

6501     /* If we have seen at least one decl-specifier, and the next token

6502       is not a parenthesis, then we must be looking at a declaration.

6503       (After "int (" we might be looking at a functional cast.)  */

6504     if (decl_specifiers

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

6506       cp_parser_commit_to_tentative_parse (parser);

6507  

6508     /* Keep going until we hit the `;' at the end of the simple

6509       declaration.  */

6510     saw_declarator = false;

6511     while (cp_lexer_next_token_is_not (parser->lexer,

6512                                   CPP_SEMICOLON))

6513     {

6514       cp_token *token;

6515       bool function_definition_p;

6516       tree decl;

6517  

6518       saw_declarator = true;

6519       /* Parse the init-declarator.  */

6520       decl = cp_parser_init_declarator (parser, decl_specifiers, attributes,

6521                                  function_definition_allowed_p,

6522                                  /*member_p=*/ false,

6523                                   declares_class_or_enum,

6524                                  &function_definition_p);

6525       /* If an error occurred while parsing tentatively, exit quickly.

6526         (That usually happens when in the body of a function; each

6527         statement is treated as a declaration-statement until proven

6528         otherwise.)  */

6529       if (cp_parser_error_occurred (parser))

6530         goto done;

6531       /* Handle function definitions specially.  */

6532       if (function_definition_p)

6533       {

6534         /* If the next token is a `,', then we are probably

6535           processing something like:

6536  

6537           void f() {}, *p;

6538  

6539           which is erroneous.  */

6540         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))

6541           error ("mixing declarations and function-definitions is forbidden");

6542         /* Otherwise, we're done with the list of declarators.  */

6543         else

6544         {

6545           pop_deferring_access_checks ();

6546           return ;

6547         }

6548       }

         

6580     }

      

6593     /* Consume the `;'.  */

6594     cp_parser_require (parser, CPP_SEMICOLON, "`;'");

6595  

6596   done:

6597     pop_deferring_access_checks ();

6598   }

 

Notice that argument declares_class_or_enum is 0 as the type-specifier is not class-specifier, enum-specifier, nor is elaborated-type-specifier. The content of init-declarator includes:

init-declarator:

     declarator initializer [opt]

function-definition:

     decl-specifier-seq [opt] declarator ctor-initializer [opt] function-body

     decl-specifier-seq [opt] declarator function-try-block 

GNU Extension:

   init-declarator:

     declarator asm-specification [opt] attributes [opt] initializer [opt]

   function-definition:

     __extension__ function-definition

Note ctor-initializer is used only in constructor.

 

9933   static tree

9934   cp_parser_init_declarator (cp_parser* parser,                                             in parser.c

9935                         tree decl_specifiers,

9936                         tree prefix_attributes,

9937                          bool function_definition_allowed_p,

9938                         bool member_p,

9939                         int declares_class_or_enum,

9940                         bool* function_definition_p)

9941   {

9942     cp_token *token;

9943     tree declarator;

9944     tree attributes;

9945     tree asm_specification;

9946     tree initializer;

9947     tree decl = NULL_TREE;

9948     tree scope;

9949     bool is_initialized;

9950     bool is_parenthesized_init;

9951     bool is_non_constant_init;

9952     int ctor_dtor_or_conv_p;

9953     bool friend_p;

9954     bool pop_p = false;

9955  

9956     /* Assume that this is not the declarator for a function

9957       definition.  */

9958     if (function_definition_p)

9959       *function_definition_p = false;

9960  

9961     /* Defer access checks while parsing the declarator; we cannot know

9962       what names are accessible until we know what is being

9963       declared.  */

9964     resume_deferring_access_checks ();

9965  

9966     /* Parse the declarator.  */

9967     declarator

9968       = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,

9969                           &ctor_dtor_or_conv_p,

9970                           /*parenthesized_p=*/ NULL,

9971                           /*member_p=*/ false);

9972     /* Gather up the deferred checks.  */

9973     stop_deferring_access_checks ();

 

The part “main ()” is the declarator, which contains “main” as declarator-id, and “()” as parameter-list. So in cp_parser_declarator , cp_parser_direct_declarator iterates its major WHILE loop twice. In first time invoking: cp_parser_declarator_id à cp_parser_id_expression à cp_parser_identifier which returns the IDENTIFIER_NODE of “main”. And in second time, invoking: cp_parser_parameter_declaration_clause which returns void_list_node for the empty parameter-list. And then the declarator-id and parameter-list are assembled tegother by make_call_declarator to form a CALL_EXPR as below (it mostly like parsing class-method we see before).

Studying note of GCC-3.4.6 source (128)_第1张图片

你可能感兴趣的:(Studying note of GCC-3.4.6 source (128))