Studying note of GCC-3.4.6 source (110)

5.12.3.2.1.2.1.2.2.            At finish

Function cp_parser_function_body simply invokes cp_parser_compound_statement to parse the compound statement. We just skip the detail of parsing compound statement here, but keep in mind that every statement will have nodes created to be linked into the statement-list(tree). Notice that the COMPOUND_STMT node being the root of the sub-statement-list(tree) for the compound statement is kept in body at line 11476 in cp_parser_ctor_initializer_opt_and_function_body .

 

10791 void

10792 finish_function_body (tree compstmt)                                                              in decl.c

10793 {

10794   /* Close the block.  */

10795   finish_compound_stmt (compstmt);

10796

10797   if (processing_template_decl )

10798     /* Do nothing now.  */ ;

10799   else if (DECL_CONSTRUCTOR_P (current_function_decl ))

10800     finish_constructor_body ();

10801   else if (DECL_DESTRUCTOR_P (current_function_decl ))

10802     finish_destructor_body ();

10803

 

As the function-body is in fact a compound statement, finish_compound_stmt is inovked. Notice that argument compound_stmt is also body created in begin_compound_stmt .

 

1029   tree

1030   finish_compound_stmt (tree compound_stmt)                                     in semantics.c

1031   {

1032     tree r;

1033     tree t;

1034  

1035     if (COMPOUND_STMT_NO_SCOPE (compound_stmt))

1036       r = NULL_TREE;

1037     else

1038       r = do_poplevel ();

 

Because arriving at the end of the compound statement, it needs go to upper scope. Recall that we have seen exitting from scope of namespace and class; however, exitting from function scope is quite different.

 

336    tree

337    do_poplevel (void)                                                                            in semantics.c

338    {

339      tree block = NULL_TREE;

340   

341      if (stmts_are_full_exprs_p ())

342      {

343        tree scope_stmts = NULL_TREE;

344   

345        block = poplevel (kept_level_p (), 1, 0);

 

When exitting from local scope, the cxx_scope node will be reclaimed, and names, labels etc., declared within the scope are not visible by later name-lookup. But nodes for the names, labels etc., if not recorded otherwise will vanish too. To remember these items, a new node of BLOCK should be created as a root of the cache tree. However, for empty local scope, this node is unnecessary, kept_level_p below can tell if this node is needed or not.

 

1492   bool

1493   kept_level_p (void)                                                                          in name-lookup.c

1494   {

1495     return ( current_binding_level ->blocks != NULL_TREE

1496           || current_binding_level->keep

1497           || current_binding_level->kind == sk_cleanup

1498           || current_binding_level->names != NULL_TREE

1499           || current_binding_level->type_decls != NULL);

1500   }

 

So below, if argument keep is nonzero, a BLOCK node will be created to remember the local declarations. And functionbody if nonzero indicates this level is the body of a function. But notice that when invoked by do_poplevel , functionbody is 0 – it is because after leaving current scope, we will enter sk_function_parms scope, which is the “function-body” in syntax sense. In fact, poplevel will be invoked again at exitting from the “function-body” in finish_function .

 

423    tree

424    poplevel (int keep, int reverse, int functionbody)                                               in decl.c

425    {

426      tree link;

427      /* The chain of decls was accumulated in reverse order.

428        Put it into forward order, just for cleanliness.  */

429      tree decls;

430      int tmp = functionbody;

431      int real_functionbody;

432      tree subblocks;

433      tree block = NULL_TREE;

434      tree decl;

435      int leaving_for_scope;

436      scope_kind kind;

437   

438      timevar_push (TV_NAME_LOOKUP);

439   

440      my_friendly_assert ( current_binding_level ->kind != sk_class, 19990916);

441   

442      real_functionbody = ( current_binding_level ->kind == sk_cleanup

443                        ? ((functionbody = 0), tmp) : functionbody);

444      subblocks = functionbody >= 0 ? current_binding_level ->blocks : 0;

445   

446      my_friendly_assert (! current_binding_level ->class_shadowed,

447                        19990414);

448   

449      /* We used to use KEEP == 2 to indicate that the new block should go

450        at the beginning of the list of blocks at this binding level,

451        rather than the end. This hack is no longer used.  */

452      my_friendly_assert (keep == 0 || keep == 1, 0);

453   

454      if ( current_binding_level ->keep)

455        keep = 1;

456 

457      /* Any uses of undefined labels, and any defined labels, now operate

458         under constraints of next binding contour.  */

459      if (cfun && !functionbody)

460      {

461         struct cp_binding_level *level_chain;

462        level_chain = current_binding_level->level_chain;

463        if (level_chain)

464         {

465           struct named_label_use_list *uses;

466           struct named_label_list *labels;

467           for (labels = named_labels; labels; labels = labels->next)

468             if (labels->binding_level == current_binding_level)

469             {

470                tree decl;

471                if (current_binding_level->kind == sk_try)

472                  labels->in_try_scope = 1;

473               if (current_binding_level->kind == sk_catch)

474                   labels->in_catch_scope = 1;

475                for (decl = labels->names_in_scope; decl;

476                      decl = TREE_CHAIN (decl))

477                   if (decl_jump_unsafe (decl))

478                     labels->bad_decls = tree_cons (NULL_TREE, decl,

479                                              labels->bad_decls);

480               labels->binding_level = level_chain;

481               labels->names_in_scope = level_chain->names;

482             }

483 

484           for (uses = named_label_uses; uses; uses = uses->next)

485             if (uses->binding_level == current_binding_level)

486             {

487                uses->binding_level = level_chain;

488                uses->names_in_scope = level_chain->names;

489            }

490        }

491      }

 

In C++, label can only appear in function body. Above at line 467, named_labels is used by cfun to record defined labels. Field names_in_scope in named_label_list is a clever design, for instance, in compound statement:

{

D1; D2;

{

D31;

goto Label1;       // inner 1

D32;

Label1:

D33;

goto Label1;       // inner 2

goto Label2;       // inner 3

}

D4;

Label2:

goto Label1;

}

When parsing Label1, names_in_scope in its named_label_list node would be set as the contain of field names of current_binding_level (at that time, it contains D32, D31. And it’s one of reasons to use field names of current_binding_level as stack). Note that at arriving at the close brace of the inner compound statement, poplevel will also be invoked (via do_poplevel ), as the function serves to leave scope. Then in FOR loop at line 475, it needs check if there is potential danger in jumping to Label1, and remembers these dangerous declarations. For example, if D31 or D32 has initializer, jumping to Label1 may cause D31 or D32 can’t be initialized expectively. GCC prohibts such behavior.

 

2206 static int

2207 decl_jump_unsafe (tree decl)                                                                             in decl.c

2208 {

2209   if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))

2210     return 0;

2211

2212   if (DECL_INITIAL (decl) == NULL_TREE

2213       && pod_type_p (TREE_TYPE (decl)))

2214     return 0;

2215

2216   /* This is really only important if we're crossing an initialization.

2217     The POD stuff is just pedantry; why should it matter if the class

2218     contains a field of pointer to member type?  */

2219   if (DECL_INITIAL (decl)

2220       || (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))

2221     return 2;

2222   return 1;

2223 }

 

See that only non-static variable is the candidate. And only variable declaration contains no initializer (DECL_INITIAL is NULL), or its type is of POD (plain old data), skipping such declarations is safe. Note! Above the goto statement marking by “inner 2” needs not consider D31 and D32.

 

1763 int

1764 pod_type_p (tree t)                                                                                    in cp/tree.c

1765 {

1766   t = strip_array_types (t);

1767

1768   if (t == error_mark_node)

1769     return 1;

1770   if (INTEGRAL_TYPE_P (t))

1771     return 1;  /* integral, character or enumeral type */

1772   if (FLOAT_TYPE_P (t))

1773     return 1;

1774   if (TYPE_PTR_P (t))

1775     return 1; /* pointer to non-member */

1776   if (TYPE_PTR_TO_MEMBER_P (t))

1777     return 1; /* pointer to member */

1778   if (TREE_CODE (t) == VECTOR_TYPE)

1779     return 1; /* vectors are (small) arrays of scalars */

1780  

1781   if (! CLASS_TYPE_P (t))

1782     return 0; /* other non-class type (reference or function) */

1783   if (CLASSTYPE_NON_POD_P (t))

1784     return 0;

1785   return 1;

1786 }

 

Can see that reference type, class containing protected or private access data member, or data member of reference type (predicate CLASSTYPE_NON_POD_P will return 0) is not POD.

Back to above example. When exitting to the outer compound statement, code at line 480 and 481 changes the scope of Label1 to the scope of the outer compound statement, and updates its names_in_scope to contain D1 and D2. At that time, jumping can only come from this level, for example, the outer goto statement. Note! This goto statement in fact is only affected by D31 and D32, it only needs consider the inner dangerous declaractions discovered by decl_jump_unsafe .

And at line 484, named_label_uses records the usage of undefined label, such as the goto statement marked as “inner 1” in above example, at parsing, this usage would be put into named_label_uses . And in this node (of type named_label_use_list), its names_in_scope contains declaractions at that time in the scope (i.e., D31). At parsing Label1, this pending reference would be removed from named_label_uses , and decl_jump_unsafe would  check declarations between the goto statement and the label (refers to check_previous_goto_1 ).

So here in FOR loop at line 484, in named_label_uses are labels undefined. No doubt, their definitions can lie in outer layers. Such as the goto statement marked as “inner 3” in the example, between it and Label2 is D4. See in the FOR loop, it updates named_label_uses of the label usage as D1 and D2, and makes its scope as the scope of the outer layer. Then its handling isn’t different from that of goto statement marked by “inner 1”.

 

poplevel (continue)

 

493      /* Get the decls in the order they were written.

494         Usually current_binding_level->names is in reverse order.

495         But parameter decls were previously put in forward order.  */

496 

497      if (reverse)

498        current_binding_level->names

499          = decls = nreverse (current_binding_level->names);

500      else

501        decls = current_binding_level ->names;

502 

503     /* Output any nested inline functions within this block

504        if they weren't already output.  */

505      for (decl = decls; decl; decl = TREE_CHAIN (decl))

506         if (TREE_CODE (decl) == FUNCTION_DECL

507           && ! TREE_ASM_WRITTEN (decl)

508            && DECL_INITIAL (decl) != NULL_TREE

509           && TREE_ADDRESSABLE (decl)

510            && decl_function_context (decl) == current_function_decl )

511      {

512         /* If this decl was copied from a file-scope decl

513            on account of a block-scope extern decl,

514           propagate TREE_ADDRESSABLE to the file-scope decl.  */

515        if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)

516           TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;

517         else

518        {

519           push_function_context ();

520           output_inline_function (decl);

521           pop_function_context ();

522         }

523      }

524 

525      /* When not in function-at-a-time mode, expand_end_bindings will

526        warn about unused variables. But, in function-at-a-time mode

527        expand_end_bindings is not passed the list of variables in the

528        current scope, and therefore no warning is emitted. So, we

529        explicitly warn here.  */

530      if (!processing_template_decl )

531        warn_about_unused_variables (getdecls ());

532   

533      /* If there were any declarations or structure tags in that level,

534        or if this level is a function body,

535        create a BLOCK to record them for the life of this function.  */

536      block = NULL_TREE;

537      if (keep == 1 || functionbody)

538        block = make_node (BLOCK);

539      if (block != NULL_TREE)

540      {

541        BLOCK_VARS (block) = decls;

542        BLOCK_SUBBLOCKS (block) = subblocks;

543      }

544   

545      /* In each subblock, record that this is its superior.  */

546      if (keep >= 0)

547         for (link = subblocks; link; link = TREE_CHAIN (link))

548           BLOCK_SUPERCONTEXT (link) = block;

 

When called by do_poplevel , parameter reverse of poplevel is 1, and is 0 in other cases. Field names of current_binding_level always records names declared in this scope, and which is used as  stack. Now it is time to restore the order of declarations.

GCC supports nested function, and the nested function must be inline. FOR loop at line 505 generates assemble for these functions (after tht their TREE_ASM_WRITTEN will be set as 1).

Above subblocks at line 542 comes from current_binding_level->blocks, which is blocks within current scioe. See that decls at line 541, it is current_binding_level->names restored declaraction order already.

 

poplevel (continue)

 

550      /* We still support the old for-scope rules, whereby the variables

551         in a for-init statement were in scope after the for-statement

552         ended. We only use the new rules if flag_new_for_scope is

553        nonzero.  */

554      leaving_for_scope

555         = current_binding_level->kind == sk_for && flag_new_for_scope == 1;

556 

557      /* Remove declarations for all the DECLs in this level.  */

558      for (link = decls; link; link = TREE_CHAIN (link))

559      {

560        if (leaving_for_scope && TREE_CODE (link) == VAR_DECL

561           && DECL_NAME (link))

562        {

563             cxx_binding *outer_binding

564             = IDENTIFIER_BINDING (DECL_NAME (link))->previous;

565          tree ns_binding;

566 

567          if (!outer_binding)

568              ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));

569          else

570            ns_binding = NULL_TREE;

571 

572          if (outer_binding

573               && outer_binding->scope == current_binding_level->level_chain)

574            /* We have something like:

575 

576              int i;

577              for (int i; ;);

578 

579                and we are leaving the `for' scope. There's no reason to

580                keep the binding of the inner `i' in this case.  */

581            pop_binding (DECL_NAME (link), link);

582          else if ((outer_binding

583                      && (TREE_CODE (outer_binding->value) == TYPE_DECL))

584                || (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))

585            /* Here, we have something like:

586 

587                typedef int I;

588 

589              void f () {

590                 for (int I; ;);

591                }

592 

593                We must pop the for-scope binding so we know what's a

594              type and what isn't.  */

595              pop_binding (DECL_NAME (link), link);

596          else

597          {

598              /* Mark this VAR_DECL as dead so that we can tell we left it

599              there only for backward compatibility.  */

600            DECL_DEAD_FOR_LOCAL (link) = 1;

601 

602              /* Keep track of what should have happened when we

603                popped the binding.  */

604            if (outer_binding && outer_binding->value)

605               DECL_SHADOWED_FOR_VAR (link) = outer_binding->value;

606 

607            /* Add it to the list of dead variables in the next

608               outermost binding to that we can remove these when we

609              leave that binding.  */

610              current_binding_level->level_chain->dead_vars_from_for

611                = tree_cons (NULL_TREE, link,

612                           current_binding_level->level_chain->

613                           dead_vars_from_for);

614 

615            /* Although we don't pop the cxx_binding, we do clear

616              its SCOPE since the scope is going away now.  */

617              IDENTIFIER_BINDING (DECL_NAME (link))->scope = NULL;

618            }

619        }

620        else

621        {

622          /* Remove the binding.  */

623          decl = link;

624          if (TREE_CODE (decl) == TREE_LIST)

625            decl = TREE_VALUE (decl);

626          if (DECL_P (decl))

627            pop_binding (DECL_NAME (decl), decl);

628          else if (TREE_CODE (decl) == OVERLOAD)

629            pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);

630          else

631            abort ();

632        }

