Studying note of GCC-3.4.6 source (153)

5.13.1.2.2.3.  Invoking the initializing method

Below, flag_elide_constructor by default is 1 which means attempt to elide constructors when possible. Whether the constructor (includes operator= (const X&) if defined) can be elided, depends on if it is trivial or not. Predicate TYPE_HAS_COMPLEX_INIT_REF holds if the class has non-trivial copy ctor; and TYPE_HAS_COMPLEX_ASSIGN_REF holds if the class has non-trivial “operator = (const X&)”.

 

build_over_call (continue)

 

4534    if (warn_format )

4535      check_function_format (NULL, TYPE_ATTRIBUTES (TREE_TYPE (fn)),

4536                          converted_args);

4537

4538    /* Avoid actually calling copy constructors and copy assignment operators,

4539      if possible.  */

4540

4541    if (! flag_elide_constructors )

4542      /* Do things the hard way.  */ ;

4543    else if (TREE_VEC_LENGTH (convs) == 1

4544          && DECL_COPY_CONSTRUCTOR_P (fn))

4545    {

4546      tree targ;

4547      arg = skip_artificial_parms_for (fn, converted_args);

4548      arg = TREE_VALUE (arg);

4549

4550       /* Pull out the real argument, disregarding const-correctness.  */

4551      targ = arg;

4552      while (TREE_CODE (targ) == NOP_EXPR

4553             || TREE_CODE (targ) == NON_LVALUE_EXPR

4554              || TREE_CODE (targ) == CONVERT_EXPR)

4555        targ = TREE_OPERAND (targ, 0);

4556      if (TREE_CODE (targ) == ADDR_EXPR)

4557      {

4558        targ = TREE_OPERAND (targ, 0);

4559        if (!same_type_ignoring_top_level_qualifiers_p

4560              (TREE_TYPE (TREE_TYPE (arg)), TREE_TYPE (targ)))

4561          targ = NULL_TREE;

4562      }

4563      else

4564        targ = NULL_TREE;

4565

4566      if (targ)

4567        arg = targ;

4568      else

4569        arg = build_indirect_ref (arg, 0);

4570

4571      /* [class.copy]: the copy constructor is implicitly defined even if

4572        the implementation elided its use.  */

4573      if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))

4574        mark_used (fn);

4575

4576      /* If we're creating a temp and we already have one, don't create a

4577        new one. If we're not creating a temp but we get one, use

4578        INIT_EXPR to collapse the temp into our target. Otherwise, if the

4579        ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a

4580        temp or an INIT_EXPR otherwise.  */

4581      if (integer_zerop (TREE_VALUE (args)))

4582      {

4583        if (TREE_CODE (arg) == TARGET_EXPR)

4584          return arg;

4585        else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))

4586          return build_target_expr_with_type (arg, DECL_CONTEXT (fn));

4587      }

4588      else if (TREE_CODE (arg) == TARGET_EXPR

4589            || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))

4590      {

4591        tree to = stabilize_reference

4592                   (build_indirect_ref (TREE_VALUE (args), 0));

4593

4594        val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);

4595        return val;

4596      }

4597    }

 

According to [3], clause 12.8 “Copying class objects”, terms 2:

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6)). [Example: X::X(const X&) and X::X(X&, int=1) are copy constructors.

class X {

public :

X(int);

X(const X&, int = 1);

};

X a(1); // calls X(int);

X b(a, 0); // calls X(const X&, int);

X c = b; // calls X(const X&, int);

end example ]

See in above, at line 4543, the value of “TREE_VEC_LENGTH (convs)” reflects the number of argumentsof the invocation (includes returned value); as constructor hasn’t returned value, here 1 means the argument number in calling this copy constructor is 1.

Before coming here, arguments undergo conversions described in previous sections, generally, can build a INDIRECT_REF node to represent this reference directly, unless it is already a reference. WHILE loop at line 4552 and IF statement at line 4556 discriminate references, consider below example:

void f (char& t) {}

void g (int& b) { f (*(char*)b); }

int main () {

int b = 5;

g (b);

}

Type gotten by “TREE_TYPE (TREE_TYPE (arg))” at line 4560 is “char”, while type gotten by “TREE_TYPE (targ)” is “int”, the reference type “int& b” can’t be used directly, it expects type “char&”.

