Studying note of GCC-3.4.6 source (151)

5.13.1.2.              The real conversion

In previous section, the conversion sequence is determined; then executing this sequence, it can get the target type from the conversion. In C++ front-end, in convert_like_real below conversion will actually occur. Among its arguments, fn and argnum are used for diagnostics, among which argnum is zero based, -1 indicates the `this' argument of a method. And inner is nonzero when being called to continue a conversion chain. It is negative when a reference binding will be applied, positive otherwise. If issue_conversion_warnings is true, warnings about suspicious conversions will be emitted if appropriate.

5.13.1.2.1.        Case of bad standard conversion supported by extension

First, if the conversion sequence is bad (predicator ICS_BAD_FLAG at line 3924 holds) and of standard conversion, to give diagnostic information as correct as possible, the front-end still executes the correct part of conversion sequence by recursing convert_like_real .

 

3917 static tree

3918 convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,                   in call.c

3919                 bool issue_conversion_warnings)

3920 {

3921    tree totype = TREE_TYPE (convs);

3922    void (*diagnostic_fn)(const char *, ...);

3923

3924    if (ICS_BAD_FLAG (convs)

3925        && TREE_CODE (convs) != USER_CONV

3926        && TREE_CODE (convs) != AMBIG_CONV

3927        && TREE_CODE (convs) != REF_BIND)

3928    {

3929      tree t = convs;

3930      for (; t; t = TREE_OPERAND (t, 0))

3931      {

3932        if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))

3933        {

3934          expr = convert_like_real (t, expr, fn, argnum, 1,

3935                               /*issue_conversion_warnings=*/ false);

3936          break ;

3937        }

3938        else if (TREE_CODE (t) == AMBIG_CONV)

3939          return convert_like_real (t, expr, fn, argnum, 1,

3940                              /*issue_conversion_warnings=*/ false);

3941        else if (TREE_CODE (t) == IDENTITY_CONV)

3942          break ;

3943      }

3944      pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);

3945      if (fn)

3946        pedwarn ("  initializing argument %P of `%D'", argnum, fn);

3947      return cp_convert (totype, expr);

3948    }

 

Here the bad conversion is that not allowed by standard but still exceptable as extension; otherwise, NULL would be returned instead of convs in previous section. The behavor of extension just ignores the bad part and gives warning about it.

5.13.1.2.2.        Case of user-defined conversion

Next in the sequence there would be a part that legal but potentially dangerous. If issue_conversion_warnings is nonzero, dubious_conversion_warnings is invoked for the checking.

 

5657 tree

5658 dubious_conversion_warnings (tree type, tree expr,                                      in typeck.c

5659                            const char *errtype, tree fndecl, int parmnum)

5660 {

5661    type = non_reference (type);

5662   

5663    /* Issue warnings about peculiar, but valid, uses of NULL.  */

5664    if (ARITHMETIC_TYPE_P (type) && expr == null_node)

5665    {

5666      if (fndecl)

5667        warning ("passing NULL used for non-pointer %s %P of `%D'",

5668                errtype, parmnum, fndecl);

5669      else

5670        warning ("%s to non-pointer type `%T' from NULL", errtype, type);

5671    }

5672   

5673    /* Warn about assigning a floating-point type to an integer type.  */

5674    if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE

5675        && TREE_CODE (type) == INTEGER_TYPE)

5676    {

5677      if (fndecl)

5678        warning ("passing `%T' for %s %P of `%D'",

5679                TREE_TYPE (expr), errtype, parmnum, fndecl);

5680       else

5681        warning ("%s to `%T' from `%T'", errtype, type, TREE_TYPE (expr));

5682    }

5683    /* And warn about assigning a negative value to an unsigned

5684      variable.  */

5685    else if (TREE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)

5686    {

5687      if (TREE_CODE (expr) == INTEGER_CST

5688         && TREE_NEGATED_INT (expr))

5689      {

5690        if (fndecl)

5691          warning ("passing negative value `%E' for %s %P of `%D'",

5692                   expr, errtype, parmnum, fndecl);

5693        else

5694          warning ("%s of negative value `%E' to `%T'",

5695                  errtype, expr, type);

5696      }

5697

5698      overflow_warning (expr);

5699

5700      if (TREE_CONSTANT (expr))

5701        expr = fold (expr);

5702    }

5703    return expr;

5704 }

 

Above the only possible revision of expr is the constant-folding if expr is a constant. After checking the dangerous operation, the conversion is handled according to its type. For user-defined conversion sequence, it is processed by following code.

 

convert_like_real (continue)

 

3950    if (issue_conversion_warnings)

3951      expr = dubious_conversion_warnings

