Studying note of GCC-3.4.6 source (107)

5.12.3.2.1.2.  Finish parsing

5.12.3.2.1.2.1.          Late parse inline methods

The parsing of rest members of the class “SingleThreaded” is almost the same as those we have seen. So we just skip these declarations, and assumes that now parser seeing the closing “}” of the class. Besides the similar handling of struct “Lock”, class “SingleThreaded”, being the top one, will undergo following processing.

 

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   {

11950     tree queue_entry;

11951     tree fn;

11952

11953     /* In a first pass, parse default arguments to the functions.

11954       Then, in a second pass, parse the bodies of the functions.

11955       This two-phased approach handles cases like:

11956     

11957          struct S {

11958               void f() { g(); }

11959               void g(int i = 3);

11960             };

11961

11962     */

11963     for (TREE_PURPOSE (parser->unparsed_functions_queues)

11964          = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));

11965          (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));

11966          TREE_PURPOSE (parser->unparsed_functions_queues)

11967            = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))

11968     {

11969       fn = TREE_VALUE (queue_entry);

11970       /* Make sure that any template parameters are in scope.  */

11971       maybe_begin_member_template_processing (fn);

11972       /* If there are default arguments that have not yet been processed,

11973         take care of them now.  */

11974       cp_parser_late_parsing_default_args (parser, fn);

11975       /* Remove any template parameters from the symbol table.  */

11976       maybe_end_member_template_processing ();

11977     }

11978     /* Now parse the body of the functions.  */

11979     for (TREE_VALUE (parser->unparsed_functions_queues)

11980           = nreverse (TREE_VALUE (parser->unparsed_functions_queues));

11981        (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));

11982        TREE_VALUE (parser->unparsed_functions_queues)

11983           = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues)))

11984     {

11985       /* Figure out which function we need to process.  */

11986       fn = TREE_VALUE (queue_entry);

11987

11988       /* A hack to prevent garbage collection.  */

11989       function_depth ++;

11990

11991       /* Parse the function.  */

11992        cp_parser_late_parsing_for_member (parser, fn);

11993       function_depth --;

11994     }

11995

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 }

 

Field unparsed_functions_queues of parser is a tree_list, whose TREE_PURPOSE field holds the chain recording default arguments of methods, and TREE_VALUE field is a chain recording inline methods defining in the class body. Note that these 2 chains are independent upon each other. For inline method, its recording tree_list has the node of METHOD_TYPE in its TREE_VALUE field (refers to cp_parser_save_member_function_body ). At time exitting the top-most class, we have enough information to handle these objects. So here it uses 2 loops to process default arguments and inline methods respectively.

 

14759 static void

14760 cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) in parser.c

14761 {

14762   cp_lexer *saved_lexer;

14763

14764   /* If this member is a template, get the underlying

14765     FUNCTION_DECL.  */

14766   if (DECL_FUNCTION_TEMPLATE_P (member_function))

14767     member_function = DECL_TEMPLATE_RESULT (member_function);

14768

14769   /* There should not be any class definitions in progress at this

14770     point; the bodies of members are only parsed outside of all class

14771     definitions.  */

14772   my_friendly_assert (parser->num_classes_being_defined == 0, 20010816);

14773   /* While we're parsing the member functions we might encounter more

14774     classes. We want to handle them right away, but we don't want

14775     them getting mixed up with functions that are currently in the

14776     queue.  */

14777   parser->unparsed_functions_queues

14778     = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);

14779

14780   /* Make sure that any template parameters are in scope.  */

14781   maybe_begin_member_template_processing (member_function);

14782

14783   /* If the body of the function has not yet been parsed, parse it

14784     now.  */

14785   if (DECL_PENDING_INLINE_P (member_function))

