+Thu May 1 18:26:37 1997 Mike Stump <mrs@cygnus.com>
+
+ * except.c (expand_exception_blocks): Ensure that we flow through
+ the end of the exception region for the exception specification.
+ Move exception region for the exception specification in, so that
+ it doesn't protect the parm cleanup. Remove some obsolete code.
+ * decl.c (store_parm_decls): Likewise.
+ (finish_function): Likewise.
+
+Tue Apr 29 15:38:54 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (build_new): Fix nothrow handling.
+
+Tue Apr 29 14:29:50 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * init.c (emit_base_init): Don't warn about the initialization
+ list for an artificial member.
+
+Fri Apr 25 17:47:59 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * expr.c (do_case): Handle !START case for the error msg.
+
+Fri Apr 25 11:55:23 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c, lang-options.h: New option -Weffc++.
+ * class.c, decl.c, init.c, typeck.c: Move Effective C++ warnings
+ to -Weffc++.
+
+ * decl2.c (finish_prevtable_vardecl): Change NO_LINKAGE_HEURISTICS
+ to MULTIPLE_SYMBOL_SPACES.
+
+Wed Apr 23 18:06:50 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * method.c (emit_thunk, generic case): Set current_function_is_thunk.
+
+ * method.c (emit_thunk, macro case): Set up DECL_RESULT.
+
+ * typeck.c (c_expand_return): Don't complain about returning void
+ to void in an artificial function.
+ * method.c (make_thunk): Change settings of READONLY/VOLATILE,
+ don't set DECL_RESULT, set DECL_ARTIFICIAL.
+ (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC.
+
Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
* init.c (init_decl_processing): Add supoprt for setjmp/longjmp based
}
/* Effective C++ rule 11. */
- if (has_pointers && extra_warnings
+ if (has_pointers && warn_ecpp
&& ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
{
cp_warning ("`%#T' has pointer data members", t);
extern int warn_pmf2ptr;
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+extern int warn_ecpp;
+
/* Non-zero means warn when a function is declared extern and later inline. */
+
extern int warn_extern_inline;
/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
}
/* More Effective C++ rule 6. */
- if (extra_warnings
+ if (warn_ecpp
&& (name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR]))
{
}
/* More Effective C++ rule 7. */
- if (extra_warnings
+ if (warn_ecpp
&& (name == ansi_opname [TRUTH_ANDIF_EXPR]
|| name == ansi_opname [TRUTH_ORIF_EXPR]
|| name == ansi_opname [COMPOUND_EXPR]))
}
/* Effective C++ rule 23. */
- if (extra_warnings
+ if (warn_ecpp
&& list_length (argtypes) == 3
&& (name == ansi_opname [PLUS_EXPR]
|| name == ansi_opname [MINUS_EXPR]
/* Effective C++ rule 14. The case of virtual functions but
non-virtual dtor is handled in finish_struct_1. */
- if (warn_nonvdtor && ! TYPE_VIRTUAL_P (basetype)
+ if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
&& TYPE_HAS_DESTRUCTOR (basetype))
cp_warning ("base class `%#T' has a non-virtual destructor",
basetype);
warning ("return-type defaults to `int'");
/* Effective C++ rule 15. See also c_expand_return. */
- if (extra_warnings
+ if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
&& TREE_TYPE (fntype) == void_type_node)
cp_warning ("`operator=' should return a reference to `*this'");
if (! processing_template_decl)
expand_function_start (fndecl, parms_have_cleanups);
+ current_function_parms_stored = 1;
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_NAME (fndecl)
+ && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
+ && DECL_CONTEXT (fndecl) == NULL_TREE)
+ {
+ expand_main_function ();
+ }
+
/* Now that we have initialized the parms, we can start their
cleanups. We cannot do this before, since expand_decl_cleanup
should not be called before the parm can be used. */
- if (parms_have_cleanups
+ if (cleanups
&& ! processing_template_decl)
{
for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
expand_start_bindings (0);
}
- current_function_parms_stored = 1;
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- expand_main_function ();
- }
-
- /* Take care of exception handling things. */
if (! processing_template_decl && flag_exceptions)
{
- rtx insns;
- start_sequence ();
-
-#if 0
- /* Mark the start of a stack unwinder if we need one. */
- start_eh_unwinder ();
-#endif
-
-#if 0
/* Do the starting of the exception specifications, if we have any. */
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
expand_start_eh_spec ();
-#endif
-
- insns = get_insns ();
- end_sequence ();
-
- if (insns)
- store_after_parms (insns);
}
+
last_dtor_insn = get_last_insn ();
}
&& ! DECL_NAME (DECL_RESULT (current_function_decl)))
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ if (flag_exceptions)
+ expand_exception_blocks ();
+
/* If this function is supposed to return a value, ensure that
we do not fall into the cleanups by mistake. The end of our
function will look like this:
to catch cleanup-generated temporaries. */
expand_end_bindings (0, 0, 0);
poplevel (0, 0, 0);
- }
- if (cleanup_label)
- /* Emit label at beginning of cleanup code for parameters. */
- emit_label (cleanup_label);
+ /* Emit label at beginning of cleanup code for parameters. */
+ emit_label (cleanup_label);
+ }
/* Get return value into register if that's where it's supposed to be. */
if (original_result_rtx)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
-
- if (flag_exceptions)
- expand_exception_blocks ();
}
/* This must come after expand_function_end because cleanups might
into a pointer to (void or function). */
int warn_pmf2ptr = 1;
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+int warn_ecpp = 0;
+
/* Nonzero means `$' can be in an identifier.
See cccp.c for reasons why this breaks some obscure ANSI C programs. */
warn_synth = setting;
else if (!strcmp (p, "pmf-conversions"))
warn_pmf2ptr = setting;
+ else if (!strcmp (p, "effc++"))
+ warn_ecpp = setting;
else if (!strcmp (p, "comment"))
; /* cpp handles this one. */
else if (!strcmp (p, "comments"))
tree ctype = DECL_CONTEXT (vars);
import_export_template (ctype);
-#ifndef NO_LINKAGE_HEURISTICS
+#ifndef MULTIPLE_SYMBOL_SPACES
if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)
&& ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{
expand_exception_blocks ()
{
rtx funcend;
- rtx insn, insns;
- rtx eh_spec_insns = NULL_RTX;
+ rtx insns;
start_sequence ();
funcend = gen_label_rtx ();
- emit_jump (funcend);
start_sequence ();
insns = get_insns ();
end_sequence ();
-
- /* Do this after we expand leftover cleanups, so that the expand_eh_region_end
- that expand_end_eh_spec does will match the right expand_eh_region_start,
- and make sure it comes out before the terminate protected region. */
+
+#if 1
+ /* Do this after we expand leftover cleanups, so that the
+ expand_eh_region_end that expand_end_eh_spec does will match the
+ right expand_eh_region_start, and make sure it comes out before
+ the terminate protected region. */
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
{
-#if 1
- {
- rtx insns;
- /* New... */
- start_sequence ();
- expand_start_eh_spec ();
- eh_spec_insns = get_insns ();
- end_sequence ();
- }
-#endif
-
- expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
- push_to_sequence (insns);
+ expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
+ push_to_sequence (insns);
- /* Now expand any new ones. */
- expand_leftover_cleanups ();
+ /* Now expand any new ones. */
+ expand_leftover_cleanups ();
- insns = get_insns ();
- end_sequence ();
+ insns = get_insns ();
+ end_sequence ();
}
+#endif
+
+ emit_jump (funcend);
if (insns)
{
expand_leftover_cleanups ();
}
- {
- /* Mark the end of the stack unwinder. */
- rtx unwind_insns;
- start_sequence ();
-#if 0
- end_eh_unwinder ();
-#endif
- unwind_insns = get_insns ();
- end_sequence ();
- if (unwind_insns)
- {
- insns = unwind_insns;
- emit_insns (insns);
- }
- }
-
emit_label (funcend);
/* Only if we had previous insns do we want to emit the jump around
insns = get_insns ();
end_sequence ();
-#if 1
- if (eh_spec_insns)
- emit_insns_after (eh_spec_insns, get_insns ());
-#else
- if (eh_spec_insns)
- store_after_parms (eh_spec_insns);
-#endif
-
- insn = get_last_insn ();
- while (GET_CODE (insn) == NOTE
- || (GET_CODE (insn) == INSN
- && (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)))
- insn = PREV_INSN (insn);
-
- emit_insns_after (insns, insn);
+ emit_insns (insns);
}
tree
{
if (end)
error ("case label within scope of cleanup or variable array");
+ else if (! start)
+ error ("`default' label within scope of cleanup or variable array");
else
cp_error ("case label `%E' within scope of cleanup or variable array", start);
}
from_init_list = 0;
/* Effective C++ rule 12. */
- if (extra_warnings && init == NULL_TREE
+ if (warn_ecpp && init == NULL_TREE
+ && !DECL_ARTIFICIAL (member)
&& TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)
cp_warning ("`%D' should be initialized in the member initialization list", member);
}
tree access;
/* unique functions are handled easily. */
- unique:
access = compute_access (basebinfo, t);
if (access == access_protected_node)
{
return error_mark_node;
}
- nothrow = (placement
- && TREE_TYPE (placement)
- && IS_AGGR_TYPE (TREE_TYPE (placement))
- && (TYPE_IDENTIFIER (TREE_TYPE (placement))
+ /* If the first placement arg is of type nothrow_t, it's allowed to
+ return 0 on allocation failure. */
+ nothrow = (placement && TREE_VALUE (placement)
+ && TREE_TYPE (TREE_VALUE (placement))
+ && IS_AGGR_TYPE (TREE_TYPE (TREE_VALUE (placement)))
+ && (TYPE_IDENTIFIER (TREE_TYPE (TREE_VALUE (placement)))
== get_identifier ("nothrow_t")));
check_new = flag_check_new || nothrow;
int flags;
int use_global_delete;
{
- tree function;
tree member;
tree expr;
tree ref;
- int ptr;
if (addr == error_mark_node)
return error_mark_node;
/* throw away const and volatile on target type of addr */
addr = convert_force (build_pointer_type (type), addr, 0);
ref = build_indirect_ref (addr, NULL_PTR);
- ptr = 1;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
addr = convert_force (build_pointer_type (type), addr, 0);
ref = build_indirect_ref (addr, NULL_PTR);
- ptr = 0;
}
my_friendly_assert (IS_AGGR_TYPE (type), 220);
of the base classes; otherwise, we must do that here. */
if (TYPE_HAS_DESTRUCTOR (type))
{
- tree parms = build_tree_list (NULL_TREE, addr);
- tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1));
tree passed_auto_delete;
tree do_delete = NULL_TREE;
tree ifexp;
- int nonnull;
if (use_global_delete)
{
"-Wno-synth",
"-Wpmf-conversions",
"-Wno-pmf-conversions",
+ "-Weffc++",
+ "-Wno-effc++",
}
if (thunk == NULL_TREE)
{
- thunk = build_lang_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_RESULT (thunk)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
- TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
- TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
- make_function_rtl (thunk);
+ thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
+ TREE_READONLY (thunk) = TREE_READONLY (func_decl);
+ TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
comdat_linkage (thunk);
TREE_SET_CODE (thunk, THUNK_DECL);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
DECL_EXTERNAL (thunk) = 1;
+ DECL_ARTIFICIAL (thunk) = 1;
/* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk);
}
return thunk;
}
+/* Emit the definition of a C++ multiple inheritance vtable thunk. */
+
void
emit_thunk (thunk_fndecl)
tree thunk_fndecl;
{
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
int delta = THUNK_DELTA (thunk_fndecl);
- char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
+ {
#ifdef ASM_OUTPUT_MI_THUNK
- current_function_decl = thunk_fndecl;
- temporary_allocation ();
- assemble_start_function (thunk_fndecl, fnname);
- ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
- assemble_end_function (thunk_fndecl, fnname);
- permanent_allocation (1);
- current_function_decl = 0;
+ char *fnname;
+ current_function_decl = thunk_fndecl;
+ temporary_allocation ();
+ DECL_RESULT (thunk_fndecl)
+ = build_decl (RESULT_DECL, 0, integer_type_node);
+ make_function_rtl (thunk_fndecl);
+ fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
+ assemble_start_function (thunk_fndecl, fnname);
+ ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+ assemble_end_function (thunk_fndecl, fnname);
+ permanent_allocation (1);
+ current_function_decl = 0;
#else /* ASM_OUTPUT_MI_THUNK */
- if (varargs_function_p (function))
- cp_error ("generic thunk code does not work for variadic function `%#D'",
- function);
- {
+ /* If we don't have the necessary macro for efficient thunks, generate a
+ thunk function that just makes a call to the real function.
+ Unfortunately, this doesn't work for varargs. */
+
tree a, t;
+ if (varargs_function_p (function))
+ cp_error ("generic thunk code fails for method `%#D' which uses `...'",
+ function);
+
/* Set up clone argument trees for the thunk. */
t = NULL_TREE;
for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
a = nreverse (t);
DECL_ARGUMENTS (thunk_fndecl) = a;
DECL_RESULT (thunk_fndecl) = NULL_TREE;
+ DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function);
+ copy_lang_decl (thunk_fndecl);
+ DECL_INTERFACE_KNOWN (thunk_fndecl) = 1;
+ DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1);
store_parm_decls ();
+ current_function_is_thunk = 1;
/* Build up the call to the real function. */
t = build_int_2 (delta, -1 * (delta < 0));
c_expand_return (t);
finish_function (lineno, 0, 0);
- }
#endif /* ASM_OUTPUT_MI_THUNK */
+ }
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
}
/* Effective C++ rule 15. See also start_function. */
- if (extra_warnings
+ if (warn_ecpp
&& DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
&& retval != current_class_ref)
cp_warning ("`operator=' should return a reference to `*this'");
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
- if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+ if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl))
+ || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
return;