Studying note of GCC-3.4.6 source (105)

5.12.3.2.1.1.3.6.1.            Exit nested class

Further, when consuming the tailing “;” of the class, it means we are going to exit the class scope and re-enter its containing scope. This operation is done by popclass at line 5257.

 

5564   void

5565   popclass (void)                                                                                       in class.c

5566   {

5567     poplevel_class ();

5568     pop_class_decls ();

5569  

5570     current_class_depth --;

5571     current_class_name = current_class_stack [current_class_depth ].name;

5572     current_class_type = current_class_stack [current_class_depth ].type;

5573     current_access_specifier = current_class_stack [current_class_depth ].access;

5574     if (current_class_stack [current_class_depth ].names_used)

5575       splay_tree_delete (current_class_stack [current_class_depth ].names_used);

5576   }

 

In poplevel_class , sees that when we exit from class stack, previous_class_type and previous_class_values caches the toppest class which may be reused in pushclass . However, for non-top class, it is not reasonable to cache them, but releases the built relation of identifers declared within the class. Considering following example:

// Global scope

int j;

class A

{

public :

     int j;

     typedef int inner_type;

     class B {

            int j;

            inner_type k;  // inner_type is A:: inner_type

     public :

            int get_j() const {

return j;      // should return B::j

                     }

                     inner_type get_k() const { return k; }

     };

     int get_j() const {

            return j;   // should return A::j

     }

};

 

int get_j() {

     return j;   // should return ::j

}

Variable j are declared within global scope, class A and class B. But, in the front-end, the identifier node for j must be unique, so the three definitions should bind at this unique node. However according to the rule of name-lookup, the j used can be determined by the current scopes. For example, searching inner_type above within class B will finally result in searching class A and find out the definition. Nevertheless the regular searching is complex. Fortunately, many searchings can be avoided if we update the identifier’s definition when entering a scope. That is the purpose of field IDENTIFIER_CLASS_VALUE to record current definition for the identifier.

 

2581   void

2582   poplevel_class (void)                                                                        in name-lookup.c

2583   {

2584     struct cp_binding_level *level = class_binding_level;

2585     tree shadowed;

2586  

2587     timevar_push (TV_NAME_LOOKUP);

2588     my_friendly_assert (level != 0, 354);

2589  

2590     /* If we're leaving a toplevel class, don't bother to do the setting

2591       of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot

2592       shouldn't even be used when current_class_type isn't set, and second,

2593       if we don't touch it here, we're able to use the cache effect if the

2594       next time we're entering a class scope, it is the same class.  */

2595     if (current_class_depth != 1)

2596     {

2597       struct cp_binding_level* b;

2598  

2599       /* Clear out our IDENTIFIER_CLASS_VALUEs.   */

2600       for (shadowed = level->class_shadowed;

2601           shadowed;

2602           shadowed = TREE_CHAIN (shadowed))

2603         IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;

2604  

2605       /* Find the next enclosing class, and recreate

2606         IDENTIFIER_CLASS_VALUEs appropriate for that class.  */

2607       b = level->level_chain;

2608       while (b && b->kind != sk_class)

2609         b = b->level_chain;

2610  

2611       if (b)

2612         for (shadowed = b->class_shadowed;

2613              shadowed;

2614             shadowed = TREE_CHAIN (shadowed))

2615         {

2616           cxx_binding *binding;

2617              

2618           binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));

2619           while (binding && binding->scope != b)

2620              binding = binding->previous;

2621  

2622           if (binding)

2623             IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))

2624                    = binding->value;

2625         }

2626     }

2627     else

2628       /* Remember to save what IDENTIFIER's were bound in this scope so we

2629         can recover from cache misses.  */

2630     {

2631       previous_class_type = current_class_type ;

2632       previous_class_values = class_binding_level->class_shadowed;

2633     }

2634     for (shadowed = level->type_shadowed;

2635         shadowed;

2636         shadowed = TREE_CHAIN (shadowed))

2637       SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));

2638  

2639     /* Remove the bindings for all of the class-level declarations.  */

2640     for (shadowed = level->class_shadowed;

2641         shadowed;

2642         shadowed = TREE_CHAIN (shadowed))

2643       pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));

2644  

2645     /* Now, pop out of the binding level which we created up in the

2646       `pushlevel_class' routine.  */

2647     if (ENABLE_SCOPE_CHECKING)

2648       is_class_level = 1;

2649  

2650     leave_scope ();

2651     timevar_pop (TV_NAME_LOOKUP);

2652   }

 

