您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (145)

2011-01-15 11:27 387 查看

5.13.

Stage after parsing

5.13.1.

Preliminaries - detail of conversion

5.13.1.1.

Determine appropriate conversion

C++ is a type-strong language. However, in practice, we always can
write code like: “1 + 5.0f;”,
in which “1” is of
integer type, and “5.0f” is of
floating point type. We can even write more amazing code like: “a + b;”
assuming both “a” and “b” are instances of certain class. It dues to the
compiler will generate code for us to do the necessary and appropriate
conversions. In this section, we will see the conversions that compiler will
use behind and rules of these conversions enacted by the language standard.

We first begin with function can_convert_arg

, which is used to test if two
specified types agree with each other.

5996

bool

5997

can_convert_arg

(tree to, tree from,
tree arg)
in
call.c

5998

{

5999

tree t = implicit_conversion
(to, from, arg, LOOKUP_NORMAL);

6000

return
(t
&& ! ICS_BAD_FLAG (t));

6001

}

Indicated by
its name, conversions carried in below function, are those the compiler can be
used freely as it considers as appropriately. It is one of interesting and
powerful features of C++ language; and frequently confuses programmer even the
seniors. In [3], section 13.3.3.1
“Implicit conversion sequences” explains what implicit conversion is in detail:

1.
An implicit conversion sequence is a
sequence of conversions used to convert an argument in a function call to the
type of the corresponding parameter of the function being called. The
sequence of conversions is an implicit conversion as defined in clause 4,
which means it is governed by the rules for initialization of an object or
reference by a single expression (8.5, 8.5.3).

2. Implicit
conversion sequences are concerned only with the type, cv-qualification, and
lvalueness of the argument and how these are converted to match the
corresponding properties of the parameter. Other properties, such as the
lifetime, storage class, alignment, or accessibility of the argument and
whether or not the argument is a bit-field are ignored. So, although an
implicit conversion sequence can be defined for a given argument-parameter
pair, the conversion from the argument to the parameter might still be
ill-formed in the final analysis.

3.
A well-formed implicit conversion sequence
is one of the following forms:

— a standard
conversion sequence (13.3.3.1.1),

— a
user-defined conversion sequence (13.3.3.1.2), or

— an ellipsis
conversion sequence (13.3.3.1.3).

4.
However, when considering the argument of a
user-defined conversion function that is a candidate by 13.3.1.3
when invoked for the copying of the temporary in the second step of a class
copy-initialization, or by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases, only
standard conversion sequences and ellipsis conversion sequences are allowed.

5.
For the case where the parameter type is a
reference, see 13.3.3.1.4. (reference
binding

)

6.
When the parameter type is not a reference,
the implicit conversion sequence models a copy-initialization of the
parameter from the argument expression. The implicit conversion sequence is
the one required to convert the argument expression to an rvalue of the type
of the parameter. [Note: when the parameter has a class type, this is a
conceptual conversion defined for the purposes of clause 13; the actual
initialization is defined in terms of constructors and is not a conversion.]
Any difference in top-level cv-qualification is subsumed by the
initialization itself and does not constitute a conversion. [Example: a
parameter of type A can be initialized from an argument of type const A. The
implicit conversion sequence for that case is the identity sequence; it
contains no “conversion” from const A to A.] When the parameter has a class type
and the argument expression has the same type, the implicit conversion
sequence is an identity conversion. When the parameter has a class type and
the argument expression has a derived class type, the implicit conversion
sequence is a derived-to-base Conversion from the derived class to the base
class. [Note: there is no such standard conversion; this derived-to-base
Conversion exists only in the description of implicit conversion sequences.]
A derived-to-base Conversion has Conversion rank (13.3.3.1.1).

7.
In all contexts, when converting to the
implicit object parameter or when converting to the left operand of an
assignment operation only standard conversion sequences that create no
temporary object for the result are allowed.

8.
If no conversions are required to match an
argument to a parameter type, the implicit conversion sequence is the
standard conversion sequence consisting of the identity conversion (13.3.3.1.1).

9.
If no sequence of conversions can be found
to convert an argument to a parameter type or the conversion is otherwise
ill-formed, an implicit conversion sequence cannot be formed.

