In this section, we go a little deeper to see in detail how to match the argument with the parameter, and do necessary conversion appropriately.
In C++ front-end, function parameters are recorded by TYPE_ARG_TYPES field in the FUNCTION_TYPE, which is a chain of tree_list, and in which TREE_VALUE of each node in this list is the type of the corresponding parameter; the TREE_PURPOSE is an expression for the default argument value, if any. If the last node in the list is void_list_node (a TREE_LIST node whose TREE_VALUE is the void_type_node ), then functions of this type do not take variable arguments. Otherwise, they do take a variable number of arguments. And arguments of the function would be constructed into a chain of tree_list, in which TREE_VALUE of each node is a representation of an assignment-expression.
In below function, arguments typelist is the tree_list for parameters and values is the tree_list for arguments for the function. So in case of no variable number parameters (typelist is ended by void_list_node ), typelist has the same length as values (at this point, any default argument used has been added into values ). Condition at line 2573 filters out the error case as we are pushing typelist and values with the same speed.
The detail of determining the conversion sequence and executing the real conversion is given in section Preliminaries - detail of conversion .
2538 tree
2539 convert_arguments (tree typelist, tree values, tree fndecl, int flags) in typeck.c
2540 {
2541 tree typetail, valtail;
2542 tree result = NULL_TREE;
2543 const char *called_thing = 0;
2544 int i = 0;
2545
2546 /* Argument passing is always copy-initialization. */
2547 flags |= LOOKUP_ONLYCONVERTING;
2548
2549 if (fndecl)
2550 {
2551 if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
2552 {
2553 if (DECL_NAME (fndecl) == NULL_TREE
2554 || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
2555 called_thing = "constructor";
2556 else
2557 called_thing = "member function";
2558 }
2559 else
2560 called_thing = "function";
2561 }
2562
2563 for (valtail = values, typetail = typelist;
2564 valtail;
2565 valtail = TREE_CHAIN (valtail), i++)
2566 {
2567 tree type = typetail ? TREE_VALUE (typetail) : 0;
2568 tree val = TREE_VALUE (valtail);
2569
2570 if (val == error_mark_node)
2571 return error_mark_node;
2572
2573 if (type == void_type_node)
2574 {
2575 if (fndecl)
2576 {
2577 cp_error_at ("too many arguments to %s `%+#D'", called_thing,
2578 fndecl);
2579 error ("at this point in file");
2580 }
2581 else
2582 error ("too many arguments to function");
2583 /* In case anybody wants to know if this argument
2584 list is valid. */
2585 if (result)
2586 TREE_TYPE (tree_last (result)) = error_mark_node;
2587 break ;
2588 }
2589
2590 /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
2591 Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
2592 if (TREE_CODE (val) == NOP_EXPR
2593 && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))
2594 && (type == 0 || TREE_CODE (type) != REFERENCE_TYPE))
2595 val = TREE_OPERAND (val, 0);
2596
2597 if (type == 0 || TREE_CODE (type) != REFERENCE_TYPE)
2598 {
2599 if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
2600 || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
2601 || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
2602 val = decay_conversion (val);
2603 }
2604
2605 if (val == error_mark_node)
2606 return error_mark_node;
2607
2608 if (type != 0)
2609 {
2610 /* Formal parm type is specified by a function prototype. */
2611 tree parmval;
2612
2613 if (!COMPLETE_TYPE_P (complete_type (type)))
2614 {
2615 if (fndecl)
2616 error ("parameter %P of `%D' has incomplete type `%T'",
2617 i, fndecl, type);
2618 else
2619 error ("parameter %P has incomplete type `%T'", i, type);
2620 parmval = error_mark_node;
2621 }
2622 else
2623 {
2624 parmval = convert_for_initialization
2625 (NULL_TREE, type, val, flags,
2626 "argument passing", fndecl, i);
2627 parmval = convert_for_arg_passing (type, parmval);
2628 }
2629
2630 if (parmval == error_mark_node)
2631 return error_mark_node;
2632
2633 result = tree_cons (NULL_TREE, parmval, result);
2634 }
2635 else
2636 {
2637 if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
2638 val = convert_from_reference (val);
2639
2640 if (fndecl && DECL_BUILT_IN (fndecl)
2641 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
2642 /* Don't do ellipsis conversion for __built_in_constant_p
2643 as this will result in spurious warnings for non-POD
2644 types. */
2645 val = require_complete_type (val);
2646 else
2647 val = convert_arg_to_ellipsis (val);
2648
2649 result = tree_cons (NULL_TREE, val, result);
2650 }
2651
2652 if (typetail)
2653 typetail = TREE_CHAIN (typetail);
2654 }
If type is the type specified in the function prototype, as line 2608 indicates, it needs ensure that the argument can be converted to the type of the parameter and then does the conversion (see that handling argument passed mostly like placing it at right hand of assignment expression). After that convert_for_arg_passing provides special conversion for argument passing based on the target platform the code generated for. Here is the detail of convert_for_initialization .
5809 tree
5810 convert_for_initialization (tree exp, tree type, tree rhs, int flags, in typeck.c
5811 const char *errtype, tree fndecl, int parmnum)
5812 {
5813 enum tree_code codel = TREE_CODE (type);
5814 tree rhstype;
5815 enum tree_code coder;
5816
5817 /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
5818 Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
5819 if (TREE_CODE (rhs) == NOP_EXPR
5820 && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))
5821 && codel != REFERENCE_TYPE)
5822 rhs = TREE_OPERAND (rhs, 0);
5823
5824 if (rhs == error_mark_node
5825 || (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
5826 return error_mark_node;
5827
5828 if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
5829 rhs = convert_from_reference (rhs);
5830
5831 if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
5832 && TREE_CODE (type) != ARRAY_TYPE
5833 && (TREE_CODE (type) != REFERENCE_TYPE
5834 || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
5835 || (TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
5836 && (TREE_CODE (type) != REFERENCE_TYPE
5837 || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE))
5838 || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
5839 rhs = decay_conversion (rhs);
5840
5841 rhstype = TREE_TYPE (rhs);
5842 coder = TREE_CODE (rhstype);
5843
5844 if (coder == ERROR_MARK)
5845 return error_mark_node;
5846
5847 /* We accept references to incomplete types, so we can
5848 return here before checking if RHS is of complete type. */
5849
5850 if (codel == REFERENCE_TYPE)
5851 {
5852 /* This should eventually happen in convert_arguments. */
5853 int savew = 0, savee = 0;
5854
5855 if (fndecl)
5856 savew = warningcount , savee = errorcount ;
5857 rhs = initialize_reference (type, rhs, /*decl=*/ NULL_TREE,
5858 /*cleanup=*/ NULL);
5859 if (fndecl)
5860 {
5861 if (warningcount > savew)
5862 cp_warning_at ("in passing argument %P of `%+D'", parmnum, fndecl);
5863 else if (errorcount > savee)
5864 cp_error_at ("in passing argument %P of `%+D'", parmnum, fndecl);
5865 }
5866 return rhs;
5867 }
5868
5869 if (exp != 0)
5870 exp = require_complete_type (exp);
5871 if (exp == error_mark_node)
5872 return error_mark_node;
5873
5874 rhstype = non_reference (rhstype);
5875
5876 type = complete_type (type);
5877
5878 if (IS_AGGR_TYPE (type))
5879 return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
5880
5881 return convert_for_assignment (type, rhs, errtype, fndecl, parmnum);
5882 }
First, argument passed having (rhs ) reference type (but the parameter isn’t) should have its value copied as this reference should be ignored, so it needs build an INDIRECT_REF expression for the purpose. Condition at line 5831, says if 1) we pass an array to the parameter that is neither of type array, nor of the reference type of the array; or 2) pass a function (in fact, its address), but the parameter is neither of function type, nor of the reference type of the function; or 3) pass a method (in fact, its address, and note that method can’t be referenced because it requires implicit argument of ‘this’ pointer); it decays rhs according to lvalue-to-rvalue conversion.
Next if the parameter is of reference type, argument passed in would be referred instead of copying the value. It is handled differently than value-copy done by initialize_reference . Section Case of conversion for reference type shows the procedure of determining the conversion sequence from argument to the reference type of parameter by reference_binding , which returns NULL if no such conversion sequence exists or “ICS_BAD_FLAG (conv)” holds if the conversion is not allowed.
6120 tree
6121 initialize_reference (tree type, tree expr, tree decl, tree *cleanup) in call.c
6122 {
6123 tree conv;
6124
6125 if (type == error_mark_node || error_operand_p (expr))
6126 return error_mark_node;
6127
6128 conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
6129 if (!conv || ICS_BAD_FLAG (conv))
6130 {
6131 if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
6132 && !real_lvalue_p (expr))
6133 error ("invalid initialization of non-const reference of "
6134 "type '%T' from a temporary of type '%T'",
6135 type, TREE_TYPE (expr));
6136 else
6137 error ("invalid initialization of reference of type "
6138 "'%T' from expression of type '%T'", type,
6139 TREE_TYPE (expr));
6140 return error_mark_node;
6141 }
… // …
6177 my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
6178 if (decl)
6179 {
…
6268 return build_nop (type, expr);
6269 }
6270
6271 /* Perform the conversion. */
6272 return convert_like (conv, expr);
6273 }
Above if argument decl is non-NULL, it is the VAR_DECL being initialized with the expr . In our scenario here, decl is NULL as we are handling call arguments, it needs compiler to create the temparory artificially. And convert_like at line 6272 is just a simple wrapper of convert_like_real ; it can simply call the function doing the conversion as we don’t need worry about the lifetime of the argument for the parameter by reference.
While if the parameter is not of reference type, the argument should be copied. As precondition, the type definition must be already completed for both argument and parameter. Further note that rhstype gives the type of argument, if we use a reference as argument, the reference semantics should be abandoned from the type (see above we have built INDIRECT_REF for using value of the argument), here non_reference helps us to fetch the underling type be referred.
Next if the parameter is a class type, it needs invoke appropriate constructor to build the instance from the argument, which is the duty of ocp_convert above. Note that argument flags in it is LOOKUP_NORMAL (bitset LOOKUP_PROTECT | LOOKUP_COMPLAIN), which forces the function to look for matching constructor but skip conversion operations; and argument convtype is bitset CONV_IMPLICIT|CONV_FORCE_TEMP, which indicates to look for implicit conversion and needs a temporary to hold the result.
For function parameter of other non-reference types, it follows the same rule as assignment, that is the function argument can be regarded as the part of right hand side of an expression.
5712 static tree
5713 convert_for_assignment (tree type, tree rhs, in typeck.c
5714 const char *errtype, tree fndecl, int parmnum)
5715 {
5716 tree rhstype;
5717 enum tree_code coder;
5718
5719 /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
5720 if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
5721 rhs = TREE_OPERAND (rhs, 0);
5722
5723 rhstype = TREE_TYPE (rhs);
5724 coder = TREE_CODE (rhstype);
5725
5726 if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE
5727 && ((*targetm .vector_opaque_p) (type)
5728 || (*targetm .vector_opaque_p) (rhstype)))
5729 return convert (type, rhs);
5730
5731 if (rhs == error_mark_node || rhstype == error_mark_node)
5732 return error_mark_node;
5733 if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
5734 return error_mark_node;
5735
5736 /* The RHS of an assignment cannot have void type. */
5737 if (coder == VOID_TYPE)
5738 {
5739 error ("void value not ignored as it ought to be");
5740 return error_mark_node;
5741 }
5742
5743 /* Simplify the RHS if possible. */
5744 if (TREE_CODE (rhs) == CONST_DECL)
5745 rhs = DECL_INITIAL (rhs);
5746
5747 /* We do not use decl_constant_value here because of this case:
5748
5749 const char* const s = "s";
5750
5751 The conversion rules for a string literal are more lax than for a
5752 variable; in particular, a string literal can be converted to a
5753 "char *" but the variable "s" cannot be converted in the same
5754 way. If the conversion is allowed, the optimization should be
5755 performed while creating the converted expression. */
5756
5757 /* [expr.ass]
5758
5759 The expression is implicitly converted (clause _conv_) to the
5760 cv-unqualified type of the left operand.
5761
5762 We allow bad conversions here because by the time we get to this point
5763 we are committed to doing the conversion. If we end up doing a bad
5764 conversion, convert_like will complain. */
5765 if (!can_convert_arg_bad (type, rhstype, rhs))
5766 {
5767 /* When -Wno-pmf-conversions is use, we just silently allow
5768 conversions from pointers-to-members to plain pointers. If
5769 the conversion doesn't work, cp_convert will complain. */
5770 if (!warn_pmf2ptr
5771 && TYPE_PTR_P (type)
5772 && TYPE_PTRMEMFUNC_P (rhstype))
5773 rhs = cp_convert (strip_top_quals (type), rhs);
5774 else
5775 {
5776 /* If the right-hand side has unknown type, then it is an
5777 overloaded function. Call instantiate_type to get error
5778 messages. */
5779 if (rhstype == unknown_type_node)
5780 instantiate_type (type, rhs, tf_error | tf_warning);
5781 else if (fndecl)
5782 error ("cannot convert `%T' to `%T' for argument `%P' to `%D'",
5783 rhstype, type, parmnum, fndecl);
5784 else
5785 error ("cannot convert `%T' to `%T' in %s", rhstype, type,
5786 errtype);
5787 return error_mark_node;
5788 }
5789 }
5790 return perform_implicit_conversion (strip_top_quals (type), rhs);
5791 }
Comments above explain the special treatment in conversion in assignment. The conversion of argument to parameter type is also subject to implicit conversion. Below function like can_convert_arg to look for the conversion sequence but but allows dubious conversions as well.
6005 bool
6006 can_convert_arg_bad (tree to, tree from, tree arg) in call.c
6007 {
6008 return implicit_conversion (to, from, arg, LOOKUP_NORMAL) != 0;
6009 }
Here the parameter is not of reference type, then the converted argument would get its value copied before later use, so it just needs convert the argument to the type without top cv-qualifier of the parameter. The rest is the same as other ways of conversion.
Back convert_arguments , for the ellipse arguments at line 2635, for argument of reference but parameter of non-reference here, the argument’s value is what we interest. At line 2641, code BUILT_IN_CONSTANT_P goes with builtin function “constant_p”, which accepts variable arguments and tells if its argument(s) is(are) constant or not. And see that convert_arg_to_ellipsis at line 2647, it gives out warning when the argument is of non-POD type which can be passed to constant_p which only evaluates the constantness and cares nothing else. So it needesn’t take trouble to invoke convert_arg_to_ellipsis .
Then following code processes the case of default argument, it is the same as that we have seen in procedure of finding user-defined conversion in implicit conversion.
convert_arguments (continue)
2656 if (typetail != 0 && typetail != void_list_node)
2657 {
2658 /* See if there are default arguments that can be used. */
2659 if (TREE_PURPOSE (typetail)
2660 && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
2661 {
2662 for (; typetail != void_list_node; ++i)
2663 {
2664 tree parmval
2665 = convert_default_arg (TREE_VALUE (typetail),
2666 TREE_PURPOSE (typetail),
2667 fndecl, i);
2668
2669 if (parmval == error_mark_node)
2670 return error_mark_node;
2671
2672 result = tree_cons (0, parmval, result);
2673 typetail = TREE_CHAIN (typetail);
2674 /* ends with `...'. */
2675 if (typetail == NULL_TREE)
2676 break ;
2677 }
2678 }
2679 else
2680 {
2681 if (fndecl)
2682 {
2683 cp_error_at ("too few arguments to %s `%+#D'",
2684 called_thing, fndecl);
2685 error ("at this point in file");
2686 }
2687 else
2688 error ("too few arguments to function");
2689 return error_mark_list ;
2690 }
2691 }
2692
2693 return nreverse (result);
2694 }