Studying note of GCC-3.4.6 source (141 - cont 2)

Then check_initializer is invoked to verify the initializers. Here argument flags is 0.

 

4463   static tree

4464   check_initializer (tree decl, tree init, int flags, tree *cleanup)                               in decl.c

4465   {

4466     tree type = TREE_TYPE (decl);

4467     tree init_code = NULL;

4468  

4469     /* If `start_decl' didn't like having an initialization, ignore it now.  */

4470     if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)

4471       init = NULL_TREE;

4472  

4473     /* If an initializer is present, DECL_INITIAL has been

4474       error_mark_node, to indicate that an as-of-yet unevaluated

4475       initialization will occur. From now on, DECL_INITIAL reflects

4476       the static initialization -- if any -- of DECL.  */

4477     DECL_INITIAL (decl) = NULL_TREE;

4478  

4479     /* Things that are going to be initialized need to have complete

4480       type.  */

4481     TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));

4482  

4483     if (type == error_mark_node)

4484       /* We will have already complained.  */

4485       init = NULL_TREE;

4486     else if (init && COMPLETE_TYPE_P (type)

4487            && !TREE_CONSTANT (TYPE_SIZE (type)))

4488     {

4489       error ("variable-sized object `%D' may not be initialized", decl);

4490       init = NULL_TREE;

4491     }

4492     else if (TREE_CODE (type) == ARRAY_TYPE

4493            && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))

4494     {

4495       error ("elements of array `%#D' have incomplete type", decl);

4496       init = NULL_TREE;

4497     }

4498     else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))

4499     {

4500       error ("`%D' has incomplete type", decl);

4501       TREE_TYPE (decl) = error_mark_node;

4502       init = NULL_TREE;

4503     }

4504  

4505     if (TREE_CODE (decl) == CONST_DECL)

4506     {

4507       my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);

4508  

4509       DECL_INITIAL (decl) = init;

4510  

4511       my_friendly_assert (init != NULL_TREE, 149);

4512       init = NULL_TREE;

4513     }

4514     else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)

4515       init = grok_reference_init (decl, type, init, cleanup);

4516     else if (init)

4517     {

4518       if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))

4519       {

4520           /* [dcl.init] paragraph 13,

4521            If T is a scalar type, then a declaration of the form

4522            T x = { a };

4523            is equivalent to

4524            T x = a;

4525       

4526            reshape_init will complain about the extra braces,

4527            and doesn't do anything useful in the case where TYPE is

4528            scalar, so just don't call it.  */

4529          if (CP_AGGREGATE_TYPE_P (type))

4530            init = reshape_init (type, &init);

4531  

4532          if ((*targetm .vector_opaque_p) (type))

4533          {

4534            error ("opaque vector types cannot be initialized");

4535            init = error_mark_node;

4536          }

4537       }

 

One of clause of [dcl.init.aggr] of C++ standard specifies that:

All implicit type conversions (clause 4) are considered when initializing the aggregate member with an initializer from an initializer-list. If the initializer can initialize a member, the member is initialized. Otherwise, if the member is itself a non-empty subaggregate, brace elision is assumed and the initializer is considered for the initialization of the first member of the subaggregate. For example:

struct A {

int i;

operator int();

};

struct B {

A a1, a2;

int z;

};

A a;

B b = { 4, a, a };

Braces are elided around the initializer for b.a1.i. b.a1.i is initialized with 4, b.a2 is initialized with a, b.z is initialized with whatever a.operator int() returns.

Routine reshape_init is invoked to transform the initializers list in form of {4, a, a } into the form of { {4, a}, a}. The rear one is what expected by the front-end.

Here for our example, the VAR_DECL is the array of vtable_entry_type and initp refers to the CONSTRUCTOR node for the initializers, which is deliberately created with empty type. So code in block at line 4289 is executed. CONSTRUCTOR_ELTS returns the inits generated in above. These initializers are treated as if enclosed by braces.

 

4267   static tree

4268   reshape_init (tree type, tree *initp)                                                                    in decl.c

