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:
Mark Mitchell 1998-10-03 23:11:19 +00:00 committed by Mark Mitchell
parent d5698b0753
commit 01240200ee
12 changed files with 173 additions and 95 deletions

View File

@ -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.

View File

@ -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 */

View File

@ -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);

View File

@ -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)

View File

@ -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.

View File

@ -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))
{

View File

@ -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)

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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));

View File

@ -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];
};