Commit 2bc9f1d1 by Jason Merrill Committed by Jason Merrill

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
parent c2b2bca6
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> 2000-05-13 Gabriel Dos Reis <gdr@codesourcery.com>
* lex.c: #include diagnostic.h. * lex.c: #include diagnostic.h.
......
...@@ -1314,6 +1314,7 @@ enum languages { lang_c, lang_cplusplus, lang_java }; ...@@ -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 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_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 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) #define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
/* This structure provides additional information above and beyond /* This structure provides additional information above and beyond
...@@ -4114,6 +4115,7 @@ extern void expand_exception_blocks PARAMS ((void)); ...@@ -4114,6 +4115,7 @@ extern void expand_exception_blocks PARAMS ((void));
extern tree build_throw PARAMS ((tree)); extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void)); extern void mark_all_runtime_matches PARAMS ((void));
extern int nothrow_libfn_p PARAMS ((tree)); extern int nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree));
/* in expr.c */ /* in expr.c */
extern void init_cplus_expand PARAMS ((void)); extern void init_cplus_expand PARAMS ((void));
......
...@@ -1106,3 +1106,87 @@ nothrow_libfn_p (fn) ...@@ -1106,3 +1106,87 @@ nothrow_libfn_p (fn)
id = DECL_ASSEMBLER_NAME (fn); id = DECL_ASSEMBLER_NAME (fn);
return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); 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;
}
...@@ -327,7 +327,7 @@ get_base_distance_recursive (binfo, depth, is_private, rval, ...@@ -327,7 +327,7 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
tree binfos; tree binfos;
int i, n_baselinks; int i, n_baselinks;
if (protect if (protect == 1
&& !current_scope_in_chain && !current_scope_in_chain
&& is_friend (BINFO_TYPE (binfo), current_scope ())) && is_friend (BINFO_TYPE (binfo), current_scope ()))
current_scope_in_chain = 1; current_scope_in_chain = 1;
...@@ -383,12 +383,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval, ...@@ -383,12 +383,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
int via_private int via_private
= (protect = ((protect == 1
&& (is_private && (is_private
|| (!TREE_VIA_PUBLIC (base_binfo) || (!TREE_VIA_PUBLIC (base_binfo)
&& !(TREE_VIA_PROTECTED (base_binfo) && !(TREE_VIA_PROTECTED (base_binfo)
&& current_scope_in_chain) && current_scope_in_chain)
&& !is_friend (BINFO_TYPE (binfo), current_scope ())))); && !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); int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
rval = get_base_distance_recursive (base_binfo, depth, via_private, rval = get_base_distance_recursive (base_binfo, depth, via_private,
...@@ -415,12 +418,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval, ...@@ -415,12 +418,15 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
Return -1 if TYPE is not derived from PARENT. Return -1 if TYPE is not derived from PARENT.
Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is
non-negative. 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 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 from PARENT to TYPE, with TREE_VIA_VIRTUAL and TREE_VIA_PUBLIC
set. 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 PARENT can also be a binfo, in which case that exact parent is found
and no other. convert_pointer_to_real uses this functionality. and no other. convert_pointer_to_real uses this functionality.
...@@ -468,7 +474,7 @@ get_base_distance (parent, binfo, protect, path_ptr) ...@@ -468,7 +474,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
return 0; return 0;
} }
if (path_ptr) if (path_ptr && watch_access == 0)
watch_access = 1; watch_access = 1;
rval = get_base_distance_recursive (binfo, 0, 0, -1, rval = get_base_distance_recursive (binfo, 0, 0, -1,
......
...@@ -838,7 +838,10 @@ finish_handler_sequence (try_block) ...@@ -838,7 +838,10 @@ finish_handler_sequence (try_block)
tree try_block; tree try_block;
{ {
if (building_stmt_tree ()) 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 else
expand_end_all_catch (); expand_end_all_catch ();
} }
...@@ -852,7 +855,10 @@ finish_function_handler_sequence (try_block) ...@@ -852,7 +855,10 @@ finish_function_handler_sequence (try_block)
in_function_try_handler = 0; in_function_try_handler = 0;
if (building_stmt_tree ()) 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 else
expand_end_all_catch (); expand_end_all_catch ();
} }
...@@ -901,6 +907,9 @@ finish_handler_parms (decl, handler) ...@@ -901,6 +907,9 @@ finish_handler_parms (decl, handler)
else if (building_stmt_tree ()) else if (building_stmt_tree ())
blocks = expand_start_catch_block (decl); blocks = expand_start_catch_block (decl);
if (decl)
TREE_TYPE (handler) = TREE_TYPE (decl);
return blocks; return blocks;
} }
......
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