aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@casey.cygnus.com>2000-05-15 01:31:45 +0000
committerJason Merrill <jason@gcc.gnu.org>2000-05-14 21:31:45 -0400
commit2bc9f1d1d1027f97e6bc0850c0605c79091330a9 (patch)
treefdcb7402c43aec74d3459daa95e59e5de36da6f9 /gcc/cp
parentc2b2bca6360e429bccc10d083edfb72618b3a658 (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/except.c84
-rw-r--r--gcc/cp/search.c24
-rw-r--r--gcc/cp/semantics.c13
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;
}