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.