14786   {

14787     tree function_scope;

14788     cp_token_cache *tokens;

14789

14790     /* The function is no longer pending; we are processing it.  */

14791     tokens = DECL_PENDING_INLINE_INFO (member_function);

14792     DECL_PENDING_INLINE_INFO (member_function) = NULL;

14793     DECL_PENDING_INLINE_P (member_function) = 0;

14794      

14795     /* If this is a local class, enter the scope of the containing

14796       function.  */

14797     function_scope = current_function_decl ;

14798     if (function_scope)

14799       push_function_context_to (function_scope);

14800      

14801     /* Save away the current lexer.  */

14802     saved_lexer = parser->lexer;

14803     /* Make a new lexer to feed us the tokens saved for this function.  */

14804     parser->lexer = cp_lexer_new_from_tokens (tokens);

14805     parser->lexer->next = saved_lexer;

14806      

14807     /* Set the current source position to be the location of the first

14808       token in the saved inline body.  */

14809     cp_lexer_peek_token (parser->lexer);

14810      

14811     /* Let the front end know that we going to be defining this

14812       function.  */

14813     start_function (NULL_TREE, member_function, NULL_TREE,

14814                 SF_PRE_PARSED | SF_INCLASS_INLINE);

14815      

14816     /* Now, parse the body of the function.  */

14817     cp_parser_function_definition_after_declarator (parser,

14818                                            /*inline_p=*/ true);

14819      

14820     /* Leave the scope of the containing function.  */

14821     if (function_scope)

14822       pop_function_context_from (function_scope);

14823     /* Restore the lexer.  */

14824     parser->lexer = saved_lexer;

14825   }

14826

14827   /* Remove any template parameters from the symbol table.  */

14828   maybe_end_member_template_processing ();

14829

14830   /* Restore the queue.  */

14831   parser->unparsed_functions_queues

14832     = TREE_CHAIN (parser->unparsed_functions_queues);

14833 }

 

Unprocessed inline method has DECL_PENDING_INLINE_P set. For our exmaple program, no function is parsed so far, so current_function_decl is null now. As we have seen, lexer feeds parser with tokens when advances ahead in the source. Now lexer stops at the end of the class body, but for parsing the body of inline method, the parser expects tokens forming the body which current lexer can’t provide. It is better to use a temperary lexer to feed parser with those cached tokens, and abandon it when finish. At line 14804, the temperary lexer is allocated in GC controls memory, and will be collected automatically after its release.

As an extension, GCC allows local class defined within function scope, and as result class methods can have class defined within too, and this fashion can be nested. For example, following code is valid in GCC.

#include <stdio.h>

 

void func1 () {

    struct A {

        void funcA() {

            struct B {

                void funcB() { printf ("funcB/n"); }

            };

            B b;

            b.funcB();

        }

    };

    A a;

    a.funcA();

}

 

main() {

    func1();

    return 0;

}

Then before processing funcB, cfun holds data of funcA; but during the processing of funcB, it must be updated with data of funcB. And after this handling, it must restore cfun with data of funcA. For the purpose, the front-end uses outer_function_chain records the function contexts in push_function_context_to at line 14799

 

324    void

325    push_function_context_to (tree context)                                                    in function.c

326    {

327      struct function *p;

328   

329      if (context)

330      {

331        if (context == current_function_decl )

332          cfun ->contains_functions = 1;

333        else

334        {

335          struct function *containing = find_function_data (context);

336          containing->contains_functions = 1;

337        }

338      }

339   

340      if (cfun == 0)

341        init_dummy_function_start ();

342      p = cfun ;

343   

344      p->outer = outer_function_chain ;

345      outer_function_chain = p;

346      p->fixup_var_refs_queue = 0;

347   

348      (*lang_hooks .function.enter_nested ) (p);

349   

350      cfun = 0;

351    }

 

For above example, outer_function_chain will record the function contexts as: funcB à funcA à func1 during processing funcB. And at line 348, the language dependent hook does specified task for C/C++ as below, it just copy the part of language_function in cfun .

 

6289   void

6290   c_push_function_context (struct function *f)                                              in c-decl.c

6291   {

6292     struct language_function *p;

6293     p = ggc_alloc (sizeof (struct language_function));

6294     f->language = p;

6295  

6296     p->base.x_stmt_tree = c_stmt_tree ;

6297     p->base.x_scope_stmt_stack = c_scope_stmt_stack ;

6298     p->x_in_iteration_stmt = c_in_iteration_stmt ;

6299     p->x_in_case_stmt = c_in_case_stmt ;

6300     p->returns_value = current_function_returns_value ;

6301     p->returns_null = current_function_returns_null ;

6302     p->returns_abnormally = current_function_returns_abnormally ;

6303     p->warn_about_return_type = warn_about_return_type ;

6304     p->extern_inline = current_extern_inline ;

6305   }

 

Obviously pop operation at line 14822, should do reversely.

5.12.3.2.1.2.1.1.    Start function handling

After creating temperary lexer, start_function will prepare and make the function scope into effective. See that argument flags indicates the inline method declaraction has been parsed; and argument declarator refers to the nodes of METHOD_TYPE.

 

10181 int

10182 start_function (tree declspecs, tree declarator, tree attrs, int flags)                        in decl.c

