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

    技术2022-06-27  66

    然后 调用 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)