10. If
several different sequences of conversions exist that each convert the
argument to the parameter type, the implicit conversion sequence associated
with the parameter is defined to be the unique conversion sequence designated
the ambiguous conversion sequence. For the purpose of ranking implicit
conversion sequences as described in 13.3.3.2,
the ambiguous conversion sequence is treated as a user-defined sequence that
is indistinguishable from any other user-defined conversion sequence (The
ambiguous conversion sequence is ranked with user-defined conversion
sequences because multiple conversion sequences for an argument can exist
only if they involve different user-defined conversions. The ambiguous
conversion sequence is indistinguishable from any other user-defined
conversion sequence because it represents at least two user-defined
conversion sequences, each with a different user-defined conversion, and any
other user-defined conversion sequence must be indistinguishable from at
least one of them.

This rule prevents a function from
becoming non-viable because of an ambiguous conversion sequence for one of
its parameters. Consider this example,

class
B;

class
A { A (B&); };

class
B { operator
A (); };

class
C { C (B&); };

void f(A) { }

void f(C) { }

B b;

f(b); //ambiguous
because b -> C via constructor and

// b -> A via
constructor or conversion function.

If it were not for this rule, f(A)
would be eliminated as a viable function for the call f(b) causing overload
resolution to select f(C) as the function to call even though it is not
clearly the best choice. On the other hand, if an f(B) were to be declared
then f(b) would resolve to that f(B) because the exact match with f(B) is
better than any of the sequences required to match f(A).

If a function that uses the ambiguous
conversion sequence is selected as the best viable function, the call will be
ill-formed because the conversion of one of the arguments in the call is
ambiguous.

11. The
three forms of implicit conversion sequences mentioned above are defined in
the following subclauses.

Before going ahead into
the code, first we need clarify the concept of lvalue and rvalue. An lvalue
refers to an object or function. It must be an entity that is addressable; i.e.,
if it refers to object, it should be able to be placed on left-hand-side of an
assignment operation (that is why it called lvalue). And those that are
non-lvalue are called rvalue (which can’t be used on left-hand-side of
assginment operation).

1097

static
tree

1098

implicit_conversion

(tree to, tree from, tree expr, int flags)
in call.c

1099

{

1100

tree conv;

1101

1102

if (from == error_mark_node
|| to == error_mark_node

1103

|| expr ==
error_mark_node)

1104

return
NULL_TREE;

1105

1106

if (TREE_CODE (to) ==
REFERENCE_TYPE)

1107

conv = reference_binding
(to, from, expr, flags);

1108

else

1109

conv = standard_conversion
(to, from, expr, flags);

1110

1111

if (conv)

1112

return
conv;

1113

1114

if (expr != NULL_TREE

1115

&& (IS_AGGR_TYPE
(from)

1116

|| IS_AGGR_TYPE
(to))

1117

&& (flags &
LOOKUP_NO_CONVERSION) == 0)

1118

{

1119

struct
z_candidate
*cand;

1120

1121

cand = build_user_type_conversion_1

1122

(to, expr,
LOOKUP_ONLYCONVERTING);

1123

if (cand)

1124

conv =
cand->second_conv;

1125

1126

/*
We used to try to bind a reference to a temporary here, but that

1127

now
handled by the recursive call to this function at the end

1128

of
reference_binding.
*/

1129

return
conv;

1130

}

1131

1132

return
NULL_TREE;

1133

}

See the conversion processing routines may recurse each other, here
to handle reference type, the function invokes reference_binding

again.
However, as we are going forward within the tree of the expression, as long as
no loop back of dependence exists there will not be the infinite recursion. And
as C++ is the language requires declaration before using, mutual dependence is illegal;
the parser should be able to find out this ill form.

5.13.1.1.1.

Case
of standard conversion sequence

[3] section 13.3.3.1.1
“Standard conversion sequence” gives detail about the sequence.

1.
Table 9
summarizes
the
conversions defined in clause 4 (“Standard conversions”, section 4 in [3]) and partitions them into four
disjoint categories: Lvalue Transformation, Qualification Adjustment,
Promotion, and Conversion. [Note:
these categories are orthogonal with
respect to lvalue-ness, cv-qualification, and data representation: the Lvalue
Transformations do not change the cv-qualification or data representation of
the type; the Qualification Adjustments do not change the lvalue

-ness
or data representation of the type; and the Promotions and Conversions do not
change the lvalue-ness or cv-qualification of the type.]

2.
[Note:
As
described in clause 4, a standard conversion sequence is either the Identity
conversion by itself (that is, no conversion) or consists of one to three
conversions from the other four categories. At most one conversion from each
category is allowed in a single standard conversion sequence. If there are
two or more conversions in the sequence, the conversions are applied in the
canonical order: Lvalue Transformation
, Promotion
or Conversion
,
Qualification Adjustment
. —end note
]

3.
Each
conversion in Table 9 also has an associated rank (Exact Match, Promotion, or
Conversion). These are used to rank standard conversion sequences (13.3.3.2).
The rank of a conversion sequence is determined by considering the rank of
each conversion in the sequence and the rank of any reference binding (13.3.3.1.4).
If any of those has Conversion rank, the sequence has Conversion rank;
otherwise, if any of those has Promotion rank, the sequence has Promotion
rank; otherwise, the sequence has Exact Match rank.

Table 9: - conversions

Conversion


Category


Rank


Subclause


No conversions required

Identity

Exact Match

Lvalue-to-rvalue conversion

Lvalue Transformation

4.1

Array-to-pointer conversion

4.2

Function-to-pointer conversion

4.3

Qualification conversion

Qualification Adjustment

4.4

Integral promotions

Promotion

Promotion

4.5

Floating point promotion

4.6

Integral conversion

Conversion

Conversion

4.7

Floating point conversion

4.8

Floating-integral conversions

4.9

Pointer conversions

4.10

Pointer to member conversions

4.11

Boolean conversions

4.12

Below we just skip the
resolving of overload from line 472 to 479 (it will be covered by section about
reference binding, remember type_unknown_p

returns true if expr

is
an overload). Always keep in mind that below standard_conversion

handles
implicit conversion, only conversions mentioned in above table are considered; never confuse it with
force conversion.

456

static
tree

457

standard_conversion

(tree to, tree from,
tree expr, int flags)
in
call.c

458

{

459

enum
tree_code fcode, tcode;

460

tree conv;

461

bool fromref = false;

462

463

to = v (to);

464

if (TREE_CODE (from) == REFERENCE_TYPE)

465

{

466

fromref = true;

467

from = TREE_TYPE (from);

468

}

469

to = strip_top_quals (to);

470

from = strip_top_quals (from);

471

472

if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P
(to))

473

&& expr && type_unknown_p
(expr))

474

{

475

expr = instantiate_type (to, expr,
tf_conv);

476

if (expr == error_mark_node)

477

return
NULL_TREE;

478

from = TREE_TYPE (expr);

479

}

480

481

fcode = TREE_CODE (from);

482

tcode = TREE_CODE (to);

483

484

conv = build1
(IDENTITY_CONV, from, expr);

485

486

if (fcode == FUNCTION_TYPE)

487

{

488

from = build_pointer_type
(from);

489

fcode = TREE_CODE (from);

490

conv = build_conv
(LVALUE_CONV, from, conv);

491

}

492

else if (fcode == ARRAY_TYPE)

493

{

494

from = build_pointer_type
(TREE_TYPE (from));

495

fcode = TREE_CODE (from);

496

conv = build_conv
(LVALUE_CONV, from, conv);

497

}

498

