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

来源:互联网 发布:云栈菜鸟淘宝打印组件 编辑:程序博客网 时间:2024/06/07 02:59

然后调用check_initializer 来验证初始值。在这里参数flags0

 

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 aninitializer is present, DECL_INITIAL has been

4474       error_mark_node, to indicatethat 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 goingto 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 havealready 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' maynot 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' haveincomplete type", decl);

4496       init = NULL_TREE;

4497     }

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

4499     {

4500       error ("`%D' has incompletetype", 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 declarationof the form

4522           T x = { a };

4523           is equivalent to

4524           T x = a;

4525       

4526           reshape_init will complain about the extrabraces,

4527           and doesn't do anything useful in the casewhere 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 cannotbe initialized");

4535           init = error_mark_node;

4536         }

4537       }

 

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

当使用一个初始化值列表中的初始值初始化聚合成员(注:聚合指关键字classstructunion声明的类型,以及数组)时,考虑所有隐式类型转换(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.i4初始化,b.a2a初始化,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)                                                                    indecl.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 theinitializer is brace-enclosed, pull initializers from the

4284       enclosed elements. Advancepast 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-aggregatetype 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 invalidto initialize a non-aggregate type with a

4309         brace-enclosedinitializer.  */

4310       if (brace_enclosed_p)

4311       {

4312         error ("brace-enclosed initializerused 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       returnold_init;

4321     }

4322  

4323     /* [dcl.init.aggr]

4324  

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

4326       initializing the aggregatemember with an initializer from an

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

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

4329       non-empty subaggregate, braceelision is assumed and the

4330       initializer is considered forthe initialization of the first

4331       member of thesubaggregate.  */

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       returnold_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 aCONSTRUCTOR 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 moreinitializers

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       /* Theinitializers 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 aremore 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 aroundinitializer");

4451     }

4452  

4453     returnnew_init;

4454   }

 

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

 

4203   static bool

4204   reshape_init_array (tree elt_type, treemax_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 zeroextended.  */

4216       else

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

4218     }

4219  

4220     /* Loop until thereare 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         returnfalse;

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 (GNUextension).  */

4237         if (TREE_CODE (designated_index) ==IDENTIFIER_NODE)

4238         {

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

4240                "initializer for anarray", 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用于所谓的指定初始化,IBMXL C支持这一特性,详情参见这里)。看到新产生的CONSTRUCTOR,与之前的相比,赋上了类型。

那么在check_initializer4532行,在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 anarray type without a specific bound, deduce the

4540         arraysize 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       gotoinitialize_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' withuninitialized const members", decl);

4600       if (CLASSTYPE_REF_FIELDS_NEED_INIT(core_type))

4601         error ("structure `%D' withuninitialized 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     returninit_code;

4613   }

 

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

 

410    tree

411     store_init_value (tree decl, tree init)                                                           intypeck2.c

412    {

413      tree value, type;

414   

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

416   

417      type = TREE_TYPE (decl);

418      if (TREE_CODE (type) == ERROR_MARK)

419        returnNULL_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 thespecified initializer into an expression. */

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

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

453        the bits that areconstant, and then return an expression that

454        will perform thedynamic initialization.  */

455      if (value != error_mark_node

456         && (! TREE_CONSTANT (value)

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

458        returnsplit_nonconstant_init (decl, value);

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

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

461        dynamicinitialization later.  */

462      DECL_INITIAL (decl) = value;

463      returnNULL_TREE;

464    }

 

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

 

476    tree

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

478    {

479      enumtree_code code = TREE_CODE (type);

480      tree element = NULL_TREE;

481      tree old_tail_contents = NULL_TREE;

482     /* Nonzero if INITis a braced grouping.  */

483      int raw_constructor;

484   

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

486        We correct thislater 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        returnerror_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 substitutedduring instantiation.  */

501        returninit;

502   

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

504        because the itsbounds 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        returnerror_mark_node;

508     

509      /* StripNON_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'tusing 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          returnelement;

526      }

527   

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

529        optionallyenclosed 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 withparameter list");

538          returnerror_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 scalartypes, including conversions,

581        and signaturepointers 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 scalarvariable requires one element");

593            returnerror_mark_node;

594          }

595          init = element;

596        }

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

598        {

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

600          init = CONSTRUCTOR_ELTS (init);

601          if (TREE_CHAIN (init))

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

603          init = TREE_VALUE (init);

604        }

605   

606        returnconvert_for_initialization (0, type, init, LOOKUP_NORMAL,

607                                  "initialization", NULL_TREE, 0);

608      }

609   

610      /* Come here onlyfor 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        returnerror_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' mustbe initialized by constructor, not by `%E'",

625                type, init);

626          returnerror_mark_node;

627        }

628        else if (raw_constructor)

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

         

649      }

650   

651      error ("invalid initializer");

652      returnerror_mark_node;

653    }

 

对于我们例子的初始值,在513行,raw_constructor为非0值;而codeARRAY_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 theelements of the result constructor,

675        in 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 thelist of elements to use for the initialization,

684        no matter how thedata was given to us.  */

685   

686      if (elts)

687      {

688        if (warn_missing_braces)

689          warning ("aggregate has a partlybracketed initializer");

690        tail = *elts;

691      }

692      else

693        tail = CONSTRUCTOR_ELTS (init);

694   

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

696        for each elementof this aggregate. Chain them together in result.

697        If there are toofew, 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 asthere are.  */

713        }

714        else

715        {

716          /* Vectors arelike 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 labeledinitializers");

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                returnnext1;

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 initializerfor array of empty elements");

745                /* Justignore 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'redone.  */

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            /* Thedefault zero-initialization is fine for us; don't

778              addanything 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 zeroinitialization.  */

911            && tail)

912      {

         

977      }

978   

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

980      if (elts)

981        *elts = tail;

982      /* If argumentswere specified as a constructor,

983        complain unlesswe used all the elements of the constructor. */

984      else if (tail)

985        pedwarn ("excess elements in aggregateinitializer");

986   

987      if (erroneous)

988        returnerror_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      returnresult;

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_decl4902行,store_init_value返回了NULL

 

cp_finish_decl (continue)

 

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

4954       after the call tocheck_initializer so that the DECL_STMT for a

4955       reference temp is added beforethe 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 theassembler code and/or RTL code for variables and functions,

4963       unless the type is anundefined structure or union.

4964       If not, it will get done whenthe 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 eithera pointer or an array type, strip through all

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

4980           an error if the element type isabstract.  */

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         /* Noinitialization 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 withexternal linkage is encountered, we will

5020           get here twicefor the same variable. We want to avoid

5021           callingexpand_static_init more than once. For variables

5022           that are notstatic data members, we can call

5023           expand_static_init only when we actuallyprocess the

5024           initializer. Itis not legal to redeclare a static data

5025           member, so thisissue 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 membervariable.

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                /* Wealso have a pushclass done that we need to undo here

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

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_STMTwas created to destroy a temporary bound to a

5052       reference, insert it in thestatement-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 wasmarked 'used', be sure it will be output. */

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

5063       mark_referenced (DECL_ASSEMBLER_NAME(decl));

5064   }

 

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

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

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

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

 

原创粉丝点击