Then if TYPE_HAS_COMPLEX_INIT_REF at line 4573 holds, it means the class defines copy constructor, has virtual base, or virtual method (obvious, such copy constructor is non-trival), mark_used is invoked to mark the copy ctor as used and synthesize its definition, if it is not declared by user but generated artifically by compiler.

At line 4581, args are the arguments of invocation. It is a tree_list with TREE_VALUE of every node holds the corresponding argument. In above example, TREE_VALUE (args) in “X b(a, 0)” is the implicit this pointer which is 0 (satisfies condition at line 4581); while in “X c = b”, it is “&c”. For the former case, it needs create the object (confined by C++ syntax, it can only be a temporary within a function), and for the rear one we can use ‘c’ as the subject of initialization. So in case TYPE_HAS_TRIVIAL_INIT_REF holds, we can ingore invoking copy constructor. And if the copy constructor can’t be avoided, we then go to below line 4637 to handle it.

Below at line 4599, copy_fn_p returns nonzero, if fn is a constructor or overloaded `operator='; and DECL_OVERLOADED_OPERATOR_P at line 4598 holds, if fn is an overloaded ‘operator=’; so to enter block at line 4601, it should be: fn is an overloaded ‘operator=’, but the assignment of this class type can use a bitwise copy (satisfies condition at line 4600).

 

build_over_call (continue)

 

4598    else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR

4599          && copy_fn_p (fn)

4600          && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))

4601    {

4602      tree to = stabilize_reference

4603                (build_indirect_ref (TREE_VALUE (converted_args), 0));

4604      tree type = TREE_TYPE (to);

4605      tree as_base = CLASSTYPE_AS_BASE (type);

4606

4607      arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);

4608      if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))

4609        val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);

4610      else

4611      {

4612        /* We must only copy the non-tail padding parts. Use

4613          CLASSTYPE_AS_BASE for the bitwise copy.  */

4614        tree to_ptr, arg_ptr, to_as_base, arg_as_base, base_ptr_type;

4615        tree save_to;

4616

4617        to_ptr = save_expr (build_unary_op (ADDR_EXPR, to, 0));

4618        arg_ptr = build_unary_op (ADDR_EXPR, arg, 0);

4619

4620        base_ptr_type = build_pointer_type (as_base);

4621        to_as_base = build_nop (base_ptr_type, to_ptr);

4622        to_as_base = build_indirect_ref (to_as_base, 0);

4623        arg_as_base = build_nop (base_ptr_type, arg_ptr);

4624        arg_as_base = build_indirect_ref (arg_as_base, 0);

4625

4626        save_to = build_indirect_ref (to_ptr, 0);

4627

4628        val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base);

4629        val = convert_to_void (val, NULL);

4630        val = build (COMPOUND_EXPR, type, val, save_to);

4631        TREE_NO_UNUSED_WARNING (val) = 1;

4632      }

4633       

4634      return val;

4635    }

 

Line 4602 fetches the class type from the implicit this pointer. CLASSTYPE_AS_BASE at line 4605 returns the part of the class without virutal bases; however as the copy assignment is trivial, that means the class should not contain any virtual base. The class base returned should have the same size of the class; except if the class has padding bytes at tail (see in layout_class_type , the size of class base excludes tail padding bytes). The tail padding bytes should not be copied bitwise.

If the copy ctor or the overloaded ‘operator=’ is non-trivial, it needs below treatment to generate the code to invoking corresponding function.

 

build_over_call (continue)

 

4637    mark_used (fn);

4638

4639    if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)

4640    {

4641      tree t, *p = &TREE_VALUE (converted_args);

4642      tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),

4643                            DECL_CONTEXT (fn),

4644                            ba_any, NULL);

4645      my_friendly_assert (binfo && binfo != error_mark_node, 20010730);

4646       

4647      *p = build_base_path (PLUS_EXPR, *p, binfo, 1);

4648      if (TREE_SIDE_EFFECTS (*p))

4649        *p = save_expr (*p);

4650      t = build_pointer_type (TREE_TYPE (fn));

4651      if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))

4652        fn = build_java_interface_fn_ref (fn, *p);

4653       else

4654        fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));

4655      TREE_TYPE (fn) = t;

4656    }

4657    else if (DECL_INLINE (fn))

4658      fn = inline_conversion (fn);

4659    else

4660      fn = build_addr_func (fn);

4661

4662    return build_cxx_call (fn, args, converted_args);

4663 }

 

If the function invoked is not virtual, just takes its address and emits code to call it. For inline function, note that inline function unless explicitly referred by reference or pointer, should not have TREE_ADDRESSABLE set (build_addr_func sets the bit) as it is always expanded at the point of invocation.

 

1464 tree

1465 inline_conversion (tree exp)                                                                       in typeck.c

1466 {

1467    if (TREE_CODE (exp) == FUNCTION_DECL)

1468      exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);

1469

1470    return exp;

1471 }

 

While if the function is virtual function, first it needs to see whether the base defining function is accessible from the class specified by p . Then it adjusts the “this” argument to the base. Next we should get the address of virtual function from vtable. Note that instance below is node of INDIRECT_REF.

 

470    tree

471    build_vfn_ref (tree instance, tree idx)                                                        in class.c

472    {

473      tree aref = build_vtbl_ref_1 (instance, idx);

474   

475      /* When using function descriptors, the address of the

476        vtable entry is treated as a function pointer.  */

477      if (TARGET_VTABLE_USES_DESCRIPTORS)

478        aref = build1 (NOP_EXPR, TREE_TYPE (aref),

479                    build_unary_op (ADDR_EXPR, aref, /*noconvert=*/ 1));

480   

481      return aref;

482    }

 

Recall that “BINFO_VTABLE (binfo)” below at line 446 returns the vtable of the base binfo . As binfo belongs to binfo of the most derived class, in prevoius we have seenn that such vtable is part of that of the most derived class. And at line 437, fixed_type_or_null will return NULL, because instance is a pointer addition, fixed_type_or_null doesn’t know its dynamic type. Next build_vfield_ref will build COMPONENT_REF to represent this vtable accesses

 

427    ic tree

428    build_vtbl_ref_1 (tree instance, tree idx)                                                    in class.c

429    {

430      tree aref;

431      tree vtbl = NULL_TREE;

432   

433      /* Try to figure out what a reference refers to, and

434        access its virtual function table directly.   */

435   

436      int cdtorp = 0;

437      tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);

438   

439      tree basetype = non_reference (TREE_TYPE (instance));

440   

441      if (fixed_type && !cdtorp)

442      {

443        tree binfo = lookup_base (fixed_type, basetype,

444                              ba_ignore|ba_quiet, NULL);

445        if (binfo)

446          vtbl = BINFO_VTABLE (binfo);

447      }

448   

449      if (!vtbl)

450        vtbl = build_vfield_ref (instance, basetype);

451     

452      assemble_external (vtbl);

453   

454      aref = build_array_ref (vtbl, idx);

455   

456      return aref;

457    }

 

At last, accessing the vtable at specified index, it can get the expected virtual function address, and code to invoking the virtual is generated by build_cxx_call at line 4662 above.

5.13.1.2.3.        Case of standard conversion

CHECK_COPY_CONSTRUCTOR_P is true in an IDENTITY_CONV or BASE_CONV if the copy constructor must be accessible, even though it is not being used. Remember the last conversion in the sequence is always IDENTITY_CONV.

And if we see an ambiguous conversion, coming here, it must through implicit conversion (implicit_conversion ). In this function, at calling build_user_type_conversion_1 , the argument flags is LOOKUP_ONLYCONVERTING which suppresses error message, so here invokes the function again with LOOKUP_NORMAL to give out the error message (here is the point the conversion is done, which is preferred by issuing error message).

 

convert_like_real (continue)

 

4017      case IDENTITY_CONV:

4018        if (type_unknown_p (expr))

4019          expr = instantiate_type (totype, expr, tf_error | tf_warning);

4020         /* Convert a non-array constant variable to its underlying

4021          value, unless we are about to bind it to a reference, in

4022          which case we need to leave it as an lvalue.  */

4023        if (inner >= 0

4024           && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)

4025           expr = decl_constant_value (expr);

4026        if (CHECK_COPY_CONSTRUCTOR_P (convs))

4027          check_constructor_callable (totype, expr);

4028       

4029        return expr;

4030      case AMBIG_CONV:

4031        /* Call build_user_type_conversion again for the error.  */

4032        return build_user_type_conversion

4033                   (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);

4034

4035      default :

4036        break ;

4037    };

 

Note that above, USER_CONV, IDENTITY_CONV or AMBIG_CONV returns at the end of their CASE block; arriving at below code, it would be other conversions. Note the recursion below at line 4039, it is the only point in the function we can step down the whole sequence. So it is clear that USER_CONV, IDENTITY_CONV, and AMBIG_CONV are the exitting point for the recursion. It does so because the sequence links the conversions in reversed order (target followed by source). See that not all conversions in the sequence would be visited, for example, in user defined conversion, the IDENTITY_CONV which is always at tail would be skipped, because the recursion stops at USER_CONV.

 

convert_like_real (continue)

 

4039    expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,

4040                          TREE_CODE (convs) == REF_BIND ? -1 : 1,

4041                         /*issue_conversion_warnings=*/ false);

4042    if (expr == error_mark_node)

4043      return error_mark_node;

4044

4045    switch (TREE_CODE (convs))

4046    {

4047      case RVALUE_CONV:

4048        if (! IS_AGGR_TYPE (totype))

4049          return expr;

4050        /* Else fall through.  */

4051      case BASE_CONV:

4052        if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))

4053        {

4054          /* We are going to bind a reference directly to a base-class

4055            subobject of EXPR.  */

4056          if (CHECK_COPY_CONSTRUCTOR_P (convs))

4057            check_constructor_callable (TREE_TYPE (expr), expr);

4058          /* Build an expression for `*((base*) &expr)'.  */

