+\f
+/* EXP is an expression that we want to pre-evaluate. Returns (in
+ *INITP) an expression that will perform the pre-evaluation. The
+ value returned by this function is a side-effect free expression
+ equivalent to the pre-evaluated expression. Callers must ensure
+ that *INITP is evaluated before EXP. */
+
+tree
+stabilize_expr (tree exp, tree* initp)
+{
+ tree init_expr;
+
+ if (!TREE_SIDE_EFFECTS (exp))
+ init_expr = NULL_TREE;
+ else if (!real_lvalue_p (exp)
+ || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
+ {
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ }
+ else
+ {
+ exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error);
+ }
+ *initp = init_expr;
+
+ gcc_assert (!TREE_SIDE_EFFECTS (exp));
+ return exp;
+}
+
+/* Add NEW_EXPR, an expression whose value we don't care about, after the
+ similar expression ORIG. */
+
+tree
+add_stmt_to_compound (tree orig, tree new_expr)
+{
+ if (!new_expr || !TREE_SIDE_EFFECTS (new_expr))
+ return orig;
+ if (!orig || !TREE_SIDE_EFFECTS (orig))
+ return new_expr;
+ return build2 (COMPOUND_EXPR, void_type_node, orig, new_expr);
+}
+
+/* Like stabilize_expr, but for a call whose arguments we want to
+ pre-evaluate. CALL is modified in place to use the pre-evaluated
+ arguments, while, upon return, *INITP contains an expression to
+ compute the arguments. */
+
+void
+stabilize_call (tree call, tree *initp)
+{
+ tree inits = NULL_TREE;
+ int i;
+ int nargs = call_expr_nargs (call);
+
+ if (call == error_mark_node || processing_template_decl)
+ {
+ *initp = NULL_TREE;
+ return;
+ }
+
+ gcc_assert (TREE_CODE (call) == CALL_EXPR);
+
+ for (i = 0; i < nargs; i++)
+ {
+ tree init;
+ CALL_EXPR_ARG (call, i) =
+ stabilize_expr (CALL_EXPR_ARG (call, i), &init);
+ inits = add_stmt_to_compound (inits, init);
+ }
+
+ *initp = inits;
+}
+
+/* Like stabilize_expr, but for an AGGR_INIT_EXPR whose arguments we want
+ to pre-evaluate. CALL is modified in place to use the pre-evaluated
+ arguments, while, upon return, *INITP contains an expression to
+ compute the arguments. */
+
+void
+stabilize_aggr_init (tree call, tree *initp)
+{
+ tree inits = NULL_TREE;
+ int i;
+ int nargs = aggr_init_expr_nargs (call);
+
+ if (call == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (call) == AGGR_INIT_EXPR);
+
+ for (i = 0; i < nargs; i++)
+ {
+ tree init;
+ AGGR_INIT_EXPR_ARG (call, i) =
+ stabilize_expr (AGGR_INIT_EXPR_ARG (call, i), &init);
+ inits = add_stmt_to_compound (inits, init);
+ }
+
+ *initp = inits;
+}
+
+/* Like stabilize_expr, but for an initialization.
+
+ If the initialization is for an object of class type, this function
+ takes care not to introduce additional temporaries.
+
+ Returns TRUE iff the expression was successfully pre-evaluated,
+ i.e., if INIT is now side-effect free, except for, possible, a
+ single call to a constructor. */
+
+bool
+stabilize_init (tree init, tree *initp)
+{
+ tree t = init;
+
+ *initp = NULL_TREE;
+
+ if (t == error_mark_node || processing_template_decl)
+ return true;
+
+ if (TREE_CODE (t) == INIT_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
+ {
+ TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+ return true;
+ }
+
+ if (TREE_CODE (t) == INIT_EXPR)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == TARGET_EXPR)
+ t = TARGET_EXPR_INITIAL (t);
+ if (TREE_CODE (t) == COMPOUND_EXPR)
+ t = expr_last (t);
+ if (TREE_CODE (t) == CONSTRUCTOR
+ && EMPTY_CONSTRUCTOR_P (t))
+ /* Default-initialization. */
+ return true;
+
+ /* If the initializer is a COND_EXPR, we can't preevaluate
+ anything. */
+ if (TREE_CODE (t) == COND_EXPR)
+ return false;
+
+ if (TREE_CODE (t) == CALL_EXPR)
+ {
+ stabilize_call (t, initp);
+ return true;
+ }
+
+ if (TREE_CODE (t) == AGGR_INIT_EXPR)
+ {
+ stabilize_aggr_init (t, initp);
+ return true;
+ }
+
+ /* The initialization is being performed via a bitwise copy -- and
+ the item copied may have side effects. */
+ return TREE_SIDE_EFFECTS (init);
+}
+
+/* Like "fold", but should be used whenever we might be processing the
+ body of a template. */
+
+tree
+fold_if_not_in_template (tree expr)
+{
+ /* In the body of a template, there is never any need to call
+ "fold". We will call fold later when actually instantiating the
+ template. Integral constant expressions in templates will be
+ evaluated via fold_non_dependent_expr, as necessary. */
+ if (processing_template_decl)
+ return expr;
+
+ /* Fold C++ front-end specific tree codes. */
+ if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
+ return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
+
+ return fold (expr);
+}
+
+/* Returns true if a cast to TYPE may appear in an integral constant
+ expression. */
+
+bool
+cast_valid_in_integral_constant_expression_p (tree type)
+{
+ return (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || dependent_type_p (type)
+ || type == error_mark_node);
+}
+
+\f
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Complain that some language-specific thing hanging off a tree
+ node has been accessed improperly. */
+
+void
+lang_check_failed (const char* file, int line, const char* function)
+{
+ internal_error ("lang_* check: failed in %s, at %s:%d",
+ function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
+
+#include "gt-cp-tree.h"