else if (fromref || (expr
&& lvalue_p
(expr)))

499

conv = build_conv
(RVALUE_CONV, from, conv);

500

501

/* Allow conversion
between `__complex__' data types.
*/

502

if (tcode == COMPLEX_TYPE && fcode ==
COMPLEX_TYPE)

503

{

504

/* The standard
conversion sequence to convert FROM to TO is

505

the standard conversion
sequence to perform componentwise

506

conversion.
*/

507

tree part_conv = standard_conversion

508

(TREE_TYPE (to), TREE_TYPE (from),
NULL_TREE, flags);

509

510

if (part_conv)

511

{

512

conv = build_conv
(TREE_CODE (part_conv), to, conv);

513

ICS_STD_RANK (conv) = ICS_STD_RANK
(part_conv);

514

}

515

else

516

conv = NULL_TREE;

517

518

return
conv;

519

}

520

521

if (same_type_p (from, to))

522

return
conv;

Line 484 builds IDENTITY_COV for identity conversion. The type of *_CONV
node indicates the source type and its first operand is the expression to be
converted. So conversion sequence will be built with a big nested *_CONV node,
with the top *_CONV is the last conversion being done, and the innermost being the
first which always is IDENTITY_CONV.

In internal, the front-end defines following ranks for conversions
instead those shown by table-9 above. And note that the less value indicates more
preference.

343

#define
IDENTITY_RANK
0
in
call.c

344

#define
EXACT_RANK
1

345

#define
PROMO_RANK
2

346

#define
STD_RANK
3

347

#define
PBOOL_RANK
4

348

#define
USER_RANK
5

349

#define
ELLIPSIS_RANK
6

350

#define
BAD_RANK
7

Conversions that can be generated internally include: IDENTITY_CONV,
LVALUE_CONV, QUAL_CONV, STD_CONV, PTR_CONV, PMEM_CONV, BASE_CONV, REF_BIND, USER_CONV,
AMBIG_CONV, and RVALUE_CONV.

408

static
tree

409

build_conv

(enum
tree_code code, tree type, tree from)
in
call.c

410

{

411

tree t;

412

int rank = ICS_STD_RANK (from);

413

414

/* We can't use
buildl1 here because CODE could be USER_CONV, which

415

takes two
arguments. In that case, the caller is responsible for

416

filling in the
second argument.

*/

417

t
=
make_node

(code);

418

TREE_TYPE (t) = type;

419

TREE_OPERAND (t, 0) = from;

420

421

switch
(code)

422

{

423

case
PTR_CONV:

424

case
PMEM_CONV:

425

case
BASE_CONV:

426

case
STD_CONV:

427

if (rank < STD_RANK)

428

rank = STD_RANK;

429

break
;

430

431

case
QUAL_CONV:

432

if (rank < EXACT_RANK)

433

rank = EXACT_RANK;

434

435

default
:

436

break
;

437

}

438

ICS_STD_RANK (t) = rank;

439

ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));

440

ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);

441

return
t;

442

}

In above function, ICS_STD_RANK in fact will store the highest rank value
seen so far, whose usage we will see in later paragraphes.

Then above line 486 and 492 in standard_conversion

handle
function-to-pointer and array-to-point conversion, which is described by [3]
clause 4.2 “Array-to-pointer conversion and clause” 4.3 “Function-to-pointer
conversion” as below.

1.
An lvalue

or rvalue

of type “array ofN T” or “array of unknown bound of T” can be converted to an
rvalue

of type “pointer to T.” The result is a pointer to the first element of the
array.

2.
A string literal (2.13.4) that is not a
wide string literal can be converted to an rvalue

of type “pointer
to char”; a wide string literal can be converted to an rvalue

of type “pointer
to wchar_t”. In either case, the result is a pointer to the first element of
the array. This conversion is considered only when there is an explicit
appropriate pointer target type, and not when there is a general need to
convert from an lvalue

to an rvalue

. [Note: this conversion is
deprecated. See Annex D.] For the purpose of ranking in overload resolution (13.3.3.1.1),
this conversion is considered an array-to-pointer conversion followed by a
qualification conversion (4.4). [Example: "abc" is converted to
“pointer to const char” as an array-to-pointer conversion, and then to
“pointer to char” as a qualification conversion.]

1.
An lvalue

of function type T can be converted to an rvalue

of type “pointer
to T.” The result is a pointer to the function. (This conversion never
applies to nonstatic member functions because an lvalue

that refers to a
nonstatic member function cannot be obtained.)

2.
[Note: See 13.4 for additional rules for
the case where the function is overloaded.]

Note that in terms 1 of
both clauses, rvalue of type “pointer to T” just means the pointer itself can’t
be modified, but its content can be changed. For example:

char a[10];

char *p = …;

a = p;
// a is
converted to rvalue of char*, assignment not allowed

*(a+1) = *p;
// object pointed
by a+1 is lvalue, it is OK

Compared with below clause, these two clauses include creation of pointer
type, the front-end must tells out these two situations from other cases of
lvalue transformation. So the front-end uses LVALUE_CONV for them.

Then in standard_conversion

,
arriving at line 498, if the condition is satisified, terms 1 mentioned in [3]
clause 4.1 “Lvalue-to-rvalue conversion” will be implemented. The front-end
uses RVALUE_CONV for the case. One difference of LVALUE_CONV and RVALUE_CONV is
that when building LVALUE_CONV, we have known the rvalue (see the pointer type
built at line 488 and 494), while for RVALUE_CONV, the rvalue is unknown at
that point, and later the front-end needs invoke decay_conversion

to do the
real conversion.

1.
An lvalue

(3.10) of a non-function, non-array type T can be converted to an rvalue

.
If T is an incomplete type, a program that necessitates this conversion is
ill-formed. If the object to which the lvalue

refers is not an object of
type T and is not an object of a type derived from T, or if the object is
uninitialized, a program that necessitates this conversion has undefined
behavior. If T is a non-class type, the type of the rvalue

