GCC-3.4.6源代码学习笔记(150)

5.13.1.1.3.2.  对确定类型的引用

对于已确定的类型, 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] 显然,如果被处理的引用初始化是用于一个拷贝构造函数调用的第一个实参,实现必须最终选择第一个方法(不涉及拷贝的绑定)来避免无限递归。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值