10183 {

10184   tree decl1;

10185   tree ctype = NULL_TREE;

10186   tree fntype;

10187   tree restype;

10188   int doing_friend = 0;

10189   struct cp_binding_level *bl;

10190   tree current_function_parms;

10191

10192   /* Sanity check.  */

10193   my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);

10194   my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);

10195

10196   /* This should only be done once on the top most decl.  */

10197   if (have_extern_spec )

10198   {

10199     declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);

10200     have_extern_spec = false;

10201   }

10202

10203   if (flags & SF_PRE_PARSED)

10204   {

10205     decl1 = declarator;

10206

10207     fntype = TREE_TYPE (decl1);

10208     if (TREE_CODE (fntype) == METHOD_TYPE)

10209       ctype = TYPE_METHOD_BASETYPE (fntype);

10210

10211     /* ISO C++ 11.4/5. A friend function defined in a class is in

10212       the (lexical) scope of the class in which it is defined.  */

10213     if (!ctype && DECL_FRIEND_P (decl1))

10214     {

10215       ctype = DECL_FRIEND_CONTEXT (decl1);

10216

10217       /* CTYPE could be null here if we're dealing with a template;

10218         for example, `inline friend float foo()' inside a template

10219         will have no CTYPE set.  */

10220       if (ctype && TREE_CODE (ctype) != RECORD_TYPE)

10221         ctype = NULL_TREE;

10222       else

10223         doing_friend = 1;

10224     }

10225   }

10226   else

10227   {

         

10257   }

10258

10259   if (DECL_DECLARED_INLINE_P (decl1)

10260       && lookup_attribute ("noinline", attrs))

10261     warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);

10262

10263   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))

10264     /* This is a constructor, we must ensure that any default args

10265       introduced by this definition are propagated to the clones

10266       now. The clones are used directly in overload resolution.  */

10267     adjust_clone_args (decl1);

10268

10269   /* Sometimes we don't notice that a function is a static member, and

10270     build a METHOD_TYPE for it. Fix that up now.  */

10271   if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)

10272       && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)

10273   {

10274     revert_static_member_fn (decl1);

10275     ctype = NULL_TREE;

10276   }

10277

10278   /* Warn if function was previously implicitly declared

10279     (but not if we warned then).  */

10280   if (! warn_implicit

10281       && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)

10282     cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));

10283

10284   /* Set up current_class_type, and enter the scope of the class, if

10285     appropriate.  */

10286   if (ctype)

10287     push_nested_class (ctype);

10288   else if (DECL_STATIC_FUNCTION_P (decl1))

10289     push_nested_class (DECL_CONTEXT (decl1));

 

Previous, at line 11925 in cp_parser_class_specifier , routine finish_struct pops the scope of the class at line 5257, and current scope now is that of the containing class/namespace. It needs push back this scope again before going ahead to handling the inline method.

 

5627   void

5628   push_nested_class (tree type)                                                                    in class.c

5629   {

5630     tree context;

5631  

5632     /* A namespace might be passed in error cases, like A::B:C.  */

5633     if (type == NULL_TREE

5634         || type == error_mark_node

5635         || TREE_CODE (type) == NAMESPACE_DECL

5636         || ! IS_AGGR_TYPE (type)

5637         || TREE_CODE (type) == TEMPLATE_TYPE_PARM

5638         || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)

5639       return ;

5640    

5641     context = DECL_CONTEXT (TYPE_MAIN_DECL (type));

5642  

5643     if (context && CLASS_TYPE_P (context))

5644       push_nested_class (context);

5645     pushclass (type);

5646   }

 

If the class is contained by another class, it is very possible we have exited from its scope, and it should be pushed into before. And for our example, it needs push back scope of “SingleThreaded”, then “Lock”.

 

start_function (continue)

 

10291   /* Now that we have entered the scope of the class, we must restore

10292     the bindings for any template parameters surrounding DECL1, if it

10293     is an inline member template. (Order is important; consider the

10294     case where a template parameter has the same name as a field of

10295     the class.) It is not until after this point that

10296     PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly.  */

10297   if (flags & SF_INCLASS_INLINE)

10298     maybe_begin_member_template_processing (decl1);

10299

10300   /* Effective C++ rule 15.  */

10301   if (warn_ecpp

10302       && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR

10303       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)

10304     warning ("`operator=' should return a reference to `*this'");

10305

10306   /* Make the init_value nonzero so pushdecl knows this is not tentative.

10307     error_mark_node is replaced below (in poplevel) with the BLOCK.  */

