summaryrefslogtreecommitdiff
path: root/gcc/cp/except.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2000-05-15 01:31:45 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2000-05-15 01:31:45 +0000
commit14c3d1e50739da45c2af368d5960c937d9ebd857 (patch)
treefdcb7402c43aec74d3459daa95e59e5de36da6f9 /gcc/cp/except.c
parent36a7b355db11acfdbf65553e31e2b4d5c60d5928 (diff)
downloadgcc-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.c84
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;
+}