PATCH for type-checking improvements
Mark Mitchell
mark@markmitchell.com
Thu Oct 1 20:46:00 GMT 1998
This patch (which I did *not* check in) removes an oddity in the way
g++ deals with type qualifiers. In particular, for something like
`const int i', g++ records the type as `int' and sets TREE_READONLY on
the VAR_DECL. While I'm well aware that top-level qualifiers don't
matter in many situations, there are those where they do, and besides
this behavior is wicked counter-intuitive.
The `const'-ness of the type and the `const'-ness of the expression
should be orthogonal. For example, a `const' object with a `mutable'
member is not TREE_READONLY, and a non-`const' object which the
compiler determines is never written could well be TREE_READONLY.
This patch makes the top-level qualifiers part of the type. (Of
course, the DECL is still marked that way too, but those bits are now
used only to guide the back-end as it lays out objects and to aid in
optimzation.)
Don't let the ChangeLog fool you; this is a relatively simple change,
repeated in several places. (There are also a few improvements to
error-recovery where I found the compiler looking at the TREE_TYPE of
an ERROR_MARK, for example.) There is at least one real bug fixed by
this change (in the test-case below). This test-case previously
failed to compile since S::X was considered of a different type than
S::X + 3.
Jason?
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-10-01 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-hadnling.
(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.
Index: testsuite/g++.old-deja/g++.pt/overload3.C
===================================================================
RCS file: overload3.C
diff -N overload3.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- overload3.C Thu Oct 1 19:12:13 1998
***************
*** 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];
+ };
+
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.87
diff -c -p -r1.87 class.c
*** class.c 1998/10/01 12:31:18 1.87
--- class.c 1998/10/02 02:13:14
*************** static tree *current_class_base, *curren
*** 48,55 ****
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. */
tree current_class_ptr, current_class_ref;
/* The following two can be derived from the previous one */
--- 48,56 ----
static int current_class_stacksize;
int current_class_depth;
! /* 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 */
Index: cp/cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.32
diff -c -p -r1.32 cvt.c
*** cvt.c 1998/09/25 08:59:51 1.32
--- cvt.c 1998/10/02 02:13:18
*************** ocp_convert (type, expr, convtype, flags
*** 664,672 ****
&& 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 (code == VOID_TYPE && (convtype & CONV_STATIC))
return build1 (CONVERT_EXPR, type, e);
--- 664,682 ----
&& 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)))
! {
! 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);
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.217
diff -c -p -r1.217 decl.c
*** decl.c 1998/09/28 17:34:29 1.217
--- decl.c 1998/10/02 02:14:05
*************** decls_match (newdecl, olddecl)
*** 2571,2590 ****
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;
}
return types_match;
--- 2571,2579 ----
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
! types_match = comptypes (TREE_TYPE (newdecl),
! TREE_TYPE (olddecl), 1);
}
return types_match;
*************** duplicate_decls (newdecl, olddecl)
*** 2908,2920 ****
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,
--- 2897,2902 ----
*************** grokdeclarator (declarator, declspecs, d
*** 9062,9068 ****
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);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
--- 9044,9050 ----
constp = !! RIDBIT_SETP (RID_CONST, specbits) + TYPE_READONLY (type);
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
! type = cp_build_type_variant (type, constp, volatilep);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
*************** grokdeclarator (declarator, declspecs, d
*** 9795,9800 ****
--- 9777,9783 ----
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;
*************** grokparms (first_parm, funcdef_flag)
*** 10881,10887 ****
NULL_TREE);
if (! decl)
continue;
! type = TREE_TYPE (decl);
if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
--- 10864,10874 ----
NULL_TREE);
if (! decl)
continue;
!
! /* 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)
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.137
diff -c -p -r1.137 decl2.c
*** decl2.c 1998/09/28 17:34:31 1.137
--- decl2.c 1998/10/02 02:14:13
*************** do_dtors (start)
*** 3185,3191 ****
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
if these calls appeared in the scope of the member's
class.
--- 3185,3191 ----
Access control for implicit calls to the constructors,
the conversion functions, or the destructor called to
! create and destroy a static data member is performed as
if these calls appeared in the scope of the member's
class.
Index: cp/error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.53
diff -c -p -r1.53 error.c
*** error.c 1998/09/09 00:52:42 1.53
--- error.c 1998/10/02 02:14:17
*************** dump_simple_decl (t, type, v)
*** 667,673 ****
{
dump_type_prefix (type, v, 0);
OB_PUTC (' ');
- dump_readonly_or_volatile (t, after);
}
if (DECL_CLASS_SCOPE_P (t))
{
--- 667,672 ----
Index: cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.66
diff -c -p -r1.66 init.c
*** init.c 1998/09/25 08:59:57 1.66
--- init.c 1998/10/02 02:14:27
*************** build_new_1 (exp)
*** 2391,2402 ****
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. */
tree deref;
rval = save_expr (rval);
deref = build_indirect_ref (rval, NULL_PTR);
TREE_READONLY (deref) = 0;
if (TREE_CHAIN (init) != NULL_TREE)
--- 2391,2416 ----
if (! TYPE_NEEDS_CONSTRUCTING (type)
&& ! IS_AGGR_TYPE (type) && ! has_array)
{
! /* 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)
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.77
diff -c -p -r1.77 lex.c
*** lex.c 1998/09/25 08:59:58 1.77
--- lex.c 1998/10/02 02:14:40
*************** is_global (d)
*** 2853,2858 ****
--- 2853,2861 ----
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:
Index: cp/sig.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/sig.c,v
retrieving revision 1.10
diff -c -p -r1.10 sig.c
*** sig.c 1998/09/07 14:25:30 1.10
--- sig.c 1998/10/02 02:14:43
*************** build_member_function_pointer (member)
*** 321,327 ****
GNU_xref_ref (current_function_decl, name);
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
! TYPE_MAIN_VARIANT (sigtable_entry_type));
TREE_CONSTANT (entry) = 1;
TREE_READONLY (entry) = 1;
--- 321,327 ----
GNU_xref_ref (current_function_decl, name);
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
! sigtable_entry_type);
TREE_CONSTANT (entry) = 1;
TREE_READONLY (entry) = 1;
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.67
diff -c -p -r1.67 tree.c
*** tree.c 1998/10/01 12:31:22 1.67
--- tree.c 1998/10/02 02:14:49
*************** lvalue_type (arg)
*** 2571,2579 ****
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;
}
--- 2571,2576 ----
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.110
diff -c -p -r1.110 typeck.c
*** typeck.c 1998/09/25 09:00:03 1.110
--- typeck.c 1998/10/02 02:15:10
*************** decay_conversion (exp)
*** 1684,1692 ****
if (code == ARRAY_TYPE)
{
register tree adr;
- tree restype;
tree ptrtype;
- int constp, volatilep;
if (TREE_CODE (exp) == INDIRECT_REF)
{
--- 1684,1690 ----
*************** decay_conversion (exp)
*** 1718,1738 ****
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);
if (TREE_CODE (exp) == VAR_DECL)
{
--- 1716,1722 ----
return error_mark_node;
}
! ptrtype = build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (exp) == VAR_DECL)
{
*************** build_component_ref (datum, component, b
*** 1954,1967 ****
tree datum, component, basetype_path;
int protect;
{
! register tree basetype = TREE_TYPE (datum);
register enum tree_code code;
register tree field = NULL;
register tree ref;
if (processing_template_decl)
return build_min_nt (COMPONENT_REF, datum, component);
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
inside it. */
switch (TREE_CODE (datum))
--- 1938,1961 ----
tree datum, component, basetype_path;
int protect;
{
! 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))
*************** build_component_ref (datum, component, b
*** 1995,2007 ****
if (code == REFERENCE_TYPE)
{
datum = convert_from_reference (datum);
! basetype = TREE_TYPE (datum);
code = TREE_CODE (basetype);
}
if (TREE_CODE (datum) == OFFSET_REF)
{
datum = resolve_offset_ref (datum);
! basetype = TREE_TYPE (datum);
code = TREE_CODE (basetype);
}
--- 1989,2001 ----
if (code == REFERENCE_TYPE)
{
datum = convert_from_reference (datum);
! basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
if (TREE_CODE (datum) == OFFSET_REF)
{
datum = resolve_offset_ref (datum);
! basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
*************** build_component_ref (datum, component, b
*** 2086,2092 ****
tree access, fndecl;
/* Unique, so use this one now. */
! basetype = TREE_PURPOSE (fndecls);
fndecl = TREE_VALUE (fndecls);
access = compute_access (TREE_PURPOSE (fndecls), fndecl);
if (access == access_public_node)
--- 2080,2086 ----
tree access, fndecl;
/* Unique, so use this one now. */
! basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
fndecl = TREE_VALUE (fndecls);
access = compute_access (TREE_PURPOSE (fndecls), fndecl);
if (access == access_public_node)
*************** build_component_ref (datum, component, b
*** 2198,2212 ****
}
}
! ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
! if (TREE_READONLY (datum) || TREE_READONLY (field))
TREE_READONLY (ref) = 1;
! if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
return ref;
}
--- 2192,2231 ----
}
}
! /* 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));
! /* 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;
! else if (volatilep)
TREE_THIS_VOLATILE (ref) = 1;
return ref;
}
*************** build_indirect_ref (ptr, errorstring)
*** 2270,2298 ****
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_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))))
return TREE_OPERAND (pointer, 0);
else
{
! tree t = TREE_TYPE (type);
! register tree ref = build1 (INDIRECT_REF,
! TYPE_MAIN_VARIANT (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);
return ref;
}
}
--- 2289,2320 ----
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 */
+ tree t = canonical_type_variant (TREE_TYPE (type));
+
if (TREE_CODE (pointer) == ADDR_EXPR
&& !flag_volatile
! && 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 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_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
TREE_SIDE_EFFECTS (ref)
! = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
|| flag_volatile);
return ref;
}
}
*************** build_array_ref (array, idx)
*** 2403,2425 ****
warning ("subscripting array declared `register'");
}
! type = TYPE_MAIN_VARIANT (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));
TREE_SIDE_EFFECTS (rval)
! |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
! | 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));
return require_complete_type (fold (rval));
}
--- 2425,2440 ----
warning ("subscripting array declared `register'");
}
! 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 (type) | TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
! |= (TYPE_VOLATILE (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
! |= (TYPE_VOLATILE (type) | TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
*************** build_unary_op (code, xarg, noconvert)
*** 4720,4726 ****
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
! argtype = build_pointer_type (argtype);
if (mark_addressable (arg) == 0)
return error_mark_node;
--- 4735,4742 ----
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
! if (argtype != error_mark_node)
! argtype = build_pointer_type (argtype);
if (mark_addressable (arg) == 0)
return error_mark_node;
*************** unary_complex_lvalue (code, arg)
*** 4876,4882 ****
{
/* 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;
}
--- 4892,4898 ----
{
/* Don't know if this should return address to just
_DECL, or actual address resolved in this expression. */
! cp_error ("address of bound pointer-to-member expression");
return error_mark_node;
}
*************** build_conditional_expr (ifexp, op1, op2)
*** 5115,5122 ****
if (type1 != type2)
type1 = cp_build_type_variant
(type1,
! TREE_READONLY (op1) || TREE_READONLY (op2),
! TREE_THIS_VOLATILE (op1) || TREE_THIS_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));
--- 5131,5138 ----
if (type1 != type2)
type1 = cp_build_type_variant
(type1,
! 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));
More information about the Gcc-patches
mailing list