is the
cv-unqualified version of T. Otherwise, the type of the rvalue

is T. [In C++
class rvalues

can have cv-qualified types (because they are
objects). This differs from ISO C, in which non-lvalues

never have
cv-qualified types.]

2.
The value contained in the object indicated
by the lvalue

is the rvalue

result. When an
lvalue-to-rvalue conversion occurs within the operand of sizeof (5.3.3) the
value contained in the referenced object is not accessed, since that operator
does not evaluate its operand.

Focus upon following
function, given expression ref

, it can tell if it is lvalue or not. And see
that pointer type built for LVALUE_CONV above is rvalue told by this function.
This function should be studied carefully.

211

int

212

lvalue_p

(tree ref)
in
tree.c

213

{

214

return

215

(lvalue_p_1
(ref,
/*class rvalue ok*/
1) != clk_none);

216

}

The various kinds of lvalues we distinguish are given in below.

2964

typedef
enum
cp_lvalue_kind {
in
cp-tree.h

2965

clk_none = 0,
/* Things that
are not an lvalue.
*/

2966

clk_ordinary = 1, /* An ordinary lvalue.

*/

2967

clk_class = 2,
/* An rvalue of
class-type.
*/

2968

clk_bitfield = 4, /* An lvalue for a bit-field.
*/

2969

clk_packed = 8
/* An lvalue for
a packed field.
*/

2970

} cp_lvalue_kind
;

In [3], clause
3.10 (lvalues and rvalues), gives the following explaination.

1.
Every
expression is either an lvalue

or an rvalue

.

2.
An lvalue

refers to an object or
function. Some rvalue

expressions—those of class or cv-qualified class type—also
refer to objects (Expressions such as invocations of constructors and of
functions that return a class type refer to objects, and the implementation can
invoke a member function upon such objects, but the expressions are not lvalues

).

3.
[Note: some built-in operators and function
calls yield lvalues

. [Example: if E is an expression of pointer type,
then *E is an lvalue

expression referring to the object or function to
which E points. As another example, the function

int&
f();

yields an lvalue

,
so the call f() is an lvalue

expression.]]

4.
[Note: some builtin operators expect lvalue

operands. [Example: built-in assignment operators all expect their left hand
operands to be lvalues

.] Other built-in operators yield rvalues

, and some
expect them. [Example: the unary and binary + operators expect rvalue

arguments and yield rvalue

results.] The discussion of
each built-in operator in clause 5 indicates whether it expects lvalue

operands and whether it yields an lvalue

.]

5.
The result of calling a function that does
not return a reference is an rvalue

. User defined operators are
functions, and whether such operators expect or yield lvalues is determined
by their parameter and return types.

6.
An expression which holds a temporary
object resulting from a cast to a nonreference type is an rvalue

(this includes the explicit creation of an object using functional notation (5.2.3)).

7.
Whenever an lvalue

appears in a
context where an rvalue

is expected, the lvalue

is converted to an rvalue

;
see 4.1, 4.2, and 4.3.

8.
The discussion of reference initialization
in 8.5.3 and of temporaries in 12.2 indicates the behavior of lvalues

and rvalues

in other significant contexts.

9.
Class rvalues

can have cv-qualified
types; non-class rvalues

always have cv-unqualified types. Rvalues

shall always have complete types or the void type; in addition to these
types, lvalues

can also have incomplete types.

10. An lvalue

for an object is
necessary in order to modify the object except that an rvalue

of class type
can also be used to modify its referent under certain circumstances.
[Example: a member function called for an object (9.3) can modify the object.]

11. Functions cannot be
modified, but pointers to functions can be modifiable.

12. A pointer to an incomplete
type can be modifiable. At some point in the program when the pointed to type
is complete, the object at which the pointer points can also be modified.

13. The referent of a
const-qualified expression shall not be modified (through that expression),
except that if it is of class type and has a mutable component, that
component can be modified (7.1.5.1).

14. If an expression can be
used to modify the object to which it refers, the expression is called
modifiable. A program that attempts to modify an object through a
nonmodifiable lvalue

or rvalue

expression is illformed.

15. If a program attempts to
access the stored value of an object through an lvalue

of other than
one of the following types the behavior is undefined (The intent of this list
is to specify those circumstances in which an object may or may not be
aliased):

— the
dynamic type of the object,

— a
cv-qualified version of the dynamic type of the object,

— a type
that is the signed or unsigned type corresponding to the dynamic type of the
object,

— a type
that is the signed or unsigned type corresponding to a cv-qualified version
of the dynamic type of the object,

— an
aggregate or union type that includes one of the aforementioned types among
its members (including, recursively, a member of a subaggregate or contained
union),

— a type
that is a (possibly cv-qualified) base class type of the dynamic type of the
object,

— a char or unsigned char type.

Considering non-static
method processed below, as non-static method must be invoked as: “a.fa();” with
given object which may not addressable (for example, in statement “A().fa();”,
“A()” returns an rvalue), non-static method is just considered as rvalue. Further,
expression “A().fa();” can modify the object, so “A()” can be considered as
lvalue if not require strict lvalue (argument treat_class_rvalues_as_lvalues

is
1). Pay attention to TARGET_EXPR at line 156, it would wrapsthe temperary
object returned by “A()” ( see comment at line 161).

62

static
cp_lvalue_kind

63

lvalue_p_1

(tree ref,
in
tree.c

64

int treat_class_rvalues_as_lvalues)

65