4269   {

4270     tree inits;

4271     tree old_init;

4272     tree old_init_value;

4273     tree new_init;

4274     bool brace_enclosed_p;

4275     bool string_init_p;

4276  

4277     old_init = *initp;

4278     old_init_value = (TREE_CODE (*initp) == TREE_LIST

4279                    ? TREE_VALUE (*initp) : old_init);

4280  

4281     my_friendly_assert (old_init_value, 20030723);

4282  

4283     /* If the initializer is brace-enclosed, pull initializers from the

4284       enclosed elements. Advance past the brace-enclosed initializer

4285       now.  */

4286     if (TREE_CODE (old_init_value) == CONSTRUCTOR

4287        && TREE_TYPE (old_init_value) == NULL_TREE

4288        && TREE_HAS_CONSTRUCTOR (old_init_value))

4289     {

4290       *initp = TREE_CHAIN (old_init);

4291       TREE_CHAIN (old_init) = NULL_TREE;

4292       inits = CONSTRUCTOR_ELTS (old_init_value);

4293       initp = &inits;

4294       brace_enclosed_p = true;

4295     }

4296     else

4297     {

4298       inits = NULL_TREE;

4299       brace_enclosed_p = false;

4300     }

4301  

4302     /* A non-aggregate type is always initialized with a single

4303       initializer.  */

4304     if (!CP_AGGREGATE_TYPE_P (type))

4305     {

4306       *initp = TREE_CHAIN (old_init);

4307       TREE_CHAIN (old_init) = NULL_TREE;

4308       /* It is invalid to initialize a non-aggregate type with a

4309         brace-enclosed initializer.  */

4310       if (brace_enclosed_p)

4311       {

4312         error ("brace-enclosed initializer used to initialize `%T'",

4313               type);

4314         if (TREE_CODE (old_init) == TREE_LIST)

4315           TREE_VALUE (old_init) = error_mark_node;

4316         else

4317           old_init = error_mark_node;

4318       }

4319       

4320       return old_init;

4321     }

4322  

4323     /* [dcl.init.aggr]

4324  

4325       All implicit type conversions (clause _conv_) are considered when

4326       initializing the aggregate member with an initializer from an

4327       initializer-list. If the initializer can initialize a member,

4328       the member is initialized. Otherwise, if the member is itself a

4329       non-empty subaggregate, brace elision is assumed and the

4330       initializer is considered for the initialization of the first

4331       member of the subaggregate.  */

4332     if (!brace_enclosed_p

4333        && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))

4334     {

4335       *initp = TREE_CHAIN (old_init);

4336       TREE_CHAIN (old_init) = NULL_TREE;

4337       return old_init;

4338     }

4339  

4340     string_init_p = false;

4341     if (TREE_CODE (old_init_value) == STRING_CST

4342        && TREE_CODE (type) == ARRAY_TYPE

4343        && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))

4344     {

          …

4356     }

4357     else

4358     {

4359       /* Build a CONSTRUCTOR to hold the contents of the aggregate.  */ 

4360       new_init = build_constructor (type, NULL_TREE);

4361       TREE_HAS_CONSTRUCTOR (new_init) = 1;

4362  

4363       if (CLASS_TYPE_P (type))

4364       {

            …

4419       }

4420       else if ((TREE_CODE (type) == ARRAY_TYPE)|| (TREE_CODE (type) == VECTOR_TYPE))

4421       {

4422          tree max_index;

4423  

4424          /* If the bound of the array is known, take no more initializers

4425            than are allowed.  */

4426          max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE))

4427                      ? array_type_nelts (type) : NULL_TREE);

4428          if (!reshape_init_array (TREE_TYPE (type), max_index,

4429                              initp, new_init))

4430            return error_mark_node;

4431       }

4432       else

4433         abort ();

4434  

4435       /* The initializers were placed in reverse order in the

4436          CONSTRUCTOR.  */

4437       CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));

4438  

4439       if (TREE_CODE (old_init) == TREE_LIST)

4440         new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);

4441     }

4442  

4443     /* If there are more initializers than necessary, issue a

4444       diagnostic.  */ 

4445     if (*initp)

