diff options
author | Jason Merrill <jason@casey.cygnus.com> | 2000-05-15 01:31:45 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2000-05-14 21:31:45 -0400 |
commit | 2bc9f1d1d1027f97e6bc0850c0605c79091330a9 (patch) | |
tree | fdcb7402c43aec74d3459daa95e59e5de36da6f9 /gcc/cp | |
parent | c2b2bca6360e429bccc10d083edfb72618b3a658 (diff) | |
download | gcc-2bc9f1d1d1027f97e6bc0850c0605c79091330a9.zip gcc-2bc9f1d1d1027f97e6bc0850c0605c79091330a9.tar.gz gcc-2bc9f1d1d1027f97e6bc0850c0605c79091330a9.tar.bz2 |
except.c (check_handlers): New fn.
* 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.
From-SVN: r33904
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 84 | ||||
-rw-r--r-- | gcc/cp/search.c | 24 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 13 |
5 files changed, 124 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index be2d295..a9a8684 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2000-05-14 Jason Merrill <jason@casey.cygnus.com> + + * 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. + 2000-05-13 Gabriel Dos Reis <gdr@codesourcery.com> * lex.c: #include diagnostic.h. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c7c0933..7961eb3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1314,6 +1314,7 @@ enum languages { lang_c, lang_cplusplus, lang_java }; #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0) #define ACCESSIBLY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, -1, (tree *)0) >= 0) #define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0) +#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 2, (tree *)0) >= 0) #define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1) /* This structure provides additional information above and beyond @@ -4114,6 +4115,7 @@ extern void expand_exception_blocks PARAMS ((void)); extern tree build_throw PARAMS ((tree)); extern void mark_all_runtime_matches PARAMS ((void)); extern int nothrow_libfn_p PARAMS ((tree)); +extern void check_handlers PARAMS ((tree)); /* in expr.c */ extern void init_cplus_expand PARAMS ((void)); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 943972e..ce8535a 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; +} diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 33eb38e..69d0739 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -327,7 +327,7 @@ get_base_distance_recursive (binfo, depth, is_private, rval, tree binfos; int i, n_baselinks; - if (protect + if (protect == 1 && !current_scope_in_chain && is_friend (BINFO_TYPE (binfo), current_scope ())) current_scope_in_chain = 1; @@ -383,12 +383,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval, tree base_binfo = TREE_VEC_ELT (binfos, i); int via_private - = (protect - && (is_private - || (!TREE_VIA_PUBLIC (base_binfo) - && !(TREE_VIA_PROTECTED (base_binfo) - && current_scope_in_chain) - && !is_friend (BINFO_TYPE (binfo), current_scope ())))); + = ((protect == 1 + && (is_private + || (!TREE_VIA_PUBLIC (base_binfo) + && !(TREE_VIA_PROTECTED (base_binfo) + && current_scope_in_chain) + && !is_friend (BINFO_TYPE (binfo), current_scope ())))) + || (protect > 1 + && (is_private || !TREE_VIA_PUBLIC (base_binfo)))); + int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo); rval = get_base_distance_recursive (base_binfo, depth, via_private, @@ -415,12 +418,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval, Return -1 if TYPE is not derived from PARENT. Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is non-negative. - Return -3 if PARENT is private to TYPE, and PROTECT is non-zero. + Return -3 if PARENT is not accessible in TYPE, and PROTECT is non-zero. If PATH_PTR is non-NULL, then also build the list of types from PARENT to TYPE, with TREE_VIA_VIRTUAL and TREE_VIA_PUBLIC set. + If PROTECT is greater than 1, ignore any special access the current + scope might have when determining whether PARENT is inaccessible. + PARENT can also be a binfo, in which case that exact parent is found and no other. convert_pointer_to_real uses this functionality. @@ -468,7 +474,7 @@ get_base_distance (parent, binfo, protect, path_ptr) return 0; } - if (path_ptr) + if (path_ptr && watch_access == 0) watch_access = 1; rval = get_base_distance_recursive (binfo, 0, 0, -1, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index afa9ff2..ca0704c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -838,7 +838,10 @@ finish_handler_sequence (try_block) tree try_block; { if (building_stmt_tree ()) - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + { + RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + check_handlers (TRY_HANDLERS (try_block)); + } else expand_end_all_catch (); } @@ -852,7 +855,10 @@ finish_function_handler_sequence (try_block) in_function_try_handler = 0; if (building_stmt_tree ()) - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + { + RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + check_handlers (TRY_HANDLERS (try_block)); + } else expand_end_all_catch (); } @@ -901,6 +907,9 @@ finish_handler_parms (decl, handler) else if (building_stmt_tree ()) blocks = expand_start_catch_block (decl); + if (decl) + TREE_TYPE (handler) = TREE_TYPE (decl); + return blocks; } |