{

66

cp_lvalue_kind op1_lvalue_kind = clk_none;

67

cp_lvalue_kind op2_lvalue_kind = clk_none;

68

69

if (TREE_CODE (TREE_TYPE (ref)) ==
REFERENCE_TYPE)

70

return
clk_ordinary;

71

72

if (ref == current_class_ptr

)

73

return
clk_none;

74

75

switch
(TREE_CODE (ref))

76

{

77

/* preincrements and predecrements are valid
lvals, provided

78

what they refer
to are valid lvals.
*/

79

case
PREINCREMENT_EXPR:

80

case
PREDECREMENT_EXPR:

81

case
SAVE_EXPR:

82

case
UNSAVE_EXPR:

83

case
TRY_CATCH_EXPR:

84

case
WITH_CLEANUP_EXPR:

85

case
REALPART_EXPR:

86

case
IMAGPART_EXPR:

87

return
lvalue_p_1 (TREE_OPERAND (ref, 0),

88

treat_class_rvalues_as_lvalues);

89

90

case
COMPONENT_REF:

91

op1_lvalue_kind = lvalue_p_1
(TREE_OPERAND (ref, 0),

92

treat_class_rvalues_as_lvalues);

93

/* In an
expression of the form "X.Y", the packed-ness of the

94

expression
does not depend on "X".
*/

95

op1_lvalue_kind &= ~clk_packed;

96

/* Look at the member designator.
*/

97

if (!op1_lvalue_kind

98

/* The
"field" can be a FUNCTION_DECL or an OVERLOAD in some

99

situations.
*/

100

|| TREE_CODE (TREE_OPERAND (ref, 1))
!= FIELD_DECL)

101

;

102

else if (DECL_C_BIT_FIELD (TREE_OPERAND
(ref, 1)))

103

{

104

/* Clear the
ordinary bit. If this object was a class

105

rvalue we
want to preserve that information.
*/

106

op1_lvalue_kind &= ~clk_ordinary;

107

/* The lvalue
is for a bitfield.
*/

108

op1_lvalue_kind |= clk_bitfield;

109

}

110

else if (DECL_PACKED (TREE_OPERAND (ref,
1)))

111

op1_lvalue_kind |= clk_packed;

112

113

return
op1_lvalue_kind;

114

115

case
STRING_CST:

116

return
clk_ordinary;

117

118

case
VAR_DECL:

119

if (TREE_READONLY (ref) && !
TREE_STATIC (ref)

120

&& DECL_LANG_SPECIFIC (ref)

121

&& DECL_IN_AGGR_P (ref))

122

return
clk_none;

123

case
INDIRECT_REF:

124

case
ARRAY_REF:

125

case
PARM_DECL:

126

case
RESULT_DECL:

127

if (TREE_CODE (TREE_TYPE (ref)) !=
METHOD_TYPE)

128

return
clk_ordinary;

129

break
;

130

131

/* A currently unresolved scope ref.
*/

132

case
SCOPE_REF:

133

abort ();

134

case
MAX_EXPR:

135

case
MIN_EXPR:

136

op1_lvalue_kind = lvalue_p_1
(TREE_OPERAND (ref, 0),

137

treat_class_rvalues_as_lvalues);

138

op2_lvalue_kind = lvalue_p_1
(TREE_OPERAND (ref, 1),

139

treat_class_rvalues_as_lvalues);

140

break
;

141

142

case
COND_EXPR:

143

op1_lvalue_kind = lvalue_p_1
(TREE_OPERAND (ref, 1),

144

treat_class_rvalues_as_lvalues);

145

op2_lvalue_kind = lvalue_p_1
(TREE_OPERAND (ref, 2),

146

treat_class_rvalues_as_lvalues);

147

break
;

148

149

case
MODIFY_EXPR:

150

return
clk_ordinary;

151

152

case
COMPOUND_EXPR:

153

return
lvalue_p_1 (TREE_OPERAND (ref, 1),

154

treat_class_rvalues_as_lvalues);

155

156

case
TARGET_EXPR:

157

return
treat_class_rvalues_as_lvalues ? clk_class : clk_none;

158

159

case
CALL_EXPR:

160

case
VA_ARG_EXPR:

161

/* Any class-valued
call would be wrapped in a TARGET_EXPR.

*/

162

return
clk_none;

163

164

case
FUNCTION_DECL:

165

/* All
functions (except non-static-member functions) are

166

lvalues.
*/

167

return
(DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)

168

? clk_none : clk_ordinary);

169

170

case
NON_DEPENDENT_EXPR:

171

/* We must
consider NON_DEPENDENT_EXPRs to be lvalues so that

172

things like
"&E" where "E" is an expression with a

173

non-dependent
type work. It is safe to be lenient because an

174

error will be
issued when the template is instantiated if "E"

175

is not an
lvalue.
*/

176

return
clk_ordinary;

177

178

default
:

179

break
;

180

}

181

182

/* If one operand is
not an lvalue at all, then this expression is

183

not an
lvalue.
*/

184

if (!op1_lvalue_kind || !op2_lvalue_kind)

185

return
clk_none;

186

187

/* Otherwise, it's
an lvalue, and it has all the odd properties

188

contributed by
either operand.
*/

189

op1_lvalue_kind = op1_lvalue_kind |
op2_lvalue_kind;

190

/* It's not an
ordinary lvalue if it involves either a bit-field or

191

a class
rvalue.
*/

192

if ((op1_lvalue_kind & ~clk_ordinary) !=
clk_none)

193

op1_lvalue_kind &= ~clk_ordinary;

194

return
op1_lvalue_kind;

195

}

Above, NON_DEPENDENT_EXPR is a placeholder for an expression that is
not type-dependent, but does occur in a template. See INDIRECT_REF is lvalue
(however pointer is rvalue itself, it is the case described by terms 3 above);
and normal variable is also lvalue (line 118); further if an array is referred,
its reference is lvalue, otherwise the array would be decayed to pointer of
rvalue. Next note that MODIFY_EXPR at line 149, no doubt must be lvalue, and
COMPOUND_EXPR following depends on its second operand. And for expressions may
contains operand of lvalue, lvalue_p_1

recurs into the operand.