3952                    (totype, expr, "converting", fn, argnum);

3953    switch (TREE_CODE (convs))

3954    {

3955      case USER_CONV:

3956      {

3957        struct z_candidate *cand = USER_CONV_CAND (convs);

3958        tree convfn = cand->fn;

3959        tree args;

3960

3961        if (DECL_CONSTRUCTOR_P (convfn))

3962        {

3963          tree t = build_int_2 (0, 0);

3964          TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));

3965

3966          args = build_tree_list (NULL_TREE, expr);

3967          if (DECL_HAS_IN_CHARGE_PARM_P (convfn)

3968             || DECL_HAS_VTT_PARM_P (convfn))

3969            /* We should never try to call the abstract or base constructor

3970              from here.  */

3971            abort ();

3972          args = tree_cons (NULL_TREE, t, args);

3973        }

3974        else

3975          args = build_this (expr);

3976        expr = build_over_call (cand, LOOKUP_NORMAL);

3977

3978        /* If this is a constructor or a function returning an aggr type,

3979          we need to build up a TARGET_EXPR.  */

3980        if (DECL_CONSTRUCTOR_P (convfn))

3981          expr = build_cplus_new (totype, expr);

3982

3983        /* The result of the call is then used to direct-initialize the object

3984          that is the destination of the copy-initialization. [dcl.init]

3985

3986          Note that this step is not reflected in the conversion sequence;

3987          it affects the semantics when we actually perform the

3988          conversion, but is not considered during overload resolution.

3989

3990          If the target is a class, that means call a ctor.  */

3991        if (IS_AGGR_TYPE (totype)

3992           && (inner >= 0 || !lvalue_p (expr)))

3993        {

3994          expr = (build_temp

3995                     (expr, totype,

3996                      /* Core issue 84, now a DR, says that we don't

3997                        allow UDCs for these args (which deliberately

3998                         breaks copy-init of an auto_ptr<Base> from an

3999                        auto_ptr<Derived>).  */

4000 LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION,

4001                      &diagnostic_fn));

4002           

4003          if (diagnostic_fn)

4004           {

4005            if (fn)

4006              diagnostic_fn

4007                  ("  initializing argument %P of `%D' from result of `%D'",

4008                    argnum, fn, convfn);

4009            else

4010              diagnostic_fn

4011                   ("  initializing temporary from result of `%D'",  convfn);

4012          }

4013          expr = build_cplus_new (totype, expr);

4014        }

4015        return expr;

4016      }

 

In previous section, we have seen that if the best candidate (in form of z_candidate) is found for user-defined conversion, a WRAPPER node is generated to wrap the found z_candidate, which is in turn put into first operand of convs , then USER_CONV_CAND at line 3957, fetches this z_candidate. So convfn at line 3958, refers to the corresponding function declaration.

It is possible that constructor is used for the conversion, for which case, the “this” pointer passed in should be NULL and points to object being created at point of exitting. After preparing the “this” pointer into the argument list, build_over_call builds necessary code of invoking this overload.

5.13.1.2.2.1.  Converting the implicit this argument

In the procedure of building the conversion sequence, if it suppresses issuing warning message, all warnings generated in joust would be stored in warnings slot at line 4392; so if warnings slot is not empty, there is pending warnings, it is the time to issue the warnings now as we are doing the real conversion.

At line 4396 DECL_FUNCTION_MEMBER_P holds if fn is a member function (static or non-static). For this case, it needs check the accessibility from “cand->access_path” which records the binfo of the base that would access the member function.

 

4362 static tree

4363 build_over_call (struct z_candidate *cand, int flags)                                            in call.c

4364 {

4365    tree fn = cand->fn;

4366    tree args = cand->args;

4367    tree convs = cand->convs;

4368    tree converted_args = NULL_TREE;

4369    tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));

4370    tree conv, arg, val;

4371    int i = 0;

4372    int is_method = 0;

4373

4374     /* In a template, there is no need to perform all of the work that

4375      is normally done. We are only interested in the type of the call

4376      expression, i.e., the return type of the function. Any semantic

4377      errors will be deferred until the template is instantiated.  */

4378    if (processing_template_decl )

4379    {

4380      tree expr;

4381      tree return_type;

4382      return_type = TREE_TYPE (TREE_TYPE (fn));

4383      expr = build (CALL_EXPR, return_type, fn, args);

4384      if (TREE_THIS_VOLATILE (fn) && cfun )

4385        current_function_returns_abnormally = 1;

4386      if (!VOID_TYPE_P (return_type))

4387        require_complete_type (return_type);

4388      return convert_from_reference (expr);

4389    }

4390

4391    /* Give any warnings we noticed during overload resolution.  */

