Studying note of GCC-3.4.6 source (93)

5.12.3.2.1.1.  Case of class-specifier

Class-specifier follows the rule: class-specifier: class-head { member-specification [opt] }

 

11855 static tree

11856 cp_parser_class_specifier (cp_parser* parser)                                             in parser.c

11857 {

11858   cp_token *token;

11859   tree type;

11860   tree attributes;

11861   int has_trailing_semicolon;

11862   bool nested_name_specifier_p;

11863   unsigned saved_num_template_parameter_lists;

11864   bool pop_p = false;

11865   tree scope = NULL_TREE;

11866

11867   push_deferring_access_checks (dk_no_deferred);

11868

11869   /* Parse the class-head.  */

11870   type = cp_parser_class_head (parser,

11871                           &nested_name_specifier_p,

11872                           &attributes);

11873   /* If the class-head was a semantic disaster, skip the entire body

11874     of the class.  */

11875   if (!type)

11876   {

11877     cp_parser_skip_to_end_of_block_or_statement (parser);

11878     pop_deferring_access_checks ();

11879     return error_mark_node;

11880   }

 

Above at line 11867, prepares deferred access control checking for this class-specifier. As the type is dk_no_deferred, so at poping out of the stack, the checkings will be done immediately.

5.12.3.2.1.1.1.          Parse class-head

class-head describes the inheritance hierachy between classes by base-clause entity, besides nested-name-specifier entity describes the binding scope the class will be defined.

class-head

class-key identifier [opt] base-clause [opt]

├ class-key nested-name-specifier [opt] base-clause [opt]

├ class-key nested-name-specifier [opt] template-id base-clause [opt]

GNU Ext ├ class-key attributes identifer [opt] base-clause [opt]

GNU Ext ├ class-key attributes nested-name-specifier [opt] base-clause [opt]

GNU Ext class-key attributes nested-name-specifier [opt] template-id base-clause [opt]

class

struct

union

So in the handling function, parameter nested_name_specifier_p is set to true if and only if one of the productions involving a nested-name-specifier was used, and false otherwise. Here for the second statement in our example contains class-head of “class SingleThreaded”.

 

12030 static tree

12031 cp_parser_class_head (cp_parser* parser,                                                   in parser.c

12032                    bool* nested_name_specifier_p,

12033                    tree *attributes_p)

12034 {

12035   cp_token *token;

12036   tree nested_name_specifier;

12037   enum tag_types class_key;

12038   tree id = NULL_TREE;

12039   tree type = NULL_TREE;

12040   tree attributes;

12041   bool template_id_p = false;

12042   bool qualified_p = false;

12043   bool invalid_nested_name_p = false;

12044   bool invalid_explicit_specialization_p = false;

12045   bool pop_p = false;

12046   unsigned num_templates;

12047

12048   /* Assume no nested-name-specifier will be present.  */

12049   *nested_name_specifier_p = false;

12050   /* Assume no template parameter lists will be used in defining the

12051     type.  */

12052   num_templates = 0;

12053

12054   /* Look for the class-key.  */

12055   class_key = cp_parser_class_key (parser);

12056   if (class_key == none_type)

12057     return error_mark_node;

12058

12059   /* Parse the attributes.  */

12060   attributes = cp_parser_attributes_opt (parser);

12061

12062   /* If the next token is `::', that is invalid -- but sometimes

12063     people do try to write:

12064

12065        struct ::S {}; 

12066

12067     Handle this gracefully by accepting the extra qualifier, and then

12068     issuing an error about it later if this really is a

12069     class-head. If it turns out just to be an elaborated type

12070     specifier, remain silent.  */

12071   if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))

12072     qualified_p = true;

12073

12074   push_deferring_access_checks (dk_no_check);

12075

12076   /* Determine the name of the class. Begin by looking for an

12077     optional nested-name-specifier.  */

12078   nested_name_specifier

12079      = cp_parser_nested_name_specifier_opt (parser,

12080                                        /*typename_keyword_p=*/false,

12081                                        /*check_dependency_p=*/false,

12082                                        /*type_p=*/false,

12083                                        /*is_declaration=*/false);

 