10308   if (!DECL_INITIAL (decl1))

10309     DECL_INITIAL (decl1) = error_mark_node;

10310

10311   /* This function exists in static storage.

10312     (This does not mean `static' in the C sense!)  */

10313   TREE_STATIC (decl1) = 1;

10314

10315   /* We must call push_template_decl after current_class_type is set

10316     up. (If we are processing inline definitions after exiting a

10317     class scope, current_class_type will be NULL_TREE until set above

10318     by push_nested_class.)  */

10319   if (processing_template_decl )

10320   {

10321     tree newdecl1 = push_template_decl (decl1);

10322     if (newdecl1 != error_mark_node)

10323       decl1 = newdecl1;

10324   }

 

TEMPLATE_DECL has been created for the method (the non-default constructor), so at line 10321 push_template_decl just does some sainty check. Already at line 5254 in finish_struct , TYPE_BEING_DEFINED has been cleared.

 

2770   tree

2771   push_template_decl_real (tree decl, int is_friend)                                              in pt.c

2772   {

2773     tree tmpl;

2774     tree args;

2775     tree info;

2776     tree ctx;

2777     int primary;

2778     int is_partial;

2779     int new_template_p = 0;

2780  

2781     /* See if this is a partial specialization.  */

2782     is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)

2783               && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE

2784               && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));

2785  

2786     is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl));

2787  

2788     if (is_friend)

2789       /* For a friend, we want the context of the friend function, not

2790         the type of which it is a friend.  */

2791       ctx = DECL_CONTEXT (decl);

2792     else if (CP_DECL_CONTEXT (decl)

2793           && TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)

2794       /* In the case of a virtual function, we want the class in which

2795         it is defined.  */

2796       ctx = CP_DECL_CONTEXT (decl);

2797     else

2798       /* Otherwise, if we're currently defining some class, the DECL

2799         is assumed to be a member of the class.  */

2800       ctx = current_scope ();

2801  

2802     if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)

2803       ctx = NULL_TREE;

2804  

2805     if (!DECL_CONTEXT (decl))

2806       DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);

2807  

2808     /* See if this is a primary template.  */

2809     primary = template_parm_scope_p ();

2810  

2811     if (primary)

2812     {

          ...

2852     }

2853  

2854     /* Check to see that the rules regarding the use of default

2855       arguments are not being violated.  */

2856     check_default_tmpl_args (decl, current_template_parms,

2857                          primary, is_partial);

2858  

2859     if (is_partial)

2860       return process_partial_specialization (decl);

2861  

2862     args = current_template_args ();

2863  

2864     if (!ctx

2865        || TREE_CODE (ctx) == FUNCTION_DECL

2866        || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))

2867        || (is_friend && !DECL_TEMPLATE_INFO (decl)))

2868     {

          ...

2904     }

2905     else

2906     {

2907       tree a, t, current, parms;

2908       int i;

2909  

2910       if (TREE_CODE (decl) == TYPE_DECL)

2911       {

            ...

2922       }

2923       else if (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))

2924       {

2925         error ("template definition of non-template `%#D'", decl);

2926          return decl;

2927       }

2928       else

2929         tmpl = DECL_TI_TEMPLATE (decl);

2930        

2931       if (DECL_FUNCTION_TEMPLATE_P (tmpl)

2932          && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)

2933          && DECL_TEMPLATE_SPECIALIZATION (decl)

2934          && is_member_template (tmpl))

2935       {

         ...

2958       }

2959  

2960       /* Make sure the template headers we got make sense.  */

2961  

2962       parms = DECL_TEMPLATE_PARMS (tmpl);

2963       i = TMPL_PARMS_DEPTH (parms);

2964       if (TMPL_ARGS_DEPTH (args) != i)

2965       {

2966         error ("expected %d levels of template parms for `%#D', got %d",

2967              i, decl, TMPL_ARGS_DEPTH (args));

2968       }

2969       else

2970         for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))

2971         {

2972           a = TMPL_ARGS_LEVEL (args, i);

2973           t = INNERMOST_TEMPLATE_PARMS (parms);

2974  

2975           if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))

2976           {

2977             if (current == decl)

2978               error ("got %d template parameters for `%#D'",

2979                    TREE_VEC_LENGTH (a), decl);

2980             else

2981               error ("got %d template parameters for `%#T'",

2982                     TREE_VEC_LENGTH (a), current);

2983             error ("  but %d required", TREE_VEC_LENGTH (t));

2984             return error_mark_node;

2985           }