4392    if (cand->warnings)

4393      for (val = cand->warnings; val; val = TREE_CHAIN (val))

4394        joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);

4395

4396    if (DECL_FUNCTION_MEMBER_P (fn))

4397    {

4398      /* If FN is a template function, two cases must be considered.

4399        For example:

4400

4401         struct A {

4402         protected:

4403           template <class T> void f();

4404         };

4405         template <class T> struct B {

4406         protected:

4407           void g();

4408         };

4409         struct C : A, B<int> {

4410           using A::f;   // #1

4411           using B<int>::g;   // #2

4412         };

4413

4414        In case #1 where `A::f' is a member template, DECL_ACCESS is

4415        recorded in the primary template but not in its specialization.

4416        We check access of FN using its primary template.

4417

4418        In case #2, where `B<int>::g' has a DECL_TEMPLATE_INFO simply

4419        because it is a member of class template B, DECL_ACCESS is

4420        recorded in the specialization `B<int>::g'. We cannot use its

4421        primary template because `B<T>::g' and `B<int>::g' may have

4422         different access.  */

4423      if (DECL_TEMPLATE_INFO (fn)

4424         && is_member_template (DECL_TI_TEMPLATE (fn)))

4425        perform_or_defer_access_check (cand->access_path,

4426                                    DECL_TI_TEMPLATE (fn));

4427      else

4428        perform_or_defer_access_check (cand->access_path, fn);

4429    }

4430

4431    if (args && TREE_CODE (args) != TREE_LIST)

4432      args = build_tree_list (NULL_TREE, args);

4433    arg = args;

4434

4435    /* The implicit parameters to a constructor are not considered by overload

4436      resolution, and must be of the proper type.  */

4437    if (DECL_CONSTRUCTOR_P (fn))

4438    {

4439      converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);

4440      arg = TREE_CHAIN (arg);

4441      parm = TREE_CHAIN (parm);

4442      if (DECL_HAS_IN_CHARGE_PARM_P (fn))

4443        /* We should never try to call the abstract constructor.  */

4444        abort ();

4445      if (DECL_HAS_VTT_PARM_P (fn))

4446      {

4447        converted_args = tree_cons

4448                       (NULL_TREE, TREE_VALUE (arg), converted_args);

4449        arg = TREE_CHAIN (arg);

4450        parm = TREE_CHAIN (parm);

4451      }

4452    }     

4453    /* Bypass access control for 'this' parameter.  */

4454    else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)

4455    {

4456      tree parmtype = TREE_VALUE (parm);

4457      tree argtype = TREE_TYPE (TREE_VALUE (arg));

4458      tree converted_arg;

4459      tree base_binfo;

4460       

4461      if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))

4462        pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",

4463                TREE_TYPE (argtype), fn);

4464

4465      /* [class.mfct.nonstatic]: If a nonstatic member function of a class

4466        X is called for an object that is not of type X, or of a type

4467        derived from X, the behavior is undefined.

4468

4469        So we can assume that anything passed as 'this' is non-null, and

4470        optimize accordingly.  */

4471      my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);

4472      /* Convert to the base in which the function was declared.  */

4473      my_friendly_assert (cand->conversion_path != NULL_TREE, 20020730);

4474      converted_arg = build_base_path (PLUS_EXPR,

4475                                  TREE_VALUE (arg),

4476                                  cand->conversion_path,

4477                                  1);

4478      /* Check that the base class is accessible.  */

4479      if (!accessible_base_p (TREE_TYPE (argtype),

4480                         BINFO_TYPE (cand->conversion_path)))

4481         error ("`%T' is not an accessible base of `%T'",

4482               BINFO_TYPE (cand->conversion_path),

4483               TREE_TYPE (argtype));

4484      /* If fn was found by a using declaration, the conversion path

4485        will be to the derived class, not the base declaring fn. We

4486        must convert from derived to base.  */

4487      base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),

4488                             TREE_TYPE (parmtype), ba_ignore, NULL);

4489      converted_arg = build_base_path (PLUS_EXPR, converted_arg,

4490                                  base_binfo, 1);

4491       

4492      converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);

4493      parm = TREE_CHAIN (parm);

4494      arg = TREE_CHAIN (arg);

4495      ++i;

4496      is_method = 1;

4497    }

 

Above before invoking build_over_call , for non-constructor, one “this” pointer having the same type as expr is built. However, the method may be defined within base instead of the type of expr , for which case, it needs extract this base from the type. So at line 4475, arg would be the “this” pointer prepared in convert_like_real , and build_base_path generates the PLUS_EXPR to adjust arg to the head of the base specified by “cand->conversion_path”.