4059          expr = build_unary_op (ADDR_EXPR, expr, 0);

4060          expr = perform_implicit_conversion (build_pointer_type (totype),

4061                                         expr);

4062          expr = build_indirect_ref (expr, "implicit conversion");

4063          return expr;

4064        }

4065

4066        /* Copy-initialization where the cv-unqualified version of the source

4067          type is the same class as, or a derived class of, the class of the

4068          destination [is treated as direct-initialization]. [dcl.init] */

4069        expr = build_temp (expr, totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,

4070                        &diagnostic_fn);

4071        if (diagnostic_fn && fn)

4072          diagnostic_fn ("  initializing argument %P of `%D'", argnum, fn);

4073        return build_cplus_new (totype, expr);

4074

4075      case REF_BIND:

4076      {

4077        tree ref_type = totype;

4078

4079        /* If necessary, create a temporary.  */

4080        if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))

4081        {

4082          tree type = TREE_TYPE (TREE_OPERAND (convs, 0));

4083          cp_lvalue_kind lvalue = real_lvalue_p (expr);

4084

4085          if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))

4086          {

4087             /* If the reference is volatile or non-const, we

4088              cannot create a temporary.  */

4089            if (lvalue & clk_bitfield)

4090              error ("cannot bind bitfield `%E' to `%T'",

4091                    expr, ref_type);

4092            else if (lvalue & clk_packed)

4093              error ("cannot bind packed field `%E' to `%T'",

4094                    expr, ref_type);

4095            else

4096              error ("cannot bind rvalue `%E' to `%T'", expr, ref_type);

4097            return error_mark_node;

4098          }