It is worth note that call expression “f();” of “int& f();” is
lvalue, but expression like “f() = 5;” is illegal; the only case this lvalue
can be used directly is using “f()” as parameter which is covered by PARM_DECL
at line 125; so CALL_EXPR not within PARM_DECL is just regarded as rvalue.
Further, being lvalue, PARM_DECL, RESULT_DECL, ARRAY_REF, and INDIRECT_REF can
be of type of non-static method of class.

standard_conversion (continue)

524

if ((tcode == POINTER_TYPE ||
TYPE_PTR_TO_MEMBER_P (to))

525

&& expr && null_ptr_cst_p
(expr))

526

conv = build_conv
(STD_CONV, to, conv);

527

else if (tcode == POINTER_TYPE &&
fcode == POINTER_TYPE

528

&& TREE_CODE (TREE_TYPE (to))
== VECTOR_TYPE

529

&& TREE_CODE (TREE_TYPE (from))
== VECTOR_TYPE

530

&& ((*targetm

.vector_opaque_p) (TREE_TYPE
(to))

531

|| (*targetm

.vector_opaque_p)
(TREE_TYPE (from))))

532

conv = build_conv
(STD_CONV, to, conv);

533

else
if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)

534

|| (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))

535

{

536

/* For backwards
brain damage compatibility, allow interconversion of

537

pointers and
integers with a pedwarn.
*/

538

conv = build_conv
(STD_CONV, to, conv);

539

ICS_BAD_FLAG (conv) = 1;

540

}

541

else if (tcode == ENUMERAL_TYPE &&
fcode == INTEGER_TYPE)

542

{

543

/* For backwards
brain damage compatibility, allow interconversion of

544

enums and
integers with a pedwarn.
*/

545

conv = build_conv
(STD_CONV, to, conv);

546

ICS_BAD_FLAG (conv) = 1;

547

}

Note above, converting between pointers and integers and between
integers and enums are both bad conversions in the context of C++ langauge (but
it just gives warning under C). So the conversion is recorded and given the
rank of lowest priority.

standard_conversion (continue)

548

else if ((tcode == POINTER_TYPE &&
fcode == POINTER_TYPE)

549

|| (TYPE_PTRMEM_P (to) &&
TYPE_PTRMEM_P (from)))

550

{

551

tree to_pointee;

552

tree from_pointee;

553

554

if (tcode == POINTER_TYPE

555

&&
same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),

556

TREE_TYPE (to)))

557

;

558

else if (VOID_TYPE_P (TREE_TYPE (to))

559

&& !TYPE_PTRMEM_P (from)

560

&& TREE_CODE (TREE_TYPE
(from)) != FUNCTION_TYPE)

561

{

562

from = build_pointer_type

563

(cp_build_qualified_type (void_type_node,

564

cp_type_quals (TREE_TYPE (from))));

565

conv = build_conv
(PTR_CONV, from, conv);

566

}

567

else if (TYPE_PTRMEM_P (from))

568

{

569

tree fbase = TYPE_PTRMEM_CLASS_TYPE
(from);

570

tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);

571

572

if (DERIVED_FROM_P (fbase, tbase)

573

&&
(same_type_ignoring_top_level_qualifiers_p

574

(TYPE_PTRMEM_POINTED_TO_TYPE (from),

575

TYPE_PTRMEM_POINTED_TO_TYPE
(to))))

576

{

577

from = build_ptrmem_type (tbase,

578

TYPE_PTRMEM_POINTED_TO_TYPE (from));

579

conv = build_conv
(PMEM_CONV, from, conv);

580

}

581

else if (!same_type_p (fbase, tbase))

582

return
NULL;

583

}

584

else if (IS_AGGR_TYPE (TREE_TYPE (from))

585

&& IS_AGGR_TYPE (TREE_TYPE
(to))

586

/* [conv.ptr]

587

588

An rvalue of
type "pointer to cv D," where D is a

589

class type,
can be converted to an rvalue of type

590

"pointer
to cv B," where B is a base class (clause

591

_class.derived_) of D. If B is an inaccessible

592

(clause
_class.access_) or ambiguous

593

(_class.member.lookup_) base class of D, a program

594

that
necessitates this conversion is ill-formed.

*/

595

/* Therefore,
we use DERIVED_FROM_P, and not

596

ACESSIBLY_UNIQUELY_DERIVED_FROM_P,
in this test.
*/

597

&& DERIVED_FROM_P (TREE_TYPE
(to), TREE_TYPE (from)))

598

{

599

from =

600

cp_build_qualified_type (TREE_TYPE
(to),

601

cp_type_quals
(TREE_TYPE (from)));

602

from = build_pointer_type
(from);

603

conv = build_conv
(PTR_CONV, from, conv);

604

}

605

606

if (tcode == POINTER_TYPE)

607

{

608

to_pointee = TREE_TYPE (to);

609

from_pointee = TREE_TYPE (from);

610

}

611

else

612

{

613

to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE
(to);

614

from_pointee =
TYPE_PTRMEM_POINTED_TO_TYPE (from);

615

}

616

617

if (same_type_p (from, to))

618

/* OK */
;

619

else
if (comp_ptr_ttypes (to_pointee, from_pointee))

620

conv = build_conv
(QUAL_CONV, to, conv);

621

else if (expr && string_conv_p (to,
expr, 0))

622

/* converting
from string constant to char *.
*/

623

conv = build_conv
(QUAL_CONV, to, conv);

624

else if (ptr_reasonably_similar
(to_pointee, from_pointee))

625

{

626

conv = build_conv
(PTR_CONV, to, conv);

627

ICS_BAD_FLAG (conv) = 1;

628

}

629

else

630

return
0;

631

632

from = to;

633

}

Again in [3]
clause 4.10 “Pointer covnersions”, finds following paragraphes. And note that
code at line 499 in the function has converted lvalue into rvalue, conv

above
holds the conversion.

1.
A null
pointer constant is an integral constant expression (5.19) rvalue

