class.c (current_class_ptr, [...]): Clarify documentation.
* class.c (current_class_ptr, current_class_ref): Clarify documentation. * cvt.c (ocp_convert): Don't expect fold to remove all trivial NOP type conversions. * decl.c (decls_match): Use comptypes directly; ignore qualifiers on the DECL. (duplicate_decls): Remove qualifier checks on DECL. (grokdeclarator): Make the type built up include top-level qualifiers. * decl2.c (do_dtors): Fix spelling error. * error.c (dump_simple_decl): Don't look at qualifiers on the decl when printing type information. * init.c (build_new_1): Add documentation. Deal with the fact that type of allocated memory now contains qualifiers. * lex.c (is_global): Improve error-recovery. * sig.c (build_member_function_pointer): Don't cast away const on fields of sigtable_entry_type. * tree.c (lvalue_type): Don't look at top-level qualifiers on expressions. * typeck.c (decay_conversion): Likewise. (build_component_ref): Make sure the type of the COMPONENT_REF contains top-level qualifiers, as appropriate. Improve error-handling. (build_indirect_ref): Simplify. Don't strip top-level qualifiers. (build_array_ref): Likewise. (build_unary_op): Improve error-recovery. (unary_complex_lvalue): Make taking the address a bound member function an error, not a sorry. (build_conditional_expr): Look at the type qualifiers, not the qualifiers on the expression itself. From-SVN: r22802
This commit is contained in:
parent
d5698b0753
commit
01240200ee
|
@ -1,3 +1,36 @@
|
|||
1998-10-03 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* class.c (current_class_ptr, current_class_ref): Clarify
|
||||
documentation.
|
||||
* cvt.c (ocp_convert): Don't expect fold to remove all trivial
|
||||
NOP type conversions.
|
||||
* decl.c (decls_match): Use comptypes directly; ignore
|
||||
qualifiers on the DECL.
|
||||
(duplicate_decls): Remove qualifier checks on DECL.
|
||||
(grokdeclarator): Make the type built up include top-level
|
||||
qualifiers.
|
||||
* decl2.c (do_dtors): Fix spelling error.
|
||||
* error.c (dump_simple_decl): Don't look at qualifiers on the decl
|
||||
when printing type information.
|
||||
* init.c (build_new_1): Add documentation. Deal with the fact
|
||||
that type of allocated memory now contains qualifiers.
|
||||
* lex.c (is_global): Improve error-recovery.
|
||||
* sig.c (build_member_function_pointer): Don't cast away const
|
||||
on fields of sigtable_entry_type.
|
||||
* tree.c (lvalue_type): Don't look at top-level qualifiers on
|
||||
expressions.
|
||||
* typeck.c (decay_conversion): Likewise.
|
||||
(build_component_ref): Make sure the type of the COMPONENT_REF
|
||||
contains top-level qualifiers, as appropriate. Improve
|
||||
error-handling.
|
||||
(build_indirect_ref): Simplify. Don't strip top-level qualifiers.
|
||||
(build_array_ref): Likewise.
|
||||
(build_unary_op): Improve error-recovery.
|
||||
(unary_complex_lvalue): Make taking the address a bound member
|
||||
function an error, not a sorry.
|
||||
(build_conditional_expr): Look at the type qualifiers, not the
|
||||
qualifiers on the expression itself.
|
||||
|
||||
1998-10-03 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl2.c (merge_functions): Remove duplicates.
|
||||
|
|
|
@ -48,8 +48,9 @@ static tree *current_class_base, *current_class_stack;
|
|||
static int current_class_stacksize;
|
||||
int current_class_depth;
|
||||
|
||||
/* The current_class_ptr is the pointer to the current class.
|
||||
current_class_ref is the actual current class. */
|
||||
/* When we're processing a member function, current_class_ptr is the
|
||||
PARM_DECL for the `this' pointer. The current_class_ref is an
|
||||
expression for `*this'. */
|
||||
tree current_class_ptr, current_class_ref;
|
||||
|
||||
/* The following two can be derived from the previous one */
|
||||
|
|
16
gcc/cp/cvt.c
16
gcc/cp/cvt.c
|
@ -664,9 +664,19 @@ ocp_convert (type, expr, convtype, flags)
|
|||
&& TYPE_HAS_CONSTRUCTOR (type))
|
||||
/* We need a new temporary; don't take this shortcut. */;
|
||||
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
|
||||
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
|
||||
return fold (build1 (NOP_EXPR, type, e));
|
||||
|
||||
{
|
||||
if (comptypes (type, TREE_TYPE (e), 1))
|
||||
/* The call to fold will not always remove the NOP_EXPR as
|
||||
might be expected, since if one of the types is a typedef;
|
||||
the comparsion in fold is just equality of pointers, not a
|
||||
call to comptypes. */
|
||||
;
|
||||
else
|
||||
e = build1 (NOP_EXPR, type, e);
|
||||
|
||||
return fold (e);
|
||||
}
|
||||
|
||||
if (code == VOID_TYPE && (convtype & CONV_STATIC))
|
||||
return build1 (CONVERT_EXPR, type, e);
|
||||
|
||||
|
|
|
@ -2571,20 +2571,9 @@ decls_match (newdecl, olddecl)
|
|||
types_match = TREE_TYPE (newdecl) == NULL_TREE;
|
||||
else if (TREE_TYPE (newdecl) == NULL_TREE)
|
||||
types_match = 0;
|
||||
/* Qualifiers must match, and they may be present on either, the type
|
||||
or the decl. */
|
||||
else if ((TREE_READONLY (newdecl)
|
||||
|| TYPE_READONLY (TREE_TYPE (newdecl)))
|
||||
== (TREE_READONLY (olddecl)
|
||||
|| TYPE_READONLY (TREE_TYPE (olddecl)))
|
||||
&& (TREE_THIS_VOLATILE (newdecl)
|
||||
|| TYPE_VOLATILE (TREE_TYPE (newdecl)))
|
||||
== (TREE_THIS_VOLATILE (olddecl)
|
||||
|| TYPE_VOLATILE (TREE_TYPE (olddecl))))
|
||||
types_match = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (newdecl)),
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)), 1);
|
||||
else
|
||||
types_match = 0;
|
||||
types_match = comptypes (TREE_TYPE (newdecl),
|
||||
TREE_TYPE (olddecl), 1);
|
||||
}
|
||||
|
||||
return types_match;
|
||||
|
@ -2908,13 +2897,6 @@ duplicate_decls (newdecl, olddecl)
|
|||
olddecl);
|
||||
}
|
||||
}
|
||||
/* These bits are logically part of the type for non-functions. */
|
||||
else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|
||||
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
|
||||
{
|
||||
cp_pedwarn ("type qualifiers for `%#D'", newdecl);
|
||||
cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
|
||||
}
|
||||
}
|
||||
|
||||
/* If new decl is `static' and an `extern' was seen previously,
|
||||
|
@ -9084,7 +9066,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
|||
|
||||
constp = !! RIDBIT_SETP (RID_CONST, specbits) + TYPE_READONLY (type);
|
||||
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
|
||||
type = build_type_variant (type, 0, 0);
|
||||
type = cp_build_type_variant (type, constp, volatilep);
|
||||
staticp = 0;
|
||||
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
|
||||
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
|
||||
|
@ -9817,6 +9799,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
|||
pedwarn ("discarding `volatile' applied to a reference");
|
||||
constp = volatilep = 0;
|
||||
}
|
||||
type = cp_build_type_variant (type, constp, volatilep);
|
||||
}
|
||||
declarator = TREE_OPERAND (declarator, 0);
|
||||
ctype = NULL_TREE;
|
||||
|
@ -10903,7 +10886,11 @@ grokparms (first_parm, funcdef_flag)
|
|||
NULL_TREE);
|
||||
if (! decl)
|
||||
continue;
|
||||
type = TREE_TYPE (decl);
|
||||
|
||||
/* Top-level qualifiers on the parameters are
|
||||
ignored for function types. */
|
||||
type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
|
||||
|
||||
if (TREE_CODE (type) == VOID_TYPE)
|
||||
decl = void_type_node;
|
||||
else if (TREE_CODE (type) == METHOD_TYPE)
|
||||
|
|
|
@ -3192,7 +3192,7 @@ do_dtors (start)
|
|||
|
||||
Access control for implicit calls to the constructors,
|
||||
the conversion functions, or the destructor called to
|
||||
create and destroy a static data member is per- formed as
|
||||
create and destroy a static data member is performed as
|
||||
if these calls appeared in the scope of the member's
|
||||
class.
|
||||
|
||||
|
|
|
@ -667,7 +667,6 @@ dump_simple_decl (t, type, v)
|
|||
{
|
||||
dump_type_prefix (type, v, 0);
|
||||
OB_PUTC (' ');
|
||||
dump_readonly_or_volatile (t, after);
|
||||
}
|
||||
if (DECL_CLASS_SCOPE_P (t))
|
||||
{
|
||||
|
|
|
@ -2391,12 +2391,26 @@ build_new_1 (exp)
|
|||
if (! TYPE_NEEDS_CONSTRUCTING (type)
|
||||
&& ! IS_AGGR_TYPE (type) && ! has_array)
|
||||
{
|
||||
/* New 2.0 interpretation: `new int (10)' means
|
||||
allocate an int, and initialize it with 10. */
|
||||
/* We are processing something like `new int (10)', which
|
||||
means allocate an int, and initialize it with 10. */
|
||||
tree deref;
|
||||
tree deref_type;
|
||||
|
||||
/* At present RVAL is a temporary variable, created to hold
|
||||
the value from the call to `operator new'. We transform
|
||||
it to (*RVAL = INIT, RVAL). */
|
||||
rval = save_expr (rval);
|
||||
deref = build_indirect_ref (rval, NULL_PTR);
|
||||
|
||||
/* Even for something like `new const int (10)' we must
|
||||
allow the expression to be non-const while we do the
|
||||
initialization. */
|
||||
deref_type = TREE_TYPE (deref);
|
||||
if (TYPE_READONLY (deref_type))
|
||||
TREE_TYPE (deref)
|
||||
= cp_build_type_variant (deref_type,
|
||||
/*constp=*/0,
|
||||
TYPE_VOLATILE (deref_type));
|
||||
TREE_READONLY (deref) = 0;
|
||||
|
||||
if (TREE_CHAIN (init) != NULL_TREE)
|
||||
|
|
|
@ -2853,6 +2853,9 @@ is_global (d)
|
|||
while (1)
|
||||
switch (TREE_CODE (d))
|
||||
{
|
||||
case ERROR_MARK:
|
||||
return 1;
|
||||
|
||||
case OVERLOAD: d = OVL_FUNCTION (d); continue;
|
||||
case TREE_LIST: d = TREE_VALUE (d); continue;
|
||||
default:
|
||||
|
|
|
@ -321,7 +321,7 @@ build_member_function_pointer (member)
|
|||
GNU_xref_ref (current_function_decl, name);
|
||||
|
||||
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
|
||||
TYPE_MAIN_VARIANT (sigtable_entry_type));
|
||||
sigtable_entry_type);
|
||||
TREE_CONSTANT (entry) = 1;
|
||||
TREE_READONLY (entry) = 1;
|
||||
|
||||
|
|
|
@ -2571,9 +2571,6 @@ lvalue_type (arg)
|
|||
tree type = TREE_TYPE (arg);
|
||||
if (TREE_CODE (arg) == OVERLOAD)
|
||||
type = unknown_type_node;
|
||||
else if (TREE_CODE (type) != ARRAY_TYPE)
|
||||
type = cp_build_type_variant
|
||||
(type, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
136
gcc/cp/typeck.c
136
gcc/cp/typeck.c
|
@ -1684,9 +1684,7 @@ decay_conversion (exp)
|
|||
if (code == ARRAY_TYPE)
|
||||
{
|
||||
register tree adr;
|
||||
tree restype;
|
||||
tree ptrtype;
|
||||
int constp, volatilep;
|
||||
|
||||
if (TREE_CODE (exp) == INDIRECT_REF)
|
||||
{
|
||||
|
@ -1718,21 +1716,7 @@ decay_conversion (exp)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
constp = volatilep = 0;
|
||||
if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
|
||||
|| TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
|
||||
{
|
||||
constp = TREE_READONLY (exp);
|
||||
volatilep = TREE_THIS_VOLATILE (exp);
|
||||
}
|
||||
|
||||
restype = TREE_TYPE (type);
|
||||
if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
|
||||
|| constp || volatilep)
|
||||
restype = cp_build_type_variant (restype,
|
||||
TYPE_READONLY (type) || constp,
|
||||
TYPE_VOLATILE (type) || volatilep);
|
||||
ptrtype = build_pointer_type (restype);
|
||||
ptrtype = build_pointer_type (TREE_TYPE (type));
|
||||
|
||||
if (TREE_CODE (exp) == VAR_DECL)
|
||||
{
|
||||
|
@ -1954,14 +1938,24 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||
tree datum, component, basetype_path;
|
||||
int protect;
|
||||
{
|
||||
register tree basetype = TREE_TYPE (datum);
|
||||
register tree basetype;
|
||||
register enum tree_code code;
|
||||
register tree field = NULL;
|
||||
register tree ref;
|
||||
tree field_type;
|
||||
int constp;
|
||||
int volatilep;
|
||||
|
||||
if (processing_template_decl)
|
||||
return build_min_nt (COMPONENT_REF, datum, component);
|
||||
|
||||
if (datum == error_mark_node
|
||||
|| TREE_TYPE (datum) == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* BASETYPE holds the type of the class containing the COMPONENT. */
|
||||
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||
|
||||
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
|
||||
inside it. */
|
||||
switch (TREE_CODE (datum))
|
||||
|
@ -1995,13 +1989,13 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||
if (code == REFERENCE_TYPE)
|
||||
{
|
||||
datum = convert_from_reference (datum);
|
||||
basetype = TREE_TYPE (datum);
|
||||
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||
code = TREE_CODE (basetype);
|
||||
}
|
||||
if (TREE_CODE (datum) == OFFSET_REF)
|
||||
{
|
||||
datum = resolve_offset_ref (datum);
|
||||
basetype = TREE_TYPE (datum);
|
||||
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||
code = TREE_CODE (basetype);
|
||||
}
|
||||
|
||||
|
@ -2086,7 +2080,7 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||
tree access, fndecl;
|
||||
|
||||
/* Unique, so use this one now. */
|
||||
basetype = TREE_PURPOSE (fndecls);
|
||||
basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
|
||||
fndecl = TREE_VALUE (fndecls);
|
||||
access = compute_access (TREE_PURPOSE (fndecls), fndecl);
|
||||
if (access == access_public_node)
|
||||
|
@ -2198,15 +2192,40 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||
}
|
||||
}
|
||||
|
||||
ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
|
||||
/* Compute the type of the field, as described in [expr.ref]. */
|
||||
constp = 0;
|
||||
volatilep = 0;
|
||||
field_type = TREE_TYPE (field);
|
||||
if (TREE_CODE (field_type) == REFERENCE_TYPE)
|
||||
/* The standard says that the type of the result should be the
|
||||
type referred to by the reference. But for now, at least, we
|
||||
do the conversion from reference type later. */
|
||||
;
|
||||
else
|
||||
{
|
||||
/* A field is const (volatile) if the enclosing object, or the
|
||||
field itself, is const (volatile). But, a mutable field is
|
||||
not const, even within a const object. */
|
||||
constp = (!(DECL_LANG_SPECIFIC (field)
|
||||
&& DECL_MUTABLE_P (field))
|
||||
&& (TYPE_READONLY (field_type)
|
||||
|| TYPE_READONLY (TREE_TYPE (datum))));
|
||||
volatilep = (TYPE_VOLATILE (field_type)
|
||||
|| TYPE_VOLATILE (TREE_TYPE (datum)));
|
||||
if (!IS_SIGNATURE (field_type))
|
||||
field_type = cp_build_type_variant (field_type, constp, volatilep);
|
||||
}
|
||||
|
||||
ref = fold (build (COMPONENT_REF, field_type,
|
||||
break_out_cleanups (datum), field));
|
||||
|
||||
if (TREE_READONLY (datum) || TREE_READONLY (field))
|
||||
/* Mark the expression const or volatile, as appropriate. Even
|
||||
though we've dealt with the type above, we still have to mark the
|
||||
expression itself. */
|
||||
if (constp)
|
||||
TREE_READONLY (ref) = 1;
|
||||
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
|
||||
else if (volatilep)
|
||||
TREE_THIS_VOLATILE (ref) = 1;
|
||||
if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
|
||||
TREE_READONLY (ref) = 0;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
@ -2270,29 +2289,34 @@ build_indirect_ref (ptr, errorstring)
|
|||
|
||||
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
|
||||
{
|
||||
/* [expr.unary.op]
|
||||
|
||||
If the type of the expression is "pointer to T," the type
|
||||
of the result is "T."
|
||||
|
||||
We must use the canonical variant because certain parts of
|
||||
the back end, like fold, do pointer comparisons between
|
||||
types. */
|
||||
tree t = canonical_type_variant (TREE_TYPE (type));
|
||||
|
||||
if (TREE_CODE (pointer) == ADDR_EXPR
|
||||
&& !flag_volatile
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))
|
||||
== TYPE_MAIN_VARIANT (TREE_TYPE (type)))
|
||||
&& (TREE_READONLY (TREE_OPERAND (pointer, 0))
|
||||
== TYPE_READONLY (TREE_TYPE (type)))
|
||||
&& (TREE_THIS_VOLATILE (TREE_OPERAND (pointer, 0))
|
||||
== TYPE_VOLATILE (TREE_TYPE (type))))
|
||||
&& comptypes (t, TREE_TYPE (TREE_OPERAND (pointer, 0)), 1))
|
||||
/* The POINTER was something like `&x'. We simplify `*&x' to
|
||||
`x'. */
|
||||
return TREE_OPERAND (pointer, 0);
|
||||
else
|
||||
{
|
||||
tree t = TREE_TYPE (type);
|
||||
register tree ref = build1 (INDIRECT_REF,
|
||||
TYPE_MAIN_VARIANT (t), pointer);
|
||||
tree ref = build1 (INDIRECT_REF, t, pointer);
|
||||
|
||||
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
|
||||
so that we get the proper error message if the result is used
|
||||
to assign to. Also, &* is supposed to be a no-op. */
|
||||
TREE_READONLY (ref) = TYPE_READONLY (t);
|
||||
TREE_SIDE_EFFECTS (ref)
|
||||
= (TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer)
|
||||
|| flag_volatile);
|
||||
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
|
||||
TREE_SIDE_EFFECTS (ref)
|
||||
= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
|
||||
|| flag_volatile);
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
@ -2403,23 +2427,16 @@ build_array_ref (array, idx)
|
|||
warning ("subscripting array declared `register'");
|
||||
}
|
||||
|
||||
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
|
||||
type = TREE_TYPE (TREE_TYPE (array));
|
||||
rval = build (ARRAY_REF, type, array, idx);
|
||||
/* Array ref is const/volatile if the array elements are
|
||||
or if the array is.. */
|
||||
TREE_READONLY (rval)
|
||||
|= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
|
||||
| TREE_READONLY (array));
|
||||
|= (TYPE_READONLY (type) | TREE_READONLY (array));
|
||||
TREE_SIDE_EFFECTS (rval)
|
||||
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
|
||||
| TREE_SIDE_EFFECTS (array));
|
||||
|= (TYPE_VOLATILE (type) | TREE_SIDE_EFFECTS (array));
|
||||
TREE_THIS_VOLATILE (rval)
|
||||
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
|
||||
/* This was added by rms on 16 Nov 91.
|
||||
It fixes vol struct foo *a; a->elts[1]
|
||||
in an inline function.
|
||||
Hope it doesn't break something else. */
|
||||
| TREE_THIS_VOLATILE (array));
|
||||
|= (TYPE_VOLATILE (type) | TREE_THIS_VOLATILE (array));
|
||||
return require_complete_type (fold (rval));
|
||||
}
|
||||
|
||||
|
@ -4720,7 +4737,8 @@ build_unary_op (code, xarg, noconvert)
|
|||
&& !lvalue_or_else (arg, "unary `&'"))
|
||||
return error_mark_node;
|
||||
|
||||
argtype = build_pointer_type (argtype);
|
||||
if (argtype != error_mark_node)
|
||||
argtype = build_pointer_type (argtype);
|
||||
|
||||
if (mark_addressable (arg) == 0)
|
||||
return error_mark_node;
|
||||
|
@ -4871,14 +4889,12 @@ unary_complex_lvalue (code, arg)
|
|||
if (TREE_OPERAND (arg, 0)
|
||||
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
|
||||
|| (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
|
||||
!= error_mark_node)))
|
||||
if (TREE_CODE (t) != FIELD_DECL)
|
||||
{
|
||||
/* Don't know if this should return address to just
|
||||
_DECL, or actual address resolved in this expression. */
|
||||
sorry ("address of bound pointer-to-member expression");
|
||||
return error_mark_node;
|
||||
}
|
||||
!= error_mark_node))
|
||||
&& TREE_CODE (t) != FIELD_DECL)
|
||||
{
|
||||
cp_error ("taking address of bound pointer-to-member expression");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Add in the offset to the field. */
|
||||
offset = convert (sizetype,
|
||||
|
@ -5115,8 +5131,8 @@ build_conditional_expr (ifexp, op1, op2)
|
|||
if (type1 != type2)
|
||||
type1 = cp_build_type_variant
|
||||
(type1,
|
||||
TREE_READONLY (op1) || TREE_READONLY (op2),
|
||||
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
|
||||
TYPE_READONLY (op1) || TYPE_READONLY (op2),
|
||||
TYPE_VOLATILE (op1) || TYPE_VOLATILE (op2));
|
||||
/* ??? This is a kludge to deal with the fact that
|
||||
we don't sort out integers and enums properly, yet. */
|
||||
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// Build don't link:
|
||||
|
||||
template <class T>
|
||||
void g(T, T);
|
||||
|
||||
template <class T>
|
||||
void g(int*, T);
|
||||
|
||||
struct S
|
||||
{
|
||||
void f() const
|
||||
{
|
||||
g(X, X+3);
|
||||
}
|
||||
|
||||
double X[3];
|
||||
};
|
||||
|
Loading…
Reference in New Issue