4446     {

4447       if (brace_enclosed_p)

4448         error ("too many initializers for `%T'", type);

4449       else if (warn_missing_braces && !string_init_p)

4450         warning ("missing braces around initializer");

4451     }

4452  

4453     return new_init;

4454   }

 

See for aggregate member, line 4333 verifies that type of the initializer can be converted to that of member. For array, below reshape_init_array iterates every element by reshape_init to verify and reshape the initializer. For non-aggregate member, the initializer is just returned.

 

4203   static bool

4204   reshape_init_array (tree elt_type, tree max_index,                                              in decl.c

4205                   tree *initp, tree new_init)

4206   {

4207     bool sized_array_p = (max_index != NULL_TREE);

4208     unsigned HOST_WIDE_INT max_index_cst = 0;

4209     unsigned HOST_WIDE_INT index;

4210  

4211     if (sized_array_p)

4212     {

4213       if (host_integerp (max_index, 1))

4214         max_index_cst = tree_low_cst (max_index, 1);

4215        /* sizetype is sign extended, not zero extended.  */

4216       else

4217         max_index_cst = tree_low_cst (convert (size_type_node, max_index), 1);

4218     }

4219  

4220     /* Loop until there are no more initializers.  */

4221     for (index = 0;

4222         *initp && (!sized_array_p || index <= max_index_cst);

4223         ++index)

4224     {

4225       tree element_init;

4226       tree designated_index;

4227  

4228       element_init = reshape_init (elt_type, initp);

4229       if (element_init == error_mark_node)

4230         return false;

4231       TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);

4232       CONSTRUCTOR_ELTS (new_init) = element_init;

4233       designated_index = TREE_PURPOSE (element_init);

4234       if (designated_index)

4235       {

4236          /* Handle array designated initializers (GNU extension).  */

4237         if (TREE_CODE (designated_index) == IDENTIFIER_NODE)

4238         {

4239           error ("name `%D' used in a GNU-style designated "

4240                "initializer for an array", designated_index);

4241           TREE_PURPOSE (element_init) = NULL_TREE;

4242         }

4243         else

4244           abort ();

4245       }

4246     }

4247  

4248     return true;

4259   }

 

Here TREE_PURPOSE of every initializer of our example is empty (TREE_PURPOSE is used for designated initializer, IBM’s XL C supports this feature, detail see here . See that the new CONSTRUCTOR generated has type assigned when compared with former one.

Then in check_initializer at line 4532, under x86 machine, vector_opaque_p hook in targetm always returns false. And below maybe_deduce_size_from_array_init sets the size field in the node of array, for example: int a[] = { 1, 2, 3}; the function should set the size of 3 into the node.

 

check_initializer (continue)

 

4539       /* If DECL has an array type without a specific bound, deduce the

4540          array size from the initializer.  */

4541       maybe_deduce_size_from_array_init (decl, init);

4542       type = TREE_TYPE (decl);

4543       if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))

4544         TREE_TYPE (init) = type;

4545  

4546       if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))

4547       {

            …

4579       }

4580       else

4581       {

4582   dont_use_constructor:

4583          if (TREE_CODE (init) != TREE_VEC)

4584          {

4585            init_code = store_init_value (decl, init);

4586            init = NULL;

4587          }

4588       }

4589     }

4590     else if (DECL_EXTERNAL (decl))

4591       ;

4592     else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))

4593       goto initialize_aggr;

4594     else if (IS_AGGR_TYPE (type))

4595     {

4596       tree core_type = strip_array_types (type);

4597  

4598       if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))

4599         error ("structure `%D' with uninitialized const members", decl);

4600       if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))

4601         error ("structure `%D' with uninitialized reference members",

4602               decl);

4603  

4604       check_for_uninitialized_const_var (decl);

4605     }

4606     else

4607       check_for_uninitialized_const_var (decl);

4608  

4609     if (init && init != error_mark_node)

4610       init_code = build (INIT_EXPR, type, decl, init);

4611  

4612     return init_code;

4613   }

 

Type of decl is vtbl_type_node which is ARRAY_TYPE of vtable_entry_type which in turn is a pointer of certain function type; of course no constructor is defined for this ARRAY_TYPE. So condition at line 4546 is false for type .

 