633      }

634 

635      /* Remove declarations for any `for' variables from inner scopes

636         that we kept around.  */

637      for (link = current_binding_level->dead_vars_from_for;

638           link; link = TREE_CHAIN (link))

639        pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));

 

In C++, the difference between FOR loop and WHILE loop, or DO WHILE loop is it has part for-init-statement. At handling FOR loop, GCC first builds scope of sk_for for FOR loop, then at seeing “ ”, adds a scope of sk_block for the body. So names of the sk_for scope records the variables declared by for-init-statement part, which are handled by IF block at line 560. Conditions at line 572 and 582, are clarified by the comments. Then ELSE block at line 596 finds variable, 1) its name doesn’t appear in outside scope; 2) its name appears in outside scope but not in the closest one. See the variables are also saved into DECL_SHADOWED_FOR_VAR, it is because before date of ISO standard, variable declared in for-init-statement has the same sccope as the FOR loop, from the point of declaration. Consider:

int i;

void g() {

for (int i = 0; i < 10; ++i) {}

extern void f(int j = i);

}

The compiler will give out below warnings:

:4: warning: name lookup of `i' changed

:1: warning:   matches this `i' under ISO standard rules

:3: warning:   matches this `i' under old rules

DECL_SHADOWED_FOR_VAR is the basis for these warnings.

Besides, to make these delcarations invisible from name-lookup, it removes associated cxx_binding node from corresponding IDENTIFIER_NODE.

 

poplevel (continue)

 

641      /* Restore the IDENTIFIER_TYPE_VALUEs.  */

642      for (link = current_binding_level ->type_shadowed;

643          link; link = TREE_CHAIN (link))

644        SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));

645 

646     /* Restore the IDENTIFIER_LABEL_VALUEs for local labels.  */

647      for (link = current_binding_level->shadowed_labels;

648           link;

649           link = TREE_CHAIN (link))

650         pop_label (TREE_VALUE (link), TREE_PURPOSE (link));

651 

652      /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs

653        list if a `using' declaration put them there. The debugging

