GCC-3.4.6源代码学习笔记(141-续2)

然后 调用 check_initializer 来验证初始值。在这里 参数 flags 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       }

 

C++ 标准的某一条款( [dcl.init.aggr] )澄清到:

当使用一个初始化值列表中的初始值初始化聚合成员(注:聚合指关键字 class struct union 声明的类型,以及数组)时,考虑所有隐式类型转换( implicit type conversions )(条文 4 )。如果该初始值能初始化一个成员,该成员就是初始化了的。否则,如果该成员本身是一个非空的子聚合,假定省略括号,该初始值用作该子聚合的第一个成员的初始化。例如:

struct A {

int i;

operator int();

};

struct B {

A a1, a2;

int z;

};

A a;

B b = { 4, a, a };

用于 b.a1.i 初始值两边的大括号被省略。 b.a1.i 4 初始化, b.a2 a 初始化, b.z 被操作符 a.operator int() 的返回值初始化。

函数 reshape_init 被调用来把初始值列表从形式 {4, a, a } ,变换为 { {4, a}, a} ,后面的形式才是前端需要的。

这里对于我们的例子,该 VAR_DECL 是一个 vtable_entry_type 类型的数组,而 initp 指向用于初始值的 CONSTRUCTOR 节点,它是深思熟虑地被创建为空类型的。因此在 4289 行的代码块被执行。 CONSTRUCTOR_ELTS 返回上面构建的 inits 。这些初始值按被大括号所包围那样处理。

 

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   }

 

看到对于聚合类型的成员, 4333 行确认初始值的类型能被转换到成员的类型。对于数组,下面的 reshape_init_array 遍历成员,使用 reshape_init 为每个成员验证及重塑初始值。而对于非聚合类型成员,初始值立即被返回。

 

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   }

 

这里我们例子中每个初始值的 TREE_PURPOSE 都是空的( TREE_PURPOSE 用于所谓的指定初始化, IBM XL C 支持这一特性,详情参见 这里 )。看到新产生的 CONSTRUCTOR ,与之前的相比,赋上了类型。

那么在 check_initializer 4532 行,在 x86 机器上, targetm 中的 vector_opaque_p 钩子总是返回 false 。而下面的 maybe_deduce_size_from_array_init 设置了数组节点的 size 域,例如:“ int a[] = { 1, 2, 3}; ”该函数应该在节点中设置大小 3

 

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   }

 

decl 的类型是 vtbl_type_node ——元素类型为 vtable_entry_type ARRAY_TYPE vtable_entry_type 本身则是某个函数类型的指针;显然没有构造函数是为这个 ARRAY_TYPE 定义的。那么对于 type 4546 行条件是 false

 

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    }

 

这里的参数 type VAR_DECL 的类型。初始值的类型不需要与对应的成员一致,只要能找到合适的转换函数。 digest_init 的目的就是,如果 type init 不能完全匹配,找出合用的转换函数,并为这个转换操作产生必要的代码。

 

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    }

 

对于我们例子的初始值,在 513 行, raw_constructor 为非 0 值;而 code ARRAY_TYPE 。那么参数 init 被传递入 process_init_constructor 进行处理。

 

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    }

 

毫不奇怪,对于 ARRAY_TYPE 的每个元素,递归调用了 digest_init 。注意在对 digest_init 的递归调用中,参数 tail 不为空,它就是初始值。在 digest_init 中如果能成功处理初始值的一部分,该部分初始值即从列表中移除。在 606 行, convert_for_initialization 被调用来做可能需要的转换。这里在我们的例子中,不需要转换因为我们事先把 init 的类型设为 vtable_entry_type 。结果,该函数直接把 init 返回。

convert_for_initialization 返回同时直接退出 digest_init ,这意味着该(部分)初始值匹配已经成功。看到在 787 行,这个返回值被链入 members 。接着在 990 行,构建了一个新的 CONSTRUCTOR 。显然 vtable 的所有成员都是常量。而且这个 CONSTRUCTOR 将分配静态存储空间(即初始化静态成员)。接着这个在 cp_finish_decl 4902 行, store_init_value 返回了 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   }

 

因为在 initialize_array 6809 行, decl 的上下文( context )被暂时清空,因此在 4956 行的 at_function_scope_p 返回 false 。而 4968 行的 maybe_commonize_var 处理这么一个情况:声明在一个内联函数中的局部静态变量;或我们有一个弱定义( weak definition ),对此,编译器必需努力在链接时刻仅为该变量构建一个实例。

那么回到 cp_finish_decl ,在 4970 行,在 make_rtl_for_nonlocal_decl 里,局部变量 defer_p 4658 行被设置为 true ,因为这个 VAR_DECL 设置了标记 DECL_VIRTUAL_P ;另外在调用时, asmspec NULL 。因此在这个函数中没有做实质性的处理。

接着,因为 5026 行的 var_definition_p true ,调用 expand_static_init ,不过因为 vtable ARRAY_TYPE 没有设置标记 YPE_NEEDS_CONSTRUCTING ,该函数立即返回。

最后, 5052 行的 cleanup 可能不是 NULL ,如果我们在处理引用(这里它是 NULL )。从 cp_finish_decl 退出,我们回到下面的 finish_struct_1 中。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值