410    tree

411     store_init_value (tree decl, tree init)                                                           in typeck2.c

412    {

413      tree value, type;

414   

415      /* If variable's type was invalidly declared, just ignore it.  */

416   

417      type = TREE_TYPE (decl);

418      if (TREE_CODE (type) == ERROR_MARK)

419        return NULL_TREE;

420   

421      if (IS_AGGR_TYPE (type))

422      {

          …

432      }

433      else if (TREE_CODE (init) == TREE_LIST

434            && TREE_TYPE (init) != unknown_type_node)

435      {

          …

448      }

449   

450      /* Digest the specified initializer into an expression.  */

451      value = digest_init (type, init, (tree *) 0);

452      /* If the initializer is not a constant, fill in DECL_INITIAL with

453        the bits that are constant, and then return an expression that

454        will perform the dynamic initialization.  */

455      if (value != error_mark_node

456         && (! TREE_CONSTANT (value)

457              || ! initializer_constant_valid_p (value, TREE_TYPE (value))))

458        return split_nonconstant_init (decl, value);

459      /* If the value is a constant, just put it in DECL_INITIAL. If DECL

460        is an automatic variable, the middle end will turn this into a

461        dynamic initialization later.  */

462      DECL_INITIAL (decl) = value;

463      return NULL_TREE;

464    }

 

Here argument type is the type of the VAR_DECL. Initializers needsn’t be the same type as corresponding member as long as appropriate convertor is found. The purpose of digest_init is to find the applicable convertor and generate necessary code for this conversion, if type and init can’t match exactly.

 

476    tree

477    digest_init (tree type, tree init, tree* tail)                                                    in typeck2.c

478    {

479      enum tree_code code = TREE_CODE (type);

480      tree element = NULL_TREE;

481      tree old_tail_contents = NULL_TREE;

482      /* Nonzero if INIT is a braced grouping.  */

483      int raw_constructor;

484   

485      /* By default, assume we use one element from a list.

486        We correct this later in the sole case where it is not true.  */

487   

488      if (tail)

489      {

490        old_tail_contents = *tail;

491        *tail = TREE_CHAIN (*tail);

492      }

493   

494      if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST

495                               && TREE_VALUE (init) == error_mark_node))

496        return error_mark_node;

497   

498      if (TREE_CODE (init) == ERROR_MARK)

499        /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside

500          a template function. This gets substituted during instantiation.  */

501        return init;

502   

503      /* We must strip the outermost array type when completing the type,

504        because the its bounds might be incomplete at the moment.  */

505      if (!complete_type_or_else (TREE_CODE (type) == ARRAY_TYPE

506                             ? TREE_TYPE (type) : type, NULL_TREE))

507        return error_mark_node;

508     

509      /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */

510      if (TREE_CODE (init) == NON_LVALUE_EXPR)

511         init = TREE_OPERAND (init, 0);

512   

513      raw_constructor = (TREE_CODE (init) == CONSTRUCTOR

514                        && TREE_HAS_CONSTRUCTOR (init));

515   

516      if (raw_constructor

517          && CONSTRUCTOR_ELTS (init) != 0

518          && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)

519      {

520        element = TREE_VALUE (CONSTRUCTOR_ELTS (init));

521         /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */

522        if (element && TREE_CODE (element) == NON_LVALUE_EXPR)

523          element = TREE_OPERAND (element, 0);

524        if (element == error_mark_node)

525          return element;

526      }

527   

528      /* Initialization of an array of chars from a string constant

529        optionally enclosed in braces.  */

530   

531      if (code == ARRAY_TYPE)

532      {

533        tree typ1;

534   

535        if (TREE_CODE (init) == TREE_LIST)

536        {

537          error ("initializing array with parameter list");

538          return error_mark_node;

539        }

540   

541        typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));

542        if (char_type_p (typ1)

543           && ((init && TREE_CODE (init) == STRING_CST)

544                || (element && TREE_CODE (element) == STRING_CST)))

545        {

            …

577        }

578      }

579   

580      /* Handle scalar types, including conversions,

581        and signature pointers and references.  */

582   