654        back-ends won't understand OVERLOAD, so we remove them here.

655        Because the BLOCK_VARS are (temporarily) shared with

656        CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have

657        popped all the bindings.  */

658      if (block)

659      {

660        tree* d;

661   

662        for (d = &BLOCK_VARS (block); *d; )

663        {

664          if (TREE_CODE (*d) == TREE_LIST)

665            *d = TREE_CHAIN (*d);

666          else

667            d = &TREE_CHAIN (*d);

668        }

669      }

670   

671      /* If the level being exited is the top level of a function,

672        check over all the labels.  */

673      if (functionbody)

674      {

675        /* Since this is the top level block of a function, the vars are

676          the function's parameters. Don't leave them in the BLOCK

677           because they are found in the FUNCTION_DECL instead.  */

678        BLOCK_VARS (block) = 0;

679        pop_labels (block);

680      }

681   

682      kind = current_binding_level ->kind;

683   

684      leave_scope ();

685      if (functionbody)

686        DECL_INITIAL (current_function_decl ) = block;

687      else if (block)

688        current_binding_level ->blocks

689          = chainon ( current_binding_level ->blocks, block);

690   

691      /* If we did not make a block for the level just exited,

692        any blocks made for inner levels

693        (since they cannot be recorded as subblocks in that level)

694        must be carried forward so they will later become subblocks

695        of something else.  */