Clearly, above from line 2600 to 2603, the associated definition/declarator of the identifiers declared within the class are cleaned. Further, if the identifier in the class shadows the same identifier outside, type_shadowed field of the class node will record the definition/declarator shadowed, it is time to restore the shadowed definitions in FOR loop at line 2634 does.

As exiting from the class, the identifiers declared within can’t be visible in current scope without nested-name-specifier, it needs to remove the cxx_binding nodes of the identifiers leading to the class by pop_binding which is the reverse of push_binding .

 

376    void

377    pop_binding (tree id, tree decl)                                                          in name-lookup.c

378    {

379      cxx_binding *binding;

380   

381      if (id == NULL_TREE)

382        /* It's easiest to write the loops that call this function without

383          checking whether or not the entities involved have names. We

384          get here for such an entity.  */

385        return ;

386   

387      /* Get the innermost binding for ID.  */

388      binding = IDENTIFIER_BINDING (id);

389   

390      /* The name should be bound.  */

391      my_friendly_assert (binding != NULL, 0);

392   

393      /* The DECL will be either the ordinary binding or the type

394        binding for this identifier. Remove that binding.  */

395      if (binding->value == decl)

396        binding->value = NULL_TREE;

397      else if (binding->type == decl)

398        binding->type = NULL_TREE;

399      else

400        abort ();

401   

402      if (!binding->value && !binding->type)

403      {

404         /* We're completely done with the innermost binding for this

405          identifier. Unhook it from the list of bindings.  */

406        IDENTIFIER_BINDING (id) = binding->previous;

407   

408        /* Add it to the free list.  */

409        cxx_binding_free (binding);

410      }

411     }

 

Notice that the innermost binding is always at head of the bindings field of the identifier node which is fetched by IDENTIFIER_BINDING at line 388.

Also when entering the class, cache all of the fields that that class provides within its inheritance lattice may accelerate the searching within specified class, especially for those large ones greatly. It is done by push_class_decls in pushclass , so when leaving, the cache should be released by pop_class_decls from search_stack .

 

2323   void

2324   pop_class_decls (void)                                                                             in search.c

2325   {

2326     /* We haven't pushed a search level when dealing with cached classes,

2327       so we'd better not try to pop it.  */

2328     if (search_stack )

2329       search_stack = pop_search_level (search_stack );

2330   }

 

What’s more, the cxx_scope represents the binding scope of the class should also need be removed from the tree rooted by global namespace scope, as its members are invisible from global namespace. If the front-end doesn’t open ENABLE_SCOPE_CHECKING, the released cxx_scopes are chained by free_binding_level in leave_scope , and can be reused in begin_scope . If this switch is not opened, leave_scope will leave free_binding_level as following.

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

Figure 85 : freeing cxx_scope by leave_scope

After finializing the parsing by finish_struct , if the class is referred by elaberator-type-specifier like: “A::B::f”, at line 11926 pop_p refers to the scope of A::B:: which also have cxx_scope built and linked into the scope tree rooted by global namespace scope. When encountering the ending “;” just means it is going to exit to current binding scope. Then the scopes of A and B similarly need be removed from the tree.

We have seen and cached the definitions of the inline method of struct “Lock”, but they are still not handled. However, considering the example:

struct A {

            struct B { void f() { sizeof (A); } };

};

It makes expand inline function f at the end of definition of B inapplicable. The appropriate point is the end of A – the outermost class. That is why all inline functions no matter which class they belonged are cached within unparsed_functions_queues in parser.

So in rest code of cp_parser_class_specifier , just pops up the deferring accessing control block from the control stack for struct “Lock”.

 

cp_parser_class_specifier (continue)

 

11928   /* If this class is not itself within the scope of another class,

11929     then we need to parse the bodies of all of the queued function

11930     definitions. Note that the queued functions defined in a class

11931     are not always processed immediately following the

11932     class-specifier for that class. Consider:

11933

11934        struct A {

11935          struct B { void f() { sizeof (A); } };

11936        };

11937

11938     If `f' were processed before the processing of `A' were

11939     completed, there would be no way to compute the size of `A'.

11940     Note that the nesting we are interested in here is lexical --

11941     not the semantic nesting given by TYPE_CONTEXT. In particular,

11942     for:

11943

11944        struct A { struct B; };

11945        struct A::B { void f() { } };

11946

11947     there is no need to delay the parsing of `A::B::f'.  */

11948   if (--parser->num_classes_being_defined == 0)

11949   {

         

11996   }

11997

11998   /* Put back any saved access checks.  */

