except.c (check_handlers): New fn.
authorJason Merrill <jason@casey.cygnus.com>
Mon, 15 May 2000 01:31:45 +0000 (01:31 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 15 May 2000 01:31:45 +0000 (21:31 -0400)
        * 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/except.c
gcc/cp/search.c
gcc/cp/semantics.c

index be2d295..a9a8684 100644 (file)
@@ -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.
index c7c0933..7961eb3 100644 (file)
@@ -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)
 \f
 /* 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));
index 943972e..ce8535a 100644 (file)
@@ -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;
+}
index 33eb38e..69d0739 100644 (file)
@@ -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,
index afa9ff2..ca0704c 100644 (file)
@@ -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;
 }