GCC-3.4.6源代码学习笔记(148)
2011-01-22 08:54
344 查看
5.13.1.1.2.2.
确定最优
在收集了所有的候选者后,需要挑出可行的候选者(因为收集的时候,我们只考虑了类型,没有别的),并为涉及的转换函数评估等级,以选出最优的候选。下面的代码执行这个处理。
build_user_type_conversion_1 (continue)
2478
candidates = splice_viable
(candidates, pedantic
, &any_viable_p);
2479
if (!any_viable_p)
2480
return
0;
2481
2482
cand = tourney
(candidates);
5.13.1.1.2.2.1.
挑选可行的候选者
在下面的函数中,其参数
strict_p
被传递入
pedantic
的值,它如果非
0
,就要求编译器对标准所禁止的一切给出警告。回忆如果隐式转换不能奏效,
implicit_conversion
将返回
NULL
;而对于标准所禁止的转换,将设置
ICS_BAD_FLAG
标记。
2165
static
struct
z_candidate
*
2166
splice_viable
(struct
z_candidate *cands,
in
call.c
2167
bool strict_p,
2168
bool
*any_viable_p)
2169
{
2170
struct
z_candidate *viable;
2171
struct
z_candidate **last_viable;
2172
struct
z_candidate **cand;
2173
2174
viable = NULL;
2175
last_viable = &viable;
2176
*any_viable_p = false;
2177
2178
cand = &cands;
2179
while
(*cand)
2180
{
2181
struct
z_candidate *c = *cand;
2182
if (strict_p ?
c->viable == 1 : c->viable)
2183
{
2184
*last_viable = c;
2185
*cand = c->next;
2186
c
->next
= NULL;
2187
last_viable =
&c->next;
2188
*any_viable_p = true;
2189
}
2190
else
2191
cand = &c->next;
2192
}
2193
2194
return
viable ? viable : cands;
2195
}
5.13.1.1.2.2.2.
选出最优
【
3
】的条文
13.3.3
.2
“隐式转换序列排名“给出了挑选最优候选者的规则
[over.ics.rank
]
。
而
implicit_conversion
通过,首先尝试标准转换及引用绑定,如果失败,才尝试用户定义转换,实现了规则
2
的第一部分。
5936
static
struct
z_candidate
*
5937
tourney
(struct
z_candidate *candidates)
in
call.c
5938
{
5939
struct
z_candidate *champ = candidates, *challenger;
5940
int fate;
5941
int
champ_compared_to_predecessor = 0;
5942
5943
/*
Walk through the list once, comparing each current champ to the next
5944
candidate, knocking out a candidate or two
with each comparison.
*/
5945
5946
for
(challenger = champ->next; challenger; )
5947
{
5948
fate = joust
(champ, challenger, 0);
5949
if (fate == 1)
5950
challenger =
challenger->next;
5951
else
5952
{
5953
if (fate == 0)
5954
{
5955
champ =
challenger->next;
5956
if (champ == 0)
5957
return
0;
5958
champ_compared_to_predecessor = 0;
5959
}
5960
else
5961
{
5962
champ = challenger;
5963
champ_compared_to_predecessor = 1;
5964
}
5965
5966
challenger =
champ->next;
5967
}
5968
}
5969
5970
/*
Make sure the champ is better than all the candidates it hasn't yet
5971
been
compared to.
*/
5972
5973
for
(challenger = candidates;
5974
challenger != champ
5975
&&
!(champ_compared_to_predecessor && challenger->next == champ);
5976
challenger =
challenger->next)
5977
{
5978
fate = joust
(champ, challenger, 0);
5979
if (fate != 1)
5980
return
0;
5981
}
5982
5983
return
champ;
5984
}
通过
joust
候选者被一个个比较来选出最佳者,该函数返回
1
如果
champ
是更优的,
-1
如果
challenger
是更优的,或者
0
如果具有二义性。注意到
champ
总是指向列表中的前一个候选者,而
challenger
是紧跟
champ
之后的候选者。看到在
5946
行的
FOR
循环中
champ
总是指向两个中较佳者,如果能确定的话。
在
5973
行的
FOR
循环中,如果
champ_compared_to_predecessor
为
0
,那么退出的条件变成:“
challenger != champ
”;否则就变成:“
challenger != champ && challenger->next != champ
”。注意到仅当
challenger
最后一次发现优于
champ
(因而
champ
被
challenger
更新),并之后没有出现二义性的结果时,
champ_compared_to_predecessor
可以是
1
;而这个标记
0
,仅当最后一次比较的结果是
champ
优于
chanlleger
。因此对于该标记为
1
,
champ
之前的候选者不需要比较,但当标记为
0
时需要包括之。为什么需要第二个
FOR
循环呢?首先注意到如果找到最佳候选者,最后一次的比较必然不会出现二义性,否则该函数将在
5957
行返回
0
。另外看到如果出现二义性,这两个候选者都被跳过,比较在后面的候选者中重新开始。因此有可能具有二义性的候选者要优于在第一个
FOR
循环中找到的最佳候选者,而这个情形,在第二
FOR
循环中,将被发现为一个错误,并在
5980
行返回
0
。
在上面看到,被选出的可行候选者的
viable
域是非
0
值。并记得如果该转换不为标准所允许,这个域将保存值
-1
。作为一个快速的挑选,不同的
viable
值显示谁为更优。毫无疑问,标准所允许的转换总是更优胜。
5653
static
int
5654
joust
(struct
z_candidate
*cand1, struct
z_candidate *cand2, bool warn)
in call.c
5655
{
5656
int winner = 0;
5657
int i, off1 = 0, off2 = 0,
len;
5658
5659
/* Candidates that involve bad conversions are
always worse than those
5660
that
don't.
*/
5661
if (cand1->viable >
cand2->viable)
5662
return
1;
5663
if (cand1->viable <
cand2->viable)
5664
return
-1;
5665
5666
/*
If we have two pseudo-candidates for conversions to the same type,
5667
or two
candidates for the same function, arbitrarily pick one.
*/
5668
if (cand1->fn ==
cand2->fn
5669
&& (TYPE_P
(cand1->fn) || DECL_P (cand1->fn)))
5670
return
1;
5671
5672
/*
a viable function F1
5673
is
defined to be a better function than another viable function F2 if
5674
for
all arguments i, ICSi(F1) is not a worse conversion sequence than
5675
ICSi(F2), and then */
5676
5677
/*
for some argument j, ICSj(F1) is a better conversion sequence than
5678
ICSj(F2) */
5679
5680
/*
For comparing static and non-static member functions, we ignore
5681
the
implicit object parameter of the non-static function. The
5682
standard says to pretend that the static
function has an object
5683
parm,
but that won't work with operator overloading.
*/
5684
len = TREE_VEC_LENGTH
(cand1->convs);
5685
if (len != TREE_VEC_LENGTH
(cand2->convs))
5686
{
5687
if (DECL_STATIC_FUNCTION_P
(cand1->fn)
5688
&& !
DECL_STATIC_FUNCTION_P (cand2->fn))
5689
off2 = 1;
5690
else if (!
DECL_STATIC_FUNCTION_P (cand1->fn)
5691
&&
DECL_STATIC_FUNCTION_P (cand2->fn))
5692
{
5693
off1 = 1;
5694
--len;
5695
}
5696
else
5697
abort ();
5698
}
5699
5700
for
(i = 0; i < len; ++i)
5701
{
5702
tree t1 = TREE_VEC_ELT
(cand1->convs, i+off1);
5703
tree t2 = TREE_VEC_ELT
(cand2->convs, i+off2);
5704
int comp =
compare_ics
(t1, t2);
5705
5706
if (comp != 0)
5707
{
5708
if (warn_sign_promo
5709
&& ICS_RANK
(t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
5710
&& TREE_CODE (t1) ==
STD_CONV
5711
&& TREE_CODE (t2) ==
STD_CONV
5712
&& TREE_CODE
(TREE_TYPE (t1)) == INTEGER_TYPE
5713
&& TREE_CODE
(TREE_TYPE (t2)) == INTEGER_TYPE
5714
&& (TYPE_PRECISION
(TREE_TYPE (t1))
5715
== TYPE_PRECISION
(TREE_TYPE (t2)))
5716
&& (TREE_UNSIGNED
(TREE_TYPE (TREE_OPERAND (t1, 0)))
5717
|| (TREE_CODE
(TREE_TYPE (TREE_OPERAND (t1, 0)))
5718
==
ENUMERAL_TYPE)))
5719
{
5720
tree type = TREE_TYPE
(TREE_OPERAND (t1, 0));
5721
tree type1, type2;
5722
struct
z_candidate *w, *l;
5723
if (comp > 0)
5724
type1 = TREE_TYPE
(t1), type2 = TREE_TYPE (t2),
5725
w = cand1, l =
cand2;
5726
else
5727
type1 = TREE_TYPE
(t2), type2 = TREE_TYPE (t1),
5728
w = cand2, l = cand1;
5729
5730
if (warn)
5731
{
5732
warning
("passing `%T' chooses `%T' over `%T'",
5733
type,
type1, type2);
5734
warning ("
in call to `%D'", w->fn);
5735
}
5736
else
5737
add_warning (w, l);
5738
}
5739
5740
if (winner &&
comp != winner)
5741
{
5742
winner = 0;
5743
goto
tweak;
5744
}
5745
winner = comp;
5746
}
5747
}
候选者中有可能同时包括了静态转换函数及非静态转换函数。如果相比较的候选者在一者是静态的,另一者不是;就需要在比较过程中忽略隐含的‘
this
’指针。因此在
5702
及
5703
行的
t1
及
t2
拷贝出需要的参数,并传递给如下的函数。
5293
static
int
5294
compare_ics
(tree ics1, tree ics2)
in
call.c
5295
{
5296
tree from_type1;
5297
tree from_type2;
5298
tree to_type1;
5299
tree to_type2;
5300
tree deref_from_type1 =
NULL_TREE;
5301
tree deref_from_type2 =
NULL_TREE;
5302
tree deref_to_type1 =
NULL_TREE;
5303
tree deref_to_type2 =
NULL_TREE;
5304
int rank1, rank2;
5305
5306
/*
REF_BINDING is nonzero if the result of the conversion sequence
5307
is a
reference type. In that case TARGET_TYPE is the
5308
type
referred to by the reference.
*/
5309
tree target_type1;
5310
tree target_type2;
5311
5312
/*
Handle implicit object parameters.
*/
5313
maybe_handle_implicit_object
(&ics1);
5314
maybe_handle_implicit_object
(&ics2);
5315
5316
/*
Handle reference parameters.
*/
5317
target_type1 =
maybe_handle_ref_bind
(&ics1);
5318
target_type2 =
maybe_handle_ref_bind (&ics2);
5319
5320
/*
[over.ics.rank]
5321
5322
When
comparing the basic forms of implicit conversion sequences (as
5323
defined in _over.best.ics_)
5324
5325
--a
standard conversion sequence (_over.ics.scs_) is a better
5326
conversion sequence than a user-defined
conversion sequence
5327
or an
ellipsis conversion sequence, and
5328
5329
--a
user-defined conversion sequence (_over.ics.user_) is a
5330
better conversion sequence than an
ellipsis conversion sequence
5331
(_over.ics.ellipsis_).
*/
5332
rank1 = ICS_RANK
(ics1);
5333
rank2 = ICS_RANK (ics2);
下面在
5258
行的注释来自【
3
】条文
13.3.1
“候选函数及实参列表”,条款
4
。它解释到现在需要把‘
this
’指针转换为相匹配
cv-
限定的引用。
5253
static
void
5254
maybe_handle_implicit_object
(tree *ics)
in
call.c
5255
{
5256
if (ICS_THIS_FLAG (*ics))
5257
{
5258
/*
[over.match.funcs]
5259
5260
For
non-static member functions, the type of the
5261
implicit object parameter is
"reference to cv X"
5262
where X is the class of which the
function is a
5263
member and cv is the cv-qualification on
the member
5264
function declaration.
*/
5265
tree t = *ics;
5266
tree reference_type;
5267
5268
/*
The `this' parameter is a pointer to a class type. Make the
5269
implicit conversion talk about a
reference to that same class
5270
type.
*/
5271
reference_type = TREE_TYPE
(TREE_TYPE (*ics));
5272
reference_type = build_reference_type
(reference_type);
5273
5274
if (TREE_CODE (t) ==
QUAL_CONV)
5275
t = TREE_OPERAND (t, 0);
5276
if (TREE_CODE (t) ==
PTR_CONV)
5277
t = TREE_OPERAND (t, 0);
5278
t = build1
(IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
5279
t = direct_reference_binding
(reference_type,
t);
5280
*ics = t;
5281
}
5282
}
既然我们知道的具体的引用类型,就可以直接构建这个转换序列。这个需要增加的转换序列应该仅是
REF_BIND
。注意上面
5274
到
5277
行的代码,看到在
standard_conversion
的
603
行,
PTR_CONV
总是构建在
QUAL_CONV
中,如果它们都出现。
895
static
tree
896
direct_reference_binding
(tree type,
tree conv)
in
call.c
897
{
898
tree t;
899
900
my_friendly_assert (TREE_CODE (type) ==
REFERENCE_TYPE, 20030306);
901
my_friendly_assert (TREE_CODE (TREE_TYPE
(conv)) != REFERENCE_TYPE,
902
20030306);
903
904
t = TREE_TYPE (type);
905
906
/* [over.ics.rank]
907
908
When a parameter
of reference type binds directly
909
(_dcl.init.ref_)
to an argument expression, the implicit
910
conversion
sequence is the identity conversion, unless the
911
argument
expression has a type that is a derived class of the
912
parameter type,
in which case the implicit conversion sequence is
913
a derived-to-base Conversion.
914
915
If the parameter
binds directly to the result of applying a
916
conversion
function to the argument expression, the implicit
917
conversion
sequence is a user-defined conversion sequence
918
(_over.ics.user_), with the second standard conversion sequence
919
either an
identity conversion or, if the conversion function
920
returns an entity
of a type that is a derived class of the
921
parameter type, a
derived-to-base conversion.
*/
922
if
(!same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (conv)))
923
{
924
/* Represent the
derived-to-base conversion.
*/
925
conv = build_conv
(BASE_CONV, t, conv);
926
/* We will
actually be binding to the base-class subobject in
927
the derived
class, so we mark this conversion appropriately.
928
That way,
convert_like knows not to generate a temporary.
*/
929
NEED_TEMPORARY_P (conv) = 0;
930
}
931
return
build_conv
(REF_BIND, type, conv);
932
}
那么在上面的
5317
行,
maybe_handle_ref_bind
获取了转换的余下部分,并返回由
REF_BIND
所得引用的援引的类型。
5270
static
tree
5271
maybe_handle_ref_bind
(tree *ics)
in
call.c
5272
{
5273
if (TREE_CODE (*ics) == REF_BIND)
5274
{
5275
tree old_ics = *ics;
5276
tree type = TREE_TYPE
(TREE_TYPE (old_ics));
5277
*ics = TREE_OPERAND
(old_ics, 0);
5278
ICS_USER_FLAG (*ics) =
ICS_USER_FLAG (old_ics);
5279
ICS_BAD_FLAG (*ics) =
ICS_BAD_FLAG (old_ics);
5280
return
type;
5281
}
5282
5283
return
NULL_TREE;
5284
}
ICS_RANK
被定义为如下。前面我们看到
C++
标准为标准转换定义了内部的等级,这个等级就保存在
ICS_STD_RANK
中,而标准转换之外的转换都只有唯一的等级。
352
#define
ICS_RANK
(NODE)
/
in
call.c
353
(ICS_BAD_FLAG
(NODE) ? BAD_RANK
/
354
:
ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK
/
355
:
ICS_USER_FLAG (NODE) ?
USER_RANK
/
356
: ICS_STD_RANK (NODE))
如果我们可以来到这里,
BAD_RANK
表示该转换不为标准所允许,但作为扩展还是
OK
的。
compare_ics (continue)
5335
if (rank1 > rank2)
5336
return
-1;
5337
else if (rank1 < rank2)
5338
return
1;
5339
5340
if (rank1 == BAD_RANK)
5341
{
5342
/*
XXX Isn't this an extension? */
5343
/*
Both ICS are bad. We try to make a decision based on what
5344
would have happened if they'd been
good.
*/
5345
if (ICS_USER_FLAG (ics1)
> ICS_USER_FLAG (ics2)
5346
|| ICS_STD_RANK (ics1)
> ICS_STD_RANK (ics2))
5347
return
-1;
5348
else if (ICS_USER_FLAG
(ics1) < ICS_USER_FLAG (ics2)
5349
|| ICS_STD_RANK
(ics1) < ICS_STD_RANK (ics2))
5350
return
1;
5351
5352
/*
We couldn't make up our minds; try to figure it out below.
*/
5353
}
5354
5355
if (ICS_ELLIPSIS_FLAG
(ics1))
5356
/*
Both conversions are ellipsis conversions.
*/
5357
return
0;
5358
5359
/*
User-defined conversion sequence U1 is a better conversion sequence
5360
than
another user-defined conversion sequence U2 if they contain the
5361
same
user-defined conversion operator or constructor and if the sec-
5362
ond
standard conversion sequence of U1 is better than the second
5363
standard conversion sequence of U2.
*/
5364
5365
if (ICS_USER_FLAG (ics1))
5366
{
5367
tree t1, t2;
5368
5369
for
(t1 = ics1; TREE_CODE (t1) !=
USER_CONV; t1 =
TREE_OPERAND (t1, 0))
5370
if (TREE_CODE (t1) == AMBIG_CONV)
5371
return
0;
5372
for
(t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
5373
if (TREE_CODE (t2) ==
AMBIG_CONV)
5374
return
0;
5375
5376
if (USER_CONV_FN (t1) !=
USER_CONV_FN (t2))
5377
return
0;
5378
5379
/*
We can just fall through here, after setting up
5380
FROM_TYPE1 and FROM_TYPE2.
*/
5381
from_type1 = TREE_TYPE
(t1);
5382
from_type2 = TREE_TYPE
(t2);
5383
}
5384
else
5385
{
5386
/*
We're dealing with two standard conversion sequences.
5387
5388
[over.ics.rank]
5389
5390
Standard conversion sequence S1 is a
better conversion
5391
sequence than standard conversion
sequence S2 if
5392
5393
--S1
is a proper subsequence of S2 (comparing the conversion
5394
sequences in the canonical form defined
by _over.ics.scs_,
5395
excluding any Lvalue Transformation; the
identity
5396
conversion sequence is considered to be
a subsequence of
5397
any
non-identity conversion sequence */
5398
5399
from_type1 = ics1;
5400
while
(TREE_CODE (from_type1) != IDENTITY_CONV)
5401
from_type1 =
TREE_OPERAND (from_type1, 0);
5402
from_type1 = TREE_TYPE
(from_type1);
5403
5404
from_type2 = ics2;
5405
while
(TREE_CODE (from_type2) != IDENTITY_CONV)
5406
from_type2 =
TREE_OPERAND (from_type2, 0);
5407
from_type2 = TREE_TYPE
(from_type2);
5408
}
上面在
5365
行,如果满足条件,表示该序列包含了用户定义转换,而在那一点上,
ics1
与
ics2
具有相同的等级,因此它们要么同时包含用户定义转换,要么都不包含。在
5376
行的
USER_CONV_FN
保存了为这个
USER_CONV
所找出的转换函数。如果这两个候选的参数所使用的用户定义转换不相同,它们是包括区分的(等级上)。
而对于标准转换序列,【
3
】的条文
13.3.3
.1.1
,条款
2
,强调以规范的次序应用转换,依次为:左值转型(
Lvalue
Transformation
),提升(
Promotion
)或转换(
Conversion
),限定调整(
Qualifier
Adjustment
);回到
standard_conversion
,看到它确实会产生这个序列,但次序相反。
compare_ics (continue)
5410
if (same_type_p (from_type1,
from_type2))
5411
{
5412
if (is_subseq
(ics1, ics2))
5413
return
1;
5414
if (is_subseq (ics2,
ics1))
5415
return
-1;
5416
}
进一步的,【
3
】的条文
13.3.3
.2
,条款
3
(
5386
行的注释),在等级评估过程中,左值转型应该被排除;在前端中,这对应着
LVALUE_CONV
及
RVALUE_CONV
。因此
is_subseq
根据标准,如果
ics1
是
ics2
的一个正确子序列,就返回
true
。
5177
static
bool
5178
is_subseq
(tree ics1, tree ics2)
in
call.c
5179
{
5180
/*
We can assume that a conversion of the same code
5181
between the same types indicates a
subsequence since we only get
5182
here
if the types we are converting from are the same.
*/
5183
5184
while
(TREE_CODE (ics1) == RVALUE_CONV
5185
|| TREE_CODE (ics1) ==
LVALUE_CONV)
5186
ics1 = TREE_OPERAND (ics1,
0);
5187
5188
while
(1)
5189
{
5190
while
(TREE_CODE (ics2) == RVALUE_CONV
5191
|| TREE_CODE (ics2)
== LVALUE_CONV)
5192
ics2 = TREE_OPERAND
(ics2, 0);
5193
5194
if (TREE_CODE (ics2) ==
USER_CONV
5195
|| TREE_CODE (ics2) ==
AMBIG_CONV
5196
|| TREE_CODE (ics2) ==
IDENTITY_CONV)
5197
/*
At this point, ICS1 cannot be a proper subsequence of
5198
ICS2. We can get a USER_CONV when we
are comparing the
5199
second standard conversion sequence of
two user conversion
5200
sequences.
*/
5201
return
false;
5202
5203
ics2 = TREE_OPERAND (ics2,
0);
5204
5205
if (TREE_CODE (ics2) ==
TREE_CODE (ics1)
5206
&& same_type_p
(TREE_TYPE (ics2), TREE_TYPE (ics1))
5207
&& same_type_p (TREE_TYPE
(TREE_OPERAND (ics2, 0)),
5208
TREE_TYPE (TREE_OPERAND
(ics1, 0))))
5209
return
true;
5210
}
5211
}
确定最优
在收集了所有的候选者后,需要挑出可行的候选者(因为收集的时候,我们只考虑了类型,没有别的),并为涉及的转换函数评估等级,以选出最优的候选。下面的代码执行这个处理。
build_user_type_conversion_1 (continue)
2478
candidates = splice_viable
(candidates, pedantic
, &any_viable_p);
2479
if (!any_viable_p)
2480
return
0;
2481
2482
cand = tourney
(candidates);
5.13.1.1.2.2.1.
挑选可行的候选者
在下面的函数中,其参数
strict_p
被传递入
pedantic
的值,它如果非
0
,就要求编译器对标准所禁止的一切给出警告。回忆如果隐式转换不能奏效,
implicit_conversion
将返回
NULL
;而对于标准所禁止的转换,将设置
ICS_BAD_FLAG
标记。
2165
static
struct
z_candidate
*
2166
splice_viable
(struct
z_candidate *cands,
in
call.c
2167
bool strict_p,
2168
bool
*any_viable_p)
2169
{
2170
struct
z_candidate *viable;
2171
struct
z_candidate **last_viable;
2172
struct
z_candidate **cand;
2173
2174
viable = NULL;
2175
last_viable = &viable;
2176
*any_viable_p = false;
2177
2178
cand = &cands;
2179
while
(*cand)
2180
{
2181
struct
z_candidate *c = *cand;
2182
if (strict_p ?
c->viable == 1 : c->viable)
2183
{
2184
*last_viable = c;
2185
*cand = c->next;
2186
c
->next
= NULL;
2187
last_viable =
&c->next;
2188
*any_viable_p = true;
2189
}
2190
else
2191
cand = &c->next;
2192
}
2193
2194
return
viable ? viable : cands;
2195
}
5.13.1.1.2.2.2.
选出最优
【
3
】的条文
13.3.3
.2
“隐式转换序列排名“给出了挑选最优候选者的规则
[over.ics.rank
]
。
而
implicit_conversion
通过,首先尝试标准转换及引用绑定,如果失败,才尝试用户定义转换,实现了规则
2
的第一部分。
1. 13.3 .3.2 基于更好的转换序列与更好的转换之间的关系,定义了隐式转换序列的一个偏序( partial ordering )。如果一个隐式转换序列 S1 被这些规则定义为比 S2 更好的转换序列,那么同时 S2 亦是比 S1 更差的转换序列。如果转换序列 S1 不比转换序列 S2 好,也不比它差,就说 S1 与 S2 是不可区分( indistinguishable )的转换序列。 2. 当比较隐式转换序列的基本形式(如 13.3.3 .1 所定义)时 — 一个标准转换序列( 13.3.3 .1.1 )是比一个用户定义转换序列或一个省略转换序列更好的转换序列,而 — 一个用户定义转换序列( 13.3.3 .1.2 )是比一个省略转换序列( 13.3.3.1.3 )更优的转换序列。 3. 两个具有相同形式的隐式转换序列是不可区分的转换序列,除非适用下面其中任一规则: — 标准转换序列 S1 是比标准转换序列 S2 更好的转换序列,如果 — S1 是 S2 的一个正确的子序列(比较 13.3.3 .1.1 所定义的规范形式的转换序列,不包括任意左值转型( Lvalue Transformation );恒等转换序列被认为是任意非恒等转换序列的一个子序列);否则, — S1 的等级比 S2 的等级高,或 S1 及 S2 具有相同的等级,并且根据下面段落的规则是不可区分的;否则, — S1 与 S2 仅是它们的限定转换不同,并且分别产生相似的类型 T1 及 T2 ( 4.4 ),而类型 T1 的 cv- 限定是类型 T2 的 cv- 限定的一个正确子集,并且 S1 不是不推荐的字符串数组到指针的转换( 4.2 )。 [ 例子: int f(const int *); int f(int *); int i; int j = f(&i); // Calls f(int *) — 例子结束 ] ;否则, — S1 及 S2 都是引用绑定( 8.5.3 ),并且除了最顶层的 cv- 限定词,这些引用的类型都相同,并且由 S2 的援引所初始化的引用的类型,比由 S1 的援引所初始化的引用的类型,具有更多的 cv- 限定。 [ 例如: int f(const int &); int f(int &); int g(const int &); int g(int); int i; int j = f(i); // Calls f(int &) int k = g(i); // ambiguous class X { public : void f() const ; void f(); }; void g(const X& a, X b) { a.f(); //Calls X::f() const b.f(); //Calls X::f() } — 例子结束 ] — 用户定义转换序列 U1 是比另一个用户定义转换序列更好的转换序列,如果它们包含了相同的用户定义转换函数或构造函数,并且如果 U1 的第二标准转换序列优于 U2 的第二标准转换序列。 [ 例如: struct A { operator short(); } a; int f(int); int f(float); int i = f(a); // Calls f(int), because short → int is better than short → float. — 例子结束 ] 4. 标准转换序列根据它们的等级排序:一个精确匹配( Exact Match )优于提升( Promotion ),提升优于转换。两个具有相同等级的转换序列是不可区分,除非适用以下任一规则: — 一个不是指针转换,或成员指针转换,或布尔转换的转换要优于这些转换。 — 如果类 B 从类 A 直接或间接派生, B* 到 A* 的转换优于 B* 到 void* 的转换, A* 到 void* 的转换优于 B* 到 void* 的转换。 — 如果类 B 从类 A 直接或间接派生,而类 C 从 B 直接或间接派生, C* 到 B* 的转换优于 C* 到 A* 的转换, [ 例如: struct A {}; struct B : public A {}; struct C : public B {}; C *pc; int f(A *); int f(B *); int i = f(pc); // Calls f(B *) — 例子结束 ] — 绑定一个具有类型 C 的表达式到一个具有类型“ B& ”的引用,要优于绑定一个具有类型 C 的表达式到一个具有类型“ A& ”的引用, — A::* 到 B::* 的转换优于 A::* 到 C::* 的转换, — C 到 B 的转换优于 C 到 A 的转换, — B* 到 A* 的转换优于 C* 到 A* 的转换, — 绑定一个具有类型 B 的表达式到一个具有类型“ A& ”的引用,要优于绑定一个具有类型 C 的表达式到一个具有类型“ A& ”的引用, — B::* 到 C::* 的转换优于 A::* 到 C::* 的转换,并且 — B 到 A 的转换优于 C 到 A 的转换。 [ 注意:仅在比较一个自用户定义的初始化转换的第二标准转换序列的上下文中,被比较的转换序列将具有不同的源类型(参见 see 13.3.3 );在其他上下文中,源类型必须是相同,而目标类型不同 ] 。 |
static
struct
z_candidate
*
5937
tourney
(struct
z_candidate *candidates)
in
call.c
5938
{
5939
struct
z_candidate *champ = candidates, *challenger;
5940
int fate;
5941
int
champ_compared_to_predecessor = 0;
5942
5943
/*
Walk through the list once, comparing each current champ to the next
5944
candidate, knocking out a candidate or two
with each comparison.
*/
5945
5946
for
(challenger = champ->next; challenger; )
5947
{
5948
fate = joust
(champ, challenger, 0);
5949
if (fate == 1)
5950
challenger =
challenger->next;
5951
else
5952
{
5953
if (fate == 0)
5954
{
5955
champ =
challenger->next;
5956
if (champ == 0)
5957
return
0;
5958
champ_compared_to_predecessor = 0;
5959
}
5960
else
5961
{
5962
champ = challenger;
5963
champ_compared_to_predecessor = 1;
5964
}
5965
5966
challenger =
champ->next;
5967
}
5968
}
5969
5970
/*
Make sure the champ is better than all the candidates it hasn't yet
5971
been
compared to.
*/
5972
5973
for
(challenger = candidates;
5974
challenger != champ
5975
&&
!(champ_compared_to_predecessor && challenger->next == champ);
5976
challenger =
challenger->next)
5977
{
5978
fate = joust
(champ, challenger, 0);
5979
if (fate != 1)
5980
return
0;
5981
}
5982
5983
return
champ;
5984
}
通过
joust
候选者被一个个比较来选出最佳者,该函数返回
1
如果
champ
是更优的,
-1
如果
challenger
是更优的,或者
0
如果具有二义性。注意到
champ
总是指向列表中的前一个候选者,而
challenger
是紧跟
champ
之后的候选者。看到在
5946
行的
FOR
循环中
champ
总是指向两个中较佳者,如果能确定的话。
在
5973
行的
FOR
循环中,如果
champ_compared_to_predecessor
为
0
,那么退出的条件变成:“
challenger != champ
”;否则就变成:“
challenger != champ && challenger->next != champ
”。注意到仅当
challenger
最后一次发现优于
champ
(因而
champ
被
challenger
更新),并之后没有出现二义性的结果时,
champ_compared_to_predecessor
可以是
1
;而这个标记
0
,仅当最后一次比较的结果是
champ
优于
chanlleger
。因此对于该标记为
1
,
champ
之前的候选者不需要比较,但当标记为
0
时需要包括之。为什么需要第二个
FOR
循环呢?首先注意到如果找到最佳候选者,最后一次的比较必然不会出现二义性,否则该函数将在
5957
行返回
0
。另外看到如果出现二义性,这两个候选者都被跳过,比较在后面的候选者中重新开始。因此有可能具有二义性的候选者要优于在第一个
FOR
循环中找到的最佳候选者,而这个情形,在第二
FOR
循环中,将被发现为一个错误,并在
5980
行返回
0
。
在上面看到,被选出的可行候选者的
viable
域是非
0
值。并记得如果该转换不为标准所允许,这个域将保存值
-1
。作为一个快速的挑选,不同的
viable
值显示谁为更优。毫无疑问,标准所允许的转换总是更优胜。
5653
static
int
5654
joust
(struct
z_candidate
*cand1, struct
z_candidate *cand2, bool warn)
in call.c
5655
{
5656
int winner = 0;
5657
int i, off1 = 0, off2 = 0,
len;
5658
5659
/* Candidates that involve bad conversions are
always worse than those
5660
that
don't.
*/
5661
if (cand1->viable >
cand2->viable)
5662
return
1;
5663
if (cand1->viable <
cand2->viable)
5664
return
-1;
5665
5666
/*
If we have two pseudo-candidates for conversions to the same type,
5667
or two
candidates for the same function, arbitrarily pick one.
*/
5668
if (cand1->fn ==
cand2->fn
5669
&& (TYPE_P
(cand1->fn) || DECL_P (cand1->fn)))
5670
return
1;
5671
5672
/*
a viable function F1
5673
is
defined to be a better function than another viable function F2 if
5674
for
all arguments i, ICSi(F1) is not a worse conversion sequence than
5675
ICSi(F2), and then */
5676
5677
/*
for some argument j, ICSj(F1) is a better conversion sequence than
5678
ICSj(F2) */
5679
5680
/*
For comparing static and non-static member functions, we ignore
5681
the
implicit object parameter of the non-static function. The
5682
standard says to pretend that the static
function has an object
5683
parm,
but that won't work with operator overloading.
*/
5684
len = TREE_VEC_LENGTH
(cand1->convs);
5685
if (len != TREE_VEC_LENGTH
(cand2->convs))
5686
{
5687
if (DECL_STATIC_FUNCTION_P
(cand1->fn)
5688
&& !
DECL_STATIC_FUNCTION_P (cand2->fn))
5689
off2 = 1;
5690
else if (!
DECL_STATIC_FUNCTION_P (cand1->fn)
5691
&&
DECL_STATIC_FUNCTION_P (cand2->fn))
5692
{
5693
off1 = 1;
5694
--len;
5695
}
5696
else
5697
abort ();
5698
}
5699
5700
for
(i = 0; i < len; ++i)
5701
{
5702
tree t1 = TREE_VEC_ELT
(cand1->convs, i+off1);
5703
tree t2 = TREE_VEC_ELT
(cand2->convs, i+off2);
5704
int comp =
compare_ics
(t1, t2);
5705
5706
if (comp != 0)
5707
{
5708
if (warn_sign_promo
5709
&& ICS_RANK
(t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
5710
&& TREE_CODE (t1) ==
STD_CONV
5711
&& TREE_CODE (t2) ==
STD_CONV
5712
&& TREE_CODE
(TREE_TYPE (t1)) == INTEGER_TYPE
5713
&& TREE_CODE
(TREE_TYPE (t2)) == INTEGER_TYPE
5714
&& (TYPE_PRECISION
(TREE_TYPE (t1))
5715
== TYPE_PRECISION
(TREE_TYPE (t2)))
5716
&& (TREE_UNSIGNED
(TREE_TYPE (TREE_OPERAND (t1, 0)))
5717
|| (TREE_CODE
(TREE_TYPE (TREE_OPERAND (t1, 0)))
5718
==
ENUMERAL_TYPE)))
5719
{
5720
tree type = TREE_TYPE
(TREE_OPERAND (t1, 0));
5721
tree type1, type2;
5722
struct
z_candidate *w, *l;
5723
if (comp > 0)
5724
type1 = TREE_TYPE
(t1), type2 = TREE_TYPE (t2),
5725
w = cand1, l =
cand2;
5726
else
5727
type1 = TREE_TYPE
(t2), type2 = TREE_TYPE (t1),
5728
w = cand2, l = cand1;
5729
5730
if (warn)
5731
{
5732
warning
("passing `%T' chooses `%T' over `%T'",
5733
type,
type1, type2);
5734
warning ("
in call to `%D'", w->fn);
5735
}
5736
else
5737
add_warning (w, l);
5738
}
5739
5740
if (winner &&
comp != winner)
5741
{
5742
winner = 0;
5743
goto
tweak;
5744
}
5745
winner = comp;
5746
}
5747
}
候选者中有可能同时包括了静态转换函数及非静态转换函数。如果相比较的候选者在一者是静态的,另一者不是;就需要在比较过程中忽略隐含的‘
this
’指针。因此在
5702
及
5703
行的
t1
及
t2
拷贝出需要的参数,并传递给如下的函数。
5293
static
int
5294
compare_ics
(tree ics1, tree ics2)
in
call.c
5295
{
5296
tree from_type1;
5297
tree from_type2;
5298
tree to_type1;
5299
tree to_type2;
5300
tree deref_from_type1 =
NULL_TREE;
5301
tree deref_from_type2 =
NULL_TREE;
5302
tree deref_to_type1 =
NULL_TREE;
5303
tree deref_to_type2 =
NULL_TREE;
5304
int rank1, rank2;
5305
5306
/*
REF_BINDING is nonzero if the result of the conversion sequence
5307
is a
reference type. In that case TARGET_TYPE is the
5308
type
referred to by the reference.
*/
5309
tree target_type1;
5310
tree target_type2;
5311
5312
/*
Handle implicit object parameters.
*/
5313
maybe_handle_implicit_object
(&ics1);
5314
maybe_handle_implicit_object
(&ics2);
5315
5316
/*
Handle reference parameters.
*/
5317
target_type1 =
maybe_handle_ref_bind
(&ics1);
5318
target_type2 =
maybe_handle_ref_bind (&ics2);
5319
5320
/*
[over.ics.rank]
5321
5322
When
comparing the basic forms of implicit conversion sequences (as
5323
defined in _over.best.ics_)
5324
5325
--a
standard conversion sequence (_over.ics.scs_) is a better
5326
conversion sequence than a user-defined
conversion sequence
5327
or an
ellipsis conversion sequence, and
5328
5329
--a
user-defined conversion sequence (_over.ics.user_) is a
5330
better conversion sequence than an
ellipsis conversion sequence
5331
(_over.ics.ellipsis_).
*/
5332
rank1 = ICS_RANK
(ics1);
5333
rank2 = ICS_RANK (ics2);
下面在
5258
行的注释来自【
3
】条文
13.3.1
“候选函数及实参列表”,条款
4
。它解释到现在需要把‘
this
’指针转换为相匹配
cv-
限定的引用。
5253
static
void
5254
maybe_handle_implicit_object
(tree *ics)
in
call.c
5255
{
5256
if (ICS_THIS_FLAG (*ics))
5257
{
5258
/*
[over.match.funcs]
5259
5260
For
non-static member functions, the type of the
5261
implicit object parameter is
"reference to cv X"
5262
where X is the class of which the
function is a
5263
member and cv is the cv-qualification on
the member
5264
function declaration.
*/
5265
tree t = *ics;
5266
tree reference_type;
5267
5268
/*
The `this' parameter is a pointer to a class type. Make the
5269
implicit conversion talk about a
reference to that same class
5270
type.
*/
5271
reference_type = TREE_TYPE
(TREE_TYPE (*ics));
5272
reference_type = build_reference_type
(reference_type);
5273
5274
if (TREE_CODE (t) ==
QUAL_CONV)
5275
t = TREE_OPERAND (t, 0);
5276
if (TREE_CODE (t) ==
PTR_CONV)
5277
t = TREE_OPERAND (t, 0);
5278
t = build1
(IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
5279
t = direct_reference_binding
(reference_type,
t);
5280
*ics = t;
5281
}
5282
}
既然我们知道的具体的引用类型,就可以直接构建这个转换序列。这个需要增加的转换序列应该仅是
REF_BIND
。注意上面
5274
到
5277
行的代码,看到在
standard_conversion
的
603
行,
PTR_CONV
总是构建在
QUAL_CONV
中,如果它们都出现。
895
static
tree
896
direct_reference_binding
(tree type,
tree conv)
in
call.c
897
{
898
tree t;
899
900
my_friendly_assert (TREE_CODE (type) ==
REFERENCE_TYPE, 20030306);
901
my_friendly_assert (TREE_CODE (TREE_TYPE
(conv)) != REFERENCE_TYPE,
902
20030306);
903
904
t = TREE_TYPE (type);
905
906
/* [over.ics.rank]
907
908
When a parameter
of reference type binds directly
909
(_dcl.init.ref_)
to an argument expression, the implicit
910
conversion
sequence is the identity conversion, unless the
911
argument
expression has a type that is a derived class of the
912
parameter type,
in which case the implicit conversion sequence is
913
a derived-to-base Conversion.
914
915
If the parameter
binds directly to the result of applying a
916
conversion
function to the argument expression, the implicit
917
conversion
sequence is a user-defined conversion sequence
918
(_over.ics.user_), with the second standard conversion sequence
919
either an
identity conversion or, if the conversion function
920
returns an entity
of a type that is a derived class of the
921
parameter type, a
derived-to-base conversion.
*/
922
if
(!same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (conv)))
923
{
924
/* Represent the
derived-to-base conversion.
*/
925
conv = build_conv
(BASE_CONV, t, conv);
926
/* We will
actually be binding to the base-class subobject in
927
the derived
class, so we mark this conversion appropriately.
928
That way,
convert_like knows not to generate a temporary.
*/
929
NEED_TEMPORARY_P (conv) = 0;
930
}
931
return
build_conv
(REF_BIND, type, conv);
932
}
那么在上面的
5317
行,
maybe_handle_ref_bind
获取了转换的余下部分,并返回由
REF_BIND
所得引用的援引的类型。
5270
static
tree
5271
maybe_handle_ref_bind
(tree *ics)
in
call.c
5272
{
5273
if (TREE_CODE (*ics) == REF_BIND)
5274
{
5275
tree old_ics = *ics;
5276
tree type = TREE_TYPE
(TREE_TYPE (old_ics));
5277
*ics = TREE_OPERAND
(old_ics, 0);
5278
ICS_USER_FLAG (*ics) =
ICS_USER_FLAG (old_ics);
5279
ICS_BAD_FLAG (*ics) =
ICS_BAD_FLAG (old_ics);
5280
return
type;
5281
}
5282
5283
return
NULL_TREE;
5284
}
ICS_RANK
被定义为如下。前面我们看到
C++
标准为标准转换定义了内部的等级,这个等级就保存在
ICS_STD_RANK
中,而标准转换之外的转换都只有唯一的等级。
352
#define
ICS_RANK
(NODE)
/
in
call.c
353
(ICS_BAD_FLAG
(NODE) ? BAD_RANK
/
354
:
ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK
/
355
:
ICS_USER_FLAG (NODE) ?
USER_RANK
/
356
: ICS_STD_RANK (NODE))
如果我们可以来到这里,
BAD_RANK
表示该转换不为标准所允许,但作为扩展还是
OK
的。
compare_ics (continue)
5335
if (rank1 > rank2)
5336
return
-1;
5337
else if (rank1 < rank2)
5338
return
1;
5339
5340
if (rank1 == BAD_RANK)
5341
{
5342
/*
XXX Isn't this an extension? */
5343
/*
Both ICS are bad. We try to make a decision based on what
5344
would have happened if they'd been
good.
*/
5345
if (ICS_USER_FLAG (ics1)
> ICS_USER_FLAG (ics2)
5346
|| ICS_STD_RANK (ics1)
> ICS_STD_RANK (ics2))
5347
return
-1;
5348
else if (ICS_USER_FLAG
(ics1) < ICS_USER_FLAG (ics2)
5349
|| ICS_STD_RANK
(ics1) < ICS_STD_RANK (ics2))
5350
return
1;
5351
5352
/*
We couldn't make up our minds; try to figure it out below.
*/
5353
}
5354
5355
if (ICS_ELLIPSIS_FLAG
(ics1))
5356
/*
Both conversions are ellipsis conversions.
*/
5357
return
0;
5358
5359
/*
User-defined conversion sequence U1 is a better conversion sequence
5360
than
another user-defined conversion sequence U2 if they contain the
5361
same
user-defined conversion operator or constructor and if the sec-
5362
ond
standard conversion sequence of U1 is better than the second
5363
standard conversion sequence of U2.
*/
5364
5365
if (ICS_USER_FLAG (ics1))
5366
{
5367
tree t1, t2;
5368
5369
for
(t1 = ics1; TREE_CODE (t1) !=
USER_CONV; t1 =
TREE_OPERAND (t1, 0))
5370
if (TREE_CODE (t1) == AMBIG_CONV)
5371
return
0;
5372
for
(t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
5373
if (TREE_CODE (t2) ==
AMBIG_CONV)
5374
return
0;
5375
5376
if (USER_CONV_FN (t1) !=
USER_CONV_FN (t2))
5377
return
0;
5378
5379
/*
We can just fall through here, after setting up
5380
FROM_TYPE1 and FROM_TYPE2.
*/
5381
from_type1 = TREE_TYPE
(t1);
5382
from_type2 = TREE_TYPE
(t2);
5383
}
5384
else
5385
{
5386
/*
We're dealing with two standard conversion sequences.
5387
5388
[over.ics.rank]
5389
5390
Standard conversion sequence S1 is a
better conversion
5391
sequence than standard conversion
sequence S2 if
5392
5393
--S1
is a proper subsequence of S2 (comparing the conversion
5394
sequences in the canonical form defined
by _over.ics.scs_,
5395
excluding any Lvalue Transformation; the
identity
5396
conversion sequence is considered to be
a subsequence of
5397
any
non-identity conversion sequence */
5398
5399
from_type1 = ics1;
5400
while
(TREE_CODE (from_type1) != IDENTITY_CONV)
5401
from_type1 =
TREE_OPERAND (from_type1, 0);
5402
from_type1 = TREE_TYPE
(from_type1);
5403
5404
from_type2 = ics2;
5405
while
(TREE_CODE (from_type2) != IDENTITY_CONV)
5406
from_type2 =
TREE_OPERAND (from_type2, 0);
5407
from_type2 = TREE_TYPE
(from_type2);
5408
}
上面在
5365
行,如果满足条件,表示该序列包含了用户定义转换,而在那一点上,
ics1
与
ics2
具有相同的等级,因此它们要么同时包含用户定义转换,要么都不包含。在
5376
行的
USER_CONV_FN
保存了为这个
USER_CONV
所找出的转换函数。如果这两个候选的参数所使用的用户定义转换不相同,它们是包括区分的(等级上)。
而对于标准转换序列,【
3
】的条文
13.3.3
.1.1
,条款
2
,强调以规范的次序应用转换,依次为:左值转型(
Lvalue
Transformation
),提升(
Promotion
)或转换(
Conversion
),限定调整(
Qualifier
Adjustment
);回到
standard_conversion
,看到它确实会产生这个序列,但次序相反。
compare_ics (continue)
5410
if (same_type_p (from_type1,
from_type2))
5411
{
5412
if (is_subseq
(ics1, ics2))
5413
return
1;
5414
if (is_subseq (ics2,
ics1))
5415
return
-1;
5416
}
进一步的,【
3
】的条文
13.3.3
.2
,条款
3
(
5386
行的注释),在等级评估过程中,左值转型应该被排除;在前端中,这对应着
LVALUE_CONV
及
RVALUE_CONV
。因此
is_subseq
根据标准,如果
ics1
是
ics2
的一个正确子序列,就返回
true
。
5177
static
bool
5178
is_subseq
(tree ics1, tree ics2)
in
call.c
5179
{
5180
/*
We can assume that a conversion of the same code
5181
between the same types indicates a
subsequence since we only get
5182
here
if the types we are converting from are the same.
*/
5183
5184
while
(TREE_CODE (ics1) == RVALUE_CONV
5185
|| TREE_CODE (ics1) ==
LVALUE_CONV)
5186
ics1 = TREE_OPERAND (ics1,
0);
5187
5188
while
(1)
5189
{
5190
while
(TREE_CODE (ics2) == RVALUE_CONV
5191
|| TREE_CODE (ics2)
== LVALUE_CONV)
5192
ics2 = TREE_OPERAND
(ics2, 0);
5193
5194
if (TREE_CODE (ics2) ==
USER_CONV
5195
|| TREE_CODE (ics2) ==
AMBIG_CONV
5196
|| TREE_CODE (ics2) ==
IDENTITY_CONV)
5197
/*
At this point, ICS1 cannot be a proper subsequence of
5198
ICS2. We can get a USER_CONV when we
are comparing the
5199
second standard conversion sequence of
two user conversion
5200
sequences.
*/
5201
return
false;
5202
5203
ics2 = TREE_OPERAND (ics2,
0);
5204
5205
if (TREE_CODE (ics2) ==
TREE_CODE (ics1)
5206
&& same_type_p
(TREE_TYPE (ics2), TREE_TYPE (ics1))
5207
&& same_type_p (TREE_TYPE
(TREE_OPERAND (ics2, 0)),
5208
TREE_TYPE (TREE_OPERAND
(ics1, 0))))
5209
return
true;
5210
}
5211
}
相关文章推荐
- GCC-3.4.6源代码学习笔记(148 - 续)
- GCC-3.4.6源代码学习笔记(159)
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(28)
- GCC-3.4.6源代码学习笔记 当前目录
- GCC-3.4.6源代码学习笔记(115)
- GCC-3.4.6源代码学习笔记(141-续1)
- GCC-3.4.6源代码学习笔记(62)
- GCC-3.4.6源代码学习笔记(34)
- GCC-3.4.6源代码学习笔记(47)
- GCC-3.4.6源代码学习笔记(145)
- GCC-3.4.6源代码学习笔记(64)
- GCC-3.4.6源代码学习笔记(15)
- GCC-3.4.6源代码学习笔记(173)
- GCC-3.4.6源代码学习笔记(177)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记(110)
- GCC-3.4.6源代码学习笔记(140 - 续)
- GCC-3.4.6源代码学习笔记(60)
- GCC-3.4.6源代码学习笔记(95)