The entity that follows class-key should be identifier or attribute. See nested-name-specifier also begins with identifier; it first tries nested-name-specifier. Nested-name-specifier may contain following members.

nested-name-specifier

class-or-namespace-name::nested-name-specifier [opt]

namespace-name --- identifier

class-name

identifier

template-id

See “SingleTheaded” or “SingleThreaded {“ are not valid nested-name-specifiers which requires “::” as the ending token, at line 12079 cp_parser_nested_name_specifier_opt will return NULL to nested_name_specifier.

What’s more, the absence of ‘::’ indicates the identifier should be found by standard name-lookup procedure stipulated by the standard. For the case, it needs clear the scope information in parser, and let the name-lookup procedure sets up it appropriately.

 

14127 static tree

14128 cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p) in parser.c

14129 {

14130   cp_token *token;

14131

14132   /* Peek at the next token.  */

14133   token = cp_lexer_peek_token (parser->lexer);

14134   /* If we're looking at a `::' token then we're starting from the

14135     global namespace, not our current location.  */

14136   if (token->type == CPP_SCOPE)

14137   {

14138     /* Consume the `::' token.  */

14139     cp_lexer_consume_token (parser->lexer);

14140     /* Set the SCOPE so that we know where to start the lookup.  */

14141     parser->scope = global_namespace;

14142     parser->qualifying_scope = global_namespace;

14143     parser->object_scope = NULL_TREE;

14144

14145     return parser->scope;

14146   }

14147   else if (!current_scope_valid_p)

14148   {

14149     parser->scope = NULL_TREE;

14150     parser->qualifying_scope = NULL_TREE;

14151     parser->object_scope = NULL_TREE;

14152   }

14153

14154   return NULL_TREE;

14155 }

 

In parser, field scope indicates the scope in which names should be looked up. If NULL_TREE, then we look up names in the scope that is currently open in the source program. If non-NULL, this is either a TYPE or NAMESPACE_DECL for the scope in which we should look. Fields object_scope and qualifying_scope give the scopes in which the last lookup took place. Object_scope is used if an expression like "x->y" or "x.y" was used; it gives the type of "*x" or "x", respectively. Qualifying_scope is used for an expression of the form "X::Y"; it refers to X.

In above function, parameter current_scope_valid_p if false, means depending on currently open scope to solve names. For class declaraction, it is obvious.

 

cp_parser_class_head (continue)

 

12084  /* If there was a nested-name-specifier, then there *must* be an

12085    identifier.  */

12086  if (nested_name_specifier)

12087  {

         

12143  }

12144  /* Otherwise, the identifier is optional.  */

12145  else

12146  {

12147    /* We don't know whether what comes next is a template-id,

12148      an identifier, or nothing at all.  */

12149    cp_parser_parse_tentatively (parser);

12150    /* Check for a template-id.  */

12151    id = cp_parser_template_id (parser,

12152                           /*template_keyword_p=*/false,

12153                           /*check_dependency_p=*/true,

12154                           /*is_declaration=*/true);

12155    /* If that didn't work, it could still be an identifier.  */

12156    if (!cp_parser_parse_definitely (parser))

12157    {

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

12159        id = cp_parser_identifier (parser);

12160      else

12161        id = NULL_TREE;

12162    }

12163    else

12164    {

12165      template_id_p = true;

12166      ++num_templates;

12167    }

12168  }

12169

12170  pop_deferring_access_checks ();

12171

12172  if (id)

12173    cp_parser_check_for_invalid_template_id (parser, id);

12174

12175  /* If it's not a `:' or a `{' then we can't really be looking at a

12176    class-head, since a class-head only appears as part of a

12177    class-specifier. We have to detect this situation before calling

12178    xref_tag, since that has irreversible side-effects.  */

12179  if (!cp_parser_next_token_starts_class_definition_p (parser))