11999   pop_deferring_access_checks ();

12000

12001   /* Restore the count of active template-parameter-lists.  */

12002   parser->num_template_parameter_lists

12003          = saved_num_template_parameter_lists;

12004

12005   return type;

12006 }

 

And at last, the intermediate tree looks like following figure, and type returned refers to the node of RECORD_TYPE.

(Click here for open )

Figure 86 : At point of exiting struct Lock

5.12.3.2.1.1.3.6.1.            Finish parsing as member

Return back to cp_parser_type_specifier from cp_parser_class_specifier , type_spec in turn refers to the RECORD_TYPE and declares_class_or_enum is set as 2 if the buffer provided. Further back to cp_parser_decl_specifier_seq , notice that the tailing “;” is not consumed yet. So it immediately make the function terminates (using GCC, if missing “;” for class definition, you may get lot of error, as cp_parser_decl_specifier_seq continues parsing for decl-specifier-seq), and as result, reference to the RECORD_TYPE is kept within decl_specs and returned.

Then back in cp_parser_member_declaration , following code will be executed.

 

cp_parser_member_declaration (continue)

 

12513   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))

12514   {

12515     /* If there was no decl-specifier-seq, and the next token is a

12516       `;', then we have something like:

12517

12518       struct S { ; };

12519

12520       [class.mem]

12521

12522       Each member-declaration shall declare at least one member

12523       name of the class.  */

12524     if (!decl_specifiers)

12525     {

12526       if (pedantic )

12527         pedwarn ("extra semicolon");

12528     }

12529     else

12530     {

12531       tree type;

12532       

12533       /* See if this declaration is a friend.  */

12534       friend_p = cp_parser_friend_p (decl_specifiers);

12535       /* If there were decl-specifiers, check to see if there was

12536         a class-declaration.  */

12537       type = check_tag_decl (decl_specifiers);

12538       /* Nested classes have already been added to the class, but

12539         a `friend' needs to be explicitly registered.  */

12540       if (friend_p)

12541       {

             

12581        }

12582       /* If there is no TYPE, an error message will already have

12583         been issued.  */

12584       else if (!type)

12585         ;

12586       /* An anonymous aggregate has to be handled specially; such

12587         a declaration really declares a data member (with a

12588         particular type), as opposed to a nested class.  */

12589       else if (ANON_AGGR_TYPE_P (type))

12590       {

12591         /* Remove constructors and such from TYPE, now that we

12592           know it is an anonymous aggregate.  */

12593         fixup_anonymous_aggr (type);

12594         /* And make the corresponding data member.  */

12595         decl = build_decl (FIELD_DECL, NULL_TREE, type);

12596         /* Add it to the class.  */

12597         finish_member_declaration (decl);

12598      }

12599      else

12600        cp_parser_check_access_in_redeclaration (TYPE_NAME (type));

12601     }

12602   }

       

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

12815 }

 

And arriving at here, the whole decl-specifier-seq is parsed, and we can have a better view about it. It is the right time to pick up contradictory components. For instance, using more than one type in declaration.

 

3474   tree

3475   check_tag_decl (tree declspecs)                                                                        in decl.c

3476   {

3477     int found_type = 0;

3478     int saw_friend = 0;

3479     int saw_typedef = 0;

3480     tree ob_modifier = NULL_TREE;

3481     tree link;

3482     /* If a class, struct, or enum type is declared by the DECLSPECS

3483       (i.e, if a class-specifier, enum-specifier, or non-typename

3484       elaborated-type-specifier appears in the DECLSPECS),

3485       DECLARED_TYPE is set to the corresponding type.  */

3486     tree declared_type = NULL_TREE;

3487     bool error_p = false;

3488  

3489     for (link = declspecs; link; link = TREE_CHAIN (link))

3490     {

3491       tree value = TREE_VALUE (link);

3492  

3493       if (TYPE_P (value) || TREE_CODE (value) == TYPE_DECL

3494          || (TREE_CODE (value) == IDENTIFIER_NODE

3495             && is_typename_at_global_scope (value)))

3496       {

3497         ++found_type;

3498  

3499         if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)

3500         {

3501           if (! in_system_header )

3502             pedwarn ("redeclaration of C++ built-in type `%T'", value);

3503           return NULL_TREE;

3504         }

3505  

3506         if (TYPE_P (value)

3507           && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))

3508                || TREE_CODE (value) == ENUMERAL_TYPE))

3509         {

3510           my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);

3511           declared_type = value;

3512         }

3513       }