2986  

2987           /* Perhaps we should also check that the parms are used in the

2988             appropriate qualifying scopes in the declarator?  */

2989  

2990           if (current == decl)

2991             current = ctx;

2992           else

2993             current = TYPE_CONTEXT (current);

2994         }

2995     }

2996  

2997     DECL_TEMPLATE_RESULT (tmpl) = decl;

2998     TREE_TYPE (tmpl) = TREE_TYPE (decl);

2999  

3000     /* Push template declarations for global functions and types. Note

3001       that we do not try to push a global template friend declared in a

3002       template class; such a thing may well depend on the template

3003       parameters of the class.  */

3004     if (new_template_p && !ctx

3005         && !(is_friend && template_class_depth (current_class_type ) > 0))

3006       tmpl = pushdecl_namespace_level (tmpl);

3007  

3008     if (primary)

3009     {

          ...

3022     }

3023  

3024     /* The DECL_TI_ARGS of DECL contains full set of arguments refering

3025       back to its most general template. If TMPL is a specialization,

3026       ARGS may only have the innermost set of arguments. Add the missing

3027       argument levels if necessary.  */

3028     if (DECL_TEMPLATE_INFO (tmpl))

3029       args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);

3030  

3031     info = tree_cons (tmpl, args, NULL_TREE);

3032  

3033     if (DECL_IMPLICIT_TYPEDEF_P (decl))

3034     {

          ...

3041     }

3042     else if (DECL_LANG_SPECIFIC (decl))

3043       DECL_TEMPLATE_INFO (decl) = info;

3044  

3045     return DECL_TEMPLATE_RESULT (tmpl);

3046   }

 

At line 2929, tmpl refers to the TEMPLATE_DECL created in previous section. But for this TEMPLATE_DECL, DECL_TEMPLATE_INFO is still null. Then the same info is created again.

 

start_function (continue)

 

10326   /* We are now in the scope of the function being defined.  */

10327   current_function_decl = decl1;

10328

10329   /* Save the parm names or decls from this function's declarator

10330     where store_parm_decls will find them.  */

10331   current_function_parms = DECL_ARGUMENTS (decl1);

10332

10333   /* Make sure the parameter and return types are reasonable. When

10334     you declare a function, these types can be incomplete, but they

10335     must be complete when you define the function.  */

10336   if (!processing_template_decl )

10337     check_function_type (decl1, current_function_parms);

10338   /* Make sure no default arg is missing.  */

10339   check_default_args (decl1);

10340

10341   /* Build the return declaration for the function.  */

10342   restype = TREE_TYPE (fntype);

10343   /* Promote the value to int before returning it.  */

10344   if (c_promoting_integer_type_p (restype))

10345     restype = type_promotes_to (restype);

10346   if (DECL_RESULT (decl1) == NULL_TREE)

10347   {

10348     DECL_RESULT (decl1)

10349        = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));

10350     c_apply_type_quals_to_decl (cp_type_quals (restype),

10351                             DECL_RESULT (decl1));

10352   }

10353

10354   /* Initialize RTL machinery. We cannot do this until

10355     CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this

10356     even when processing a template; this is how we get

10357     CFUN set up, and our per-function variables initialized.

10358     FIXME factor out the non-RTL stuff.  */

10359   bl = current_binding_level ;

10360   allocate_struct_function (decl1);

10361   current_binding_level = bl;

10362

10363   /* Even though we're inside a function body, we still don't want to

10364     call expand_expr to calculate the size of a variable-sized array.

10365     We haven't necessarily assigned RTL to all variables yet, so it's

10366     not safe to try to expand expressions involving them.  */

10367   immediate_size_expand = 0;

10368   cfun ->x_dont_save_pending_sizes_p = 1;

10369

10370   /* Start the statement-tree, start the tree now.  */

10371   begin_stmt_tree (&DECL_SAVED_TREE (decl1));

 

In front-end, TREE_TYPE of METHOD_TYPE describes the returned type. Surprising, if the returned type is integer type having size less that int, it should be promoted to int type.

 

3560   bool

3561   c_promoting_integer_type_p (tree t)                                                         in c-common.c

