From: Jason Merrill Date: Sat, 7 Aug 1999 01:31:58 +0000 (+0000) Subject: decl.c (bad_specifiers): It's OK to have an EH spec on a function pointer. X-Git-Tag: releases/gcc-2.95.1~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92410ebf67bfc510f3a7b1f7528cd4dfb83755ab;p=thirdparty%2Fgcc.git decl.c (bad_specifiers): It's OK to have an EH spec on a function pointer. * decl.c (bad_specifiers): It's OK to have an EH spec on a function pointer. * pt.c (maybe_get_template_decl_from_type_decl): Make sure that we're looking at a class. * decl.c (lookup_name_real): Set the complain flag if we're looking for a namespace member. * decl.c (pushdecl): Only give an error for shadowing a parm from *this* function. * decl2.c (build_expr_from_tree, case METHOD_CALL_EXPR): Only build_expr_from_tree on the args of a TEMPLATE_ID_EXPR. * class.c (mark_overriders): Fix order of args to overrides. (warn_hidden): Likewise. Fix for having virtual and non-virtual functions with the same name. * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for virtual functions and MI. Simplify. * typeck.c (c_expand_return): Downgrade pedwarn about returning NULL from op new to warning. * decl2.c (reparse_absdcl_as_casts): Don't warn about old-style casts in system headers or extern "C" blocks. * pt.c (do_decl_instantiation): Downgrade duplicate instantiation errors to pedwarn. * error.c (dump_type_real): Handle TREE_LIST again. * typeck.c (comp_target_parms): Don't complain about converting from () to (...) if !flag_strict_prototype. * class.c (instantiate_type): Downgrade errors for object-dependent memfn refs to pedwarn. From-SVN: r28563 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 153c4260bb5c..bfebb6e241b9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,45 @@ +1999-08-06 Jason Merrill + + * decl.c (bad_specifiers): It's OK to have an EH spec on a function + pointer. + + * pt.c (maybe_get_template_decl_from_type_decl): Make sure that + we're looking at a class. + + * decl.c (lookup_name_real): Set the complain flag if we're + looking for a namespace member. + + * decl.c (pushdecl): Only give an error for shadowing a parm + from *this* function. + + * decl2.c (build_expr_from_tree, case METHOD_CALL_EXPR): Only + build_expr_from_tree on the args of a TEMPLATE_ID_EXPR. + + * class.c (mark_overriders): Fix order of args to overrides. + (warn_hidden): Likewise. Fix for having virtual and non-virtual + functions with the same name. + + * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. + * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for + virtual functions and MI. Simplify. + + * typeck.c (c_expand_return): Downgrade pedwarn about returning NULL + from op new to warning. + + * decl2.c (reparse_absdcl_as_casts): Don't warn about old-style + casts in system headers or extern "C" blocks. + + * pt.c (do_decl_instantiation): Downgrade duplicate instantiation + errors to pedwarn. + + * error.c (dump_type_real): Handle TREE_LIST again. + + * typeck.c (comp_target_parms): Don't complain about + converting from () to (...) if !flag_strict_prototype. + + * class.c (instantiate_type): Downgrade errors for object-dependent + memfn refs to pedwarn. + 1999-08-06 Alexandre Oliva * pt.c (tsubst): Use build_index_type to build in-template array diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 31dcb67126f5..400c67de41ad 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2785,18 +2785,18 @@ get_basefndecls (fndecl, t) /* Mark the functions that have been hidden with their overriders. Since we start out with all functions already marked with a hider, - no need to mark functions that are just hidden. */ + no need to mark functions that are just hidden. + + Subroutine of warn_hidden. */ static void mark_overriders (fndecl, base_fndecls) tree fndecl, base_fndecls; { - while (base_fndecls) + for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) { - if (overrides (TREE_VALUE (base_fndecls), fndecl)) + if (overrides (fndecl, TREE_VALUE (base_fndecls))) TREE_PURPOSE (base_fndecls) = fndecl; - - base_fndecls = TREE_CHAIN (base_fndecls); } } @@ -2884,8 +2884,15 @@ warn_hidden (t) tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - fndecl = OVL_CURRENT (fns); - if (DECL_VINDEX (fndecl) == NULL_TREE) + /* First see if we have any virtual functions in this batch. */ + for (; fns; fns = OVL_NEXT (fns)) + { + fndecl = OVL_CURRENT (fns); + if (DECL_VINDEX (fndecl)) + break; + } + + if (fns == NULL_TREE) continue; /* First we get a list of all possible functions that might be @@ -2900,38 +2907,28 @@ warn_hidden (t) } fns = OVL_NEXT (fns); - if (fns) - fndecl = OVL_CURRENT (fns); - else - fndecl = NULL_TREE; /* ...then mark up all the base functions with overriders, preferring overriders to hiders. */ if (base_fndecls) - while (fndecl) + for (; fns; fns = OVL_NEXT (fns)) { - mark_overriders (fndecl, base_fndecls); - - fns = OVL_NEXT (fns); - if (fns) - fndecl = OVL_CURRENT (fns); - else - fndecl = NULL_TREE; + fndecl = OVL_CURRENT (fns); + if (DECL_VINDEX (fndecl)) + mark_overriders (fndecl, base_fndecls); } /* Now give a warning for all base functions without overriders, as they are hidden. */ - while (base_fndecls) + for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) { - if (! overrides (TREE_VALUE (base_fndecls), - TREE_PURPOSE (base_fndecls))) + if (! overrides (TREE_PURPOSE (base_fndecls), + TREE_VALUE (base_fndecls))) { /* Here we know it is a hider, and no overrider exists. */ cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls)); } - - base_fndecls = TREE_CHAIN (base_fndecls); } } } @@ -5019,15 +5016,15 @@ instantiate_type (lhstype, rhs, flags) field = OVL_FUNCTION (field); if (TREE_CODE (field) == FUNCTION_DECL) { - cp_error ("object-dependent reference `%E' can only be used in a call", + cp_pedwarn ("object-dependent reference `%E' can only be used in a call", DECL_NAME (field)); - cp_error (" to form a pointer to member function, say `&%T::%E'", + cp_pedwarn (" to form a pointer to member function, say `&%T::%E'", t, DECL_NAME (field)); } else - cp_error ("object-dependent reference can only be used in a call"); + cp_pedwarn ("object-dependent reference can only be used in a call"); } - return error_mark_node; + return r; } return r; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ad1c370e0518..7d643078deeb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1327,6 +1327,10 @@ struct lang_decl (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace) #define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE)) +/* For a virtual function, the base where we find its vtable entry. + For a non-virtual function, the base where it is defined. */ +#define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE) + /* 1 iff NODE has namespace scope, including the global namespace. */ #define DECL_NAMESPACE_SCOPE_P(NODE) \ (DECL_CONTEXT (NODE) == NULL_TREE \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a3e18798056a..ea472082e19f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4154,8 +4154,10 @@ pushdecl (x) /* Warn if shadowing an argument at the top level of the body. */ else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x) - && TREE_CODE (oldlocal) == PARM_DECL - && TREE_CODE (x) != PARM_DECL) + && TREE_CODE (oldlocal) == PARM_DECL + /* Don't complain if it's from an enclosing function. */ + && DECL_CONTEXT (oldlocal) == current_function_decl + && TREE_CODE (x) != PARM_DECL) { /* Go to where the parms should be and see if we find them there. */ @@ -5815,6 +5817,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) { struct tree_binding b; val = binding_init (&b); + flags |= LOOKUP_COMPLAIN; if (!qualified_lookup_using_namespace (name, type, val, flags)) return NULL_TREE; val = select_decl (val, flags); @@ -8706,9 +8709,9 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", object, type); if (friendp) - cp_error_at ("invalid friend declaration", object); - if (raises) - cp_error_at ("invalid exception specifications", object); + cp_error_at ("`%D' declared as a friend", object); + if (raises && ! TYPE_PTRFN_P (TREE_TYPE (object))) + cp_error_at ("`%D' declared with an exception specification", object); } /* CTYPE is class type, or null if non-class. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5003f60982f0..debcf3717e91 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3814,7 +3814,8 @@ reparse_absdcl_as_casts (decl, expr) expr = build_c_cast (type, expr); } - if (warn_old_style_cast) + if (warn_old_style_cast && ! in_system_header + && current_lang_name != lang_name_c) warning ("use of old-style cast"); return expr; @@ -3988,7 +3989,7 @@ build_expr_from_tree (t) else { tree fn = TREE_OPERAND (t, 0); - + /* We can get a TEMPLATE_ID_EXPR here on code like: x->f<2>(); @@ -3999,7 +4000,9 @@ build_expr_from_tree (t) build_expr_from_tree. So, just use build_expr_from_tree when we really need it. */ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - fn = build_expr_from_tree (fn); + fn = lookup_template_function + (TREE_OPERAND (fn, 0), + build_expr_from_tree (TREE_OPERAND (fn, 1))); return build_method_call (build_expr_from_tree (TREE_OPERAND (t, 1)), diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ed316e1dafcd..4da1d2f3b87d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -211,6 +211,11 @@ dump_type_real (t, v, canonical_name) OB_PUTS ("{unknown type}"); break; + case TREE_LIST: + /* A list of function parms. */ + dump_parameters (t, 0, canonical_name); + break; + case IDENTIFIER_NODE: OB_PUTID (t); break; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5789c3f74a6a..e6209f906820 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3574,6 +3574,7 @@ maybe_get_template_decl_from_type_decl (decl) return (decl != NULL_TREE && TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl) + && CLASS_TYPE_P (decl) && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))) ? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl; } @@ -8909,8 +8910,8 @@ do_decl_instantiation (declspecs, declarator, storage) No program shall both explicitly instantiate and explicitly specialize a template. */ - cp_error ("explicit instantiation of `%#D' after", result); - cp_error_at ("explicit specialization here", result); + cp_pedwarn ("explicit instantiation of `%#D' after", result); + cp_pedwarn_at ("explicit specialization here", result); return; } else if (DECL_EXPLICIT_INSTANTIATION (result)) @@ -8924,7 +8925,7 @@ do_decl_instantiation (declspecs, declarator, storage) first instantiation was `extern' and the second is not, and EXTERN_P for the opposite case. */ if (DECL_INTERFACE_KNOWN (result) && !extern_p) - cp_error ("duplicate explicit instantiation of `%#D'", result); + cp_pedwarn ("duplicate explicit instantiation of `%#D'", result); /* If we've already instantiated the template, just return now. */ if (DECL_INTERFACE_KNOWN (result)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 23ae9edee377..d0743e950f40 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1355,8 +1355,13 @@ comp_target_parms (parms1, parms2, strict) if (t1 == 0 && t2 != 0) { - cp_pedwarn ("ANSI C++ prohibits conversion from `(%#T)' to `(...)'", - parms2); + if (! flag_strict_prototype && t2 == void_list_node) + /* t1 might be the arglist of a function pointer in extern "C" + declared to take (), which we fudged to (...). Don't make the + user pay for our mistake. */; + else + cp_pedwarn ("ANSI C++ prohibits conversion from `%#T' to `(...)'", + parms2); return self_promoting_args_p (t2); } if (t2 == 0) @@ -6360,7 +6365,12 @@ build_x_modify_expr (lhs, modifycode, rhs) /* Get difference in deltas for different pointer to member function types. Return integer_zero_node, if FROM cannot be converted to a - TO type. If FORCE is true, then allow reverse conversions as well. */ + TO type. If FORCE is true, then allow reverse conversions as well. + + Note that the naming of FROM and TO is kind of backwards; the return + value is what we add to a TO in order to get a FROM. They are named + this way because we call this function to find out how to convert from + a pointer to member of FROM to a pointer to member of TO. */ static tree get_delta_difference (from, to, force) @@ -6618,38 +6628,41 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) { tree type = TREE_TYPE (cst); tree fn = PTRMEM_CST_MEMBER (cst); + tree ptr_class, fn_class; my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0); - - *delta - = get_delta_difference (TYPE_METHOD_BASETYPE - (TREE_TYPE (fn)), - TYPE_PTRMEMFUNC_OBJECT_TYPE (type), - /*force=*/0); + + /* The class that the function belongs to. */ + fn_class = DECL_CLASS_CONTEXT (fn); + + /* The class that we're creating a pointer to member of. */ + ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type); + + /* First, calculate the adjustment to the function's class. */ + *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0); + if (!DECL_VIRTUAL_P (fn)) { - *idx = size_binop (MINUS_EXPR, integer_zero_node, - integer_one_node); - *pfn = build_addr_func (fn); - if (!same_type_p (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)), - TYPE_PTRMEMFUNC_OBJECT_TYPE (type))) - *pfn = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), - *pfn); + *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node); + *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn)); *delta2 = NULL_TREE; } else { - *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), - integer_one_node); + /* If we're dealing with a virtual function, we have to adjust 'this' + again, to point to the base which provides the vtable entry for + fn; the call will do the opposite adjustment. */ + tree orig_class = DECL_VIRTUAL_CONTEXT (fn); + tree binfo = binfo_or_else (orig_class, fn_class); + *delta = size_binop (PLUS_EXPR, *delta, BINFO_OFFSET (binfo)); + + /* Map everything down one to make room for the null PMF. */ + *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), integer_one_node); *pfn = NULL_TREE; - *delta2 = get_binfo (DECL_CONTEXT (fn), - DECL_CLASS_CONTEXT (fn), - 0); - *delta2 = get_vfield_offset (*delta2); - *delta2 = size_binop (PLUS_EXPR, *delta2, - build_binary_op (PLUS_EXPR, - *delta, - integer_zero_node)); + + /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS. */ + *delta2 = size_binop (PLUS_EXPR, *delta, + get_vfield_offset (TYPE_BINFO (orig_class))); } } @@ -7353,7 +7366,7 @@ c_expand_return (retval) || DECL_NAME (current_function_decl) == ansi_opname[(int) VEC_NEW_EXPR]) && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl)) && null_ptr_cst_p (retval)) - cp_pedwarn ("operator new should throw an exception, not return NULL"); + cp_warning ("operator new should throw an exception, not return NULL"); if (retval == NULL_TREE) {