4099          /* If the source is a packed field, and we must use a copy

4100            constructor, then building the target expr will require

4101            binding the field to the reference parameter to the

4102            copy constructor, and we'll end up with an infinite

4103            loop. If we can use a bitwise copy, then we'll be

4104            OK.  */

4105          if ((lvalue & clk_packed)

4106              && CLASS_TYPE_P (type)

4107             && !TYPE_HAS_TRIVIAL_INIT_REF (type))

4108          {

4109            error ("cannot bind packed field `%E' to `%T'",

4110                  expr, ref_type);

4111            return error_mark_node;

4112          }

4113          expr = build_target_expr_with_type (expr, type);

4114        }

4115

4116         /* Take the address of the thing to which we will bind the

4117          reference.  */

4118        expr = build_unary_op (ADDR_EXPR, expr, 1);

4119        if (expr == error_mark_node)

4120          return error_mark_node;

4121

4122        /* Convert it to a pointer to the type referred to by the

4123          reference. This will adjust the pointer if a derived to

4124           base conversion is being performed.  */

4125        expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),

4126                        expr);

4127        /* Convert the pointer to the desired reference type.  */

4128        return build_nop (ref_type, expr);

4129      }

4130

4131      case LVALUE_CONV:

4132        return decay_conversion (expr);

4133

4134      case QUAL_CONV:

4135        /* Warn about deprecated conversion if appropriate.  */

4136        string_conv_p (totype, expr, 1);

4137        break ;

4138       

4139      default :