of integer type that evaluates to zero. A null pointer constant can be
converted to a pointer type; the result is the null pointer value of that type
and is distinguishable from every other value of pointer to object or pointer
to function type. Two null pointer values of the same type shall compare
equal. The conversion of a null pointer constant to a pointer to cv-qualified
type is a single conversion, and not the sequence of a pointer conversion
followed by a qualification conversion (4.4).

2.
An rvalue

of type “pointer to cv T,”
where T is an object type, can be converted to an rvalue of type “pointer to
cv void.” The result of converting a “pointer to cv T” to a “pointer to cv
void” points to the start of the storage location where the object of type T
resides, as if the object is a most derived object (1.8) of type T (that is,
not a base class subobject).

3.
An rvalue

of type “pointer to cv D,”
where D is a class type, can be converted to an rvalue

of type “pointer
to cv B,” where B is a base class (clause 10) of D. If B is an inaccessible
(clause 11) or ambiguous (10.2) base class of D, a program that necessitates
this conversion is ill-formed. The result of the conversion is a pointer to
the base class sub-object of the derived class object. The null pointer value
is converted to the null pointer value of the destination type.

Terms 1 is worked by line
526 above. It is one step STD_CONV. And condition of terms 2 is tested by code
at line 558 ~ 560. Then condition in line 584 ~ 597 fullfils terms 3.

Further clause
4.11 “Pointer to member conversion” is shown in below.

1.
A null
pointer constant (4.10) can be converted to a pointer to member type; the
result is the null member pointer value of that type and is distinguishable
from any pointer to member not created from a null pointer constant. Two null
member pointer values of the same type shall compare equal. The conversion of
a null pointer constant to a pointer to member of cv-qualified type is a
single conversion, and not the sequence of a pointer to member conversion
followed by a qualification conversion (4.4).

2.
An rvalue

of type “pointer to member
of B of type cv T,” where B is a class type, can be converted to an rvalue

of type “pointer to member of D of type cv T,” where D is a derived class
(clause 10) of B. If B is an inaccessible (clause 11), ambiguous (10.2) or
virtual (10.1) base class of D, a program that necessitates this conversion
is ill-formed. The result of the conversion refers to the same member as the
pointer to member before the conversion took place, but it refers to the base
class member as if it were a member of the derived class. The result refers
to the member in D’s instance of B. Since the result has type “pointer to member
of D of type cv T,” it can be dereferenced with a D object. The result is the
same as if the pointer to member of B were dereferenced with the B sub-object
of D. The null member pointer value is converted to the null member pointer
value of the destination type. [The rule for conversion of pointers to
members (from pointer to member of base to pointer to member of derived)
appears inverted compared to the rule for pointers to objects (from pointer
to derived to pointer to base) (4.10, clause 10). This inversion is necessary
to ensure type safety. Note that a pointer to member is not a pointer to
object or a pointer to function and the rules for conversions of such
pointers do not apply to pointers to members. In particular, a pointer to
member cannot be converted to a void*.]

Terms 1 is also covered by
line 526 above. And terms 2 is handled by block at line 567. Arriving at line
617, with above conversion sequence, from

and to

should be either of same type, or just with
different cv-qualifiers; otherwise, no conversion sequence is applicable.

Below conversion between pointer-to-method is similar with that of
pointer-to-member. Note that fromfn

and tofn

are functions pointed respectively; fbase

and tbase

are the implicit this

pointer each. So conversion can be carried out is: “an rvalue of type “pointer
to method of B of type cv T,” where B is a class type, can be converted to an rvalue
of type “pointer to the same
method
of D of type cv T,” where D is a derived class of B.” And see that “same” here
is a little stricter than the that meaning among overloads.

standard_conversion (continue)

634

else if (TYPE_PTRMEMFUNC_P (to) &&
TYPE_PTRMEMFUNC_P (from))

635

{

636

tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE
(from));

637

tree tofn = TREE_TYPE
(TYPE_PTRMEMFUNC_FN_TYPE (to));

638

tree fbase = TREE_TYPE (TREE_VALUE
(TYPE_ARG_TYPES (fromfn)));

639

tree tbase = TREE_TYPE (TREE_VALUE
(TYPE_ARG_TYPES (tofn)));

640

641

if (!DERIVED_FROM_P (fbase, tbase)

642

|| !same_type_p (TREE_TYPE (fromfn),
TREE_TYPE (tofn))

643

|| !compparms (TREE_CHAIN
(TYPE_ARG_TYPES (fromfn)),

644

TREE_CHAIN (TYPE_ARG_TYPES
(tofn)))

645

|| cp_type_quals (fbase) != cp_type_quals
(tbase))

646

return
0;

647

648

from = cp_build_qualified_type (tbase,
cp_type_quals (fbase));

649

from = build_method_type_directly

(from,

650

TREE_TYPE (fromfn),

651

TREE_CHAIN
(TYPE_ARG_TYPES (fromfn)));

652

from = build_ptrmemfunc_type (build_pointer_type
(from));

653

conv = build_conv
(PMEM_CONV, from, conv);

654

}

[3], clause
4.12 “Boolean conversions” gives guideline how to do the conversion as below.

1.
An rvalue of arithmetic, enumeration,
pointer, or pointer to member type can be converted to an rvalue of type
bool. A zero value, null pointer value, or null member pointer value is
converted to false; any other value is converted to true.

However, conversion from
pointer to boolean is alittle bit inferior to those of integer types.

standard_conversion (continue)

655

else if (tcode == BOOLEAN_TYPE)

656

