+1999-08-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <oliva@dcc.unicamp.br>
* pt.c (tsubst): Use build_index_type to build in-template array
/* 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);
}
}
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
}
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);
}
}
}
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;
(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 \
/* 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. */
{
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);
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.
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;
else
{
tree fn = TREE_OPERAND (t, 0);
-
+
/* We can get a TEMPLATE_ID_EXPR here on code like:
x->f<2>();
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)),
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;
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;
}
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))
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))
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)
\f
/* 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)
{
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)));
}
}
|| 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)
{