diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-15 01:31:45 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-15 01:31:45 +0000 |
commit | 14c3d1e50739da45c2af368d5960c937d9ebd857 (patch) | |
tree | fdcb7402c43aec74d3459daa95e59e5de36da6f9 /gcc/cp/except.c | |
parent | 36a7b355db11acfdbf65553e31e2b4d5c60d5928 (diff) | |
download | gcc-14c3d1e50739da45c2af368d5960c937d9ebd857.tar.gz |
* except.c (check_handlers): New fn.
* cp-tree.h: Declare it.
* semantics.c (finish_handler_sequence): Call it.
(finish_function_handler_sequence): Likewise.
(finish_handler_parms): Set TREE_TYPE on the handler.
* cp-tree.h (PUBLICLY_UNIQUELY_DERIVED_P): New macro.
* search.c (get_base_distance_recursive): If protect>1, ignore
special access.
(get_base_distance): Don't reduce watch_access.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33904 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/except.c')
-rw-r--r-- | gcc/cp/except.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 943972e5ffb..ce8535a8622 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1106,3 +1106,87 @@ nothrow_libfn_p (fn) id = DECL_ASSEMBLER_NAME (fn); return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); } + +/* Returns nonzero if an exception of type FROM will be caught by a + handler for type TO, as per [except.handle]. */ + +static int +can_convert_eh (to, from) + tree to, from; +{ + if (TREE_CODE (to) == REFERENCE_TYPE) + to = TREE_TYPE (to); + if (TREE_CODE (from) == REFERENCE_TYPE) + from = TREE_TYPE (from); + + if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE) + { + to = TREE_TYPE (to); + from = TREE_TYPE (from); + + if (! at_least_as_qualified_p (to, from)) + return 0; + + if (TREE_CODE (to) == VOID_TYPE) + return 1; + + /* else fall through */ + } + + if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && PUBLICLY_UNIQUELY_DERIVED_P (to, from)) + return 1; + + return 0; +} + +/* Check whether any of HANDLERS are shadowed by another handler accepting + TYPE. Note that the shadowing may not be complete; even if an exception + of type B would be caught by a handler for A, there could be a derived + class C for which A is an ambiguous base but B is not, so the handler + for B would catch an exception of type C. */ + +static void +check_handlers_1 (master, handlers) + tree master; + tree handlers; +{ + tree type = TREE_TYPE (master); + tree handler; + + for (handler = handlers; handler; handler = TREE_CHAIN (handler)) + if (TREE_TYPE (handler) + && can_convert_eh (type, TREE_TYPE (handler))) + { + lineno = STMT_LINENO (handler); + cp_warning ("exception of type `%T' will be caught", + TREE_TYPE (handler)); + lineno = STMT_LINENO (master); + cp_warning (" by earlier handler for `%T'", type); + break; + } +} + +/* Given a chain of HANDLERs, make sure that they're OK. */ + +void +check_handlers (handlers) + tree handlers; +{ + tree handler; + int save_line = lineno; + for (handler = handlers; handler; handler = TREE_CHAIN (handler)) + { + if (TREE_CHAIN (handler) == NULL_TREE) + /* No more handlers; nothing to shadow. */; + else if (TREE_TYPE (handler) == NULL_TREE) + { + lineno = STMT_LINENO (handler); + cp_pedwarn + ("`...' handler must be the last handler for its try block"); + } + else + check_handlers_1 (handler, TREE_CHAIN (handler)); + } + lineno = save_line; +} |