696      else if (subblocks)

697        current_binding_level ->blocks

698          = chainon ( current_binding_level ->blocks, subblocks);

699   

700      /* Each and every BLOCK node created here in `poplevel' is important

701        (e.g. for proper debugging information) so if we created one

702        earlier, mark it as "used".  */

703      if (block)

704        TREE_USED (block) = 1;

705   

706      /* Take care of compiler's internal binding structures.  */

707      if (kind == sk_cleanup)

708      {

709        tree scope_stmts;

710   

711         scope_stmts

712             = add_scope_stmt (/*begin_p=*/ 0, /*partial_p=*/ 1);

713        if (block)

714        {

715          SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;

716          SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;

717        }

718   

719        block = poplevel (keep, reverse, functionbody);

720      }

721   

722      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);

723    }

 

Pay attention to line 678, if functionbody is nonzero, we are exitting sk_function_parms scope, in which only contains function parameters, which needn’t be recorded into BLOCK as they are kept in the FUNCTION_DECL. At line 684, executing level_scope , makes current_binding_level refers to upper scope. Then see that at line 686, field DECL_INITIAL of FUNCTION_DECL preserves blocks within. At last this BLOCK node is returned and it is possible to return NULL if the function has empty body.

 

do_poplevel (continue)

 

346        if (!processing_template_decl )

