Commit 8d2733ca by Mike Stump

36th Cygnus<->FSF merge

From-SVN: r7221
parent 19d3f3c5
Fri May 6 01:25:38 1994 Mike Stump (mrs@cygnus.com)
Add alpha exception handling support to the compiler.
Quick and dirty backend in except.c.
* cp/*: Remove most remnants of old exception handling support.
* decl.c (finish_function): Call expand_exception_blocks to put
the exception hanlding blocks at the end of the function.
* dec.c (hack_incomplete_structures): Make sure expand_decl_cleanup
comes after expand_decl_init.
* except.c: Reimplementation.
* expr.c (cplus_expand_expr): Handle THROW_EXPRs.
* lex.c (init_lex): Always have catch, try and throw be reserved
words, so that we may always parse exception handling.
* parse.y: Cleanup to support new interface into exception handling.
* tree.def (THROW_EXPR): Add.
Thu May 5 17:35:37 1994 Jason Merrill (jason@deneb.cygnus.com)
* parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt.
(various): Lose .kindof_pushlevel and partially_scoped_stmt.
Thu May 5 16:17:27 1994 Kung Hsu (kung@mexican.cygnus.com)
* parse.y (already_scoped_stmt): move expand_end_binding() to
fix the unmatched LBB/LBE in stabs.
Thu May 5 14:36:17 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (set_nested_typename): Set TREE_MANGLED on the new
identifiers.
(pushdecl): Check TREE_MANGLED.
(xref_tag): Ditto.
* cp-tree.h (TREE_MANGLED): This identifier is a
DECL_NESTED_TYPENAME (named to allow for future use to denote
mangled function names as well).
Implement inconsistency checking specified in [class.scope0].
* decl.c (lookup_name_real): Don't set ICV here after all.
(finish_enum): Also set the type of the enumerators themselves.
(build_enumerator): Put the CONST_DECL in the list instead of its
initial value.
(pushdecl_class_level): Check inconsistent use of a name in the
class body.
* class.c (finish_struct): Check inconsistent use of a name in the
class body. Don't set DECL_CONTEXT on types here anymore.
* parse.y (qualified_type_name): Note that the identifier has now
been used (as a type) in the class body.
* lex.c (do_identifier): Note that the identifier has now been used
(as a constant) in the class body.
* error.c (dump_decl): Print type and enum decls better.
Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com) Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
* typeck.c (build_modify_expr): Warn about assignment to `this'. * typeck.c (build_modify_expr): Warn about assignment to `this'.
......
...@@ -2924,18 +2924,6 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2924,18 +2924,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
need_vtbl = maybe_needed; need_vtbl = maybe_needed;
instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance); instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
} }
else if (instance == current_exception_object)
{
instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type),
TREE_OPERAND (current_exception_object, 0));
mark_addressable (TREE_OPERAND (current_exception_object, 0));
result = build_field_call (TYPE_BINFO (current_exception_type),
instance_ptr, name, parms);
if (result)
return result;
cp_error ("exception member `%D' cannot be invoked", name);
return error_mark_node;
}
else else
{ {
/* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */ /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */
......
...@@ -2504,7 +2504,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2504,7 +2504,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
int warn_anon; int warn_anon;
{ {
extern int interface_only, interface_unknown; extern int interface_only, interface_unknown;
extern tree EHS_type;
int old; int old;
int round_up_size = 1; int round_up_size = 1;
...@@ -2727,10 +2726,25 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2727,10 +2726,25 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! fields) if (! fields)
fields = x; fields = x;
last_x = x; last_x = x;
DECL_CONTEXT (x) = t;
continue; continue;
} }
/* Check for inconsistent use of this name in the class body.
Enums, types and static vars have already been checked. */
if (TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
{
tree name = DECL_NAME (x);
tree icv = name ? IDENTIFIER_CLASS_VALUE (name) : NULL_TREE;
/* Don't complain about constructors. */
if (icv && name != constructor_name (current_class_type))
{
cp_error_at ("declaration of identifier `%D' as `%+#D'",
name, x);
cp_error_at ("conflicts with other use in class as `%#D'",
icv);
}
}
if (TREE_CODE (x) == FUNCTION_DECL) if (TREE_CODE (x) == FUNCTION_DECL)
{ {
...@@ -3129,9 +3143,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3129,9 +3143,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
fn_fields = default_fn; fn_fields = default_fn;
} }
/* Create default copy constructor, if needed. Don't do it for /* Create default copy constructor, if needed. */
the exception handler. */ if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor)
if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor && t != EHS_type)
{ {
/* ARM 12.18: You get either X(X&) or X(const X&), but /* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */ not both. --Chip */
......
...@@ -55,10 +55,9 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1) ...@@ -55,10 +55,9 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3) DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3) DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3)
/* Distinguish variables that are only used to identify exceptions /* A throw expression. operand 0 is the expression, if there was one,
that were caught. Only the DECL_NAME (and TREE_CHAIN) else it is NULL_TREE. */
is really used. */ DEFTREECODE (THROW_EXPR, "throw_expr", "e", 1)
DEFTREECODE (CPLUS_CATCH_DECL, "catch_decl", "d", 0)
/* Template definition. The following fields have the specified uses, /* Template definition. The following fields have the specified uses,
although there are other macros in cp-tree.h that should be used for although there are other macros in cp-tree.h that should be used for
......
...@@ -271,10 +271,6 @@ extern int interface_only, interface_unknown; ...@@ -271,10 +271,6 @@ extern int interface_only, interface_unknown;
extern int flag_elide_constructors; extern int flag_elide_constructors;
/* Nonzero means recognize and handle exception handling constructs. */
extern int flag_handle_exceptions;
/* Nonzero means handle things in ANSI, instead of GNU fashion. */ /* Nonzero means handle things in ANSI, instead of GNU fashion. */
extern int flag_ansi; extern int flag_ansi;
...@@ -282,7 +278,7 @@ extern int flag_ansi; ...@@ -282,7 +278,7 @@ extern int flag_ansi;
/* Nonzero means recognize and handle ansi-style exception handling /* Nonzero means recognize and handle ansi-style exception handling
constructs. */ constructs. */
extern int flag_ansi_exceptions; extern int flag_handle_exceptions;
/* Nonzero means do argument matching for overloading according to the /* Nonzero means do argument matching for overloading according to the
ANSI rules, rather than what g++ used to believe to be correct. */ ANSI rules, rather than what g++ used to believe to be correct. */
...@@ -1083,10 +1079,14 @@ struct lang_decl ...@@ -1083,10 +1079,14 @@ struct lang_decl
or virtual baseclasses. */ or virtual baseclasses. */
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE)) #define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user
gave; it's a DECL_NESTED_TYPENAME. Someone may want to set this on
mangled function names, too, but it isn't currently. */
#define TREE_MANGLED(NODE) (TREE_LANG_FLAG_0 (NODE))
#if 0 /* UNUSED */ #if 0 /* UNUSED */
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */ should be looked up in a non-standard way. */
#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE)) #define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
#endif #endif
...@@ -1921,27 +1921,20 @@ extern tree lookup_name_nonclass PROTO((tree)); ...@@ -1921,27 +1921,20 @@ extern tree lookup_name_nonclass PROTO((tree));
/* in edsel.c */ /* in edsel.c */
/* in except.c */ /* in except.c */
extern tree lookup_exception_cname PROTO((tree, tree, tree));
extern tree lookup_exception_tname PROTO((tree)); extern void start_protect PROTO((void));
extern tree lookup_exception_object PROTO((tree, tree, int)); extern void end_protect PROTO((tree));
extern tree lookup_exception_type PROTO((tree, tree, tree)); extern void expand_exception_blocks PROTO((void));
extern tree finish_exception PROTO((tree, tree)); extern void expand_start_try_stmts PROTO((void));
extern void finish_exception_decl PROTO((tree, tree)); extern void expand_end_try_stmts PROTO((void));
extern void end_exception_decls PROTO((void)); extern void expand_start_all_catch PROTO((void));
extern void cplus_expand_start_try PROTO((int)); extern void expand_end_all_catch PROTO((void));
extern tree cplus_expand_end_try PROTO((int)); extern void start_catch_block PROTO((tree, tree));
extern void cplus_expand_start_except PROTO((tree, tree)); extern void end_catch_block PROTO((void));
extern void cplus_expand_end_except PROTO((tree)); extern void expand_throw PROTO((tree));
extern void cplus_expand_raise PROTO((tree, tree, tree, int)); extern void build_exception_table PROTO((void));
extern tree ansi_exception_object_lookup PROTO((tree)); extern tree build_throw PROTO((tree));
extern void cplus_expand_throw PROTO((tree));
extern tree cplus_expand_start_catch PROTO((tree));
extern tree ansi_expand_start_catch PROTO((tree));
extern void cplus_expand_end_catch PROTO((int));
extern void cplus_expand_reraise PROTO((tree));
extern void setup_exception_throw_decl PROTO((void));
extern void init_exception_processing PROTO((void)); extern void init_exception_processing PROTO((void));
extern void init_exception_processing_1 PROTO((void));
/* in expr.c */ /* in expr.c */
/* skip cplus_expand_expr */ /* skip cplus_expand_expr */
...@@ -2291,18 +2284,6 @@ extern void GNU_xref_assign PROTO((tree)); ...@@ -2291,18 +2284,6 @@ extern void GNU_xref_assign PROTO((tree));
extern void GNU_xref_hier PROTO((char *, char *, int, int, int)); extern void GNU_xref_hier PROTO((char *, char *, int, int, int));
extern void GNU_xref_member PROTO((tree, tree)); extern void GNU_xref_member PROTO((tree, tree));
#define in_try_block(X) (0)
#define in_exception_handler(X) (0)
#define expand_raise(X) (0)
#define expand_start_try(A,B,C) ((void)0)
#define expand_end_try() ((void)0)
#define expand_start_except(A,B) ((void)0)
#define expand_escape_except() (0)
#define expand_end_except() (NULL_TREE)
#define expand_catch(X) (0)
#define expand_catch_default() (0)
#define expand_end_catch() (0)
/* -- end of C++ */ /* -- end of C++ */
#endif /* not _CP_TREE_H */ #endif /* not _CP_TREE_H */
...@@ -266,16 +266,10 @@ int write_virtuals; ...@@ -266,16 +266,10 @@ int write_virtuals;
int flag_elide_constructors; int flag_elide_constructors;
/* Nonzero means recognize and handle exception handling constructs. /* Nonzero means recognize and handle exception handling constructs.
2 means handle exceptions the way Spring wants them handled. */ Use ansi syntax and semantics. WORK IN PROGRESS! */
int flag_handle_exceptions; int flag_handle_exceptions;
/* Nonzero means recognize and handle exception handling constructs.
Use ansi syntax and semantics. WORK IN PROGRESS!
2 means handle exceptions the way Spring wants them handled. */
int flag_ansi_exceptions;
/* Nonzero means recognize and handle signature language constructs. */ /* Nonzero means recognize and handle signature language constructs. */
int flag_handle_signatures; int flag_handle_signatures;
...@@ -354,9 +348,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -354,9 +348,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"memoize-lookups", &flag_memoize_lookups, 1}, {"memoize-lookups", &flag_memoize_lookups, 1},
{"elide-constructors", &flag_elide_constructors, 1}, {"elide-constructors", &flag_elide_constructors, 1},
{"handle-exceptions", &flag_handle_exceptions, 1}, {"handle-exceptions", &flag_handle_exceptions, 1},
{"ansi-exceptions", &flag_ansi_exceptions, 1},
{"handle-signatures", &flag_handle_signatures, 1}, {"handle-signatures", &flag_handle_signatures, 1},
{"spring-exceptions", &flag_handle_exceptions, 2},
{"default-inline", &flag_default_inline, 1}, {"default-inline", &flag_default_inline, 1},
{"dollars-in-identifiers", &dollars_in_ident, 1}, {"dollars-in-identifiers", &dollars_in_ident, 1},
{"enum-int-equiv", &flag_int_enum_equivalence, 1}, {"enum-int-equiv", &flag_int_enum_equivalence, 1},
...@@ -2493,6 +2485,8 @@ finish_file () ...@@ -2493,6 +2485,8 @@ finish_file ()
tree vars = static_aggregates; tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0; int needs_cleaning = 0, needs_messing_up = 0;
build_exception_table ();
if (flag_detailed_statistics) if (flag_detailed_statistics)
dump_tree_statistics (); dump_tree_statistics ();
......
...@@ -559,14 +559,19 @@ dump_decl (t, v) ...@@ -559,14 +559,19 @@ dump_decl (t, v)
break; break;
case TYPE_DECL: case TYPE_DECL:
if (TYPE_NAME (TREE_TYPE (t)) != t) {
{ /* Don't say 'typedef class A' */
if (v > 0) tree type = TREE_TYPE (t);
OB_PUTS ("typedef "); if (IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type)
goto general; && type == TYPE_MAIN_VARIANT (type))
} {
dump_type (type, v);
dump_type (TREE_TYPE (t), v); break;
}
}
if (v > 0)
OB_PUTS ("typedef ");
goto general;
break; break;
case VAR_DECL: case VAR_DECL:
...@@ -586,9 +591,8 @@ dump_decl (t, v) ...@@ -586,9 +591,8 @@ dump_decl (t, v)
OB_PUTC (' '); OB_PUTC (' ');
} }
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */ /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
if (TREE_CODE (t) == FIELD_DECL if (DECL_CONTEXT (t)
|| (TREE_CODE (t) == VAR_DECL && DECL_CONTEXT (t) && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
{ {
dump_type (DECL_CONTEXT (t), 0); dump_type (DECL_CONTEXT (t), 0);
OB_PUTC2 (':', ':'); OB_PUTC2 (':', ':');
...@@ -696,14 +700,7 @@ dump_decl (t, v) ...@@ -696,14 +700,7 @@ dump_decl (t, v)
case CONST_DECL: case CONST_DECL:
if (NEXT_CODE (t) == ENUMERAL_TYPE) if (NEXT_CODE (t) == ENUMERAL_TYPE)
{ goto general;
if (DECL_CONTEXT (t))
{
dump_decl (DECL_CONTEXT (t), 0);
OB_PUTC2 (':', ':');
}
OB_PUTID (DECL_NAME (t));
}
else else
dump_expr (DECL_INITIAL (t), 0); dump_expr (DECL_INITIAL (t), 0);
break; break;
......
...@@ -214,6 +214,10 @@ cplus_expand_expr (exp, target, tmode, modifier) ...@@ -214,6 +214,10 @@ cplus_expand_expr (exp, target, tmode, modifier)
case THUNK_DECL: case THUNK_DECL:
return DECL_RTL (exp); return DECL_RTL (exp);
case THROW_EXPR:
expand_throw (TREE_OPERAND (exp, 0));
return NULL;
default: default:
break; break;
} }
......
...@@ -26,14 +26,6 @@ __typeof__, TYPEOF, NORID ...@@ -26,14 +26,6 @@ __typeof__, TYPEOF, NORID
__volatile, TYPE_QUAL, RID_VOLATILE __volatile, TYPE_QUAL, RID_VOLATILE
__volatile__, TYPE_QUAL, RID_VOLATILE __volatile__, TYPE_QUAL, RID_VOLATILE
__wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */, __wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,
all, ALL, NORID /* Extension */,
except, EXCEPT, NORID /* Extension */,
exception, AGGR, RID_EXCEPTION /* Extension */,
raise, RAISE, NORID /* Extension */,
raises, RAISES, NORID /* Extension */,
reraise, RERAISE, NORID /* Extension */,
throw, THROW, NORID /* Extension */,
try, TRY, NORID /* Extension */,
asm, ASM_KEYWORD, NORID, asm, ASM_KEYWORD, NORID,
auto, SCSPEC, RID_AUTO, auto, SCSPEC, RID_AUTO,
break, BREAK, NORID, break, BREAK, NORID,
...@@ -79,7 +71,9 @@ static, SCSPEC, RID_STATIC, ...@@ -79,7 +71,9 @@ static, SCSPEC, RID_STATIC,
struct, AGGR, RID_RECORD, struct, AGGR, RID_RECORD,
switch, SWITCH, NORID, switch, SWITCH, NORID,
this, THIS, NORID, this, THIS, NORID,
throw, THROW, NORID,
template, TEMPLATE, NORID, template, TEMPLATE, NORID,
try, TRY, NORID,
typedef, SCSPEC, RID_TYPEDEF, typedef, SCSPEC, RID_TYPEDEF,
typeof, TYPEOF, NORID, typeof, TYPEOF, NORID,
typeid, TYPEID, NORID, typeid, TYPEID, NORID,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
@node Top, Limitations of g++, (dir), (dir) @node Top, Limitations of g++, (dir), (dir)
@chapter Internal Architecture of the Compiler @chapter Internal Architecture of the Compiler
This is meant to describe the C++ frontend for gcc in detail. This is meant to describe the C++ front-end for gcc in detail.
Questions and comments to mrs@@cygnus.com. Questions and comments to mrs@@cygnus.com.
@menu @menu
...@@ -24,6 +24,7 @@ Questions and comments to mrs@@cygnus.com. ...@@ -24,6 +24,7 @@ Questions and comments to mrs@@cygnus.com.
* Error Reporting:: * Error Reporting::
* Parser:: * Parser::
* Copying Objects:: * Copying Objects::
* Exception Handling::
* Concept Index:: * Concept Index::
@end menu @end menu
...@@ -555,7 +556,7 @@ IDENTIFIER_NODEs for TYPE_DECLs ...@@ -555,7 +556,7 @@ IDENTIFIER_NODEs for TYPE_DECLs
@item DECL_IGNORED_P @item DECL_IGNORED_P
A bit that can be set to inform the debug information output routines in A bit that can be set to inform the debug information output routines in
the backend that a certain _DECL node should be totally ignored. the back-end that a certain _DECL node should be totally ignored.
Used in cases where it is known that the debugging information will be Used in cases where it is known that the debugging information will be
output in another file, or where a sub-type is known not to be needed output in another file, or where a sub-type is known not to be needed
...@@ -989,7 +990,7 @@ completely unrelated to access control! ...@@ -989,7 +990,7 @@ completely unrelated to access control!
@node Error Reporting, Parser, Access Control, Top @node Error Reporting, Parser, Access Control, Top
@section Error Reporting @section Error Reporting
The C++ frontend uses a call-back mechanism to allow functions to print The C++ front-end uses a call-back mechanism to allow functions to print
out reasonable strings for types and functions without putting extra out reasonable strings for types and functions without putting extra
logic in the functions where errors are found. The interface is through logic in the functions where errors are found. The interface is through
the @code{cp_error} function (or @code{cp_warning}, etc.). The the @code{cp_error} function (or @code{cp_warning}, etc.). The
...@@ -1115,7 +1116,7 @@ conflicts. ...@@ -1115,7 +1116,7 @@ conflicts.
Unlike the others, this ambiguity is not recognized by the Working Paper. Unlike the others, this ambiguity is not recognized by the Working Paper.
@node Copying Objects, Concept Index, Parser, Top @node Copying Objects, Exception Handling, Parser, Top
@section Copying Objects @section Copying Objects
The generated copy assignment operator in g++ does not currently do the The generated copy assignment operator in g++ does not currently do the
...@@ -1141,7 +1142,54 @@ them. ...@@ -1141,7 +1142,54 @@ them.
This issue is currently under discussion in the core reflector This issue is currently under discussion in the core reflector
(2/28/94). (2/28/94).
@node Concept Index, , Copying Objects, Top @node Copying Objects, Concept Index, Copying Objects, Top
@section Exception Handling
This section describes the mapping of C++ exceptions in the C++
front-end, into the back-end exception handling framework.
The basic mechanism of exception handling in the back-end is
unwind-protect a la elisp. This is a general, robust, and language
independent representation for exceptions.
The C++ front-end exceptions are mapping into the unwind-protect
semantics by the C++ front-end. The mapping is describe below.
Objects with RTTI support, should use the RTTI information to do mapping
and checking. Objects without RTTI, like int and const char *, have to
use another means of matching. Currently we use the normal mangling used in
building functions names. Int's are "i", const char * is PCc, etc...
Unfortunately, the standard allows standard type conversions on throw
parameters so they can match catch handlers. This means we need a
mechanism to handle type conversion at run time, ICK.
In C++, all cleanups should be protected by exception regions. The
region starts just after the reason why the cleanup is created has
ended. For example, with an automatic variable, that has a constructor,
it would be right after the constructor is run. The region ends just
before the finalization is expanded. Since the backend may expand the
cleanup multiple times along different paths, once for normal end of the
region, once for non-local gotos, once for returns, etc, the backend
must take special care to protect the finalization expansion, if the
expansion is for any other reason than normal region end, and it is
`inline' (it is inside the exception region). The backend can either
choose to move them out of line, or it can created an exception region
over the finalization to protect it, and in the handler associated with
it, it would not run the finalization as it otherwise would have, but
rather just rethrow to the outer handler, careful to skip the normal
handler for the original region.
In Ada, they will use the more runtime intensive approach of having
fewer regions, but at the cost of additional work at run time, to keep a
list of things that need cleanups. When a variable has finished
construction, they add the cleanup to the list, when the come to the end
of the lifetime of the variable, the run the list down. If the take a
hit before the section finishes normally, they examine the list for
actions to perform. I hope they add this logic into the back-end, as it
would be nice to get that alternative approach in C++.
@node Concept Index, , Exception Handling, Top
@section Concept Index @section Concept Index
@printindex cp @printindex cp
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
struct resword { char *name; short token; enum rid rid;}; struct resword { char *name; short token; enum rid rid;};
#define TOTAL_KEYWORDS 86 #define TOTAL_KEYWORDS 80
#define MIN_WORD_LENGTH 2 #define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 13 #define MAX_WORD_LENGTH 13
#define MIN_HASH_VALUE 4 #define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 196 #define MAX_HASH_VALUE 166
/* maximum key range = 193, duplicates = 0 */ /* maximum key range = 163, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
inline inline
...@@ -20,19 +20,19 @@ hash (str, len) ...@@ -20,19 +20,19 @@ hash (str, len)
{ {
static unsigned char asso_values[] = static unsigned char asso_values[] =
{ {
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
197, 197, 197, 197, 197, 0, 197, 93, 3, 35, 167, 167, 167, 167, 167, 0, 167, 36, 6, 60,
3, 0, 71, 8, 4, 78, 197, 3, 30, 6, 17, 0, 16, 5, 41, 38, 167, 11, 22, 7,
29, 18, 37, 197, 55, 0, 4, 11, 7, 20, 26, 0, 4, 167, 22, 0, 4, 44, 19, 8,
0, 8, 197, 197, 197, 197, 197, 197, 5, 18, 167, 167, 167, 167, 167, 167,
}; };
register int hval = len; register int hval = len;
...@@ -68,127 +68,103 @@ is_reserved_word (str, len) ...@@ -68,127 +68,103 @@ is_reserved_word (str, len)
{"",}, {"",}, {"",}, {"",},
{"__asm__", GCC_ASM_KEYWORD, NORID}, {"__asm__", GCC_ASM_KEYWORD, NORID},
{"this", THIS, NORID,}, {"this", THIS, NORID,},
{"delete", DELETE, NORID,}, {"goto", GOTO, NORID,},
{"except", EXCEPT, NORID /* Extension */,},
{"__asm", GCC_ASM_KEYWORD, NORID},
{"double", TYPESPEC, RID_DOUBLE,},
{"typeid", TYPEID, NORID,},
{"switch", SWITCH, NORID,},
{"try", TRY, NORID /* Extension */,},
{"enum", ENUM, NORID,},
{"void", TYPESPEC, RID_VOID,},
{"",}, {"",}, {"",},
{"struct", AGGR, RID_RECORD,},
{"",},
{"do", DO, NORID,},
{"",}, {"",}, {"",}, {"",},
{"__headof__", HEADOF, NORID}, {"__headof__", HEADOF, NORID},
{"",}, {"",}, {"",},
{"__asm", GCC_ASM_KEYWORD, NORID},
{"__const__", TYPE_QUAL, RID_CONST}, {"__const__", TYPE_QUAL, RID_CONST},
{"__volatile", TYPE_QUAL, RID_VOLATILE}, {"__volatile", TYPE_QUAL, RID_VOLATILE},
{"__const", TYPE_QUAL, RID_CONST}, {"__const", TYPE_QUAL, RID_CONST},
{"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"__volatile__", TYPE_QUAL, RID_VOLATILE},
{"extern", SCSPEC, RID_EXTERN,}, {"throw", THROW, NORID,},
{"enum", ENUM, NORID,},
{"do", DO, NORID,},
{"template", TEMPLATE, NORID,},
{"sigof", SIGOF, NORID /* Extension */,},
{"sizeof", SIZEOF, NORID,},
{"delete", DELETE, NORID,},
{"__headof", HEADOF, NORID},
{"try", TRY, NORID,},
{"typeof", TYPEOF, NORID,},
{"typeid", TYPEID, NORID,},
{"__typeof__", TYPEOF, NORID}, {"__typeof__", TYPEOF, NORID},
{"",}, {"double", TYPESPEC, RID_DOUBLE,},
{"signed", TYPESPEC, RID_SIGNED,}, {"private", VISSPEC, RID_PRIVATE,},
{"case", CASE, NORID,}, {"short", TYPESPEC, RID_SHORT,},
{"class", AGGR, RID_CLASS,}, {"extern", SCSPEC, RID_EXTERN,},
{"__classof__", CLASSOF, NORID}, {"__classof__", CLASSOF, NORID},
{"__extension__", EXTENSION, NORID},
{"",},
{"const", TYPE_QUAL, RID_CONST,},
{"static", SCSPEC, RID_STATIC,},
{"",}, {"",},
{"throw", THROW, NORID /* Extension */,}, {"while", WHILE, NORID,},
{"goto", GOTO, NORID,},
{"signature", AGGR, RID_SIGNATURE /* Extension */,},
{"long", TYPESPEC, RID_LONG,}, {"long", TYPESPEC, RID_LONG,},
{"private", VISSPEC, RID_PRIVATE,},
{"new", NEW, NORID,}, {"new", NEW, NORID,},
{"template", TEMPLATE, NORID,},
{"",},
{"while", WHILE, NORID,},
{"",},
{"protected", VISSPEC, RID_PROTECTED,}, {"protected", VISSPEC, RID_PROTECTED,},
{"continue", CONTINUE, NORID,},
{"",},
{"raise", RAISE, NORID /* Extension */,},
{"raises", RAISES, NORID /* Extension */,},
{"",},
{"union", AGGR, RID_UNION,},
{"short", TYPESPEC, RID_SHORT,},
{"",},
{"__inline", SCSPEC, RID_INLINE},
{"",},
{"__inline__", SCSPEC, RID_INLINE},
{"",},
{"__alignof__", ALIGNOF, NORID},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"sizeof", SIZEOF, NORID,},
{"virtual", SCSPEC, RID_VIRTUAL,},
{"catch", CATCH, NORID,},
{"friend", SCSPEC, RID_FRIEND,}, {"friend", SCSPEC, RID_FRIEND,},
{"typeof", TYPEOF, NORID,}, {"auto", SCSPEC, RID_AUTO,},
{"",}, {"",}, {"for", FOR, NORID,},
{"headof", HEADOF, NORID,}, {"__typeof", TYPEOF, NORID},
{"typedef", SCSPEC, RID_TYPEDEF,},
{"__extension__", EXTENSION, NORID},
{"int", TYPESPEC, RID_INT,}, {"int", TYPESPEC, RID_INT,},
{"",}, {"",}, {"asm", ASM_KEYWORD, NORID,},
{"__classof", CLASSOF, NORID},
{"__signed__", TYPESPEC, RID_SIGNED}, {"__signed__", TYPESPEC, RID_SIGNED},
{"__signed", TYPESPEC, RID_SIGNED}, {"signed", TYPESPEC, RID_SIGNED,},
{"",}, {"",}, {"",}, {"mutable", SCSPEC, RID_MUTABLE,},
{"switch", SWITCH, NORID,},
{"operator", OPERATOR, NORID,},
{"__attribute", ATTRIBUTE, NORID}, {"__attribute", ATTRIBUTE, NORID},
{"sigof", SIGOF, NORID /* Extension */,}, {"struct", AGGR, RID_RECORD,},
{"__attribute__", ATTRIBUTE, NORID}, {"__attribute__", ATTRIBUTE, NORID},
{"if", IF, NORID,},
{"void", TYPESPEC, RID_VOID,},
{"break", BREAK, NORID,},
{"__alignof__", ALIGNOF, NORID},
{"__inline", SCSPEC, RID_INLINE},
{"float", TYPESPEC, RID_FLOAT,},
{"__inline__", SCSPEC, RID_INLINE},
{"__signed", TYPESPEC, RID_SIGNED},
{"case", CASE, NORID,},
{"class", AGGR, RID_CLASS,},
{"",}, {"",},
{"__headof", HEADOF, NORID}, {"__label__", LABEL, NORID},
{"default", DEFAULT, NORID,},
{"const", TYPE_QUAL, RID_CONST,},
{"static", SCSPEC, RID_STATIC,},
{"",}, {"",}, {"",}, {"",},
{"unsigned", TYPESPEC, RID_UNSIGNED,}, {"__alignof", ALIGNOF, NORID},
{"return", RETURN, NORID,}, {"virtual", SCSPEC, RID_VIRTUAL,},
{"asm", ASM_KEYWORD, NORID,}, {"union", AGGR, RID_UNION,},
{"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, {"",}, {"",}, {"",},
{"break", BREAK, NORID,}, {"signature", AGGR, RID_SIGNATURE /* Extension */,},
{"__typeof", TYPEOF, NORID}, {"headof", HEADOF, NORID,},
{"mutable", SCSPEC, RID_MUTABLE,},
{"",}, {"",},
{"public", VISSPEC, RID_PUBLIC,}, {"inline", SCSPEC, RID_INLINE,},
{"overload", OVERLOAD, NORID,},
{"",}, {"",},
{"__classof", CLASSOF, NORID}, {"volatile", TYPE_QUAL, RID_VOLATILE,},
{"default", DEFAULT, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"exception", AGGR, RID_EXCEPTION /* Extension */,}, {"register", SCSPEC, RID_REGISTER,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"all", ALL, NORID /* Extension */,}, {"public", VISSPEC, RID_PUBLIC,},
{"",}, {"",}, {"",}, {"",},
{"for", FOR, NORID,}, {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
{"",}, {"",}, {"",}, {"",},
{"__label__", LABEL, NORID}, {"return", RETURN, NORID,},
{"auto", SCSPEC, RID_AUTO,}, {"classof", CLASSOF, NORID,},
{"",}, {"",}, {"",}, {"",},
{"volatile", TYPE_QUAL, RID_VOLATILE,},
{"__alignof", ALIGNOF, NORID},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"dynamic_cast", DYNAMIC_CAST, NORID,}, {"unsigned", TYPESPEC, RID_UNSIGNED,},
{"",},
{"char", TYPESPEC, RID_CHAR,}, {"char", TYPESPEC, RID_CHAR,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"if", IF, NORID,}, {"continue", CONTINUE, NORID,},
{"",},
{"typedef", SCSPEC, RID_TYPEDEF,},
{"operator", OPERATOR, NORID,},
{"reraise", RERAISE, NORID /* Extension */,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"inline", SCSPEC, RID_INLINE,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",},
{"float", TYPESPEC, RID_FLOAT,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"overload", OVERLOAD, NORID,}, {"dynamic_cast", DYNAMIC_CAST, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"classof", CLASSOF, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"register", SCSPEC, RID_REGISTER,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"catch", CATCH, NORID,},
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
......
...@@ -217,12 +217,8 @@ perform_member_init (member, name, init, explicit) ...@@ -217,12 +217,8 @@ perform_member_init (member, name, init, explicit)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
} }
if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type)) cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member);
{
cplus_expand_start_try (1);
push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
}
} }
/* Subroutine of emit_member_init. */ /* Subroutine of emit_member_init. */
...@@ -390,20 +386,6 @@ emit_base_init (t, immediately) ...@@ -390,20 +386,6 @@ emit_base_init (t, immediately)
emit_line_note_force (DECL_SOURCE_FILE (current_function_decl), emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl)); DECL_SOURCE_LINE (current_function_decl));
/* In this case, we always need IN_CHARGE_NODE, because we have
to know whether to deallocate or not before exiting. */
if (flag_handle_exceptions == 2
&& lookup_name (in_charge_identifier, 0) == NULL_TREE)
{
tree in_charge_node = pushdecl (build_decl (VAR_DECL, in_charge_identifier,
integer_type_node));
store_init_value (in_charge_node, build (EQ_EXPR, integer_type_node,
current_class_decl,
integer_zero_node));
expand_decl (in_charge_node);
expand_decl_init (in_charge_node);
}
start = ! TYPE_USES_VIRTUAL_BASECLASSES (t); start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
for (pass = start; pass < 2; pass++) for (pass = start; pass < 2; pass++)
{ {
...@@ -521,11 +503,6 @@ emit_base_init (t, immediately) ...@@ -521,11 +503,6 @@ emit_base_init (t, immediately)
expand_aggr_init_1 (t_binfo, 0, expand_aggr_init_1 (t_binfo, 0,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (binfo), LOOKUP_COMPLAIN); BINFO_OFFSET_ZEROP (binfo), LOOKUP_COMPLAIN);
if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
{
cplus_expand_start_try (1);
push_exception_cleanup (member);
}
} }
if (pass == 0) if (pass == 0)
...@@ -594,12 +571,6 @@ emit_base_init (t, immediately) ...@@ -594,12 +571,6 @@ emit_base_init (t, immediately)
expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE, expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE,
BINFO_OFFSET_ZEROP (base_binfo), BINFO_OFFSET_ZEROP (base_binfo),
LOOKUP_COMPLAIN); LOOKUP_COMPLAIN);
if (flag_handle_exceptions == 2
&& TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
cplus_expand_start_try (1);
push_exception_cleanup (base);
}
} }
} }
CLEAR_BINFO_BASEINIT_MARKED (base_binfo); CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
......
...@@ -766,40 +766,16 @@ init_lex () ...@@ -766,40 +766,16 @@ init_lex ()
do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \ do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \
if (s) s->name = ""; } while (0) if (s) s->name = ""; } while (0)
if (flag_ansi_exceptions) #if 0
flag_handle_exceptions = 2; /* let's parse things, and if they use it, then give them an error. */
if (!flag_handle_exceptions)
if (!flag_ansi_exceptions)
{ {
UNSET_RESERVED_WORD ("throw");
UNSET_RESERVED_WORD ("try");
UNSET_RESERVED_WORD ("catch"); UNSET_RESERVED_WORD ("catch");
} }
#endif
if (! flag_handle_exceptions)
{
/* Easiest way to not recognize exception
handling extensions... */
UNSET_RESERVED_WORD ("all");
UNSET_RESERVED_WORD ("except");
UNSET_RESERVED_WORD ("exception");
UNSET_RESERVED_WORD ("raise");
UNSET_RESERVED_WORD ("raises");
UNSET_RESERVED_WORD ("reraise");
UNSET_RESERVED_WORD ("try");
UNSET_RESERVED_WORD ("throw");
}
else if (flag_ansi_exceptions)
{
/* Easiest way to not recognize exception
handling extensions... */
UNSET_RESERVED_WORD ("exception");
UNSET_RESERVED_WORD ("all");
UNSET_RESERVED_WORD ("except");
UNSET_RESERVED_WORD ("raise");
UNSET_RESERVED_WORD ("raises");
UNSET_RESERVED_WORD ("reraise");
is_reserved_word ("try", sizeof ("try") - 1)->token = ANSI_TRY;
is_reserved_word ("throw", sizeof ("throw") - 1)->token = ANSI_THROW;
}
if (! (flag_gc || flag_dossier)) if (! (flag_gc || flag_dossier))
{ {
UNSET_RESERVED_WORD ("classof"); UNSET_RESERVED_WORD ("classof");
...@@ -3171,6 +3147,13 @@ do_identifier (token) ...@@ -3171,6 +3147,13 @@ do_identifier (token)
} }
} }
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
if (id && current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_CLASS_VALUE (token))
pushdecl_class_level (id);
if (!id || id == error_mark_node) if (!id || id == error_mark_node)
{ {
if (id == error_mark_node && current_class_type != NULL_TREE) if (id == error_mark_node && current_class_type != NULL_TREE)
...@@ -3496,7 +3479,14 @@ real_yylex () ...@@ -3496,7 +3479,14 @@ real_yylex ()
if (strcmp ("catch", token_buffer) == 0 if (strcmp ("catch", token_buffer) == 0
|| strcmp ("throw", token_buffer) == 0 || strcmp ("throw", token_buffer) == 0
|| strcmp ("try", token_buffer) == 0) || strcmp ("try", token_buffer) == 0)
pedwarn ("`catch', `throw', and `try' are all C++ reserved words"); {
static int did_warn = 0;
if (! did_warn && ! flag_handle_exceptions)
{
pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
did_warn = 1;
}
}
if (value == IDENTIFIER || value == TYPESPEC) if (value == IDENTIFIER || value == TYPESPEC)
GNU_xref_ref (current_function_decl, token_buffer); GNU_xref_ref (current_function_decl, token_buffer);
......
...@@ -1494,44 +1494,6 @@ build_exception_variant (ctype, type, raises) ...@@ -1494,44 +1494,6 @@ build_exception_variant (ctype, type, raises)
int constp = TYPE_READONLY (type); int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type); int volatilep = TYPE_VOLATILE (type);
if (raises && TREE_CHAIN (raises))
{
for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++)
a[i] = t;
/* NULL terminator for list. */
a[i] = NULL_TREE;
qsort (a, i, sizeof (tree), id_cmp);
while (i--)
TREE_CHAIN (a[i]) = a[i+1];
raises = a[0];
}
else if (raises)
/* do nothing. */;
else
return build_type_variant (v, constp, volatilep);
if (ctype)
{
cname = TYPE_NAME (ctype);
if (TREE_CODE (cname) == TYPE_DECL)
cname = DECL_NAME (cname);
}
else
cname = NULL_TREE;
for (t = raises; t; t = TREE_CHAIN (t))
{
/* See that all the exceptions we are thinking about
raising have been declared. */
tree this_cname = lookup_exception_cname (ctype, cname, t);
tree decl = lookup_exception_object (this_cname, TREE_VALUE (t), 1);
if (decl == NULL_TREE)
decl = lookup_exception_object (this_cname, TREE_VALUE (t), 0);
/* Place canonical exception decl into TREE_TYPE of RAISES list. */
TREE_TYPE (t) = decl;
}
for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v)) for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
{ {
if (TYPE_READONLY (v) != constp if (TYPE_READONLY (v) != constp
......
...@@ -2280,6 +2280,7 @@ build_function_call_real (function, params, require_complete, flags) ...@@ -2280,6 +2280,7 @@ build_function_call_real (function, params, require_complete, flags)
function, coerced_params, NULL_TREE); function, coerced_params, NULL_TREE);
TREE_SIDE_EFFECTS (result) = 1; TREE_SIDE_EFFECTS (result) = 1;
/* Remove this sometime. */
TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype); TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype);
if (! require_complete) if (! require_complete)
return result; return result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment