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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182233
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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
#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
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);
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:
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
/* 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);
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
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;
}
}
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;