GCC-3.4.6源代码学习笔记(149)
来源:互联网 发布:今晚非农数据最新 编辑:程序博客网 时间:2024/05/13 03:50
5.13.1.1.3. 引用类型的转换
如果目标类型是引用类型(参见implicit_conversion的1106行),这是由【3】条文13.3.3.1.4“引用绑定”[over.ics.ref]所指定的引用绑定的情形。
1. 当一个引用类型的形参直接绑定(8.5.3)到一个实参表达式,其隐式转换序列是恒等转换,除非该实参表达式的类型是形参类型的一个派生类,这时其隐式转换序列是一个派生类到基类的转换(13.3.3.1)。[例子:
struct A {};
struct B : public A {} b;
int f(A&);
int f(B&);
int i = f(b); // Calls f(B&), an exact match, rather than
// f(A&), a conversion
—例子结束] 如果该形参直接绑定到应用在该实参表达式的一个转换函数的结果,其隐式转换序列是一个用户定义转换(13.3.3.1.2),其中的第二标准转换序列或者是一个恒等转换,或者,如果该转换函数返回该形参类型的一个派生类的实体,是派生类到基类的转换。
2. 当一个引用类型的形参不是直接绑定到一个实参表达式,其转换序列被要求根据13.3.3.1(亦即,隐式转换序列)把实参表达式转换到该引用的援引类型。在概念上,这个转换序列负责通过该实参表达式拷贝初始化一个该引用援引类型的临时对象。最顶层的cv-限定的差别被归入初始化本身,而不构成一个转换。
3. 一个标准转换序列不能形成,如果要求绑定一个非常量引用到一个右值(除了在绑定一个隐含对象参数;参见在13.3.1中对这个情形的特殊规则)。[注意:这意味着,例如,如果一个候选函数具有一个非常量引用参数(隐含对象参数以外),并且对应的实参是一个临时对象,或为了初始化这个引用要求一个临时对象(参见8.5.3)]。
4. 不过,绑定一个引用到一个特定的实参的其他限制不影响一个标准转换序列的构成。[例如:一个具有int引用参数的函数可以是一个可行候选,即便对应的实参是一个int的位域。隐式转换序列把int位域作为一个int左值处理,并查找形参的一个精确匹配。如果是通过重载解析来选择,这样这个函数的调用将是非法的,因为禁止绑定一个非常量的引用到一个位域(8.5.3)]。
5. 一个引用到一个与引用兼容,带有更多限定的表达式的绑定,会影响一个标准转换序列的等级;参考13.3.3.2及8.5.3。
940 static tree
941 reference_binding (tree rto, tree rfrom,tree expr, int flags) incall.c
942 {
943 tree conv = NULL_TREE;
944 tree to = TREE_TYPE (rto);
945 tree from = rfrom;
946 bool related_p;
947 bool compatible_p;
948 cp_lvalue_kind lvalue_p = clk_none;
949
950 if (TREE_CODE (to) == FUNCTION_TYPE&& expr && type_unknown_p (expr))
951 {
952 expr = instantiate_type(to, expr, tf_none);
953 if (expr == error_mark_node)
954 return NULL_TREE;
955 from = TREE_TYPE (expr);
956 }
5.13.1.1.3.1. 重载引用的解析
如果被援引的目标类型是一个函数或方法的类型,并且被传入的实参表达式一个重载,其类型是unknown_type_node并且使得type_unknown_p成立(它可能是一个baselink或template-id)。这也需要为该实参确定正确的候选者。
下面的函数将实例化在中rhs给定的表达式的类型,来匹配由lhstype给定的类型。
6001 tree
6002 instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) in class.c
6003 {
6004 tsubst_flags_t flags_in = flags;
6005
6006 flags &= ~tf_ptrmem_ok;
6007
6008 if (TREE_CODE (lhstype) ==UNKNOWN_TYPE)
6009 {
6010 if (flags & tf_error)
6011 error ("not enoughtype information");
6012 returnerror_mark_node;
6013 }
6014
6015 if (TREE_TYPE (rhs) !=NULL_TREE && ! (type_unknown_p (rhs)))
6016 {
6017 if (same_type_p (lhstype,TREE_TYPE (rhs)))
6018 returnrhs;
6019 if (flag_ms_extensions
6020 && TYPE_PTRMEMFUNC_P(lhstype)
6021 &&!TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
6022 /*Microsoft allows `A::f' to be resolved to a
6023 pointer-to-member. */
6024 ;
6025 else
6026 {
6027 if (flags &tf_error)
6028 error ("argumentof type `%T' does not match `%T'",
6029 TREE_TYPE (rhs),lhstype);
6030 returnerror_mark_node;
6031 }
6032 }
看到6015行的条件如果满足,rhs的类型是确实已知的,它必须与目标类型(lhstype)相同;否则不匹配的类型rhs及lhs会导致一个错误。如果rhs在TREE_TYPE中具有unknown_type_node或NULL,这表示有多个表达式适合rhs,就需要由lhs的类型来确定最后胜出者。
正如6042行的注释所提到的,在6047行开始的SWITCH块用于区分这是哪种指向函数的指针(事实上也包括引用)。
在下面6072行的NOP_EXPR,它用于表示不要求任何代码产生的转换。例如,一个‘char*’到一个‘int*’的转换不要求产生任何代码;这样的一个转换由一个NOP_EXPR来代表。其唯一的操作数是要被转换的表达式。从一个指针到一个引用的转换也是由一个NOP_EXPR来表示。如果我们来到这个分支,NOP_EXPR的TREE_TYPE必须是NULL或者unknown_type_node来显示多种选择。在剥除这个顶层的NOP_EXPR之后,需要通过设置其操作数的TREE_TYPE为unknown_type_node,来保留这个显示不确定性的信息。
instantiate_type (continue)
6034 if (TREE_CODE (rhs) ==BASELINK)
6035 rhs = BASELINK_FUNCTIONS(rhs);
6036
6037 /*We don't overwrite rhs if it is an overloaded function.
6038 Copying it would destroy the treelink. */
6039 if (TREE_CODE (rhs) !=OVERLOAD)
6040 rhs = copy_node (rhs);
6041
6042 /*This should really only be used when attempting to distinguish
6043 whatsort of a pointer to function we have. For now, any
6044 arithmetic operation which is not supportedon pointers
6045 isrejected as an error. */
6046
6047 switch(TREE_CODE (rhs))
6048 {
6049 caseTYPE_EXPR:
6050 caseCONVERT_EXPR:
6051 caseSAVE_EXPR:
6052 caseCONSTRUCTOR:
6053 caseBUFFER_REF:
6054 abort ();
6055 returnerror_mark_node;
6056
6057 caseINDIRECT_REF:
6058 caseARRAY_REF:
6059 {
6060 tree new_rhs;
6061
6062 new_rhs = instantiate_type (build_pointer_type (lhstype),
6063 TREE_OPERAND (rhs,0), flags);
6064 if (new_rhs ==error_mark_node)
6065 return error_mark_node;
6066
6067 TREE_TYPE (rhs) =lhstype;
6068 TREE_OPERAND (rhs, 0) =new_rhs;
6069 returnrhs;
6070 }
6071
6072 caseNOP_EXPR:
6073 rhs = copy_node(TREE_OPERAND (rhs, 0));
6074 TREE_TYPE (rhs) =unknown_type_node;
6075 returninstantiate_type (lhstype, rhs, flags);
6076
6077 caseCOMPONENT_REF:
6078 {
6079 tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1),flags);
6080
6081 if (addr != error_mark_node
6082 &&TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
6083 /* Do not lose object's side effects. */
6084 addr = build(COMPOUND_EXPR, TREE_TYPE (addr),
6085 TREE_OPERAND (rhs, 0),addr);
6086 returnaddr;
6087 }
6088
6089 caseOFFSET_REF:
6090 rhs = TREE_OPERAND (rhs,1);
6091 if (BASELINK_P (rhs))
6092 return instantiate_type(lhstype, BASELINK_FUNCTIONS (rhs), flags_in);
6093
6094 /*This can happen if we are forming a pointer-to-member for a
6095 member template. */
6096 my_friendly_assert(TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
6097
6098 /*Fall through. */
6099
6100 caseTEMPLATE_ID_EXPR:
6101 {
6102 tree fns = TREE_OPERAND(rhs, 0);
6103 tree args = TREE_OPERAND(rhs, 1);
6104
6105 return
6106 resolve_address_of_overloaded_function(lhstype, fns, flags_in,
6107 /*template_only=*/true,
6108 args);
6109 }
6110
6111 caseOVERLOAD:
6112 caseFUNCTION_DECL:
6113 return
6114 resolve_address_of_overloaded_function(lhstype, rhs, flags_in,
6115 /*template_only=*/false,
6116 /*explicit_targs=*/NULL_TREE);
6117
6118 caseTREE_LIST:
6119 /*Now we should have a baselink. */
6120 my_friendly_assert(BASELINK_P (rhs), 990412);
6121
6122 returninstantiate_type (lhstype, BASELINK_FUNCTIONS(rhs), flags);
6123
6124 caseCALL_EXPR:
6125 /*This is too hard for now. */
6126 abort ();
6127 returnerror_mark_node;
6128
6129 casePLUS_EXPR:
6130 caseMINUS_EXPR:
6131 caseCOMPOUND_EXPR:
6132 TREE_OPERAND (rhs, 0)
6133 = instantiate_type (lhstype, TREE_OPERAND (rhs, 0),flags);
6134 if (TREE_OPERAND (rhs,0) == error_mark_node)
6135 return error_mark_node;
6136 TREE_OPERAND (rhs, 1)
6137 = instantiate_type (lhstype, TREE_OPERAND (rhs, 1),flags);
6138 if (TREE_OPERAND (rhs,1) == error_mark_node)
6139 return error_mark_node;
6140
6141 TREE_TYPE (rhs) = lhstype;
6142 returnrhs;
6143
6144 caseMULT_EXPR:
6145 caseTRUNC_DIV_EXPR:
6146 caseFLOOR_DIV_EXPR:
6147 caseCEIL_DIV_EXPR:
6148 caseROUND_DIV_EXPR:
6149 caseRDIV_EXPR:
6150 caseTRUNC_MOD_EXPR:
6151 caseFLOOR_MOD_EXPR:
6152 caseCEIL_MOD_EXPR:
6153 caseROUND_MOD_EXPR:
6154 caseFIX_ROUND_EXPR:
6155 caseFIX_FLOOR_EXPR:
6156 caseFIX_CEIL_EXPR:
6157 caseFIX_TRUNC_EXPR:
6158 caseFLOAT_EXPR:
6159 caseNEGATE_EXPR:
6160 caseABS_EXPR:
6161 caseMAX_EXPR:
6162 caseMIN_EXPR:
6163
6164 caseBIT_AND_EXPR:
6165 caseBIT_IOR_EXPR:
6166 caseBIT_XOR_EXPR:
6167 caseLSHIFT_EXPR:
6168 caseRSHIFT_EXPR:
6169 caseLROTATE_EXPR:
6170 caseRROTATE_EXPR:
6171
6172 casePREINCREMENT_EXPR:
6173 casePREDECREMENT_EXPR:
6174 casePOSTINCREMENT_EXPR:
6175 casePOSTDECREMENT_EXPR:
6176 if (flags &tf_error)
6177 error ("invalidoperation on uninstantiated type");
6178 returnerror_mark_node;
6179
6180 caseTRUTH_AND_EXPR:
6181 caseTRUTH_OR_EXPR:
6182 caseTRUTH_XOR_EXPR:
6183 caseLT_EXPR:
6184 caseLE_EXPR:
6185 caseGT_EXPR:
6186 caseGE_EXPR:
6187 caseEQ_EXPR:
6188 caseNE_EXPR:
6189 caseTRUTH_ANDIF_EXPR:
6190 caseTRUTH_ORIF_EXPR:
6191 caseTRUTH_NOT_EXPR:
6192 if (flags &tf_error)
6193 error ("notenough type information");
6194 returnerror_mark_node;
6195
6196 caseCOND_EXPR:
6197 if (type_unknown_p(TREE_OPERAND (rhs, 0)))
6198 {
6199 if (flags &tf_error)
6200 error ("notenough type information");
6201 return error_mark_node;
6202 }
6203 TREE_OPERAND (rhs, 1)
6204 = instantiate_type (lhstype, TREE_OPERAND (rhs, 1),flags);
6205 if (TREE_OPERAND (rhs,1) == error_mark_node)
6206 return error_mark_node;
6207 TREE_OPERAND (rhs, 2)
6208 = instantiate_type (lhstype, TREE_OPERAND (rhs, 2),flags);
6209 if (TREE_OPERAND (rhs,2) == error_mark_node)
6210 return error_mark_node;
6211
6212 TREE_TYPE (rhs) =lhstype;
6213 returnrhs;
6214
6215 caseMODIFY_EXPR:
6216 TREE_OPERAND (rhs, 1)
6217 = instantiate_type (lhstype, TREE_OPERAND (rhs, 1),flags);
6218 if (TREE_OPERAND (rhs,1) == error_mark_node)
6219 return error_mark_node;
6220
6221 TREE_TYPE (rhs) =lhstype;
6222 returnrhs;
6223
6224 caseADDR_EXPR:
6225 {
6226 if (PTRMEM_OK_P (rhs))
6227 flags |= tf_ptrmem_ok;
6228
6229 returninstantiate_type (lhstype, TREE_OPERAND (rhs,0), flags);
6230 }
6231 caseENTRY_VALUE_EXPR:
6232 abort ();
6233 returnerror_mark_node;
6234
6235 caseERROR_MARK:
6236 returnerror_mark_node;
6237
6238 default:
6239 abort ();
6240 returnerror_mark_node;
6241 }
6242 }
上面的代码清楚地显示了关注的是指定类别节点哪个操作数(为表达式构建节点的函数,例如,build_binary_op,将把操作数统一到同一个类型。因此对于表达式“ptr+5”(ptr是类型“int*”),这个表达式构建函数将把‘5’提升为类型“int*”)。
如果该重载是合法的(为TEMPLATE_ID_EXPR,FUNCITON_DECL,或OVERLOAD),它需要被解析以找出匹配者;显然,多于一个的匹配会导致二义性的问题。看到下面的参数explicit_targs仅用于模板的匹配,它保存了显式给定的模板实参。
【3】,条文13.4“重载函数地址”([over.over]),给出了这个语法成分的意义和用法,连同例子。
1. 一个不带参数的重载函数名,在特定上下文中,被解析为一个函数,指向重载函数集中一个特定函数的函数的指针,或指向成员函数的指针。一个函数模板名被视为,在这样的上下文中,命名了一个重载函数集。被选中的函数,其类型与该上下文所要求的目标类型相匹配。这个目标类型可以是
— 要被初始化的一个对象或引用(8.5,8.5.3),
— 一个赋值的左手侧(5.17),
— 一个函数的一个参数(5.2.2),
— 一个用户定义操作符的一个参数(13.5),
— 一个函数,运算符函数,转换函数的返回值(6.6.3),
— 一个显式类型转换(5.2.3,5.2.9, 5.4),或者
— 一个非类型模板参数(14.3.2)。
该重载函数名之前可以是&操作符。一个重载函数名,在那些没有列出的上下文中,不能不带参数来使用。[注意:包围该重载函数名的任意多余括号对被忽略(5.1)]。
2. 如果这个名字是一个函数模板,执行模板实参推导(14.8.2.2),并且如果实参推导成功,产生的模板实参列表被用于产生一个函数模板特化,这个特化被加入这个正在关注的重载函数集中。
3. 非成员函数及静态成员函数匹配的目标类型为“函数指针”或“函数引用”。非静态成员函数匹配的目标类型是“成员函数指针”;成员指针中的函数类型用于,从重载成员函数集中,选择成员函数。如果一个非静态成员函数被选中,对该重载函数名的一个引用被要求具有一个成员指针的形式,如5.3.1中描述的那样。
4. 如果选中了多于一个函数,如果这个集包含了非模板函数,这个集中的函数模板特化都被淘汰;给定函数模板特化F1,如果在这个集中包含了第二个函数模板特化,其函数模板的特化程度,根据14.5.5.2的偏序规则,比F1的函数模板的特化程度高,淘汰F1。在这样的淘汰之后,应该只留下一个中选的函数。
5. [例子:
int f(double);
int f(int);
int (*pfd)(double) = &f; // selects f(double)
int (*pfi)(int) = &f; // selects f(int)
int (*pfe)(...) = &f; // error: type mismatch
int (&rfi)(int) = f; // selects f(int)
int (&rfd)(double) = f; // selects f(double)
void g() {
(int (*)(int))&f; // cast expression as selector
}
pfe的初始化是非法的,因为没有定义具有类型int(…)的f(),而不是因为二义性。另一个例子,
struct X {
int f(int);
static int f(long);
};
int (X::*p1)(int) = &X::f; // OK
int (*p2)(int) = &X::f; // error: mismatch
int (*p3)(long) = &X::f; // OK
int (X::*p4)(long) = &X::f; // error: mismatch
int (X::*p5)(int) = &(X::f); // error: wrong syntax for pointer to member
int (*p6)(long) = &(X::f); // OK
—例子结束]
6. [注意:如果f()及g()都是重载函数,解析f(&g),或相当的表达式f(g),必须考虑可能性的叉积(cross product)]。
7. [注意:这里没有一个函数指针到另一个函数指针的标准转换(条文4)。特别是,即使B是D的一个公有基类,我们有
D* f();
B* (*p1)() = &f; // error
void g(D*);
void (*p2)(B*) = &g; // error
—注意结束]
5723 static tree
5724 resolve_address_of_overloaded_function (tree target_type, inclass.c
5725 treeoverload,
5726 tsubst_flags_tflags,
5727 booltemplate_only,
5728 tree explicit_targs)
5729 {
5730 /*Here's what the standard says:
5731
5732 [over.over]
5733
5734 If thename is a function template, template argument deduction
5735 isdone, and if the argument deduction succeeds, the deduced
5736 arguments are used to generate a singletemplate function, which
5737 isadded to the set of overloaded functions considered.
5738
5739 Non-member functions and static memberfunctions match targets of
5740 type"pointer-to-function" or "reference-to-function." Nonstatic
5741 memberfunctions match targets of type "pointer-to-member
5742 function;" the function type of thepointer to member is used to
5743 selectthe member function from the set of overloaded member
5744 functions. If a nonstatic member functionis selected, the
5745 reference to the overloaded function nameis required to have the
5746 formof a pointer to member as described in 5.3.1.
5747
5748 Ifmore than one function is selected, any template functions in
5749 theset are eliminated if the set also contains a non-template
5750 function, and any given template functionis eliminated if the
5751 setcontains a second template function that is more specialized
5752 than the first according to the partialordering rules 14.5.5.2.
5753 Aftersuch eliminations, if any, there shall remain exactly one
5754 selected function. */
5755
5756 int is_ptrmem = 0;
5757 int is_reference = 0;
5758 /*We store the matches in a TREE_LIST rooted here. The functions
5759 arethe TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
5760 interoperability withmost_specialized_instantiation. */
5761 tree matches = NULL_TREE;
5762 tree fn;
5763
5764 /* By the time we get here, we should beseeing only real
5765 pointer-to-member types, not the internalPOINTER_TYPE to
5766 METHOD_TYPE representation. */
5767 my_friendly_assert(!(TREE_CODE (target_type) == POINTER_TYPE
5768 && (TREE_CODE(TREE_TYPE (target_type))
5769 ==METHOD_TYPE)), 0);
5770
5771 my_friendly_assert (is_overloaded_fn (overload), 20030910);
5772
5773 /*Check that the TARGET_TYPE is reasonable. */
5774 if (TYPE_PTRFN_P(target_type))
5775 /*This is OK. */;
5776 else if (TYPE_PTRMEMFUNC_P(target_type))
5777 /*This is OK, too. */
5778 is_ptrmem = 1;
5779 else if (TREE_CODE(target_type) == FUNCTION_TYPE)
5780 {
5781 /* This is OK, too.This comes from a conversion to reference
5782 type. */
5783 target_type = build_reference_type (target_type);
5784 is_reference = 1;
5785 }
5786 else
5787 {
5788 if (flags & tf_error)
5789 error ("/
5790 cannot resolveoverloaded function `%D' based on conversion to type `%T'",
5791 DECL_NAME(OVL_FUNCTION (overload)), target_type);
5792 returnerror_mark_node;
5793 }
5794
5795 /*If we can find a non-template function that matches, we can just
5796 useit. There's no point in generating template instantiations
5797 ifwe're just going to throw them out anyhow. But, of course, we
5798 canonly do this when we don't *need* a template function. */
5799 if (!template_only)
5800 {
5801 tree fns;
5802
5803 for(fns = overload; fns; fns = OVL_NEXT (fns))
5804 {
5805 tree fn = OVL_CURRENT(fns);
5806 tree fntype;
5807
5808 if (TREE_CODE (fn) ==TEMPLATE_DECL)
5809 /* We're not looking for templates just yet. */
5810 continue;
5811
5812 if ((TREE_CODE(TREE_TYPE (fn)) == METHOD_TYPE)
5813 != is_ptrmem)
5814 /* We're looking for a non-static member, and this isn't
5815 one, or vice versa. */
5816 continue;
5817
5818 /*Ignore anticipated decls of undeclared builtins. */
5819 if (DECL_ANTICIPATED(fn))
5820 continue;
5821
5822 /*See if there's a match. */
5823 fntype = TREE_TYPE (fn);
5824 if (is_ptrmem)
5825 fntype =build_ptrmemfunc_type (build_pointer_type (fntype));
5826 else if (!is_reference)
5827 fntype = build_pointer_type (fntype);
5828
5829 if (can_convert_arg (target_type, fntype, fn))
5830 matches = tree_cons(fn, NULL_TREE, matches);
5831 }
5832 }
记得重载被串接在一个以OVERLOAD节点开头的链表中,不过在这个头部之后的节点分别包含了FUNCTION_DECL节点,它在5805行由OVL_CURRENT获取。然后,在5823行的fntype将是确定的FUNCTION_TYPE,而不是unknown_type_node。因此从它构建指针类型。对于这些类型,can_convert_arg将检查该类型是否可以被隐式地转换到target_type,并且在处理这个指针转换的standard_conversion中,在619行,我们可以看到函数指针要求精确匹配,就像上面例子所显示的那样。
而在重载函数中,非模板函数优于模板函数,如果找到了非模板函数,就忽略所有的模板函数。如果我们不能找到匹配的非模板函数,那么我们就要查找匹配的模板函数,我们将进入下面5837行的IF块。
resolve_address_of_overloaded_function(continue)
5834 /*Now, if we've already got a match (or matches), there's no need
5835 toproceed to the template functions. But, if we don't have a
5836 matchwe need to look at them, too. */
5837 if (!matches)
5838 {
5839 tree target_fn_type;
5840 tree target_arg_types;
5841 tree target_ret_type;
5842 tree fns;
5843
5844 if (is_ptrmem)
5845 target_fn_type
5846 = TREE_TYPE(TYPE_PTRMEMFUNC_FN_TYPE (target_type));
5847 else
5848 target_fn_type =TREE_TYPE (target_type);
5849 target_arg_types =TYPE_ARG_TYPES (target_fn_type);
5850 target_ret_type =TREE_TYPE (target_fn_type);
5851
5852 /*Never do unification on the 'this' parameter. */
5853 if (TREE_CODE(target_fn_type) == METHOD_TYPE)
5854 target_arg_types =TREE_CHAIN (target_arg_types);
5855
5856 for(fns = overload; fns; fns = OVL_NEXT (fns))
5857 {
5858 tree fn = OVL_CURRENT(fns);
5859 tree instantiation;
5860 tree instantiation_type;
5861 tree targs;
5862
5863 if (TREE_CODE (fn) !=TEMPLATE_DECL)
5864 /* We're only looking for templates. */
5865 continue;
5866
5867 if ((TREE_CODE(TREE_TYPE (fn)) == METHOD_TYPE)
5868 != is_ptrmem)
5869 /* We're not looking for a non-static member, and this is
5870 one, or vice versa. */
5871 continue;
5872
5873 /*Try to do argument deduction. */
5874 targs = make_tree_vec(DECL_NTPARMS (fn));
5875 if (fn_type_unification (fn, explicit_targs, targs,
5876 target_arg_types,target_ret_type,
5877 DEDUCE_EXACT, -1) !=0)
5878 /* Argument deduction failed. */
5879 continue;
5880
5881 /*Instantiate the template. */
5882 instantiation =instantiate_template (fn, targs, flags);
5883 if (instantiation ==error_mark_node)
5884 /* Instantiation failed. */
5885 continue;
5886
5887 /*See if there's a match. */
5888 instantiation_type =TREE_TYPE (instantiation);
5889 if (is_ptrmem)
5890 instantiation_type =
5891 build_ptrmemfunc_type (build_pointer_type (instantiation_type));
5892 else if (!is_reference)
5893 instantiation_type = build_pointer_type (instantiation_type);
5894 if (can_convert_arg (target_type, instantiation_type,instantiation))
5895 matches = tree_cons(instantiation, fn, matches);
5896 }
5897
5898 /*Now, remove all but the most specialized of the matches. */
5899 if (matches)
5900 {
5901 tree match =most_specialized_instantiation (matches);
5902
5903 if (match !=error_mark_node)
5904 matches = tree_cons(match, NULL_TREE, NULL_TREE);
5905 }
5906 }
在前一节,我们已经看过了模板实参推导。这里我们就不麻烦再看一遍了。
resolve_address_of_overloaded_function(continue)
5908 Now we should have exactly one function inMATCHES. */
5909 if (matches == NULL_TREE)
5910 {
5911 /*There were *no* matches. */
5912 if (flags & tf_error)
5913 {
5914 error ("no matchesconverting function `%D' to type `%#T'",
5915 DECL_NAME(OVL_FUNCTION (overload)),
5916 target_type);
5917
5918 /* print_candidates expects a chain with thefunctions in
5919 TREE_VALUE slots, so we cons one uphere (we're losing anyway,
5920 sowhy be clever?). */
5921 for(; overload; overload = OVL_NEXT (overload))
5922 matches = tree_cons(NULL_TREE, OVL_CURRENT (overload),
5923 matches);
5924
5925 print_candidates(matches);
5926 }
5927 returnerror_mark_node;
5928 }
5929 else if (TREE_CHAIN(matches))
5930 {
5931 /*There were too many matches. */
5932
5933 if (flags & tf_error)
5934 {
5935 tree match;
5936
5937 error ("convertingoverloaded function `%D' to type `%#T' is ambiguous",
5938 DECL_NAME(OVL_FUNCTION (overload)),
5939 target_type);
5940
5941 /*Since print_candidates expects the functions in the
5942 TREE_VALUE slot, we flip themhere. */
5943 for(match = matches; match; match = TREE_CHAIN (match))
5944 TREE_VALUE (match) =TREE_PURPOSE (match);
5945
5946 print_candidates(matches);
5947 }
5948
5949 returnerror_mark_node;
5950 }
5951
5952 /*Good, exactly one match. Now, convert it to the correct type. */
5953 fn = TREE_PURPOSE (matches);
5954
5955 if(DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
5956 && !(flags &tf_ptrmem_ok) && !flag_ms_extensions)
5957 {
5958 staticint explained;
5959
5960 if (!(flags &tf_error))
5961 returnerror_mark_node;
5962
5963 pedwarn ("assumingpointer to member `%D'", fn);
5964 if (!explained)
5965 {
5966 pedwarn ("(apointer to member can only be formed with `&%E')", fn);
5967 explained = 1;
5968 }
5969 }
5970
5971 /*If we're doing overload resolution purely for the purpose of
5972 determining conversion sequences, we shouldnot consider the
5973 function used. If this conversion sequenceis selected, the
5974 function will be marked as used at thispoint. */
5975 if (!(flags & tf_conv))
5976 mark_used(fn);
5977
5978 if (TYPE_PTRFN_P(target_type) || TYPE_PTRMEMFUNC_P (target_type))
5979 returnbuild_unary_op (ADDR_EXPR, fn, 0);
5980 else
5981 {
5982 /*The target must be a REFERENCE_TYPE. Above, build_unary_op
5983 willmark the function as addressed, but here we must do it
5984 explicitly. */
5985 cxx_mark_addressable (fn);
5986
5987 returnfn;
5988 }
5989 }
最后,需要把合格的查找结果标记为可取址,这是对代码产生有重要意义的信息。而由该函数返回的fn是匹配的重载。并且这个返回值在952行被保存入expr。而from在955行被更新到这个类型。
- GCC-3.4.6源代码学习笔记(149)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记 (102)
- GCC-3.4.6源代码学习笔记 (103)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记 (105)
- GCC-3.4.6源代码学习笔记 (106)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(2)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(4)
- GCC-3.4.6源代码学习笔记(5)
- GCC-3.4.6源代码学习笔记(7)
- GCC-3.4.6源代码学习笔记(8)
- 简易旁注大婶器
- DataTable与Json相互转化
- Delphi与SQL模糊查询
- exploitscanner
- windowsXp系统的linux虚拟机上安装vm tools
- GCC-3.4.6源代码学习笔记(149)
- MFC编程中,应用程序界面最小化与显示之间切换时,GDI对象增加
- Studying note of GCC-3.4.6 source (149)
- Linux下将Tinyxml编译为静态库
- 基于总差变模型的图像去噪
- js的escape()函数 ASP.NET中c#的URL编码处理 万恶的IE6
- 《中国医学大成》目录
- CString类转换成char*(LPSTR)类型
- 三种故障还原模型