583      if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE

584           || code == ENUMERAL_TYPE || code == REFERENCE_TYPE

585          || code == BOOLEAN_TYPE || code == COMPLEX_TYPE

586          || TYPE_PTR_TO_MEMBER_P (type))

587      {

588        if (raw_constructor)

589        {

590          if (element == 0)

591          {

592            error ("initializer for scalar variable requires one element");

593            return error_mark_node;

594          }

595          init = element;

596        }

597        while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))

598        {

599          pedwarn ("braces around scalar initializer for `%T'", type);

600          init = CONSTRUCTOR_ELTS (init);

601          if (TREE_CHAIN (init))

602            pedwarn ("ignoring extra initializers for `%T'", type);

603          init = TREE_VALUE (init);

604        }

605   

606        return convert_for_initialization (0, type, init, LOOKUP_NORMAL,

607                                   "initialization", NULL_TREE, 0);

608      }

609   

610      /* Come here only for records and arrays (and unions with constructors).  */

611    

612      if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))

613      {

614        error ("variable-sized object of type `%T' may not be initialized",

615              type);

616        return error_mark_node;

617      }

618   

619      if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code))

620      {

621        if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)

622           && TREE_HAS_CONSTRUCTOR (init))

623        {

624          error ("subobject of type `%T' must be initialized by constructor, not by `%E'",

625                type, init);

626          return error_mark_node;

627        }

628        else if (raw_constructor)

629          return process_init_constructor (type, init, (tree *)0);

          …

649      }

650   

651      error ("invalid initializer");

652      return error_mark_node;

653    }

 

For the initializers of our example, at line 513, raw_constructor is nonzero; and code is ARRAY_TYPE. Then argument init is passed to process_init_constructor for handling.

 

670    static tree

671    process_init_constructor (tree type, tree init, tree* elts)                               in typeck2.c

672    {

673      tree tail;

674      /* List of the elements of the result constructor,

675        i n reverse order.  */

676      tree members = NULL;

677      tree next1;

678      tree result;

679      int allconstant = 1;

680      int allsimple = 1;

681      int erroneous = 0;

682   

683      /* Make TAIL be the list of elements to use for the initialization,

684        no matter how the data was given to us.  */

685   

686      if (elts)

687      {

688        if (warn_missing_braces )

689           warning ("aggregate has a partly bracketed initializer");

690        tail = *elts;

691      }

692      else

693        tail = CONSTRUCTOR_ELTS (init);

694   

695      /* Gobble as many elements as needed, and make a constructor or initial value

696        for each element of this aggregate. Chain them together in result.

697        If there are too few, use 0 for each scalar ultimate component.  */

698   

699      if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)

700      {

701        long len;

702        int i;

703   

704        if (TREE_CODE (type) == ARRAY_TYPE)

705        {

706          tree domain = TYPE_DOMAIN (type);

707          if (domain)

708            len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))

709                  - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))

710                   + 1);

711           else

712            len = -1;  /* Take as many as there are.  */

713        }

714        else

715        {

716          /* Vectors are like simple fixed-size arrays.  */

717          len = TYPE_VECTOR_SUBPARTS (type);

718        }

719   

720        for (i = 0; len < 0 || i < len; i++)

721        {

722          if (tail)

723          {

724            if (TREE_PURPOSE (tail)

725              && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST

726                   || compare_tree_int (TREE_PURPOSE (tail), i) != 0))

727              sorry ("non-trivial labeled initializers");

728   

729            if (TREE_VALUE (tail) != 0)

730            {

731              tree tail1 = tail;

732              next1 = digest_init (TREE_TYPE (type),

733                              TREE_VALUE (tail), &tail1);

734              if (next1 == error_mark_node)

735                return next1;

736              my_friendly_assert

737                   (same_type_ignoring_top_level_qualifiers_p

738                         (TREE_TYPE (type), TREE_TYPE (next1)),

739                         981123);

740              my_friendly_assert (tail1 == 0

741                               || TREE_CODE (tail1) == TREE_LIST, 319);

742              if (tail == tail1 && len < 0)

743              {

744                error ("non-empty initializer for array of empty elements");

745                /* Just ignore what we were supposed to use.  */

746                tail1 = NULL_TREE;

747              }

748              tail = tail1;

749            }

750            else

751            {

752              next1 = error_mark_node;

753              tail = TREE_CHAIN (tail);

754            }

755          }

