#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "c-common.h"
#include "toplev.h"
#include "tree-gimple.h"
static void genericize_try_block (tree *);
static void genericize_catch_block (tree *);
static void genericize_eh_spec_block (tree *);
static void gimplify_must_not_throw_expr (tree *, tree *);
static void cp_gimplify_init_expr (tree *, tree *, tree *);
int
cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
{
tree stmt = *stmt_p;
switch (TREE_CODE (stmt))
{
case TRY_BLOCK:
genericize_try_block (stmt_p);
return 1;
case HANDLER:
genericize_catch_block (stmt_p);
return 1;
case EH_SPEC_BLOCK:
genericize_eh_spec_block (stmt_p);
return 1;
case USING_STMT:
*stmt_p = build_empty_stmt ();
return 1;
default:
break;
}
return 0;
}
static void
genericize_try_block (tree *stmt_p)
{
tree body = TRY_STMTS (*stmt_p);
tree cleanup = TRY_HANDLERS (*stmt_p);
c_gimplify_stmt (&body);
if (CLEANUP_P (*stmt_p))
;
else
c_gimplify_stmt (&cleanup);
*stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
}
static void
genericize_catch_block (tree *stmt_p)
{
tree type = HANDLER_TYPE (*stmt_p);
tree body = HANDLER_BODY (*stmt_p);
c_gimplify_stmt (&body);
*stmt_p = build (CATCH_EXPR, void_type_node, type, body);
}
static void
genericize_eh_spec_block (tree *stmt_p)
{
tree body = EH_SPEC_STMTS (*stmt_p);
tree allowed = EH_SPEC_RAISES (*stmt_p);
tree failure = build_call (call_unexpected_node,
tree_cons (NULL_TREE, build_exc_ptr (),
NULL_TREE));
c_gimplify_stmt (&body);
*stmt_p = gimple_build_eh_filter (body, allowed, failure);
}
int
cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
{
switch (TREE_CODE (*expr_p))
{
case PTRMEM_CST:
*expr_p = cplus_expand_constant (*expr_p);
return GS_OK;
case AGGR_INIT_EXPR:
simplify_aggr_init_expr (expr_p);
return GS_OK;
case THROW_EXPR:
*expr_p = TREE_OPERAND (*expr_p, 0);
return GS_OK;
case MUST_NOT_THROW_EXPR:
gimplify_must_not_throw_expr (expr_p, pre_p);
return GS_OK;
case INIT_EXPR:
case MODIFY_EXPR:
cp_gimplify_init_expr (expr_p, pre_p, post_p);
return GS_OK;
case EMPTY_CLASS_EXPR:
{
tree i = build_int_2 (0, 0);
TREE_TYPE (i) = TREE_TYPE (*expr_p);
*expr_p = i;
}
return GS_OK;
case BASELINK:
*expr_p = BASELINK_FUNCTIONS (*expr_p);
return GS_OK;
default:
return c_gimplify_expr (expr_p, pre_p, post_p);
}
}
static void
cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
{
tree from = TREE_OPERAND (*expr_p, 1);
tree to = TREE_OPERAND (*expr_p, 0);
tree sub;
if (TREE_CODE (from) == TARGET_EXPR)
from = TARGET_EXPR_INITIAL (from);
sub = from;
if (TREE_CODE (from) == STMT_EXPR)
sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
while (TREE_CODE (sub) == COMPOUND_EXPR)
sub = TREE_OPERAND (sub, 1);
if (TREE_CODE (sub) == AGGR_INIT_EXPR)
{
gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
TREE_OPERAND (sub, 2) = to;
*expr_p = from;
if (from != sub)
TREE_TYPE (from) = void_type_node;
}
}
static void
gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
{
tree stmt = *expr_p;
tree temp = voidify_wrapper_expr (stmt);
tree body = TREE_OPERAND (stmt, 0);
gimplify_stmt (&body);
stmt = gimple_build_eh_filter (body, NULL_TREE,
build_call (terminate_node, NULL_TREE));
if (temp)
{
append_to_statement_list (stmt, pre_p);
*expr_p = temp;
}
else
*expr_p = stmt;
}