Next at line 4487, as we have seen, “TREE_TYPE (converted_arg)” would be TYPE_DECL of the base type, in which TREE_TYPE would be the corresponding RECORD_TYPE; and parmtype is the implicit “this” parameter in the method definiton, which would be the exact class that defining the method. It needs further adjustment down from line 4487, dues to fact demonstrated by following example:

class A {

protected : int operator () { return 0; }

};

class B: public A {

public : using A::operator ;

};

class C: public B {};

void func (int) {}

int main() {

func (C c);

}

When searching conversion sequence, the front-end will select B as “cand->conversion_path”; however, the conversion operator in fact is defined within A. The real “this” argument should be the subobject of A within the derived. And note that with the using directive, the private member of the base can be visible within the derived, then even outer global. So the adjustment starting from line 4487 checks the accessiblilty in lookup_base is enough.

5.13.1.2.2.2.  Converting other arguments

5.12.5.2.2.2.1.          Normal arguments

After converting the implicit “this” argument, next to convert other arguments. Below, arg is the list of arguments passed by user, in which node TREE_VALUE is the expression for the argument; and parm is the list of parameters of the function, in which node TREE_VALUE is the corresponding type, and TREE_PURPOSE is the expression for the default argument value, if any.

 

build_over_call (continue)

 

4499    for (; arg && parm;

4500         parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)

4501    {

4502      tree type = TREE_VALUE (parm);

4503

4504      conv = TREE_VEC_ELT (convs, i);

4505      val = convert_like_with_context

4506                (conv, TREE_VALUE (arg), fn, i - is_method);

4507

4508      val = convert_for_arg_passing (type, val);

4509      converted_args = tree_cons (NULL_TREE, val, converted_args);

4510    }

4511

4512    /* Default arguments */

4513    for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)

4514      converted_args

4515        = tree_cons (NULL_TREE,

4516                  convert_default_arg (TREE_VALUE (parm),

4517                                   TREE_PURPOSE (parm),

4518                                   fn, i - is_method),

4519                  converted_args);

4520

4521    /* Ellipsis */

4522    for (; arg; arg = TREE_CHAIN (arg))

4523    {

4524      tree a = TREE_VALUE (arg);

4525      if (magic_varargs_p (fn))

4526        /* Do no conversions for magic varargs.  */ ;

4527      else

4528        a = convert_arg_to_ellipsis (a);

4529      converted_args = tree_cons (NULL_TREE, a, converted_args);

4530    }

4531

4532    converted_args = nreverse (converted_args);

 

Further, TREE_VEC_ELT of convs records the conversion sequence for corresponding user provided arguments. With this conversion sequence, convert_like_with_context at line 4508, is defined as below.

 

52      #define convert_like_with_context (CONV, EXPR, FN, ARGNO)    /                    in call.c

53        convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0,          /

54                          /*issue_conversion_warnings=*/ true)

 

It calls convert_like_real for every argument. Here the warning message should be issued as soon as possible, and It is the top invocation for arguments, so argument inner of the invocation is 0.

After undergoing the normal conversion we are studying now, argument needs extra conversions provided by below function.

 

4317 tree

4318 convert_for_arg_passing (tree type, tree val)                                                      in call.c

4319 {

4320    if (val == error_mark_node)

4321      ;

4322     /* Pass classes with copy ctors by invisible reference.  */

4323    else if (TREE_ADDRESSABLE (type))

4324      val = build1 (ADDR_EXPR, build_reference_type (type), val);

4325    else if (PROMOTE_PROTOTYPES

4326          && INTEGRAL_TYPE_P (type)

4327          && COMPLETE_TYPE_P (type)

4328          && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),

4329                                      TYPE_SIZE (integer_type_node)))

4330      val = perform_integral_promotions (val);

4331    return val;

4332 }

 

Consider below example [7] :

A a;

func (a);   // of declaration void func (A a)

The compiler will generate following pseudo code to realize the progmatics meaning of above statements:

A __temp0;      // temporary generated by compiler

__temp0.A::A(a);     // invocation of copy ctor by compiler

func (__temp0);

Copy constructor must be invoked to initialize temporary object to be compitable with the semantic of the copy constructor. It is more efficient, if the compiler revises func as: “void func (A& a)”. There is an extra precondition that “a” must not be placed into register (if into register, TREE_ADDRESSABLE returns 0).

Next, PROMOTE_PROTOTYPES at line 4325 is defined as 1 for x86 chip which means when a prototype says `char' or `short', really pass an `int' (x86 can't easily push less than an int). So above perform_integral_promotions at line 4330 does this promotion for the case.

 

你可能感兴趣的:(function,tree,null,Build,Constructor,Warnings)