12180  {

12181    cp_parser_error (parser, "expected `{' or `:'");

12182    return error_mark_node;

12183  }

12184

12185  /* At this point, we're going ahead with the class-specifier, even

12186    if some other problem occurs.  */

12187  cp_parser_commit_to_tentative_parse (parser);

12188  /* Issue the error about the overly-qualified name now.  */

12189  if (qualified_p)

12190    cp_parser_error (parser,

12191                  "global qualification of class name is invalid");

12192  else if (invalid_nested_name_p)

12193    cp_parser_error (parser,

12194                  "qualified name does not name a class");

12195  else if (nested_name_specifier)

12196  {

         

12232  }

12233  /* An explicit-specialization must be preceded by "template <>". If

12234    it is not, try to recover gracefully.  */

12235  if (at_namespace_scope_p ()

12236     && parser->num_template_parameter_lists == 0

12237     && template_id_p)

12238  {

12239    error ("an explicit specialization must be preceded by 'template <>'");

12240    invalid_explicit_specialization_p = true;

12241    /* Take the same action that would have been taken by

12242      cp_parser_explicit_specialization.  */

12243    ++parser->num_template_parameter_lists;

12244    begin_specialization ();

12245  }

12246  /* There must be no "return" statements between this point and the

12247    end of this function; set "type "to the correct return value and

12248    use "goto done;" to return.  */

12249  /* Make sure that the right number of template parameters were

12250    present.  */

12251  if (!cp_parser_check_template_parameters (parser, num_templates))

12252  {

12253    /* If something went wrong, there is no point in even trying to

12254      process the class-definition.  */

12255    type = NULL_TREE;

12256    goto done;

12257  }

If before base-clause is template-id, it is a template specialization, for example: “template <> class A <int>: public B { … };”. For normal class template, it should be an identifier. Template-id is a complex structure, we will see it later.

5.12.3.2.1.1.1.1.    Sanity check before going ahead

Before going ahead, it needs to check if any error occured. First, token “<” can’t follow a type-specifier, routine cp_parser_check_for_invalid_template_id checks for this error case.

 

1883 static void

1884 cp_parser_check_for_invalid_template_id (cp_parser* parser,                        in parser.c

1885                                    tree type)

1886 {

1887   ptrdiff_t start;

1888   cp_token *token;

1889

1890   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))

1891   {

1892     if (TYPE_P (type))

1893       error ("`%T' is not a template", type);

1894     else if (TREE_CODE (type) == IDENTIFIER_NODE)

1895       error ("`%s' is not a template", IDENTIFIER_POINTER (type));

1896     else

1897       error ("invalid template-id");

1898     /* Remember the location of the invalid "<".  */

1899     if (cp_parser_parsing_tentatively (parser)

1900        && !cp_parser_committed_to_tentative_parse (parser))

1901     {

1902       token = cp_lexer_peek_token (parser->lexer);

1903       token = cp_lexer_prev_token (parser->lexer, token);

1904       start = cp_lexer_token_difference (parser->lexer,

1905                                   parser->lexer->first_token,

1906                                   token);

1907     }

1908     else

1909       start = -1;

1910     /* Consume the "<".  */

1911     cp_lexer_consume_token (parser->lexer);

1912     /* Parse the template arguments.  */

1913     cp_parser_enclosed_template_argument_list (parser);

1914     /* Permanently remove the invalid template arguments so that

1915       this error message is not issued again.  */

1916     if (start >= 0)

1917     {

1918       token = cp_lexer_advance_token (parser->lexer,

1919                                   parser->lexer->first_token,

1920                                   start);

1921       cp_lexer_purge_tokens_after (parser->lexer, token);

1922     }

1923   }

1924 }

 

Then it needs to see tokens coming can construct a valid class-head, which must be “{“ or “:”.

 

15199 static bool

15200 cp_parser_next_token_starts_class_definition_p (cp_parser *parser)              in parser.c

15201 {

15202   cp_token *token;

15203

15204   token = cp_lexer_peek_token (parser->lexer);

15205   return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);

15206 }

 