3514       else if (value == ridpointers [(int) RID_TYPEDEF])

3515         saw_typedef = 1;

3516       else if (value == ridpointers [(int) RID_FRIEND])

3517       {

3518         if (current_class_type == NULL_TREE

3519            || current_scope () != current_class_type )

3520           ob_modifier = value;

3521         else

3522           saw_friend = 1;

3523       }

3524       else if (value == ridpointers [(int) RID_STATIC]

3525             || value == ridpointers [(int) RID_EXTERN]

3526             || value == ridpointers [(int) RID_AUTO]

3527             || value == ridpointers [(int) RID_REGISTER]

3528             || value == ridpointers [(int) RID_INLINE]

3529             || value == ridpointers [(int) RID_VIRTUAL]

3530             || value == ridpointers [(int) RID_CONST]

3531             || value == ridpointers [(int) RID_VOLATILE]

3532             || value == ridpointers [(int) RID_EXPLICIT]

3533             || value == ridpointers [(int) RID_THREAD])

3534         ob_modifier = value;

3535       else if (value == error_mark_node)

3536         error_p = true;

3537     }

3538  

3539     if (found_type > 1)

3540       error ("multiple types in one declaration");

3541  

3542     if (declared_type == NULL_TREE && ! saw_friend && !error_p)

3543       pedwarn ("declaration does not declare anything");

3544     /* Check for an anonymous union.  */

3545     else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))

3546           && TYPE_ANONYMOUS_P (declared_type))

3547     {

3548       /* 7/3 In a simple-declaration, the optional init-declarator-list

3549         can be omitted only when declaring a class (clause 9) or

3550         enumeration (7.2), that is, when the decl-specifier-seq contains

3551         either a class-specifier, an elaborated-type-specifier with

3552         a class-key (9.1), or an enum-specifier. In these cases and

3553         whenever a class-specifier or enum-specifier is present in the

3554         decl-specifier-seq, the identifiers in these specifiers are among

3555         the names being declared by the declaration (as class-name,

3556         enum-names, or enumerators, depending on the syntax). In such

3557         cases, and except for the declaration of an unnamed bit-field (9.6),

3558         the decl-specifier-seq shall introduce one or more names into the

3559         program, or shall redeclare a name introduced by a previous

3560         declaration. [Example:

3561           enum { };            // ill-formed

3562           typedef class { };   // ill-formed

3563         --end example]  */

3564       if (saw_typedef)

3565       {

3566         error ("missing type-name in typedef-declaration");

3567         return NULL_TREE;

3568       }

3569       /* Anonymous unions are objects, so they can have specifiers.  */ ;

3570       SET_ANON_AGGR_TYPE_P (declared_type);

3571  

3572       if (TREE_CODE (declared_type) != UNION_TYPE && pedantic

3573          && !in_system_header )

3574         pedwarn ("ISO C++ prohibits anonymous structs");

3575     }

3576  

3577     else if (ob_modifier)

3578     {

3579       if (ob_modifier == ridpointers [(int) RID_INLINE]

3580          || ob_modifier == ridpointers [(int) RID_VIRTUAL])

3581         error ("`%D' can only be specified for functions", ob_modifier);

3582       else if (ob_modifier == ridpointers [(int) RID_FRIEND])

3583         error ("`%D' can only be specified inside a class", ob_modifier);

3584       else if (ob_modifier == ridpointers [(int) RID_EXPLICIT])

3585         error ("`%D' can only be specified for constructors",

3586              ob_modifier);

3587       else

3588         error ("`%D' can only be specified for objects and functions",

3589              ob_modifier);

3590     }

3591  

3592     return declared_type;

3593   }

 

Note that if the using of keywords is valid, at here, their meaning should be integrated into flags in node of decl-specifier-seq, nodes of these keywords shouldn’t be present. Once found, it means error, which is handled by block at line 3577. Anyway the node of type declared is returned by the function. For the type returned by check_tag_decl , if it is not an annoymous class, it checks if decl is redeclared with different access than its original declaration. This applies to nested classes and nested class templates and done by below function.

 

15282 static void cp_parser_check_access_in_redeclaration (tree decl)                           in parser.c

15283 {

15284   if (!CLASS_TYPE_P (TREE_TYPE (decl)))

15285     return ;

15286

15287   if ((TREE_PRIVATE (decl)

15288       != (current_access_specifier == access_private_node))

15289      || (TREE_PROTECTED (decl)

15290        != (current_access_specifier == access_protected_node)))

15291     error ("%D redeclared with different access", decl);

15292 }

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