756          else if (len < 0)

757            /* We're done.  */

758            break ;

759          else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))

760          {

              …

771          }

772           else if (! zero_init_p (TREE_TYPE (type)))

773            next1 = build_zero_init (TREE_TYPE (type),

774                                /*nelts=*/ NULL_TREE,

775                                /*static_storage_p=*/ false);

776          else

777            /* The default zero-initialization is fine for us; don't

778              add anything to the CONSTRUCTOR.  */

779            break ;

780   

781          if (next1 == error_mark_node)

782            erroneous = 1;

783          else if (!TREE_CONSTANT (next1))

784            allconstant = 0;

785          else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))

786            allsimple = 0;

787          members = tree_cons (size_int (i), next1, members);

788        }

789      }

790      else if (TREE_CODE (type) == RECORD_TYPE)

791      {

          …

908      }

909      else if (TREE_CODE (type) == UNION_TYPE

910            /* If the initializer was empty, use default zero initialization.  */

911             && tail)

912      {

          …

977      }

978   

979      /* If arguments were specified as a list, just remove the ones we used.   */

980      if (elts)

981        *elts = tail;

982      /* If arguments were specified as a constructor,

983        complain unless we used all the elements of the constructor.  */

984      else if (tail)

985        pedwarn ("excess elements in aggregate initializer");

986   

987      if (erroneous)

988        return error_mark_node;

989   

990      result = build_constructor (type, nreverse (members));

991      if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE)

992        complete_array_type (type, result, /*do_default=*/ 0);

993      if (init)

994        TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);

995      if (allconstant) TREE_CONSTANT (result) = 1;

996      if (allconstant && allsimple) TREE_STATIC (result) = 1;

997      return result;

998    }

 

Not surprising, for each element of ARRAY_TYPE, digest_init is recursed. Note that in this invocation, argument tail is the initializers. If digest_init can process part of initializers successfully. This part will be removed from the list of initializers. At line 606, convert_for_initialization is invoked to do the possible conversion. Here in our example, no conversion is expected as we prepare init of type vtable_entry_type before hand. As a result, the function returns init as returned value.

Exitting convert_for_initialization gets out of digest_init immediately, which means this (part) initializer is verified. At line 787, this returned value is chained into members . Next at line 990, new version CONSTRUCTOR is created. See that all elements of vtable should be constant. And this CONSTRUCTOR allocates static storage (i.e, initializes static member). Then at line 4902 in cp_finish_decl , store_init_value returns NULL

 

cp_finish_decl (continue)

 

4953     /* Add this declaration to the statement-tree. This needs to happen

4954       after the call to check_initializer so that the DECL_STMT for a

4955       reference temp is added before the DECL_STMT for the reference itself.  */

4956     if (at_function_scope_p ())

4957       add_decl_stmt (decl);

4958  

4959     if (TREE_CODE (decl) == VAR_DECL)

4960       layout_var_decl (decl);

4961  

4962     /* Output the assembler code and/or RTL code for variables and functions,

4963       unless the type is an undefined structure or union.

4964       If not, it will get done when the type is completed.  */

4965     if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)

4966     {

4967       if (TREE_CODE (decl) == VAR_DECL)

4968         maybe_commonize_var (decl);

4969  

4970       make_rtl_for_nonlocal_decl (decl, init, asmspec);

4971  

4972       if (TREE_CODE (type) == FUNCTION_TYPE

4973           || TREE_CODE (type) == METHOD_TYPE)

4974         abstract_virtuals_error (decl,

4975                              strip_array_types (TREE_TYPE (type)));

4976       else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)

4977       {

4978         /* If it's either a pointer or an array type, strip through all

4979            of them but the last one. If the last is an array type, issue

4980            an error if the element type is abstract.  */

4981         while (POINTER_TYPE_P (TREE_TYPE (type))

4982                || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)

4983            type = TREE_TYPE (type);

4984         if (TREE_CODE (type) == ARRAY_TYPE)

4985            abstract_virtuals_error (decl, TREE_TYPE (type));

4986       }