4140        break ;

4141    }

4142    return ocp_convert (totype, expr, CONV_IMPLICIT,

4143                     LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);

4144 }

 

Obvious, LVALUE_CONV, RVALUE_CONV, REF_BIND,    QUAL_CONV, and BASE_CONV here are performed according to steps of converting source to target type. Conversions of PTR_CONV, QUAL_CONV, and PMEM_CONV are processed in below function.

Below argument convtype is a collect of bitfields, in which bit CONV_FORCE_TEMP means to require a new temporary when converting to the same aggregate type (however within our inovcation context here, the argument is CONV_IMPLICIT which means to perform implicit conversions). The function converts expression passed in argument expr to the type specified by the argument type .

 

614    tree

615    ocp_convert (tree type, tree expr, int convtype, int flags)                                          in cvt.c

616    {

617      tree e = expr;

618      enum tree_code code = TREE_CODE (type);

619   

620      if (error_operand_p (e) || type == error_mark_node)

621        return error_mark_node;

622   

623      complete_type (type);

624      complete_type (TREE_TYPE (expr));

625   

626      e = decl_constant_value (e);

627   

628      if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)

629           /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)

630             don't go through finish_struct, so they don't have the synthesized

631             constructors. So don't force a temporary.  */

632          && TYPE_HAS_CONSTRUCTOR (type))

633      /* We need a new temporary; don't take this shortcut.  */ ;

634      else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))

635      {

636        if (same_type_p (type, TREE_TYPE (e)))

637          /* The call to fold will not always remove the NOP_EXPR as

638             might be expected, since if one of the types is a typedef;

639             the comparison in fold is just equality of pointers, not a

640             call to comptypes. We don't call fold in this case because

641             that can result in infinite recursion; fold will call

642             convert, which will call ocp_convert, etc.  */

643          return e;

644        /* For complex data types, we need to perform componentwise

645          conversion.  */

646        else if (TREE_CODE (type) == COMPLEX_TYPE)

647          return fold (convert_to_complex (type, e));

648        else if (TREE_CODE (e) == TARGET_EXPR)

649        {

650          /* Don't build a NOP_EXPR of class type. Instead, change the

651             type of the temporary. Only allow this for cv-qual changes,

652             though.  */

653          if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),

654                         TYPE_MAIN_VARIANT (type)))

655            abort ();

656           TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;

657          return e;

658        }

659        else if (TREE_ADDRESSABLE (type))

660          /* We shouldn't be treating objects of ADDRESSABLE type as rvalues.  */

661          abort ();

662        else

663           return fold (build1 (NOP_EXPR, type, e));

664      }

665   

666      if (code == VOID_TYPE && (convtype & CONV_STATIC))

667      {

668        e = convert_to_void (e, /*implicit=*/ NULL);

669        return e;

670      }

671   

672      if (INTEGRAL_CODE_P (code))

673      {

674        tree intype = TREE_TYPE (e);

675        /* enum = enum, enum = int, enum = float, (enum)pointer are all

676          errors.  */

677        if (TREE_CODE (type) == ENUMERAL_TYPE

678           && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))

679                || (TREE_CODE (intype) == POINTER_TYPE)))

680        {

681          pedwarn ("conversion from `%#T' to `%#T'", intype, type);

682   

683          if (flag_pedantic_errors )

684            return error_mark_node;

685        }

686        if (IS_AGGR_TYPE (intype))

687        {

688          tree rval;

689          rval = build_type_conversion (type, e);

690          if (rval)

691            return rval;

692          if (flags & LOOKUP_COMPLAIN)

693            error ("`%#T' used where a `%T' was expected", intype, type);

694          if (flags & LOOKUP_SPECULATIVELY)

695            return NULL_TREE;

696          return error_mark_node;

697        }

698        if (code == BOOLEAN_TYPE)

699          return cp_truthvalue_conversion (e);

700   

701        return fold (convert_to_integer (type, e));

702      }

703      if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))

704        return fold (cp_convert_to_pointer (type, e, false));

 

Above, line from 672 to 702 processes conversion to integer type. The function would be used for static_cast , const_cast , and reinterpret_cast , which are represented by the bitfield of CONV_STATIC, CONV_CONST and CONV_REINTERPRET respectively. In above code, it can see clearly the restriction of the casts.

 

你可能感兴趣的:(function,tree,Class,Build,reference,Constructor)