Next for our example, variable template_id_p remains false as the declaration is not a template-id. And also notice that now variable num_templates is still 0.

 

14018 static bool

14019 cp_parser_check_template_parameters (cp_parser* parser,                           in parser.c

14020                                 unsigned num_templates)

14021 {

14022   /* If there are more template classes than parameter lists, we have

14023     something like:

14024     

14025        template <class T> void S<T>::R<T>::f ();  */

14026   if (parser->num_template_parameter_lists < num_templates)

14027   {

14028     error ("too few template-parameter-lists");

14029     return false;

14030   }

14031   /* If there are the same number of template classes and parameter

14032     lists, that's OK.  */

14033   if (parser->num_template_parameter_lists == num_templates)

14034     return true;

14035  /* If there are more, but only one more, then we are referring to a

14036     member template. That's OK too.  */

14037   if (parser->num_template_parameter_lists == num_templates + 1)

14038      return true;

14039   /* Otherwise, there are too many template parameter lists. We have

14040     something like:

14041

14042      template <class T> template <class U> void S::f();  */

14043   error ("too many template-parameter-lists");

14044   return false;

14045 }

 

As we have seen in previous section, slot num_template_parameter_lists of parser records the nested level of template parameter, and num_templates records the nested level of templates has been seen within cp_parser_class_head. For valid declaration, they must match each other.

5.12.3.2.1.1.1.2.    Push tag of class SingleThreaded

Now after sanity check, there are three valid cases for token parsed: 1) template-id, it may forms a partial specialized template; 2) no nested-name-specified found, it should be a class type defintiion; 3) nested-name-specifier found, it may be nested class type definition, or class member definition. They need be handled case by case.

Here the “tag” will tell the compiler it is the user-defined type. From here on, this type can be used within type-specifier (if it is just a forward declaration, only limited use permited, e.g. in pointer).

 

cp_parser_class_head (continue)

 

12259   /* Look up the type.  */

12260   if (template_id_p)

12261   {

12262     type = TREE_TYPE (id);

12263     maybe_process_partial_specialization (type);

12264   }

12265   else if (!nested_name_specifier)

12266   {

12267     /* If the class was unnamed, create a dummy name.  */

12268     if (!id)

12269       id = make_anon_name ();

12270     type = xref_tag (class_key, id, /*globalize=*/false,

12271                   parser->num_template_parameter_lists);

12272   }

12273   else

12274   {

         

12316   }

 

Here for our example, as we see, variable nested_name_specifier is NULL, routine xre_tag is invoked. In the function, parameter tag_code indicates the type of tag associating with the name. And tag_type has following definition.

 

2954 enum tag_types {                                                                                      in cp-tree.h

2955   none_type = 0, /* Not a tag type.  */

2956   record_type,   /* "struct" types.  */

2957   class_type,    /* "class" types.  */

2958   union_type,    /* "union" types.  */

2959   enum_type,     /* "enum" types.  */

2960   typename_type  /* "typename" types.  */

2961 };

 

Besides, parameter globalize is false when this is also a definition. Only look in the current scope for the name; template_header_p is true when this declaration is preceded by a set of template parameters (here it is 1, which comes from parser->num_template_parameter_lists).

 

9443 tree

9444 xref_tag (enum tag_types tag_code, tree name,                                                    in decl.c

9445         bool globalize, bool template_header_p)

9446 {

9447   enum tree_code code;

9448   tree t;

9449   struct cp_binding_level *b = current_binding_level;

9450   tree context = NULL_TREE;

9451

9452   timevar_push (TV_NAME_LOOKUP);

9453

9454   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);

9455

9456   switch (tag_code)

9457   {

9458     case record_type:

9459     case class_type:

9460       code = RECORD_TYPE;

9461       break;

9462     case union_type:

9463       code = UNION_TYPE;

9464       break;

9465     case enum_type:

9466       code = ENUMERAL_TYPE;

9467       break;

9468     default:

9469       abort ();

9470   }

9471

9472   if (! globalize)