4987       else

4988         abstract_virtuals_error (decl, type);

4989  

4990       if (TREE_CODE (decl) == FUNCTION_DECL

4991           || TREE_TYPE (decl) == error_mark_node)

4992         /* No initialization required.  */

4993         ;

4994       else if (DECL_EXTERNAL (decl)

4995              && ! (DECL_LANG_SPECIFIC (decl)

4996                    && DECL_NOT_REALLY_EXTERN (decl)))

4997       {

4998          if (init)

4999            DECL_INITIAL (decl) = init;

5000       }

5001       else

5002       {

5003          /* A variable definition.  */

5004          if (DECL_FUNCTION_SCOPE_P (decl))

5005          {

5006            /* This is a local declaration.  */

5007              maybe_inject_for_scope_var (decl);

5008            /* Initialize the local variable.  */

5009            if (processing_template_decl )

5010           {

5011              if (init || DECL_INITIAL (decl) == error_mark_node)

5012                DECL_INITIAL (decl) = init;

5013           }

5014            else if (!TREE_STATIC (decl))

5015             initialize_local_var (decl, init);

5016          }

5017  

5018          /* If a variable is defined, and then a subsequent

5019             definintion with external linkage is encountered, we will

5020             get here twice for the same variable. We want to avoid

5021             calling expand_static_init more than once. For variables

5022             that are not static data members, we can call

5023             expand_static_init only when we actually process the

5024             initializer. It is not legal to redeclare a static data

5025             member, so this issue does not arise in that case.  */

5026          if (var_definition_p && TREE_STATIC (decl))

5027            expand_static_init (decl, init);

5028       }

5029   finish_end0:

5030  

5031        /* Undo call to `pushclass' that was done in `start_decl'

5032          due to initialization of qualified member variable.

5033         I.e., Foo::x = 10;  */

5034       {

5035         tree context = CP_DECL_CONTEXT (decl);

5036         if (context

5037             && TYPE_P (context)

5038             && (TREE_CODE (decl) == VAR_DECL

5039                /* We also have a pushclass done that we need to undo here

5040                   if we're at top level and declare a method.  */

5041                || TREE_CODE (decl) == FUNCTION_DECL)

5042             /* If size hasn't been set, we're still defining it,

5043               and therefore inside the class body; don't pop

5044                  the binding level..  */

5045               && COMPLETE_TYPE_P (context)

5046               && context == current_class_type )

5047             pop_nested_class ();

5048       }

5049     }

5050  

5051     /* If a CLEANUP_STMT was created to destroy a temporary bound to a

5052       reference, insert it in the statement-tree now.  */

5053     if (cleanup)

5054       add_stmt (cleanup);

5055  

5056   finish_end:

5057  

5058     if (was_readonly)

5059       TREE_READONLY (decl) = 1;

5060  

5061     /* If this was marked 'used', be sure it will be output.  */

5062     if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))

5063       mark_referenced (DECL_ASSEMBLER_NAME (decl));

5064   }

 

As in initialize_array at line 6809, context of decl is temperarily cleaned, at_function_scope_p at line 4956 returns false. Then maybe_commonize_var at line 4968 handles the situation in which a local static variable is declared in an inline function, or we have a weak definition, for which the compile must endeavor to create only one instance of the variable at link-time.

Then back cp_finish_decl , at line 4970, within make_rtl_for_nonlocal_decl , the local variable defer_p is set as true at line 4658 as this VAR_DECL has flag DECL_VIRTUAL_P set; further at invocation, asmspec is NULL. So nothing non-trivial is done in this function.

Next, as var_definition_p is true at line 5026, expand_static_init is invoked, however, as the ARRAY_TYPE of the vtable hasn’t flag TYPE_NEEDS_CONSTRUCTING set, the function exits immediately.

At last, cleanup at line 5053 may be not NULL if we are handling referecne (here it is NULL). Exitting from cp_finish_decl , we go back finish_struct_1 in below.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值