+Mon May 6 01:23:32 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_file): Don't try to emit functions that haven't
+ been compiled.
+
+Fri May 3 09:30:13 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_vtable_vardecl): Oops.
+
+ * decl.c (maybe_push_to_top_level): Do save previous_class_*.
+ Also store the bindings from previous_class_values.
+ (pop_from_top_level): Restore them.
+
+Thu May 2 21:56:49 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_vtable_vardecl): Only write out vtable if its
+ symbol has been referenced.
+ (finish_file): Re-join synthesis/vtable loop with inline emission
+ loop, disable inlining when an inline is output.
+
+Thu May 2 17:20:02 1996 Mike Stump <mrs@cygnus.com>
+
+ * except.c (init_exception_processing): Setup saved_in_catch.
+ (push_eh_cleanup): Reset __eh_in_catch.
+ (expand_start_catch_block): Set __eh_in_catch.
+
+Thu May 2 16:21:17 1996 Mike Stump <mrs@cygnus.com>
+
+ * except.c (push_eh_cleanup): Add tracking for whether or not we
+ have an active exception object.
+ (expand_builtin_throw): Use it to make sure a rethrow without an
+ exception object is caught.
+
+Thu May 2 11:26:41 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (maybe_push_to_top_level): Clear out class-level bindings
+ cache.
+
Wed May 1 11:26:52 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (finish_file): Also use sentries for vars with
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
{
- int is_constructor;
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- is_constructor = DECL_CONSTRUCTOR_P (function);
- function = default_conversion (function);
- }
- else
- {
- is_constructor = 0;
- function = default_conversion (function);
- }
+ int is_constructor
+ = TREE_CODE (function) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (function);
+
+ function = default_conversion (function);
result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
int minimal_parse_mode;
tree last_function_parms;
tree template_parms;
+ tree previous_class_type, previous_class_values;
};
static struct saved_scope *current_saved_scope;
-extern tree prev_class_type;
tree
store_bindings (names, old_bindings)
struct binding_level *b = inner_binding_level;
tree old_bindings = NULL_TREE;
+ if (previous_class_type)
+ old_bindings = store_bindings (previous_class_values, old_bindings);
+
/* Have to include global_binding_level, because class-level decls
aren't listed anywhere useful. */
for (; b; b = b->level_chain)
s->minimal_parse_mode = minimal_parse_mode;
s->last_function_parms = last_function_parms;
s->template_parms = current_template_parms;
+ s->previous_class_type = previous_class_type;
+ s->previous_class_values = previous_class_values;
current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
minimal_parse_mode = 0;
+ previous_class_type = previous_class_values = NULL_TREE;
if (!pseudo)
current_template_parms = NULL_TREE;
minimal_parse_mode = s->minimal_parse_mode;
last_function_parms = s->last_function_parms;
current_template_parms = s->template_parms;
+ previous_class_type = s->previous_class_type;
+ previous_class_values = s->previous_class_values;
free (s);
}
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
/* Tell the back-end to use or not use .common as appropriate. If we say
- -fconserve-space, we want this to save space, at the expense of wrong
- semantics. If we say -fno-conserve-space, we want this to produce
- errors about redefs; to do this we force variables into the data
- segment. Common storage is okay for non-public uninitialized data;
- the linker can't match it with storage from other files, and we may
- save some disk space. */
+ -fconserve-space, we want this to save .data space, at the expense of
+ wrong semantics. If we say -fno-conserve-space, we want this to
+ produce errors about redefs; to do this we force variables into the
+ data segment. */
DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#endif
tree prev, vars;
{
if (write_virtuals >= 0
- && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))
+ && ! DECL_EXTERNAL (vars)
+ && ((TREE_PUBLIC (vars) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars))
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
&& ! TREE_ASM_WRITTEN (vars))
{
/* Write it out. */
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
return 1;
}
- else if (! TREE_USED (vars))
+ else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
/* We don't know what to do with this one yet. */
return 0;
reconsider = 1;
}
+ /* Catch new template instantiations. */
if (decl != TREE_VALUE (*p))
- ;
- else if (TREE_ASM_WRITTEN (decl)
- || (DECL_SAVED_INSNS (decl) == 0
- && ! DECL_ARTIFICIAL (decl)))
- *p = TREE_CHAIN (*p);
- else
- p = &TREE_CHAIN (*p);
- }
- }
+ continue;
- reconsider = 1; /* More may be referenced; check again */
- while (reconsider)
- {
- tree *p = &saved_inlines;
- reconsider = 0;
-
- while (*p)
- {
- tree decl = TREE_VALUE (*p);
-
- if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
+ if (TREE_ASM_WRITTEN (decl)
+ || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl)))
*p = TREE_CHAIN (*p);
- else if ((TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
+ else if (DECL_INITIAL (decl) == 0)
+ p = &TREE_CHAIN (*p);
+ else if ((TREE_PUBLIC (decl) && ! DECL_WEAK (decl)
+ && ! DECL_ONE_ONLY (decl))
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|| flag_keep_inline_functions)
{
{
DECL_EXTERNAL (decl) = 0;
reconsider = 1;
+ /* We can't inline this function after it's been
+ emitted, so just disable inlining. We want a
+ variant of output_inline_function that doesn't
+ prevent subsequent integration... */
+ flag_no_inline = 1;
temporary_allocation ();
output_inline_function (decl);
permanent_allocation (1);
static tree saved_throw_value;
/* Holds the cleanup for the value being thrown. */
static tree saved_cleanup;
+/* Indicates if we are in a catch clause. */
+static tree saved_in_catch;
static int throw_used;
DECL_COMMON (d) = 1;
cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0);
+
+ declspecs = tree_cons (NULL_TREE, get_identifier ("bool"), NULL_TREE);
+ d = get_identifier ("__eh_in_catch");
+ d = start_decl (d, declspecs, 0, NULL_TREE);
+ DECL_COMMON (d) = 1;
+ cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
+ saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0);
}
/* call this to begin a block of unwind protection (ie: when an object is
/* Arrange to do a dynamically scoped cleanup upon exit from this region. */
tree cleanup = build_function_call (saved_cleanup, NULL_TREE);
+ cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
+ build_modify_expr (saved_in_catch, NOP_EXPR,
+ build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
cp_expand_decl_cleanup (NULL_TREE, cleanup);
resume_momentary (yes);
/* Fall into the catch all section. */
}
+ emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
/* This is the starting of something to protect. */
emit_label (protect_label_rtx);
top_of_loop = gen_label_rtx ();
unwind_first = gen_label_rtx ();
+ /* These two can be frontend specific. If wanted, they can go in
+ expand_throw. */
+ /* Do we have a valid object we are throwing? */
+ emit_cmp_insn (DECL_RTL (saved_throw_type), const0_rtx, EQ, NULL_RTX,
+ GET_MODE (DECL_RTL (saved_throw_type)), 0, 0);
+ emit_jump_insn (gen_beq (gotta_call_terminate));
+
emit_jump (unwind_first);
emit_label (top_of_loop);
{
rtx cleanup_insns;
tree object;
+
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, TREE_TYPE (exp),
build_tree_list (NULL_TREE, exp),
all unwinded scopes. Completely constructed parts of partially
constructed objects are cleaned up. This includes partially built
arrays. Exception specifications are now handled. Thrown objects are
-now cleaned up all the time.
+now cleaned up all the time. We can now tell if we have an active
+exception being thrown or not (__eh_type != 0). We use this to call
+terminate if someone does a throw; without there being an active
+exception object. uncaught_exception () works.
The below points out some flaws in g++'s exception handling, as it now
stands.
Only exact type matching or reference matching of throw types works when
--fno-rtti is used. Only works on a SPARC (like Suns), i386, arm,
-rs6000, PowerPC, Alpha, mips, VAX, m68k and z8k machines. Partial support
-is in for all other machines, but a stack unwinder called
+-fno-rtti is used. Only works on a SPARC (like Suns), SPARClite, i386,
+arm, rs6000, PowerPC, Alpha, mips, VAX, m68k and z8k machines. Partial
+support is in for all other machines, but a stack unwinder called
__unwind_function has to be written, and added to libgcc2 for them. The
new EH code doesn't rely upon the __unwind_function for C++ code,
instead it creates per function unwinders right inside the function,