347        {

348          /* This needs to come after the poplevel so that partial scopes

349             are properly nested.  */

350          scope_stmts = add_scope_stmt (/*begin_p=*/ 0, /*partial_p=*/ 0);

351          if (block)

352          {

353            SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;

354            SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;

355          }

356        }

357      }

358   

359      return block;

360    }

 

Back do_poplevel , see that block at line 351 is that returned by poplevel at line 722. And in the function at line 350, it closes the scope added by do_pushlevel . And the content of the scope is the block .

 

finish_compound_stmt (continue)

 

1040     RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt));

1041  

1042     /* When we call finish_stmt we will lose LAST_EXPR_TYPE. But, since

1043       the precise purpose of that variable is store the type of the

1044       last expression statement within the last compound statement, we

1045       preserve the value.  */

1046     t = last_expr_type;

1047     finish_stmt ();

1048     last_expr_type = t;

1049  

1050     return r;

1051   }

 

Above macro RECHAIN_STMTS rearranges the node of COMPOUND_STMT by moving the list of statements underlying from chain field to operands[0] field.

 

315    #define RECHAIN_STMTS (stmt, substmt)              /                           in c-common.h

316      do {                                     /

317        substmt = TREE_CHAIN (stmt);              /

318        TREE_CHAIN (stmt) = NULL_TREE;            /

319        last_tree = stmt;                        /

320      } while (0)

 

It is strange that code from line 1046 to 1048 in fact does nothing.

 

11252 void

11253 finish_stmt (void)                                                                                          in decl.c

11254 {

11255   /* Always assume this statement was not an expression statement. If

11256     it actually was an expression statement, its our callers

11257     responsibility to fix this up.  */

11258   last_expr_type = NULL_TREE;

11259 }

 

At this point, following nodes will be created for the function-body parsed. Nodes created for statements within the function-body are omitted; they are prepresented by ‘…’ in figure. However, they take the similar form as this outer-most COMPOUND_STMT. We will see the detail of these nodes later.

(Click here for open )

Figure 95 : nodes created for function-body parsing

The difference between class-template method and non-template method is great. For non-template method, see that a pair of SCOPE_STMTs will be created for every scope for the function, and a tree_list node will hold them to record this effective range of the scope. Further current_scope_stmt_stack records the scopes within the stack. Every call of finish_compound_stmt will pop up the stack, and go scope one level up.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值