summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/tree.c')
-rw-r--r--contrib/gcc/cp/tree.c341
1 files changed, 240 insertions, 101 deletions
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index cdfa49c..ce6137e 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -22,16 +22,17 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
+#include "real.h"
#include "rtl.h"
#include "toplev.h"
#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
+#include "target.h"
static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *));
@@ -39,12 +40,11 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree));
static int list_hash_eq PARAMS ((const void *, const void *));
static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
+static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int));
static tree no_linkage_helper PARAMS ((tree *, int *, void *));
static tree build_srcloc PARAMS ((const char *, int));
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
static tree cp_unsave_r PARAMS ((tree *, int *, void *));
-static void cp_unsave PARAMS ((tree *));
static tree build_target_expr PARAMS ((tree, tree));
static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
@@ -57,12 +57,13 @@ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, boo
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- non-zero, rvalues of class type are considered lvalues. */
+ nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
tree ref;
int treat_class_rvalues_as_lvalues;
+ int allow_cast_as_lvalue;
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -85,16 +86,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- /* This shouldn't be here, but there are lots of places in the compiler
- that are sloppy about tacking on NOP_EXPRs to the same type when
- no actual conversion is happening. */
- case NOP_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+
+ case NOP_EXPR:
+ /* If expression doesn't change the type, we consider it as an
+ lvalue even when cast_as_lvalue extension isn't selected.
+ That's because parts of the compiler are alleged to be sloppy
+ about sticking in NOP_EXPR node for no good reason. */
+ if (allow_cast_as_lvalue ||
+ same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+ else
+ return clk_none;
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
@@ -135,16 +148,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case MAX_EXPR:
case MIN_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case MODIFY_EXPR:
@@ -152,7 +169,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
@@ -197,7 +215,19 @@ cp_lvalue_kind
real_lvalue_p (ref)
tree ref;
{
- return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
+}
+
+/* Returns the kind of lvalue that REF is, in the sense of
+ [basic.lval]. This function should really be named lvalue_p; it
+ computes the C++ definition of lvalue. */
+
+cp_lvalue_kind
+real_non_cast_lvalue_p (tree ref)
+{
+ return lvalue_p_1 (ref,
+ /*treat_class_rvalues_as_lvalues=*/0,
+ /*allow_cast_as_lvalue=*/0);
}
/* This differs from real_lvalue_p in that class rvalues are
@@ -208,7 +238,15 @@ lvalue_p (ref)
tree ref;
{
return
- (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none);
+}
+
+int
+non_cast_lvalue_p (ref)
+ tree ref;
+{
+ return
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 0) != clk_none);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -219,7 +257,20 @@ lvalue_or_else (ref, string)
tree ref;
const char *string;
{
- int win = lvalue_p (ref);
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1);
+ int win = (ret != clk_none);
+ if (! win)
+ error ("non-lvalue in %s", string);
+ return win;
+}
+
+int
+non_cast_lvalue_or_else (ref, string)
+ tree ref;
+ const char *string;
+{
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0);
+ int win = (ret != clk_none);
if (! win)
error ("non-lvalue in %s", string);
return win;
@@ -235,7 +286,7 @@ build_target_expr (decl, value)
tree t;
t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value,
- maybe_build_cleanup (decl), NULL_TREE);
+ cxx_maybe_build_cleanup (decl), NULL_TREE);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
ignore the TARGET_EXPR. If there really turn out to be no
side-effects, then the optimizer should be able to get rid of
@@ -293,7 +344,7 @@ build_cplus_new (type, init)
return rval;
}
-/* Buidl a TARGET_EXPR using INIT to initialize a new temporary of the
+/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
tree
@@ -471,7 +522,7 @@ build_cplus_array_type_1 (elt_type, index_type)
&& index_type && TYPE_MAX_VALUE (index_type)
&& TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
|| uses_template_parms (elt_type)
- || uses_template_parms (index_type))
+ || (index_type && uses_template_parms (index_type)))
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
@@ -496,14 +547,16 @@ build_cplus_array_type (elt_type, index_type)
{
tree t;
int type_quals = cp_type_quals (elt_type);
+ int cv_quals = type_quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
+ int other_quals = type_quals & ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
- if (type_quals != TYPE_UNQUALIFIED)
- elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
+ if (cv_quals)
+ elt_type = cp_build_qualified_type (elt_type, other_quals);
t = build_cplus_array_type_1 (elt_type, index_type);
- if (type_quals != TYPE_UNQUALIFIED)
- t = cp_build_qualified_type (t, type_quals);
+ if (cv_quals)
+ t = cp_build_qualified_type (t, cv_quals);
return t;
}
@@ -610,9 +663,12 @@ cp_build_qualified_type_real (type, type_quals, complain)
return error_mark_node;
/* See if we already have an identically qualified type. */
- t = get_qualified_type (type, type_quals);
-
- /* If we didn't already have it, create it now. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (cp_type_quals (t) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+ break;
+
if (!t)
{
/* Make a new array type, just like the old one, but with the
@@ -651,13 +707,13 @@ cp_build_qualified_type_real (type, type_quals, complain)
result = build_qualified_type (type, type_quals);
/* If this was a pointer-to-method type, and we just made a copy,
- then we need to clear the cached associated
- pointer-to-member-function type; it is not valid for the new
- type. */
+ then we need to unshare the record that holds the cached
+ pointer-to-member-function type, because these will be distinct
+ between the unqualified and qualified types. */
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- TYPE_SET_PTRMEMFUNC_TYPE (result, NULL_TREE);
+ TYPE_LANG_SPECIFIC (result) = NULL;
return result;
}
@@ -717,7 +773,7 @@ unshare_base_binfos (binfo)
While all these live in the same table, they are completely independent,
and the hash code is computed differently for each of these. */
-static htab_t list_hash_table;
+static GTY ((param_is (union tree_node))) htab_t list_hash_table;
struct list_proxy
{
@@ -955,7 +1011,7 @@ is_overloaded_fn (x)
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
- x = TREE_VALUE (x);
+ x = BASELINK_FUNCTIONS (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -970,10 +1026,25 @@ really_overloaded_fn (x)
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
- x = TREE_VALUE (x);
- return (TREE_CODE (x) == OVERLOAD
- && (TREE_CHAIN (x) != NULL_TREE
- || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
+ x = BASELINK_FUNCTIONS (x);
+
+ return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x))
+ || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
+ || TREE_CODE (x) == TEMPLATE_ID_EXPR);
+}
+
+/* Return the OVERLOAD or FUNCTION_DECL inside FNS. FNS can be an
+ OVERLOAD, FUNCTION_DECL, TEMPLATE_ID_EXPR, or baselink. */
+
+tree
+get_overloaded_fn (fns)
+ tree fns;
+{
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ fns = TREE_OPERAND (fns, 0);
+ if (BASELINK_P (fns))
+ fns = BASELINK_FUNCTIONS (fns);
+ return fns;
}
tree
@@ -981,9 +1052,9 @@ get_first_fn (from)
tree from;
{
my_friendly_assert (is_overloaded_fn (from), 9);
- /* A baselink is also considered an overloaded function. */
+ /* A baselink is also considered an overloaded function. */
if (BASELINK_P (from))
- from = TREE_VALUE (from);
+ from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
@@ -998,7 +1069,7 @@ bound_pmf_p (t)
&& TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
}
-/* Return a new OVL node, concatenating it with the old one. */
+/* Return a new OVL node, concatenating it with the old one. */
tree
ovl_cons (decl, chain)
@@ -1037,7 +1108,7 @@ is_aggr_type_2 (t1, t2)
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-/* Returns non-zero if CODE is the code for a statement. */
+/* Returns nonzero if CODE is the code for a statement. */
int
cp_statement_code_p (code)
@@ -1045,8 +1116,6 @@ cp_statement_code_p (code)
{
switch (code)
{
- case SUBOBJECT:
- case CTOR_STMT:
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:
@@ -1064,7 +1133,7 @@ cp_statement_code_p (code)
#define PRINT_RING_SIZE 4
const char *
-lang_printable_name (decl, v)
+cxx_printable_name (decl, v)
tree decl;
int v;
{
@@ -1500,19 +1569,19 @@ build_min VPARAMS ((enum tree_code code, tree tt, ...))
same node; therefore, callers should never modify the node
returned. */
+static GTY(()) tree shared_int_cache[256];
+
tree
build_shared_int_cst (i)
int i;
{
- static tree cache[256];
-
if (i >= 256)
return build_int_2 (i, 0);
- if (!cache[i])
- cache[i] = build_int_2 (i, 0);
+ if (!shared_int_cache[i])
+ shared_int_cache[i] = build_int_2 (i, 0);
- return cache[i];
+ return shared_int_cache[i];
}
tree
@@ -1680,8 +1749,10 @@ cp_tree_equal (t1, t2)
return 0;
case TEMPLATE_PARM_INDEX:
- return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
- && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
+ return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+ && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+ && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
+ TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -1729,25 +1800,15 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Build a wrapper around some pointer PTR so we can use it as a tree. */
+/* Build a wrapper around a 'struct z_candidate' so we can use it as a
+ tree. */
tree
-build_ptr_wrapper (ptr)
- void *ptr;
+build_zc_wrapper (ptr)
+ struct z_candidate *ptr;
{
tree t = make_node (WRAPPER);
- WRAPPER_PTR (t) = ptr;
- return t;
-}
-
-/* Build a wrapper around some integer I so we can use it as a tree. */
-
-tree
-build_int_wrapper (i)
- int i;
-{
- tree t = make_node (WRAPPER);
- WRAPPER_INT (t) = i;
+ WRAPPER_ZC (t) = ptr;
return t;
}
@@ -1861,7 +1922,12 @@ maybe_dummy_object (type, binfop)
if (binfop)
*binfop = binfo;
- if (current_class_ref && context == current_class_type)
+ if (current_class_ref && context == current_class_type
+ /* Kludge: Make sure that current_class_type is actually
+ correct. It might not be if we're in the middle of
+ tsubst_default_argument. */
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+ current_class_type))
decl = current_class_ref;
else
decl = build_dummy_object (context);
@@ -1889,6 +1955,8 @@ pod_type_p (t)
{
t = strip_array_types (t);
+ if (t == error_mark_node)
+ return 1;
if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
@@ -1912,24 +1980,27 @@ pod_type_p (t)
int
zero_init_p (t)
- tree t ATTRIBUTE_UNUSED;
+ tree t;
{
- /* This is not a correct implementation of this function. As a
- result, pointers-to-members will not be correctly
- zero-initialized.
+ t = strip_array_types (t);
+
+ if (t == error_mark_node)
+ return 1;
- However, using a correct implementation of this function results
- in many other failures. Correcting these other failures required
- a major infrastructure improvement, which was undertaken in the
- GCC 3.3 source base.
+ /* NULL pointers to data members are initialized with -1. */
+ if (TYPE_PTRMEM_P (t))
+ return 0;
+
+ /* Classes that contain types that can't be zero-initialized, cannot
+ be zero-initialized themselves. */
+ if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t))
+ return 0;
- In order to reduce risk, these changes were not ported to the GCC
- 3.2 source base. */
return 1;
}
/* Table of valid C++ attributes. */
-const struct attribute_spec cp_attribute_table[] =
+const struct attribute_spec cxx_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
@@ -2031,7 +2102,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
/* Static objects in functions are initialized the
first time control passes through that
function. This is not precise enough to pin down an
- init_priority value, so don't allow it. */
+ init_priority value, so don't allow it. */
|| current_function_decl)
{
error ("can only use `%s' attribute on file-scope definitions of objects of class type",
@@ -2181,6 +2252,14 @@ cp_cannot_inline_tree_fn (fnp)
return 1;
}
+ /* Don't auto-inline anything that might not be bound within
+ this unit of translation. */
+ if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
if (varargs_function_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
@@ -2290,8 +2369,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
- DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
- DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+ DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
/* Don't lose initialization info. */
DECL_INITIAL (var) = DECL_INITIAL (nrv);
@@ -2307,7 +2385,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
return var;
}
-/* Record that we're about to start inlining FN, and return non-zero if
+/* Record that we're about to start inlining FN, and return nonzero if
that's OK. Used for lang_hooks.tree_inlining.start_inlining. */
int
@@ -2336,14 +2414,8 @@ cp_end_inlining (fn)
void
init_tree ()
{
- make_lang_type_fn = cp_make_lang_type;
- lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p;
- lang_set_decl_assembler_name = mangle_decl;
- list_hash_table = htab_create (31, list_hash, list_hash_eq, NULL);
- ggc_add_root (&list_hash_table, 1,
- sizeof (list_hash_table),
- mark_tree_hashtable);
+ list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
/* Called via walk_tree. If *TP points to a DECL_STMT for a local
@@ -2429,12 +2501,11 @@ cp_unsave_r (tp, walk_subtrees, data)
return NULL_TREE;
}
-/* Called by unsave_expr_now whenever an expression (*TP) needs to be
- unsaved. */
+/* Called whenever an expression needs to be unsaved. */
-static void
-cp_unsave (tp)
- tree *tp;
+tree
+cxx_unsave_expr_now (tp)
+ tree tp;
{
splay_tree st;
@@ -2443,18 +2514,20 @@ cp_unsave (tp)
st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
/* Walk the tree once figuring out what needs to be remapped. */
- walk_tree (tp, mark_local_for_remap_r, st, NULL);
+ walk_tree (&tp, mark_local_for_remap_r, st, NULL);
/* Walk the tree again, copying, remapping, and unsaving. */
- walk_tree (tp, cp_unsave_r, st, NULL);
+ walk_tree (&tp, cp_unsave_r, st, NULL);
/* Clean up. */
splay_tree_delete (st);
+
+ return tp;
}
/* Returns the kind of special function that DECL (a FUNCTION_DECL)
- is. Note that this sfk_none is zero, so this function can be used
- as a predicate to test whether or not DECL is a special function. */
+ is. Note that sfk_none is zero, so this function can be used as a
+ predicate to test whether or not DECL is a special function. */
special_function_kind
special_function_p (decl)
@@ -2483,7 +2556,23 @@ special_function_p (decl)
return sfk_none;
}
-/* Returns non-zero if TYPE is a character type, including wchar_t. */
+/* Returns true if and only if NODE is a name, i.e., a node created
+ by the parser when processing an id-expression. */
+
+bool
+name_p (tree node)
+{
+ if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
+ node = TREE_OPERAND (node, 0);
+ return (/* An ordinary unqualified name. */
+ TREE_CODE (node) == IDENTIFIER_NODE
+ /* A destructor name. */
+ || TREE_CODE (node) == BIT_NOT_EXPR
+ /* A qualified name. */
+ || TREE_CODE (node) == SCOPE_REF);
+}
+
+/* Returns nonzero if TYPE is a character type, including wchar_t. */
int
char_type_p (type)
@@ -2537,3 +2626,53 @@ decl_linkage (decl)
/* Everything else has internal linkage. */
return lk_internal;
}
+
+/* EXP is an expression that we want to pre-evaluate. Returns via INITP an
+ expression to perform the pre-evaluation, and returns directly an
+ expression to use the precalculated result. */
+
+tree
+stabilize_expr (exp, initp)
+ tree exp;
+ tree *initp;
+{
+ tree init_expr;
+
+ if (!TREE_SIDE_EFFECTS (exp))
+ {
+ init_expr = void_zero_node;
+ }
+ 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 = build_unary_op (ADDR_EXPR, exp, 1);
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ exp = build_indirect_ref (exp, 0);
+ }
+
+ *initp = init_expr;
+ return exp;
+}
+
+#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 (file, line, function)
+ 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"
OpenPOWER on IntegriCloud