/* Language-dependent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
static hashval_t list_hash_pieces (tree, tree, tree);
static hashval_t list_hash (const void *);
static cp_lvalue_kind lvalue_p_1 (tree, int);
-static tree mark_local_for_remap_r (tree *, int *, void *);
-static tree cp_unsave_r (tree *, int *, void *);
static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
/* A currently unresolved scope ref. */
case SCOPE_REF:
- abort ();
+ gcc_unreachable ();
case MAX_EXPR:
case MIN_EXPR:
+ /* Disallow <? and >? as lvalues if either argument side-effects. */
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
+ || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
+ return clk_none;
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
(lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
}
-/* Return nonzero if REF is an lvalue valid for this language;
- otherwise, print an error message and return zero. */
-
-int
-lvalue_or_else (tree ref, const char* string)
-{
- if (!lvalue_p (ref))
- {
- error ("non-lvalue in %s", string);
- return 0;
- }
- return 1;
-}
-
/* Build a TARGET_EXPR, initializing the DECL with the VALUE. */
static tree
{
tree t;
- t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value,
- cxx_maybe_build_cleanup (decl), NULL_TREE);
+ t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
+ 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
{
tree slot = build_decl (VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (slot) = 1;
+ DECL_IGNORED_P (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
layout_decl (slot, 0);
return slot;
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
- rval = build (AGGR_INIT_EXPR, void_type_node, fn,
- TREE_OPERAND (init, 1), slot);
+ rval = build3 (AGGR_INIT_EXPR, void_type_node, fn,
+ TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
}
{
tree slot;
- my_friendly_assert (!VOID_TYPE_P (type), 20040130);
+ gcc_assert (!VOID_TYPE_P (type));
if (TREE_CODE (init) == TARGET_EXPR)
return init;
{
tree slot;
- my_friendly_assert (!VOID_TYPE_P (type), 20040130);
+ gcc_assert (!VOID_TYPE_P (type));
slot = build_local_temp (type);
return build_target_expr (slot, init);
{
/* Make a new array type, just like the old one, but with the
appropriately qualified element type. */
- t = build_type_copy (type);
+ t = build_variant_type_copy (type);
TREE_TYPE (t) = element_type;
}
tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
if (!(complain & tf_ignore_bad_quals))
- error ("`%V' qualifiers cannot be applied to `%T'",
+ error ("%qV qualifiers cannot be applied to %qT",
bad_type, type);
}
}
int ix;
tree base_binfo;
- my_friendly_assert (!BINFO_DEPENDENT_BASE_P (binfo), 20040712);
- my_friendly_assert (type == BINFO_TYPE (binfo), 20040714);
+ gcc_assert (!BINFO_DEPENDENT_BASE_P (binfo));
+ gcc_assert (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), type));
BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo);
BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (binfo);
{
tree new_base_binfo;
- my_friendly_assert (!BINFO_DEPENDENT_BASE_P (base_binfo), 20040713);
+ gcc_assert (!BINFO_DEPENDENT_BASE_P (base_binfo));
new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo),
t, igo_prev,
BINFO_VIRTUAL_P (base_binfo));
{
return hash_tree_cons (NULL_TREE, value, chain);
}
-
-/* Similar, but used for concatenating two lists. */
-
-tree
-hash_chainon (tree list1, tree list2)
-{
- if (list2 == 0)
- return list1;
- if (list1 == 0)
- return list2;
- if (TREE_CHAIN (list1) == NULL_TREE)
- return hash_tree_chain (TREE_VALUE (list1), list2);
- return hash_tree_chain (TREE_VALUE (list1),
- hash_chainon (TREE_CHAIN (list1), list2));
-}
\f
void
debug_binfo (tree elem)
}
int
-count_functions (tree t)
-{
- int i;
- if (TREE_CODE (t) == FUNCTION_DECL)
- return 1;
- else if (TREE_CODE (t) == OVERLOAD)
- {
- for (i = 0; t; t = OVL_CHAIN (t))
- i++;
- return i;
- }
-
- abort ();
- return 0;
-}
-
-int
is_overloaded_fn (tree x)
{
/* A baselink is also considered an overloaded function. */
tree
get_first_fn (tree from)
{
- my_friendly_assert (is_overloaded_fn (from), 9);
+ gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
-/* Returns nonzero if T is a ->* or .* expression that refers to a
- member function. */
-
-int
-bound_pmf_p (tree t)
-{
- return (TREE_CODE (t) == OFFSET_REF
- && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
-}
-
/* Return a new OVL node, concatenating it with the old one. */
tree
ring_counter += 1;
if (ring_counter == PRINT_RING_SIZE)
ring_counter = 0;
- if (decl_ring[ring_counter] == current_function_decl)
- abort ();
+ gcc_assert (decl_ring[ring_counter] != current_function_decl);
}
if (print_ring[ring_counter])
return v;
/* Need to build a new variant. */
- v = build_type_copy (type);
+ v = build_variant_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
}
/* If this statement is already present in the hash table, then
there is a circularity in the statement tree. */
- if (htab_find (*statements, t))
- abort ();
+ gcc_assert (!htab_find (*statements, t));
slot = htab_find_slot (*statements, t, INSERT);
*slot = t;
tree
array_type_nelts_top (tree type)
{
- return fold (build (PLUS_EXPR, sizetype,
- array_type_nelts (type),
- integer_one_node));
+ return fold (build2 (PLUS_EXPR, sizetype,
+ array_type_nelts (type),
+ integer_one_node));
}
/* Return, as an INTEGER_CST node, the number of elements for TYPE
while (TREE_CODE (type) == ARRAY_TYPE)
{
tree n = array_type_nelts_top (type);
- sz = fold (build (MULT_EXPR, sizetype, sz, n));
+ sz = fold (build2 (MULT_EXPR, sizetype, sz, n));
type = TREE_TYPE (type);
}
return sz;
return t;
}
-/* Returns an INTEGER_CST (of type `int') corresponding to I.
- Multiple calls with the same value of I may or may not yield the
- same node; therefore, callers should never modify the node
- returned. */
-
-static GTY(()) tree shared_int_cache[256];
-
-tree
-build_shared_int_cst (int i)
-{
- if (i >= 256)
- return build_int_cst (NULL_TREE, i, 0);
-
- if (!shared_int_cache[i])
- shared_int_cache[i] = build_int_cst (NULL_TREE, i, 0);
-
- return shared_int_cache[i];
-}
-
tree
get_type_decl (tree t)
{
return t;
if (TYPE_P (t))
return TYPE_STUB_DECL (t);
- if (t == error_mark_node)
- return t;
-
- abort ();
-
- /* Stop compiler from complaining control reaches end of non-void function. */
- return 0;
+ gcc_assert (t == error_mark_node);
+ return t;
}
/* Returns the namespace that contains DECL, whether directly or
case IDENTIFIER_NODE:
return false;
+ case BASELINK:
+ return (BASELINK_BINFO (t1) == BASELINK_BINFO (t2)
+ && BASELINK_ACCESS_BINFO (t1) == BASELINK_ACCESS_BINFO (t2)
+ && cp_tree_equal (BASELINK_FUNCTIONS (t1),
+ BASELINK_FUNCTIONS (t2)));
+
case TEMPLATE_PARM_INDEX:
return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
return same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2));
+ case OVERLOAD:
+ if (OVL_FUNCTION (t1) != OVL_FUNCTION (t2))
+ return false;
+ return cp_tree_equal (OVL_CHAIN (t1), OVL_CHAIN (t2));
+
default:
break;
}
switch (TREE_CODE_CLASS (code1))
{
- case '1':
- case '2':
- case '<':
- case 'e':
- case 'r':
- case 's':
+ case tcc_unary:
+ case tcc_binary:
+ case tcc_comparison:
+ case tcc_expression:
+ case tcc_reference:
+ case tcc_statement:
{
int i;
return true;
}
- case 't':
+ case tcc_type:
return same_type_p (t1, t2);
+ default:
+ gcc_unreachable ();
}
-
- my_friendly_assert (0, 20030617);
+ /* We can get here with --disable-checking. */
return false;
}
if (current_class_type
&& (binfo = lookup_base (current_class_type, type,
- ba_ignore | ba_quiet, NULL)))
+ ba_unique | ba_quiet, NULL)))
context = current_class_type;
else
{
return 1; /* pointer to member */
if (TREE_CODE (t) == VECTOR_TYPE)
- return 1; /* vectors are (small) arrays if scalars */
+ return 1; /* vectors are (small) arrays of scalars */
if (! CLASS_TYPE_P (t))
return 0; /* other non-class type (reference or function) */
|| !CLASS_TYPE_P (*node)
|| !TYPE_FOR_JAVA (*node))
{
- error ("`%E' attribute can only be applied to Java class definitions",
+ error ("%qE attribute can only be applied to Java class definitions",
name);
*no_add_attrs = true;
return NULL_TREE;
}
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
+ *node = build_variant_type_copy (*node);
TYPE_JAVA_INTERFACE (*node) = 1;
return NULL_TREE;
|| !CLASS_TYPE_P (*node)
|| *node != TYPE_MAIN_VARIANT (*node))
{
- warning ("`%E' attribute can only be applied to class definitions",
- name);
+ warning ("%qE attribute can only be applied to class definitions", name);
return NULL_TREE;
}
if (!warned++)
- warning ("`%E' is obsolete; g++ vtables are now COM-compatible by default",
+ warning ("%qE is obsolete; g++ vtables are now COM-compatible by default",
name);
return NULL_TREE;
init_priority value, so don't allow it. */
|| current_function_decl)
{
- error ("can only use `%E' attribute on file-scope definitions "
+ error ("can only use %qE attribute on file-scope definitions "
"of objects of class type", name);
*no_add_attrs = true;
return NULL_TREE;
}
else
{
- error ("`%E' attribute is not supported on this platform", name);
+ error ("%qE attribute is not supported on this platform", name);
*no_add_attrs = true;
return NULL_TREE;
}
tree
cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
- void *data, void *htab)
+ void *data, struct pointer_set_t *pset)
{
enum tree_code code = TREE_CODE (*tp);
location_t save_locus;
#define WALK_SUBTREE(NODE) \
do \
{ \
- result = walk_tree (&(NODE), func, data, htab); \
+ result = walk_tree (&(NODE), func, data, pset); \
if (result) goto out; \
} \
while (0)
return prev_fn;
}
-/* Determine whether a tree node is an OVERLOAD node. Used to decide
- whether to copy a node or to preserve its chain when inlining a
- function. */
-
-int
-cp_is_overload_p (tree t)
-{
- return TREE_CODE (t) == OVERLOAD;
-}
-
/* Determine whether VAR is a declaration of an automatic variable in
function FN. */
&& nonstatic_local_decl_p (var));
}
-/* FN body has been duplicated. Update language specific fields. */
-
-void
-cp_update_decl_after_saving (tree fn,
- void* decl_map_)
-{
- splay_tree decl_map = (splay_tree)decl_map_;
- tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
- if (nrv)
- {
- DECL_SAVED_FUNCTION_DATA (fn)->x_return_value
- = (tree) splay_tree_lookup (decl_map, (splay_tree_key) nrv)->value;
- }
-}
/* Initialize tree.c. */
void
list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
-/* Called via walk_tree. If *TP points to a DECL_EXPR for a local
- declaration, copies the declaration and enters it in the splay_tree
- pointed to by DATA (which is really a `splay_tree *'). */
-
-static tree
-mark_local_for_remap_r (tree* tp,
- int* walk_subtrees ATTRIBUTE_UNUSED ,
- void* data)
-{
- tree t = *tp;
- splay_tree st = (splay_tree) data;
- tree decl;
-
-
- if (TREE_CODE (t) == DECL_EXPR
- && nonstatic_local_decl_p (DECL_EXPR_DECL (t)))
- decl = DECL_EXPR_DECL (t);
- else if (TREE_CODE (t) == LABEL_EXPR)
- decl = LABEL_EXPR_LABEL (t);
- else if (TREE_CODE (t) == TARGET_EXPR
- && nonstatic_local_decl_p (TREE_OPERAND (t, 0)))
- decl = TREE_OPERAND (t, 0);
- else if (TREE_CODE (t) == CASE_LABEL_EXPR)
- decl = CASE_LABEL (t);
- else
- decl = NULL_TREE;
-
- if (decl)
- {
- tree copy;
-
- /* Make a copy. */
- copy = copy_decl_for_inlining (decl,
- DECL_CONTEXT (decl),
- DECL_CONTEXT (decl));
-
- /* Remember the copy. */
- splay_tree_insert (st,
- (splay_tree_key) decl,
- (splay_tree_value) copy);
- }
-
- return NULL_TREE;
-}
-
-/* Called via walk_tree when an expression is unsaved. Using the
- splay_tree pointed to by ST (which is really a `splay_tree'),
- remaps all local declarations to appropriate replacements. */
-
-static tree
-cp_unsave_r (tree* tp,
- int* walk_subtrees,
- void* data)
-{
- splay_tree st = (splay_tree) data;
- splay_tree_node n;
-
- /* Only a local declaration (variable or label). */
- if (nonstatic_local_decl_p (*tp))
- {
- /* Lookup the declaration. */
- n = splay_tree_lookup (st, (splay_tree_key) *tp);
-
- /* If it's there, remap it. */
- if (n)
- *tp = (tree) n->value;
- }
- else if (TREE_CODE (*tp) == SAVE_EXPR)
- remap_save_expr (tp, st, walk_subtrees);
- else
- {
- copy_tree_r (tp, walk_subtrees, NULL);
-
- /* Do whatever unsaving is required. */
- unsave_expr_1 (*tp);
- }
-
- /* Keep iterating. */
- return NULL_TREE;
-}
-
-/* Called whenever an expression needs to be unsaved. */
-
-tree
-cxx_unsave_expr_now (tree tp)
-{
- splay_tree st;
-
- /* Create a splay-tree to map old local variable declarations to new
- ones. */
- 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 the tree again, copying, remapping, and unsaving. */
- 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 sfk_none is zero, so this function can be used as a
predicate to test whether or not DECL is a special function. */
return sfk_none;
}
-/* 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
return exp;
}
+/* Add NEW, an expression whose value we don't care about, after the
+ similar expression ORIG. */
+
+tree
+add_stmt_to_compound (tree orig, tree new)
+{
+ if (!new || !TREE_SIDE_EFFECTS (new))
+ return orig;
+ if (!orig || !TREE_SIDE_EFFECTS (orig))
+ return new;
+ return build2 (COMPOUND_EXPR, void_type_node, orig, new);
+}
+
/* Like stabilize_expr, but for a call whose args we want to
pre-evaluate. */
if (call == error_mark_node)
return;
- if (TREE_CODE (call) != CALL_EXPR
- && TREE_CODE (call) != AGGR_INIT_EXPR)
- abort ();
+ gcc_assert (TREE_CODE (call) == CALL_EXPR
+ || TREE_CODE (call) == AGGR_INIT_EXPR);
for (t = TREE_OPERAND (call, 1); t; t = TREE_CHAIN (t))
if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
{
tree init;
TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
- if (!init)
- /* Nothing. */;
- else if (inits)
- inits = build (COMPOUND_EXPR, void_type_node, inits, init);
- else
- inits = init;
+ inits = add_stmt_to_compound (inits, init);
}
*initp = inits;
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
&& CONSTRUCTOR_ELTS (t) == NULL_TREE)
{
return true;
}
+/* 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. */
+ return (processing_template_decl ? expr : fold (expr));
+}
+
\f
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree