Add condition to MUST_NOT_THROW_EXPR.
authorTorvald Riegel <triegel@redhat.com>
Mon, 12 Dec 2011 12:05:18 +0000 (12:05 +0000)
committerTorvald Riegel <torvald@gcc.gnu.org>
Mon, 12 Dec 2011 12:05:18 +0000 (12:05 +0000)
gcc/cp/
* cp-tree.def (MUST_NOT_THROW_EXPR): Add condition parameter.
* cp-tree.h (MUST_NOT_THROW_COND): New.
(build_must_not_throw_expr): Declare.
* dump.c (cp_dump_tree): Dump MUST_NOT_THROW_EXPR condition.
* except.c (build_must_not_throw_expr): New.
(initialize_handler_parm): Use it.
(begin_eh_spec_block, wrap_cleanups_r): Adapt to condition.
* pt.c (tsubst_expr): Handle MUST_NOT_THROW_EXPR.

From-SVN: r182233

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/dump.c
gcc/cp/except.c
gcc/cp/pt.c

index 1ba9f347a17815c57eac25ef8165a1e4ac8c63c6..d553dce240e63c58f2706112200aaf3f1ea074ec 100644 (file)
@@ -1,3 +1,14 @@
+2011-12-12  Torvald Riegel  <triegel@redhat.com>
+
+       * cp-tree.def (MUST_NOT_THROW_EXPR): Add condition parameter.
+       * cp-tree.h (MUST_NOT_THROW_COND): New.
+       (build_must_not_throw_expr): Declare.
+       * dump.c (cp_dump_tree): Dump MUST_NOT_THROW_EXPR condition.
+       * except.c (build_must_not_throw_expr): New.
+       (initialize_handler_parm): Use it.
+       (begin_eh_spec_block, wrap_cleanups_r): Adapt to condition.
+       * pt.c (tsubst_expr): Handle MUST_NOT_THROW_EXPR.
+
 2011-12-12  Richard Guenther  <rguenther@suse.de>
 
        PR lto/51262
index 5fc5496ef9e2fd0d12ebd758b1e4a87329d852f4..83e0b5baab67aa96ecc36accbe7ca706d6bc3d6b 100644 (file)
@@ -281,8 +281,9 @@ DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", tcc_statement, 2)
 DEFTREECODE (HANDLER, "handler", tcc_statement, 2)
 
 /* A MUST_NOT_THROW_EXPR wraps an expression that may not
-   throw, and must call terminate if it does.  */
-DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", tcc_expression, 1)
+   throw, and must call terminate if it does.  The second argument
+   is a condition, used in templates to express noexcept (condition).  */
+DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", tcc_expression, 2)
 
 /* A CLEANUP_STMT marks the point at which a declaration is fully
    constructed.  The CLEANUP_EXPR is run on behalf of CLEANUP_DECL
index 955d0eb366816da8a0f52337331645a6003c0ed3..c28b2297486ad2facc386d3818b3b45e9abea4db 100644 (file)
@@ -3016,6 +3016,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define VEC_INIT_EXPR_VALUE_INIT(NODE) \
   TREE_LANG_FLAG_1 (VEC_INIT_EXPR_CHECK (NODE))
 
+/* The condition under which this MUST_NOT_THROW_EXPR actually blocks
+   exceptions.  NULL_TREE means 'true'.  */
+#define MUST_NOT_THROW_COND(NODE) \
+  TREE_OPERAND (MUST_NOT_THROW_EXPR_CHECK (NODE), 1)
+
 /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
    TEMPLATE_DECL.  This macro determines whether or not a given class
    type is really a template type, as opposed to an instantiation or
@@ -5148,6 +5153,7 @@ extern bool type_noexcept_p                       (const_tree);
 extern bool type_throw_all_p                   (const_tree);
 extern tree build_noexcept_spec                        (tree, int);
 extern void choose_personality_routine         (enum languages);
+extern tree build_must_not_throw_expr          (tree,tree);
 extern tree eh_type_info                       (tree);
 extern tree begin_eh_spec_block                        (void);
 extern void finish_eh_spec_block               (tree, tree);
index d1631fc35cd68efa9f242775e792fc01bca67b26..a461094f504642a5f513bc9b9382fb2b98b81798 100644 (file)
@@ -413,6 +413,7 @@ cp_dump_tree (void* dump_info, tree t)
     case MUST_NOT_THROW_EXPR:
       dump_stmt (di, t);
       dump_child ("body", TREE_OPERAND (t, 0));
+      dump_child ("cond", MUST_NOT_THROW_COND (t));
       break;
 
     case USING_STMT:
index 670a66f161154d4f79635cb2ae7aff8781ab6a89..c56dc2c734b05534fb0552a0f40e6aee6546b943 100644 (file)
@@ -374,6 +374,28 @@ choose_personality_routine (enum languages lang)
   state = gave_error;
 }
 
+/* Wrap EXPR in a MUST_NOT_THROW_EXPR expressing that EXPR must
+   not throw any exceptions if COND is true.  A condition of
+   NULL_TREE is treated as 'true'.  */
+
+tree
+build_must_not_throw_expr (tree body, tree cond)
+{
+  tree type = body ? TREE_TYPE (body) : void_type_node;
+
+  if (cond && !value_dependent_expression_p (cond))
+    {
+      cond = cxx_constant_value (cond);
+      if (integer_zerop (cond))
+       return body;
+      else if (integer_onep (cond))
+       cond = NULL_TREE;
+    }
+
+  return build2 (MUST_NOT_THROW_EXPR, type, body, cond);
+}
+
+
 /* Initialize the catch parameter DECL.  */
 
 static void
@@ -418,7 +440,7 @@ initialize_handler_parm (tree decl, tree exp)
       /* Force cleanups now to avoid nesting problems with the
         MUST_NOT_THROW_EXPR.  */
       init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
-      init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
+      init = build_must_not_throw_expr (init, NULL_TREE);
     }
 
   decl = pushdecl (decl);
@@ -560,7 +582,8 @@ begin_eh_spec_block (void)
      MUST_NOT_THROW_EXPR.  */
   if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
     {
-      r = build_stmt (spec_location, MUST_NOT_THROW_EXPR, NULL_TREE);
+      r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
+                     NULL_TREE, NULL_TREE);
       TREE_SIDE_EFFECTS (r) = 1;
     }
   else
@@ -664,7 +687,8 @@ wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
   cleanup = TARGET_EXPR_CLEANUP (exp);
   if (cleanup)
     {
-      cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
+      cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup,
+                       NULL_TREE);
       TARGET_EXPR_CLEANUP (exp) = cleanup;
     }
 
index bb5aa0c1484edc04e165f0f6e741838f7960cda5..f5a317525064ea2783a24f41d6f35e4dbbd3d467 100644 (file)
@@ -13260,6 +13260,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       }
       break;
 
+    case MUST_NOT_THROW_EXPR:
+      return build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
+                                       RECUR (MUST_NOT_THROW_COND (t)));
+
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
       return error_mark_node;