{

657

/* [conv.bool]

658

659

An rvalue of
arithmetic, enumeration, pointer, or pointer to

660

member type can
be converted to an rvalue of type bool.

*/

661

if (ARITHMETIC_TYPE_P (from)

662

|| fcode == ENUMERAL_TYPE

663

|| fcode == POINTER_TYPE

664

|| TYPE_PTR_TO_MEMBER_P (from))

665

{

666

conv = build_conv
(STD_CONV, to, conv);

667

if (fcode == POINTER_TYPE

668

|| TYPE_PTRMEM_P (from)

669

|| (TYPE_PTRMEMFUNC_P (from)

670

&& ICS_STD_RANK (conv) <
PBOOL_RANK))

671

ICS_STD_RANK (conv) = PBOOL_RANK;

672

return
conv;

673

}

674

675

return
NULL_TREE;

676

}

Then below
code handles coversions described by [3], clause 4.5 “Integeral promotions”,
4.6 “Floating point promotion”, 4.7 “Integral conversions”, 4.8 “Floating point
conversions”, and 4.9 “Floating-integral conversions”. And below paragraphes
give the detail.

1.
An rvalue

of type char
, signed char
, unsigned char
,
short int
, or unsigned short int
can be converted to an rvalue

of type int
if int
can represent all the values

of the source type;
otherwise, the source rvalue

can be converted to an rvalue

of type unsigned int
.

2.
An rvalue

of type wchar_t
(3.9.1) or an enumeration type
(7.2) can be converted to an rvalue

of the first of the
following types that can represent all the values of its underlying type: int
, unsigned int
, long
, or unsigned long
.

3.
An rvalue

for an integral bit-field
(9.6) can be converted to an rvalue

of type int
if int
can represent all the values of the bit-field; otherwise, it
can be converted to unsigned int
if
unsigned int
can represent all the
values of the bit-field. If the bit-field is larger yet, no integral
promotion applies to it. If the bit-field has an enumerated type, it is
treated as any other value of that type for promotion purposes.

4.
An rvalue

of type bool
can be converted to an rvalue

of type int
, with false becoming
zero and true becoming one.

5.

These conversions are called integral promotions.

1.

An rvalue

of type float
can be converted to an rvalue

of type double
. The value is unchanged.

2.

This conversion is called floating point promotion.

1.

An rvalue

of an integer type can be converted to an rvalue

of another integer type. An rvalue

of an enumeration type can
be converted to an rvalue

of an integer type.

2.

If the destination type is unsigned, the resulting value is the least
unsigned integer congruent to the source integer (modulo 2n
where
n is the number of bits used to represent the unsigned type). [Note: In a
two’s complement representation, this conversion is conceptual and there is no
change in the bit pattern (if
there is no truncation).]

3.

If the destination type is signed, the value is unchanged if it can be
represented in the destination type (and bit-field width); otherwise, the
value is implementation-defined.

4.

If the destination type is bool
,
see 4.12. If the source type is bool
,
the value false is converted to zero and the value true is converted to one.

5.

The conversions allowed as integral promotions are excluded
from the set of integral
conversions.

1.

An rvalue

of floating point type can be converted to an rvalue

of another floating point type.
If the
source value can be exactly represented in the destination type, the result
of the conversion is that exact representation. If the source value is
between two adjacent destination values, the result of the conversion is an
implementation-defined choice of either of those values. Otherwise, the
behavior is undefined.

2.

The conversions allowed as floating point promotions are excluded
from the set of floating
point conversions.

1.

An rvalue

of a floating point type can be converted to an rvalue

of an integer type. The conversion truncates; that is, the fractional part is
discarded. The behavior is undefined if the truncated value cannot be
represented in the destination type. [Note:If the destination type is bool,
see 4.12.]

2.

An rvalue

of an integer type or of an enumeration type can be
converted to an rvalue

of a floating point type. The result is exact if
possible. Otherwise, it is an implementation-defined choice of either the
next lower or higher representable value. [Note: loss of precision occurs if
the integral value cannot be represented exactly as a value of the floating
type.] If the source type is bool, the value false is converted to zero and
the value true is converted to one.

Code from line 679 to 690
covers all cases mentioned above. As PROMO_RANK is preferred to STD_RANK, it
always uses PROMO_RANK as possible.

standard_conversion (continue)

677

/* We don't check
for ENUMERAL_TYPE here because there are no standard

678

conversions to
enum type.
*/

679

else if (tcode == INTEGER_TYPE || tcode ==
BOOLEAN_TYPE

680

|| tcode == REAL_TYPE)

681

{

682

if (! (INTEGRAL_CODE_P (fcode) || fcode ==
REAL_TYPE))

683

return
0;

684

conv = build_conv
(STD_CONV, to, conv);

685

686

/* Give this a better
rank if it's a promotion.
*/

687

if (same_type_p (to, type_promotes_to
(from))

688

&& ICS_STD_RANK (TREE_OPERAND
(conv, 0)) <= PROMO_RANK)

689

ICS_STD_RANK (conv) = PROMO_RANK;

690

}

691

else if (fcode == VECTOR_TYPE &&
tcode == VECTOR_TYPE

692

&& ((*targetm

.vector_opaque_p) (from)

693

|| (*targetm

.vector_opaque_p) (to)))

694

return
build_conv
(STD_CONV, to, conv);

695

else if (!(flags &
LOOKUP_CONSTRUCTOR_CALLABLE)

696

&& IS_AGGR_TYPE (to)
&& IS_AGGR_TYPE (from)

697

&& is_properly_derived_from
(from, to))

698

{

699

if (TREE_CODE (conv) == RVALUE_CONV)

700

conv = TREE_OPERAND (conv, 0);

701

conv = build_conv
(BASE_CONV, to, conv);

702

/* The
derived-to-base conversion indicates the initialization

703

of a parameter
with base type from an object of a derived

704

type. A
temporary object is created to hold the result of

705

the
conversion.
*/

706

NEED_TEMPORARY_P (conv) = 1;

707

}

708

else

709

return
0;

710

711

return
conv;

712

}

Code between line 695 to 707 handles the case of derived-to-base
conversion, which is defined by terms 6 of the clause “Implicit conversion
sequeunces”.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: