From 01240200ee6cb2f0a7b731faf63b8aa2a3049f61 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 3 Oct 1998 23:11:19 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 33 +++++ gcc/cp/class.c | 5 +- gcc/cp/cvt.c | 16 ++- gcc/cp/decl.c | 31 ++-- gcc/cp/decl2.c | 2 +- gcc/cp/error.c | 1 - gcc/cp/init.c | 18 ++- gcc/cp/lex.c | 3 + gcc/cp/sig.c | 2 +- gcc/cp/tree.c | 3 - gcc/cp/typeck.c | 136 ++++++++++-------- gcc/testsuite/g++.old-deja/g++.pt/overload3.C | 18 +++ 12 files changed, 173 insertions(+), 95 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/overload3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8604334c7bf..7634176757c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,36 @@ +1998-10-03 Mark Mitchell + + * 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 * decl2.c (merge_functions): Remove duplicates. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 8e7d715eb89..b64a91ad9a6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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 */ diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index c76b743dc25..06c5290c424 100644 --- a/gcc/cp/cvt.c +++ b/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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a4ed7b9d4ac..71fe530e66e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 50eea9f8247..492688b6c96 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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. diff --git a/gcc/cp/error.c b/gcc/cp/error.c index f06705ecc9f..fb6995fe49f 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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)) { diff --git a/gcc/cp/init.c b/gcc/cp/init.c index c5ba2c4d233..b6a20ba8687 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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) diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index ac4d8b49982..d69dc6ea452 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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: diff --git a/gcc/cp/sig.c b/gcc/cp/sig.c index 65350db7962..e70ec3f17ed 100644 --- a/gcc/cp/sig.c +++ b/gcc/cp/sig.c @@ -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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index e66cbff5b60..00202b31bba 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 40b5b7e76fb..d0be08addad 100644 --- a/gcc/cp/typeck.c +++ b/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)); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/overload3.C b/gcc/testsuite/g++.old-deja/g++.pt/overload3.C new file mode 100644 index 00000000000..a716917bc0a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/overload3.C @@ -0,0 +1,18 @@ +// Build don't link: + +template +void g(T, T); + +template +void g(int*, T); + +struct S +{ + void f() const + { + g(X, X+3); + } + + double X[3]; +}; +