对于已确定的类型, reference_binding 用下面的代码来处理。
reference_binding (continue)
958 if (TREE_CODE (from) == REFERENCE_TYPE)
959 {
960 /* Anything with reference type is an lvalue. */
961 lvalue_p = clk_ordinary;
962 from = TREE_TYPE (from);
963 }
964 else if (expr)
965 lvalue_p = real_lvalue_p (expr);
966
967 /* Figure out whether or not the types are reference-related and
968 reference compatible. We have do do this after stripping
969 references from FROM. */
970 related_p = reference_related_p (to, from);
971 compatible_p = reference_compatible_p (to, from);
下面 2 个函数确定 to 及 from 之间相关的引用及兼容的引用。关于这个,【 3 】的条文 8.5.3 “引用”如下给出了其定义与目的。
4. 给定类型“ cv1 T1” 及“ cv2 T2” ,“ cv1 T1” 是“ cv2 T2” 的引用相关( reference-related ),如果 T1 与 T2 类型相同,或者 T1 是 T2 的一个基类类型。“ cv1 T1” 与“ cv2 T2” 是引用兼容( reference-compatible ),如果 T1 是 T2 的引用相关,及 cv1 是不弱于 cv2 的 cv- 限定。出于重载解析的目的, cv1 是比 cv2 更强的 cv- 限定的情形,被确定为具有额外限定的引用兼容( reference compatible with added qualification ,参考 13.3.3 .2 )。 T1 是 T2 的一个基类,在所有那些使用这两个类型的引用相关或引用兼容的关系,来建立一个引用绑定的有效性的情形中,如果 T1 是 T2 的一个不可访问(条文 11 )或二义性(条文 11 )的基类,需要这样一个绑定的程序是非法的。 |
716 static bool
717 reference_related_p (tree t1, tree t2) in call.c
718 {
719 t1 = TYPE_MAIN_VARIANT (t1);
720 t2 = TYPE_MAIN_VARIANT (t2);
721
722 /* [dcl.init.ref]
723
724 Given types "cv1 T1" and "cv2 T2," "cv1 T1" is reference-related
725 to "cv2 T2" if T1 is the same type as T2, or T1 is a base class
726 of T2. */
727 return (same_type_p (t1, t2)
728 || (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
729 && DERIVED_FROM_P (t1, t2)));
730 }
简而言之,如果 T1 至少是 T2 的引用相关(看到引用兼容的条件要稍微强一些),形如“ T1& t1 = t2; // t2 of type T2 ”的表达式是合法的。
734 static bool
735 reference_compatible_p (tree t1, tree t2) in call.c
736 {
737 /* [dcl.init.ref]
738
739 "cv1 T1" is reference compatible with "cv2 T2" if T1 is
740 reference-related to T2 and cv1 is the same cv-qualification as,
741 or greater cv-qualification than, cv2. */
742 return (reference_related_p (t1, t2)
743 && at_least_as_qualified_p (t1, t2));
744 }
下面 975 及 1005 行,及其他带有标记 [dcl.init.ref] 的注释摘录自【 3 】, 8.5.3 “引用”。
1 .一个被声明为“ T& ”,即是“类型 T 的引用”的变量,应该被一个类型 T 的对象,或函数或能够被转换到 T 的对象所初始化。 [ 例子: int g(int); void f() { int i; int& r = i; // r refers to i r = 1; // the value of i becomes 1 int* p = &r; // p points to i int& rr = r; // rr refers to what r refers to, that is, to i int (&rg)(int) = g; // rg refers to the function g rg(i); //calls function g int a[3]; int (&ra)[3] = a; // ra refers to the array a ra[1] = i; // modifies a[1] } — 例子结束 ] 2 .一个引用在初始化之后,不能被更改援引另一个对象。注意到一个引用的初始化与对它的赋值的处理非常的不同。实参传递( 5.2.2 )及函数返回值( 6.6.3 )都是初始化。 3 .仅在一个参数声明( 8.3.5 )中,函数返回值声明中,包含在其类声明中的类成员声明( 9.2 )中,及显示使用了 extern 说明符的情况下,可以忽略一个引用的初始值。 [ 例子: int& r1; // error: initializer missing extern int& r2; // OK —end example] 4 .参见上面 5 .类型“ cv1 T1” 的一个引用被一个类型为“ cv2 T2” 的表达式如下初始化: — 如果该初始值表达式 — 是一个左值(但不是一个位域),并且“ cv1 T1” 与“ cv2 T2” 是引用兼容的,或者 — 具有一个类类型(即, T2 是一个类类型),并且能被隐式地转换到类型“ cv3 T3” 的一个左值,其中“ cv1 T1” 与“ cv3 T3” 是引用兼容的 [1] )(这个转换通过枚举适用的转换函数( 13.3.1 .6 )并由重载解析( 13.3 )选择最优者来选定),那么,在第一个情形中,该引用是直接绑定到该初始值表达式的左值,在第二个情形中,该引用是绑定到转换结果的左值。在这些情形中,该引用被称为直接绑定到初始值表达式。 [ 注意:当完成这样的到左值的直接绑定,通常的左值到右值( 4.1 ),数组到指针( 4.2 ),及函数到指针( 4.3 )的标准转换都不需要,并因此被压制 ] 。 [ 例子: double d = 2.0; double& rd = d; // rd refers to d const double & rcd = d; // rcd refers to d struct A { }; struct B : public A { } b; A& ra = b; // ra refers to A sub-object in b const A& rca = b; // rca refers to A sub-object in b — 例子结束 ] — 否则,该引用应该绑定到一个非易变性( non-volatile )常量类型(即, cv1 应该是常量)。 [ 例子: double& rd2 = 2.0; // error: not an lvalue and reference not const int i = 2; double& rd3 = i; // error: type mismatch and reference not const — 例子结束 ] — 如果该初始值表达式是一个右值,同时 T2 是类类型,而且“ cv1 T1” 与“ cv2 T2” 引用兼容,该引用以以下方式之一绑定(其选择由实现决定): — 该引用绑定到由该右值(参见 3.10 )表示的对象,或到该对象的一个子对象。 — 类型“ cv1 T2” 的临时对象被构建,并且调用一个构造函数来拷贝整个这个右值对象到这个临时对象。该引用绑定到这个临时对象或该临时对象的一个子对象 [2] )。用于这个拷贝的构造函数必须是可调用的,无论该拷贝最终是否执行。 [ 例子: struct A { }; struct B : public A { } b; extern B f(); const A& rca = f(); // Either bound to the A sub-object of the B rvalue, // or the entire B object is copied and the reference // is bound to the A sub-object of the copy — 例子结束 ] — 否则,类型“ cv1 T1” 的一个临时对象被构建,并且由该初始值表达式使用用于非引用拷贝初始化( 8.5 )的规则来初始化。然后该引用绑定到这个临时对象。如果 T1 与 T2 是引用相关, cv1 必须是等于或大于 cv2 的 cv 限定;否则,该程序是非法的。 [ 例子: const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 const volatile int cvi = 1; const int& r = cvi; // error: type qualifiers dropped — 例子结束 ] 6 . [ 注意: 12.2 描述了绑定到引用的临时对象的生命周期 ] 。 |
reference_binding (continue)
973 if (lvalue_p && compatible_p)
974 {
975 /* [dcl.init.ref]
976
977 If the initializer expression
978
979 -- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
1000 is reference-compatible with "cv2 T2,"
1001
1002 the reference is bound directly to the initializer expression
1003 lvalue. */
1004 conv = build1 (IDENTITY_CONV, from, expr);
1005 conv = direct_reference_binding (rto, conv);
1006 if ((lvalue_p & clk_bitfield) != 0
1007 || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
1008 /* For the purposes of overload resolution, we ignore the fact
1009 this expression is a bitfield or packed field. (In particular,
1010 [over.ics.ref] says specifically that a function with a
1011 non-const reference parameter is viable even if the
1012 argument is a bitfield.)
1013
1014 However, when we actually call the function we must create
1015 a temporary to which to bind the reference. If the
1016 reference is volatile, or isn't const, then we cannot make
1017 a temporary, so we just issue an error when the conversion
1018 actually occurs. */
1019 NEED_TEMPORARY_P (conv) = 1;
1020
1021 return conv;
1022 }
1023 else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
1024 {
1025 /* [dcl.init.ref]
1026
1027 If the initializer expression
1028
1029 -- has a class type (i.e., T2 is a class type) can be
1030 implicitly converted to an lvalue of type "cv3 T3," where
1031 "cv1 T1" is reference-compatible with "cv3 T3". (this
1032 conversion is selected by enumerating the applicable
1033 conversion functions (_over.match.ref_) and choosing the
1034 best one through overload resolution. (_over.match_).
1035
1036 the reference is bound to the lvalue result of the conversion
1037 i n the second case. */
1038 conv = convert_class_to_reference (to, from, expr);
1039 if (conv)
1040 return conv;
1041 }
看到,仅当我们已经知道源类型与目标类型是引用兼容时,调用 direct_reference_binding ,并且传入的实参 conv 应该是源类型的一个 IDENTITY_CONV 。而上面 1008 行注释所提到的是引用绑定条文中的条款 4 (参见 引用类型的转换 )。这里我们接受位域的情况,但正如注释所说,除非引用的是一个常量,在真正执行转换的地方会发生错误——因为不能创建临时对象。
如果源类型不是引用,或者源类型与目标类型不是引用兼容,那么在 1023 行,如果源类型是类类型,并且用户定义转换允许使用,前端将在类定义中搜索来查找可以返回与目标类型引用兼容的返回值的转换操作符。
749 static tree
750 convert_class_to_reference (tree t, tree s, tree expr) in call.c
751 {
752 tree conversions;
753 tree arglist;
754 tree conv;
755 tree reference_type;
756 struct z_candidate *candidates;
757 struct z_candidate *cand;
758 bool any_viable_p;
759
760 conversions = lookup_conversions (s);
761 if (!conversions)
762 return NULL_TREE;
763
764 /* [over.match.ref]
765
766 Assuming that "cv1 T" is the underlying type of the reference
767 being initialized, and "cv S" is the type of the initializer
768 expression, with S a class type, the candidate functions are
769 selected as follows:
770
771 --The conversion functions of S and its base classes are
772 considered. Those that are not hidden within S and yield type
773 "reference to cv2 T2", where "cv1 T" is reference-compatible
774 (_dcl.init.ref_) with "cv2 T2", are candidate functions.
775
776 The argument list has one argument, which is the initializer
777 expression. */
778
779 candidates = 0;
780
781 /* Conceptually, we should take the address of EXPR and put it in
782 the argument list. Unfortunately, however, that can result in
783 error messages, which we should not issue now because we are just
784 trying to find a conversion operator. Therefore, we use NULL,
785 cast to the appropriate type. */
786 arglist = build_int_2 (0, 0);
787 TREE_TYPE (arglist) = build_pointer_type (s);
788 arglist = build_tree_list (NULL_TREE, arglist);
789
790 reference_type = build_reference_type (t);
791
792 while (conversions)
793 {
794 tree fns = TREE_VALUE (conversions);
795
796 for (; fns; fns = OVL_NEXT (fns))
797 {
798 tree f = OVL_CURRENT (fns);
799 tree t2 = TREE_TYPE (TREE_TYPE (f));
800
801 cand = NULL;
802
803 /* If this is a template function, try to get an exact
804 match. */
805 if (TREE_CODE (f) == TEMPLATE_DECL)
806 {
807 cand = add_template_candidate (&candidates,
808 f, s,
809 NULL_TREE,
810 arglist,
811 reference_type,
812 TYPE_BINFO (s),
813 TREE_PURPOSE (conversions),
814 LOOKUP_NORMAL,
815 DEDUCE_CONV);
816
817 if (cand)
818 {
819 /* Now, see if the conversion function really returns
820 an lvalue of the appropriate type. From the
821 point of view of unification, simply returning an
822 rvalue of the right type is good enough. */
823 f = cand->fn;
824 t2 = TREE_TYPE (TREE_TYPE (f));
825 if (TREE_CODE (t2) != REFERENCE_TYPE
826 || ! reference_compatible_p (t, TREE_TYPE (t2)))
827 {
828 candidates = candidates->next;
829 cand = NULL;
830 }
831 }
832 }
833 else if (TREE_CODE (t2) == REFERENCE_TYPE
834 && reference_compatible_p (t, TREE_TYPE (t2)))
835 cand = add_function_candidate (&candidates, f, s, arglist,
836 TYPE_BINFO (s),
837 TREE_PURPOSE (conversions),
838 LOOKUP_NORMAL);
839
840 if (cand)
841 {
842 /* Build a standard conversion sequence indicating the
843 binding from the reference type returned by the
844 function to the desired REFERENCE_TYPE. */
845 cand->second_conv
846 = (direct_reference_binding
847 (reference_type,
848 build1 (IDENTITY_CONV,
849 TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
850 NULL_TREE)));
851 ICS_BAD_FLAG (cand->second_conv)
852 |= ICS_BAD_FLAG (TREE_VEC_ELT (cand->convs, 0));
853 }
854 }
855 conversions = TREE_CHAIN (conversions);
856 }
857
858 candidates = splice_viable (candidates, pedantic , &any_viable_p);
859 /* If none of the conversion functions worked out, let our caller
860 know. */
861 if (!any_viable_p)
862 return NULL_TREE;
863
864 cand = tourney (candidates);
865 if (!cand)
866 return NULL_TREE;
867
868 /* Now that we know that this is the function we're going to use fix
869 the dummy first argument. */
870 cand->args = tree_cons (NULL_TREE,
871 build_this (expr),
872 TREE_CHAIN (cand->args));
873
874 /* Build a user-defined conversion sequence representing the
875 conversion. */
876 conv = build_conv (USER_CONV,
877 TREE_TYPE (TREE_TYPE (cand->fn)),
878 build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
879 TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
880
881 /* Merge it with the standard conversion sequence from the
882 conversion function's return type to the desired type. */
883 cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
884
885 if (cand->viable == -1)
886 ICS_BAD_FLAG (conv) = 1;
887
888 return cand->second_conv;
889 }
为引用绑定找出适合的转换的整个过程几乎与非引用转换的一样,除了在 883 行所构建的 second_conv 。记得上面的代码处理所谓的“直接绑定“,它不需要临时对象。否则,需要下面的代码来涵盖剩下的情形。
reference_binding (continue)
1023 /* From this point on, we conceptually need temporaries, even if we
1024 elide them. Only the cases above are "direct bindings". */
1025 if (flags & LOOKUP_NO_TEMP_BIND)
1026 return NULL_TREE;
1027
1028 /* [over.ics.rank]
1029
1030 When a parameter of reference type is not bound directly to an
1031 argument expression, the conversion sequence is the one required
1032 to convert the argument expression to the underlying type of the
1033 reference according to _over.best.ics_. Conceptually, this
1034 conversion sequence corresponds to copy-initializing a temporary
1035 of the underlying type with the argument expression. Any
1036 difference in top-level cv-qualification is subsumed by the
1037 initialization itself and does not constitute a conversion. */
1038
1039 /* [dcl.init.ref]
1040
1041 Otherwise, the reference shall be to a non-volatile const type. */
1042 if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
1043 return NULL_TREE;
1044
1045 /* [dcl.init.ref]
1046
1047 If the initializer expression is an rvalue, with T2 a class type,
1048 and "cv1 T1" is reference-compatible with "cv2 T2", the reference
1049 is bound in one of the following ways:
1050
1051 -- The reference is bound to the object represented by the rvalue
1052 or to a sub-object within that object.
1053
1054 -- ...
1055
1056 We use the first alternative. The implicit conversion sequence
1057 is supposed to be same as we would obtain by generating a
1058 temporary. Fortunately, if the types are reference compatible,
1059 then this is either an identity conversion or the derived-to-base
1060 conversion, just as for direct binding. */
1061 if (CLASS_TYPE_P (from) && compatible_p)
1062 {
1063 conv = build1 (IDENTITY_CONV, from, expr);
1064 conv = direct_reference_binding (rto, conv);
1065 if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
1066 CHECK_COPY_CONSTRUCTOR_P (TREE_OPERAND (conv, 0)) = 1;
1067 return conv;
1068 }
1069
1070 /* [dcl.init.ref]
1071
1072 Otherwise, a temporary of type "cv1 T1" is created and
1073 initialized from the initializer expression using the rules for a
1074 non-reference copy initialization. If T1 is reference-related to
1075 T2, cv1 must be the same cv-qualification as, or greater
1076 cv-qualification than, cv2; otherwise, the program is ill-formed. */
1077 if (related_p && !at_least_as_qualified_p (to, from))
1078 return NULL_TREE;
1079
1080 conv = implicit_conversion (to, from, expr, flags);
1081 if (!conv)
1082 return NULL_TREE;
1083
1084 conv = build_conv (REF_BIND, rto, conv);
1085 /* This reference binding, unlike those above, requires the
1086 creation of a temporary. */
1087 NEED_TEMPORARY_P (conv) = 1;
1088
1089 return conv;
1090 }
上面 1025 行的 LOOKUP_NO_TEMP_BIND ,如果设置了,就意味着临时对象不能绑定到引用。能绑定到临时对象的引用必须是常量,这由上面 1042 行的条件来保证。
前面在所引用的【 3 】的条文 8.5.3 “引用”,条款 5 中看到,如果初始值表达式是一个右值,有两种实现的方式。这里前端同时应用了两者。
1 )如果源类型是类类型,而且源类型与目标类型引用兼容,这里的条件除了初始值表达式不是一个左值之外(这里则是引用为常量),其他条件相同。那么按直接绑定来处理。
2 )其他情况(参考上面的条款 5 ),创建临时对象来绑定引用。
[1] 这要求有一个转换函数( 12.3.2 )返回一个引用类型。
[2] 显然,如果被处理的引用初始化是用于一个拷贝构造函数调用的第一个实参,实现必须最终选择第一个方法(不涉及拷贝的绑定)来避免无限递归。