3562   {

3563     switch (TREE_CODE (t))

3564     {

3565       case INTEGER_TYPE:

3566         return (TYPE_MAIN_VARIANT (t) == char_type_node

3567               || TYPE_MAIN_VARIANT (t) == signed_char_type_node

3568               || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node

3569               || TYPE_MAIN_VARIANT (t) == short_integer_type_node

3570               || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node

3571               || TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node));

3572  

3573       case ENUMERAL_TYPE:

3574         /* ??? Technically all enumerations not larger than an int

3575           promote to an int. But this is used along code paths

3576           that only want to notice a size change.  */

3577         return TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node);

3578  

3579       case BOOLEAN_TYPE:

3580         return 1;

3580  

3581       default :

3582         return 0;

3583     }

3584   }

 

Promoting to int, is just to find out builtin integer type of desired size. In the procedure of setting up run-time environment, we can see details about creating internal presentation of such types and the way to find them out in the intermediate tree.

 

1115   tree

1116   type_promotes_to (tree type)                                                                           in cvt.c

1117   {

1118     if (type == error_mark_node)

1119       return error_mark_node;

1120  

1121     type = TYPE_MAIN_VARIANT (type);

1122  

1123     /* bool always promotes to int (not unsigned), even if it's the same

1124       size.  */

1125     if (type == boolean_type_node)

1126       type = integer_type_node;

1127  

1128     /* Normally convert enums to int, but convert wide enums to something

1129       wider.  */

1130     else if (TREE_CODE (type) == ENUMERAL_TYPE

1131           || type == wchar_type_node)

1132     {

1133       int precision = MAX (TYPE_PRECISION (type),

1134                         TYPE_PRECISION (integer_type_node));

1135       tree totype = c_common_type_for_size (precision, 0);

1136       if (TREE_UNSIGNED (type)

1137          && ! int_fits_type_p (TYPE_MAX_VALUE (type), totype))

1138         type = c_common_type_for_size (precision, 1);

1139       else

1140         type = totype;

1141     }

1142     else if (c_promoting_integer_type_p (type))

1143     {

1144       /* Retain unsignedness if really not getting bigger.  */

1145       if (TREE_UNSIGNED (type)

1146          && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))

1147         type = unsigned_type_node;

1148       else

1149         type = integer_type_node;

1150     }

1151     else if (type == float_type_node)

1152       type = double_type_node;

1153      

1154     return type;

1155   }

 

Above from line 10346 to 10352, the returned type, according to the specification of C++ language must be one defined or forward declared for case of address returned. Then if any cv-qualifier applied, in natural it has nothing different than type appears other place. However, the front-end needs to know the returned type of the function to do some optimization, so returned type has RESULT_DECL created for, and linked into DECL_RESULT field of the FUNCTION_DECL node. As result, the cv-qualifier applied is enforced upon the RESULT_DECL node instead by c_apply_type_quals_to_decl .

 

2805   void

2806   c_apply_type_quals_to_decl (int type_quals, tree decl)                         in c-common.c

2807   {

2808     tree type = TREE_TYPE (decl);

2809    

2810     if (type == error_mark_node)

2811       return ;

2812  

2813     if (((type_quals & TYPE_QUAL_CONST)

2814         || (type && TREE_CODE (type) == REFERENCE_TYPE))

2815           /* An object declared 'const' is only readonly after it is

2816             initialized. We don't have any way of expressing this currently,

2817             so we need to be conservative and unset TREE_READONLY for types

2818             with constructors. Otherwise aliasing code will ignore stores in

2819             an inline constructor.  */

2820           && !(type && TYPE_NEEDS_CONSTRUCTING (type)))

2821       TREE_READONLY (decl) = 1;

2822     if (type_quals & TYPE_QUAL_VOLATILE)

2823     {

2824       TREE_SIDE_EFFECTS (decl) = 1;

2825        TREE_THIS_VOLATILE (decl) = 1;

2826     }

2827     if (type_quals & TYPE_QUAL_RESTRICT)

2828     {

2829       while (type && TREE_CODE (type) == ARRAY_TYPE)

2830         /* Allow 'restrict' on arrays of pointers.

2831           FIXME currently we just ignore it.  */

2832         type = TREE_TYPE (type);

2833       if (!type

2834          || !POINTER_TYPE_P (type)

2835          || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))

2836         error ("invalid use of `restrict'");

2837       else if (flag_strict_aliasing && type == TREE_TYPE (decl))

2838              /* Indicate we need to make a unique alias set for this pointer.

2839              We can't do it here because it might be pointing to an

2840              incomplete type.  */

2841        DECL_POINTER_ALIAS_SET (decl) = -2;

2842     }

2843   }

 

The so-called apply-type-quals-to-decl in fact sets relevant flags in the node.

 

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