9473   {

9474     /* If we know we are defining this tag, only look it up in

9475       this scope and don't try to find it as a type.  */

9476     t = lookup_tag (code, name, b, 1);

9477   }

9478   else

9479   {

         ...

9556  }

 

As globalize is false, at invoking lookup_tag, it passes 1 for parameter thislevel_only which indicates to searche only the specified context (but skips any sk_cleanup contexts to find one that is meaningful for tags).

 

2369 tree

2370 lookup_tag (enum tree_code form, tree name,                                       in name-lookup.c

2371           cxx_scope *binding_level, int thislevel_only)

2372 {

2373   struct cp_binding_level *level;

2374   /* Nonzero if, we should look past a template parameter level, even

2375     if THISLEVEL_ONLY.  */

2376   int allow_template_parms_p = 1;

2377   bool type_is_anonymous = ANON_AGGRNAME_P (name);

2378

2379   timevar_push (TV_NAME_LOOKUP);

2380   for (level = binding_level; level; level = level->level_chain)

2381   {

2382     tree tail;

2383     if (type_is_anonymous && level->type_decls != NULL)

2384     {

2385       tree type = binding_table_find_anon_type (level->type_decls, name);

2386       /* There is no need for error checking here, because

2387         anon names are unique throughout the compilation.  */

2388       if (type != NULL)

2389         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);

2390     }

2391     else if (level->kind == sk_namespace)

2392       /* Do namespace lookup.  */

2393       for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))

2394       {

2395         cxx_binding *binding =

2396             cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);

2397         tree old;

2398

2399         /* If we just skipped past a template parameter level,

2400           even though THISLEVEL_ONLY, and we find a template

2401           class declaration, then we use the _TYPE node for the

2402           template. See the example below.  */

2403        if (thislevel_only && !allow_template_parms_p

2404           && binding && binding->value

2405           && DECL_CLASS_TEMPLATE_P (binding->value))

2406         old = binding->value;

2407       else if (binding)

2408         old = select_decl (binding, LOOKUP_PREFER_TYPES);

2409       else

2410         old = NULL_TREE;

2411

2412       if (old)

2413       {

             ...

2429       }

2430       if (thislevel_only || tail == global_namespace)

2431         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);

2432     }

2433     else if (level->type_decls != NULL)

2434     {

           ...

2449     }

2450     if (thislevel_only && level->kind != sk_cleanup)

2451     {

2452       if (level->kind == sk_template_parms && allow_template_parms_p)

2453       {

2454         /* We must deal with cases like this:

2455

2456           template <class T> struct S;

2457           template <class T> struct S {};

2458

2459           When looking up `S', for the second declaration, we

2460           would like to find the first declaration. But, we

2461           are in the pseudo-global level created for the

2462           template parameters, rather than the (surrounding)

2463           namespace level. Thus, we keep going one more level,

2464           even though THISLEVEL_ONLY is nonzero.  */

2465         allow_template_parms_p = 0;

2466         continue;

2467       }

2468       else

2469         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);

2470     }

2471   }

2472   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);

2473 }

 

First see that if thislevel_only is 0, it will look up the tag from current scope up till arriving global namespace; but if it is nonzero, the function exits immediately after searching the specified scope. Now we are doing declaration within scope “sk_template_parms” (see it is pushed by begin_template_parm_list); so we will reenter the loop even though thislevel_only is 1. And then do look-up within namespace “Loki”. Of course cxx_scope_find_binding_for_name shouldn’t find anything. As result NULL_TREE will be returned by lookup_tag.

 

xref_tag (continue)

 

9558   if (! t)

9559   {

9560     /* If no such tag is yet defined, create a forward-reference node

9561       and record it as the "definition".

9562       When a real declaration of this type is found,

9563       the forward-reference will be altered into a real type.  */

9564     if (code == ENUMERAL_TYPE)

9565     {

9566       error ("use of enum `%#D' without previous declaration", name);

9567       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

9568     }

9569     else

9570     {

9571       t = make_aggr_type (code);

9572       TYPE_CONTEXT (t) = context;

9573       pushtag (name, t, globalize);

9574     }

9575   }

9576   else

9577   {

9578     if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))

9579       redeclare_class_template (t, current_template_parms);

9580     else if (!processing_template_decl

9581           && CLASS_TYPE_P (t)

9582           && CLASSTYPE_IS_TEMPLATE (t))

9583     {

9584       error ("redeclaration of `%T' as a non-template", t);

9585       t = error_mark_node;

9586     }

9587   }

9588

9589   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);

9590 }

 

When back to xref_tag, variable t at line 9558 will be NULL. Tree node of RECORD_TYPE is created for the type. And see that the name will be pushed into namespace “Loki” by pushtag at line 9573.

Now current_binding_level refers to the cxx_scope object of sk_template_parms. So in WHILE loop at line 4596 below, b is going up to scope of namespace of “Loki”.

 

4589 void

4590 pushtag (tree name, tree type, int globalize)                                          in name-lookup.c

4591 {

4592   struct cp_binding_level *b;

4593

4594   timevar_push (TV_NAME_LOOKUP);

4595   b = current_binding_level;

4596   while (/* Cleanup scopes are not scopes from the point of view of

4597           the language.  */

4598        b->kind == sk_cleanup

4599        /* Neither are the scopes used to hold template parameters

4600          for an explicit specialization. For an ordinary template

4601          declaration, these scopes are not scopes from the point of

4602          view of the language -- but we need a place to stash

4603          things that will go in the containing namespace when the

4604          template is instantiated.  */

4605        || (b->kind == sk_template_parms && b->explicit_spec_p)

4606        || (b->kind == sk_class

4607          && (globalize

4608              /* We may be defining a new type in the initializer

4609                of a static member variable. We allow this when

4610                not pedantic, and it is particularly useful for

4611                type punning via an anonymous union.  */

4612              || COMPLETE_TYPE_P (b->this_entity))))

4613     b = b->level_chain;

4614

4615   if (b->type_decls == NULL)

4616     b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);

4617   binding_table_insert (b->type_decls, name, type);

 

Here name refers to node of identifier of “SingleThreaded”, which had not been declared yet, so below at line 4622 IDENTIFIER_TYPE_VALUE returns NULL as result. Also see in xref_tag, TYPE_CONTEXT is NULL for the node.

 

pushtag (continue)

 

4619   if (name)

4620   {

4621     /* Do C++ gratuitous typedefing.  */

4622     if (IDENTIFIER_TYPE_VALUE (name) != type)

4623     {

4624       tree d = NULL_TREE;

4625       int in_class = 0;

4626       tree context = TYPE_CONTEXT (type);

4627

4628        if (! context)

4629        {

4630          tree cs = current_scope ();

4631

4632          if (! globalize)

4633            context = cs;

4634          else if (cs != NULL_TREE && TYPE_P (cs))

4635            /* When declaring a friend class of a local class, we want

4636              to inject the newly named class into the scope

4637              containing the local class, not the namespace scope.  */

4638            context = decl_function_context (get_type_decl (cs));

4639        }

4640        if (!context)

4641          context = current_namespace;

4642

4643       if (b->kind == sk_class

4644          || (b->kind == sk_template_parms

4645            && b->level_chain->kind == sk_class))

4646         in_class = 1;

4647

4648       if (current_lang_name == lang_name_java)

4649         TYPE_FOR_JAVA (type) = 1;

4650

4651       d = create_implicit_typedef (name, type);

4652       DECL_CONTEXT (d) = FROB_CONTEXT (context);

4653       if (! in_class)

4654         set_identifier_type_value_with_scope (name, d, b);

 

Routine current_scope will return non-null only if current enclosing type is class (also struct, union) or function, and which returns NULL here. Then variable context is set as namespace “Loki” at line 4641 instead.

Figure 52: Push tag of class SingleThreaded – step 1

After inserting the name into the namespace “Loki” at line 4654, the layout of intermediate tree is roughly like above figure.

 

 

 

 

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