#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "real.h"
#include "rtl.h"
#include "toplev.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
#include "debug.h"
#include "target.h"
#include "convert.h"
static tree bot_manip (tree *, int *, void *);
static tree bot_replace (tree *, int *, void *);
static tree build_cplus_array_type_1 (tree, tree);
static int list_hash_eq (const void *, const void *);
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 build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
static tree build_local_temp (tree);
static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
static cp_lvalue_kind
lvalue_p_1 (tree ref,
int treat_class_rvalues_as_lvalues)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return clk_ordinary;
if (ref == current_class_ptr)
return clk_none;
switch (TREE_CODE (ref))
{
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case SAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
if (!op1_lvalue_kind
|| TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
;
else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
op1_lvalue_kind &= ~clk_ordinary;
op1_lvalue_kind |= clk_bitfield;
}
else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
op1_lvalue_kind |= clk_packed;
return op1_lvalue_kind;
case STRING_CST:
return clk_ordinary;
case CONST_DECL:
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return clk_none;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return clk_ordinary;
break;
case SCOPE_REF:
gcc_unreachable ();
case MAX_EXPR:
case MIN_EXPR:
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),
treat_class_rvalues_as_lvalues);
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues);
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
case VA_ARG_EXPR:
return (treat_class_rvalues_as_lvalues
&& CLASS_TYPE_P (TREE_TYPE (ref))
? clk_class : clk_none);
case CALL_EXPR:
return clk_none;
case FUNCTION_DECL:
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : clk_ordinary);
case NON_DEPENDENT_EXPR:
return clk_ordinary;
default:
break;
}
if (!op1_lvalue_kind || !op2_lvalue_kind)
return clk_none;
op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
op1_lvalue_kind &= ~clk_ordinary;
return op1_lvalue_kind;
}
cp_lvalue_kind
real_lvalue_p (tree ref)
{
return lvalue_p_1 (ref,
0);
}
int
lvalue_p (tree ref)
{
return
(lvalue_p_1 (ref, 1) != clk_none);
}
bool
builtin_valid_in_constant_expr_p (tree decl)
{
return DECL_IS_BUILTIN_CONSTANT_P (decl);
}
static tree
build_target_expr (tree decl, tree value)
{
tree t;
t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
cxx_maybe_build_cleanup (decl), NULL_TREE);
TREE_SIDE_EFFECTS (t) = 1;
return t;
}
static tree
build_local_temp (tree type)
{
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;
}
tree
build_cplus_new (tree type, tree init)
{
tree fn;
tree slot;
tree rval;
int is_ctor;
abstract_virtuals_error (NULL_TREE, type);
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init);
fn = TREE_OPERAND (init, 0);
is_ctor = (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
slot = build_local_temp (type);
if (is_ctor || TREE_ADDRESSABLE (type))
{
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;
}
else
rval = init;
rval = build_target_expr (slot, rval);
TARGET_EXPR_IMPLICIT_P (rval) = 1;
return rval;
}
tree
build_target_expr_with_type (tree init, tree type)
{
gcc_assert (!VOID_TYPE_P (type));
if (TREE_CODE (init) == TARGET_EXPR)
return init;
else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
&& TREE_CODE (init) != VA_ARG_EXPR)
return force_rvalue (init);
return force_target_expr (type, init);
}
tree
force_target_expr (tree type, tree init)
{
tree slot;
gcc_assert (!VOID_TYPE_P (type));
slot = build_local_temp (type);
return build_target_expr (slot, init);
}
tree
get_target_expr (tree init)
{
return build_target_expr_with_type (init, TREE_TYPE (init));
}
tree
convert_bitfield_to_declared_type (tree expr)
{
tree bitfield_type;
bitfield_type = is_bitfield_expr_with_lowered_type (expr);
if (bitfield_type)
expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
expr);
return expr;
}
tree
rvalue (tree expr)
{
tree type;
if (error_operand_p (expr))
return expr;
type = TREE_TYPE (expr);
if (!CLASS_TYPE_P (type) && cp_type_quals (type))
type = TYPE_MAIN_VARIANT (type);
if (!processing_template_decl && real_lvalue_p (expr))
expr = build1 (NON_LVALUE_EXPR, type, expr);
else if (type != TREE_TYPE (expr))
expr = build_nop (type, expr);
return expr;
}
static tree
build_cplus_array_type_1 (tree elt_type, tree index_type)
{
tree t;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
if (dependent_type_p (elt_type)
|| (index_type
&& value_dependent_expression_p (TYPE_MAX_VALUE (index_type))))
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
}
else
t = build_array_type (elt_type, index_type);
TYPE_NEEDS_CONSTRUCTING (t)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
return t;
}
tree
build_cplus_array_type (tree elt_type, tree index_type)
{
tree t;
int type_quals = cp_type_quals (elt_type);
if (type_quals != TYPE_UNQUALIFIED)
elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
t = build_cplus_array_type_1 (elt_type, index_type);
if (type_quals != TYPE_UNQUALIFIED)
t = cp_build_qualified_type (t, type_quals);
return t;
}
tree
cp_build_qualified_type_real (tree type,
int type_quals,
tsubst_flags_t complain)
{
tree result;
int bad_quals = TYPE_UNQUALIFIED;
if (type == error_mark_node)
return type;
if (type_quals == cp_type_quals (type))
return type;
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree t;
tree element_type
= cp_build_qualified_type_real (TREE_TYPE (type),
type_quals,
complain);
if (element_type == error_mark_node)
return error_mark_node;
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)
{
t = build_variant_type_copy (type);
TREE_TYPE (t) = element_type;
}
TYPE_NEEDS_CONSTRUCTING (t)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
return t;
}
else if (TYPE_PTRMEMFUNC_P (type))
{
tree t;
t = TYPE_PTRMEMFUNC_FN_TYPE (type);
t = cp_build_qualified_type_real (t, type_quals, complain);
return build_ptrmemfunc_type (t);
}
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
&& TREE_CODE (type) != FUNCTION_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
type_quals &= ~TYPE_QUAL_RESTRICT;
}
if (bad_quals == TYPE_UNQUALIFIED)
;
else if (!(complain & (tf_error | tf_ignore_bad_quals)))
return error_mark_node;
else
{
if (complain & tf_ignore_bad_quals)
bad_quals &= ~TYPE_QUAL_CONST;
if (bad_quals)
{
tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
if (!(complain & tf_ignore_bad_quals))
error ("%qV qualifiers cannot be applied to %qT",
bad_type, type);
}
}
result = build_qualified_type (type, type_quals);
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
TYPE_LANG_SPECIFIC (result) = NULL;
return result;
}
tree
canonical_type_variant (tree t)
{
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
}
tree
copy_binfo (tree binfo, tree type, tree t, tree *igo_prev, int virt)
{
tree new_binfo;
if (virt)
{
new_binfo = binfo_for_vbase (type, t);
if (new_binfo)
return new_binfo;
}
new_binfo = make_tree_binfo (binfo ? BINFO_N_BASE_BINFOS (binfo) : 0);
BINFO_TYPE (new_binfo) = type;
TREE_CHAIN (*igo_prev) = new_binfo;
*igo_prev = new_binfo;
if (binfo)
{
int ix;
tree base_binfo;
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);
BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (binfo);
for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
{
tree new_base_binfo;
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));
if (!BINFO_INHERITANCE_CHAIN (new_base_binfo))
BINFO_INHERITANCE_CHAIN (new_base_binfo) = new_binfo;
BINFO_BASE_APPEND (new_binfo, new_base_binfo);
}
}
else
BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
if (virt)
{
VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
BINFO_VIRTUAL_P (new_binfo) = 1;
BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
}
return new_binfo;
}
static GTY ((param_is (union tree_node))) htab_t list_hash_table;
struct list_proxy
{
tree purpose;
tree value;
tree chain;
};
static int
list_hash_eq (const void* entry, const void* data)
{
tree t = (tree) entry;
struct list_proxy *proxy = (struct list_proxy *) data;
return (TREE_VALUE (t) == proxy->value
&& TREE_PURPOSE (t) == proxy->purpose
&& TREE_CHAIN (t) == proxy->chain);
}
static hashval_t
list_hash_pieces (tree purpose, tree value, tree chain)
{
hashval_t hashcode = 0;
if (chain)
hashcode += TREE_HASH (chain);
if (value)
hashcode += TREE_HASH (value);
else
hashcode += 1007;
if (purpose)
hashcode += TREE_HASH (purpose);
else
hashcode += 1009;
return hashcode;
}
static hashval_t
list_hash (const void* p)
{
tree t = (tree) p;
return list_hash_pieces (TREE_PURPOSE (t),
TREE_VALUE (t),
TREE_CHAIN (t));
}
tree
hash_tree_cons (tree purpose, tree value, tree chain)
{
int hashcode = 0;
void **slot;
struct list_proxy proxy;
hashcode = list_hash_pieces (purpose, value, chain);
proxy.purpose = purpose;
proxy.value = value;
proxy.chain = chain;
slot = htab_find_slot_with_hash (list_hash_table, &proxy, hashcode,
INSERT);
if (!*slot)
*slot = tree_cons (purpose, value, chain);
return (tree) *slot;
}
tree
hash_tree_chain (tree value, tree chain)
{
return hash_tree_cons (NULL_TREE, value, chain);
}
void
debug_binfo (tree elem)
{
HOST_WIDE_INT n;
tree virtuals;
fprintf (stderr, "type \"%s\", offset = " HOST_WIDE_INT_PRINT_DEC
"\nvtable type:\n",
TYPE_NAME_STRING (BINFO_TYPE (elem)),
TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
debug_tree (BINFO_TYPE (elem));
if (BINFO_VTABLE (elem))
fprintf (stderr, "vtable decl \"%s\"\n",
IDENTIFIER_POINTER (DECL_NAME (get_vtbl_decl_for_binfo (elem))));
else
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem);
n = 0;
while (virtuals)
{
tree fndecl = TREE_VALUE (virtuals);
fprintf (stderr, "%s [%ld =? %ld]\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
(long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
++n;
virtuals = TREE_CHAIN (virtuals);
}
}
tree
build_qualified_name (tree type, tree scope, tree name, bool template_p)
{
tree t;
if (type == error_mark_node
|| scope == error_mark_node
|| name == error_mark_node)
return error_mark_node;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
return t;
}
int
is_overloaded_fn (tree x)
{
if (TREE_CODE (x) == OFFSET_REF
|| TREE_CODE (x) == COMPONENT_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);
if (TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
|| (TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x)))
return 2;
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == OVERLOAD);
}
bool
really_overloaded_fn (tree x)
{
return is_overloaded_fn (x) == 2;
}
tree
get_first_fn (tree from)
{
gcc_assert (is_overloaded_fn (from));
if (TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
tree
ovl_cons (tree decl, tree chain)
{
tree result = make_node (OVERLOAD);
TREE_TYPE (result) = unknown_type_node;
OVL_FUNCTION (result) = decl;
TREE_CHAIN (result) = chain;
return result;
}
tree
build_overload (tree decl, tree chain)
{
if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
return decl;
if (chain && TREE_CODE (chain) != OVERLOAD)
chain = ovl_cons (chain, NULL_TREE);
return ovl_cons (decl, chain);
}
#define PRINT_RING_SIZE 4
const char *
cxx_printable_name (tree decl, int v)
{
static tree decl_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
static int ring_counter;
int i;
if (v < 2
|| TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
return lang_decl_name (decl, v);
for (i = 0; i < PRINT_RING_SIZE; i++)
if (decl_ring[i] == decl)
return print_ring[i];
if (++ring_counter == PRINT_RING_SIZE)
ring_counter = 0;
if (current_function_decl != NULL_TREE)
{
if (decl_ring[ring_counter] == current_function_decl)
ring_counter += 1;
if (ring_counter == PRINT_RING_SIZE)
ring_counter = 0;
gcc_assert (decl_ring[ring_counter] != current_function_decl);
}
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
decl_ring[ring_counter] = decl;
return print_ring[ring_counter];
}
tree
build_exception_variant (tree type, tree raises)
{
tree v = TYPE_MAIN_VARIANT (type);
int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
if (check_qualified_type (v, type, type_quals)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
return v;
v = build_variant_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
}
tree
bind_template_template_parm (tree t, tree newargs)
{
tree decl = TYPE_NAME (t);
tree t2;
t2 = make_aggr_type (BOUND_TEMPLATE_TEMPLATE_PARM);
decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);
TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
= tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
newargs, NULL_TREE);
TREE_TYPE (decl) = t2;
TYPE_NAME (t2) = decl;
TYPE_STUB_DECL (t2) = decl;
TYPE_SIZE (t2) = 0;
return t2;
}
static tree
count_trees_r (tree *tp, int *walk_subtrees, void *data)
{
++*((int *) data);
if (TYPE_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
int
count_trees (tree t)
{
int n_trees = 0;
walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
return n_trees;
}
static tree
verify_stmt_tree_r (tree* tp,
int* walk_subtrees ATTRIBUTE_UNUSED ,
void* data)
{
tree t = *tp;
htab_t *statements = (htab_t *) data;
void **slot;
if (!STATEMENT_CODE_P (TREE_CODE (t)))
return NULL_TREE;
gcc_assert (!htab_find (*statements, t));
slot = htab_find_slot (*statements, t, INSERT);
*slot = t;
return NULL_TREE;
}
void
verify_stmt_tree (tree t)
{
htab_t statements;
statements = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
htab_delete (statements);
}
tree
no_linkage_check (tree t, bool relaxed_p)
{
tree r;
if (processing_template_decl)
return NULL_TREE;
switch (TREE_CODE (t))
{
tree fn;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
case UNION_TYPE:
if (!CLASS_TYPE_P (t))
return NULL_TREE;
case ENUMERAL_TYPE:
if (TYPE_ANONYMOUS_P (t))
return t;
fn = decl_function_context (TYPE_MAIN_DECL (t));
if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
return t;
return NULL_TREE;
case ARRAY_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
return no_linkage_check (TREE_TYPE (t), relaxed_p);
case OFFSET_TYPE:
ptrmem:
r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t),
relaxed_p);
if (r)
return r;
return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
case METHOD_TYPE:
r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
if (r)
return r;
case FUNCTION_TYPE:
{
tree parm;
for (parm = TYPE_ARG_TYPES (t);
parm && parm != void_list_node;
parm = TREE_CHAIN (parm))
{
r = no_linkage_check (TREE_VALUE (parm), relaxed_p);
if (r)
return r;
}
return no_linkage_check (TREE_TYPE (t), relaxed_p);
}
default:
return NULL_TREE;
}
}
#ifdef GATHER_STATISTICS
extern int depth_reached;
#endif
void
cxx_print_statistics (void)
{
print_search_statistics ();
print_class_statistics ();
#ifdef GATHER_STATISTICS
fprintf (stderr, "maximum template instantiation depth reached: %d\n",
depth_reached);
#endif
}
tree
array_type_nelts_top (tree type)
{
return fold_build2 (PLUS_EXPR, sizetype,
array_type_nelts (type),
integer_one_node);
}
tree
array_type_nelts_total (tree type)
{
tree sz = array_type_nelts_top (type);
type = TREE_TYPE (type);
while (TREE_CODE (type) == ARRAY_TYPE)
{
tree n = array_type_nelts_top (type);
sz = fold_build2 (MULT_EXPR, sizetype, sz, n);
type = TREE_TYPE (type);
}
return sz;
}
static tree
bot_manip (tree* tp, int* walk_subtrees, void* data)
{
splay_tree target_remap = ((splay_tree) data);
tree t = *tp;
if (!TYPE_P (t) && TREE_CONSTANT (t))
{
*walk_subtrees = 0;
return NULL_TREE;
}
if (TREE_CODE (t) == TARGET_EXPR)
{
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
u = build_cplus_new
(TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
else
u = build_target_expr_with_type
(break_out_target_exprs (TREE_OPERAND (t, 1)), TREE_TYPE (t));
splay_tree_insert (target_remap,
(splay_tree_key) TREE_OPERAND (t, 0),
(splay_tree_value) TREE_OPERAND (u, 0));
*tp = u;
*walk_subtrees = 0;
return NULL_TREE;
}
return copy_tree_r (tp, walk_subtrees, NULL);
}
static tree
bot_replace (tree* t,
int* walk_subtrees ATTRIBUTE_UNUSED ,
void* data)
{
splay_tree target_remap = ((splay_tree) data);
if (TREE_CODE (*t) == VAR_DECL)
{
splay_tree_node n = splay_tree_lookup (target_remap,
(splay_tree_key) *t);
if (n)
*t = (tree) n->value;
}
return NULL_TREE;
}
tree
break_out_target_exprs (tree t)
{
static int target_remap_count;
static splay_tree target_remap;
if (!target_remap_count++)
target_remap = splay_tree_new (splay_tree_compare_pointers,
NULL,
NULL);
walk_tree (&t, bot_manip, target_remap, NULL);
walk_tree (&t, bot_replace, target_remap, NULL);
if (!--target_remap_count)
{
splay_tree_delete (target_remap);
target_remap = NULL;
}
return t;
}
tree
build_min_nt (enum tree_code code, ...)
{
tree t;
int length;
int i;
va_list p;
va_start (p, code);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
for (i = 0; i < length; i++)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
}
va_end (p);
return t;
}
tree
build_min (enum tree_code code, tree tt, ...)
{
tree t;
int length;
int i;
va_list p;
va_start (p, tt);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
TREE_TYPE (t) = tt;
for (i = 0; i < length; i++)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
TREE_SIDE_EFFECTS (t) = 1;
}
va_end (p);
return t;
}
tree
build_min_non_dep (enum tree_code code, tree non_dep, ...)
{
tree t;
int length;
int i;
va_list p;
va_start (p, non_dep);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
TREE_TYPE (t) = TREE_TYPE (non_dep);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
for (i = 0; i < length; i++)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
}
if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
COMPOUND_EXPR_OVERLOADED (t) = 1;
va_end (p);
return t;
}
tree
get_type_decl (tree t)
{
if (TREE_CODE (t) == TYPE_DECL)
return t;
if (TYPE_P (t))
return TYPE_STUB_DECL (t);
gcc_assert (t == error_mark_node);
return t;
}
tree
decl_namespace_context (tree decl)
{
while (1)
{
if (TREE_CODE (decl) == NAMESPACE_DECL)
return decl;
else if (TYPE_P (decl))
decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl));
else
decl = CP_DECL_CONTEXT (decl);
}
}
bool
decl_anon_ns_mem_p (tree decl)
{
while (1)
{
if (decl == NULL_TREE || decl == error_mark_node)
return false;
if (TREE_CODE (decl) == NAMESPACE_DECL
&& DECL_NAME (decl) == NULL_TREE)
return true;
else if (TYPE_P (decl))
return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
else if (TREE_CODE (decl) == NAMESPACE_DECL)
return (TREE_PUBLIC (decl) == 0);
else
decl = DECL_CONTEXT (decl);
}
}
bool
cp_tree_equal (tree t1, tree t2)
{
enum tree_code code1, code2;
if (t1 == t2)
return true;
if (!t1 || !t2)
return false;
for (code1 = TREE_CODE (t1);
code1 == NOP_EXPR || code1 == CONVERT_EXPR
|| code1 == NON_LVALUE_EXPR;
code1 = TREE_CODE (t1))
t1 = TREE_OPERAND (t1, 0);
for (code2 = TREE_CODE (t2);
code2 == NOP_EXPR || code2 == CONVERT_EXPR
|| code1 == NON_LVALUE_EXPR;
code2 = TREE_CODE (t2))
t2 = TREE_OPERAND (t2, 0);
if (t1 == t2)
return true;
if (code1 != code2)
return false;
switch (code1)
{
case INTEGER_CST:
return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
&& TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
case REAL_CST:
return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
case STRING_CST:
return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
&& !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
TREE_STRING_LENGTH (t1));
case COMPLEX_CST:
return cp_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
&& cp_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
case CONSTRUCTOR:
if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
return false;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TREE_LIST:
if (!cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
return false;
if (!cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
return false;
return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
case SAVE_EXPR:
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
case CALL_EXPR:
if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
return false;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TARGET_EXPR:
{
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE
&& !DECL_RTL_SET_P (o1))
;
else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
&& !DECL_RTL_SET_P (o2))
;
else if (!cp_tree_equal (o1, o2))
return false;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
}
case WITH_CLEANUP_EXPR:
if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
return false;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
case COMPONENT_REF:
if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
return false;
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
case VAR_DECL:
case PARM_DECL:
case CONST_DECL:
case FUNCTION_DECL:
case TEMPLATE_DECL:
case IDENTIFIER_NODE:
case SSA_NAME:
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)
&& same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
case TEMPLATE_ID_EXPR:
{
unsigned ix;
tree vec1, vec2;
if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
return false;
vec1 = TREE_OPERAND (t1, 1);
vec2 = TREE_OPERAND (t2, 1);
if (!vec1 || !vec2)
return !vec1 && !vec2;
if (TREE_VEC_LENGTH (vec1) != TREE_VEC_LENGTH (vec2))
return false;
for (ix = TREE_VEC_LENGTH (vec1); ix--;)
if (!cp_tree_equal (TREE_VEC_ELT (vec1, ix),
TREE_VEC_ELT (vec2, ix)))
return false;
return true;
}
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
if (TREE_CODE (o1) != TREE_CODE (o2))
return false;
if (TYPE_P (o1))
return same_type_p (o1, o2);
else
return cp_tree_equal (o1, o2);
}
case PTRMEM_CST:
if (PTRMEM_CST_MEMBER (t1) != PTRMEM_CST_MEMBER (t2))
return false;
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 tcc_unary:
case tcc_binary:
case tcc_comparison:
case tcc_expression:
case tcc_reference:
case tcc_statement:
{
int i;
for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
return false;
return true;
}
case tcc_type:
return same_type_p (t1, t2);
default:
gcc_unreachable ();
}
return false;
}
tree
lvalue_type (tree arg)
{
tree type = TREE_TYPE (arg);
return type;
}
tree
error_type (tree arg)
{
tree type = TREE_TYPE (arg);
if (TREE_CODE (type) == ARRAY_TYPE)
;
else if (TREE_CODE (type) == ERROR_MARK)
;
else if (real_lvalue_p (arg))
type = build_reference_type (lvalue_type (arg));
else if (IS_AGGR_TYPE (type))
type = lvalue_type (arg);
return type;
}
int
varargs_function_p (tree function)
{
tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
for (; parm; parm = TREE_CHAIN (parm))
if (TREE_VALUE (parm) == void_type_node)
return 0;
return 1;
}
int
member_p (tree decl)
{
const tree ctx = DECL_CONTEXT (decl);
return (ctx && TYPE_P (ctx));
}
tree
build_dummy_object (tree type)
{
tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
return build_indirect_ref (decl, NULL);
}
tree
maybe_dummy_object (tree type, tree* binfop)
{
tree decl, context;
tree binfo;
if (current_class_type
&& (binfo = lookup_base (current_class_type, type,
ba_unique | ba_quiet, NULL)))
context = current_class_type;
else
{
context = type;
binfo = TYPE_BINFO (type);
}
if (binfop)
*binfop = binfo;
if (current_class_ref && context == current_class_type
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
current_class_type))
decl = current_class_ref;
else
decl = build_dummy_object (context);
return decl;
}
int
is_dummy_object (tree ob)
{
if (TREE_CODE (ob) == INDIRECT_REF)
ob = TREE_OPERAND (ob, 0);
return (TREE_CODE (ob) == NOP_EXPR
&& TREE_OPERAND (ob, 0) == void_zero_node);
}
int
pod_type_p (tree t)
{
t = strip_array_types (t);
if (t == error_mark_node)
return 1;
if (INTEGRAL_TYPE_P (t))
return 1;
if (FLOAT_TYPE_P (t))
return 1;
if (TYPE_PTR_P (t))
return 1;
if (TYPE_PTR_TO_MEMBER_P (t))
return 1;
if (TREE_CODE (t) == VECTOR_TYPE)
return 1;
if (! CLASS_TYPE_P (t))
return 0;
if (CLASSTYPE_NON_POD_P (t))
return 0;
return 1;
}
int
zero_init_p (tree t)
{
t = strip_array_types (t);
if (t == error_mark_node)
return 1;
if (TYPE_PTRMEM_P (t))
return 0;
if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t))
return 0;
return 1;
}
const struct attribute_spec cxx_attribute_table[] =
{
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
{ "com_interface", 0, 0, false, false, false, handle_com_interface_attribute },
{ "init_priority", 1, 1, true, false, false, handle_init_priority_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
static tree
handle_java_interface_attribute (tree* node,
tree name,
tree args ATTRIBUTE_UNUSED ,
int flags,
bool* no_add_attrs)
{
if (DECL_P (*node)
|| !CLASS_TYPE_P (*node)
|| !TYPE_FOR_JAVA (*node))
{
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_variant_type_copy (*node);
TYPE_JAVA_INTERFACE (*node) = 1;
return NULL_TREE;
}
static tree
handle_com_interface_attribute (tree* node,
tree name,
tree args ATTRIBUTE_UNUSED ,
int flags ATTRIBUTE_UNUSED ,
bool* no_add_attrs)
{
static int warned;
*no_add_attrs = true;
if (DECL_P (*node)
|| !CLASS_TYPE_P (*node)
|| *node != TYPE_MAIN_VARIANT (*node))
{
warning (OPT_Wattributes, "%qE attribute can only be applied "
"to class definitions", name);
return NULL_TREE;
}
if (!warned++)
warning (0, "%qE is obsolete; g++ vtables are now COM-compatible by default",
name);
return NULL_TREE;
}
static tree
handle_init_priority_attribute (tree* node,
tree name,
tree args,
int flags ATTRIBUTE_UNUSED ,
bool* no_add_attrs)
{
tree initp_expr = TREE_VALUE (args);
tree decl = *node;
tree type = TREE_TYPE (decl);
int pri;
STRIP_NOPS (initp_expr);
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
{
error ("requested init_priority is not an integer constant");
*no_add_attrs = true;
return NULL_TREE;
}
pri = TREE_INT_CST_LOW (initp_expr);
type = strip_array_types (type);
if (decl == NULL_TREE
|| TREE_CODE (decl) != VAR_DECL
|| !TREE_STATIC (decl)
|| DECL_EXTERNAL (decl)
|| (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE)
|| current_function_decl)
{
error ("can only use %qE attribute on file-scope definitions "
"of objects of class type", name);
*no_add_attrs = true;
return NULL_TREE;
}
if (pri > MAX_INIT_PRIORITY || pri <= 0)
{
error ("requested init_priority is out of range");
*no_add_attrs = true;
return NULL_TREE;
}
if (pri <= MAX_RESERVED_INIT_PRIORITY)
{
warning
(0, "requested init_priority is reserved for internal use");
}
if (SUPPORTS_INIT_PRIORITY)
{
SET_DECL_INIT_PRIORITY (decl, pri);
DECL_HAS_INIT_PRIORITY_P (decl) = 1;
return NULL_TREE;
}
else
{
error ("%qE attribute is not supported on this platform", name);
*no_add_attrs = true;
return NULL_TREE;
}
}
tree
make_ptrmem_cst (tree type, tree member)
{
tree ptrmem_cst = make_node (PTRMEM_CST);
TREE_TYPE (ptrmem_cst) = type;
PTRMEM_CST_MEMBER (ptrmem_cst) = member;
return ptrmem_cst;
}
tree
cp_build_type_attribute_variant (tree type, tree attributes)
{
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
if (TREE_CODE (new_type) == FUNCTION_TYPE
&& (TYPE_RAISES_EXCEPTIONS (new_type)
!= TYPE_RAISES_EXCEPTIONS (type)))
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (type));
gcc_assert (!CLASS_TYPE_P (type) || new_type == type);
return new_type;
}
tree
cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
void *data, struct pointer_set_t *pset)
{
enum tree_code code = TREE_CODE (*tp);
location_t save_locus;
tree result;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_tree (&(NODE), func, data, pset); \
if (result) goto out; \
} \
while (0)
save_locus = input_location;
if (EXPR_HAS_LOCATION (*tp))
input_location = EXPR_LOCATION (*tp);
result = NULL_TREE;
switch (code)
{
case DEFAULT_ARG:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case UNBOUND_CLASS_TEMPLATE:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
case TYPENAME_TYPE:
case TYPEOF_TYPE:
case BASELINK:
*walk_subtrees_p = 0;
break;
case TINST_LEVEL:
WALK_SUBTREE (TINST_DECL (*tp));
*walk_subtrees_p = 0;
break;
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
*walk_subtrees_p = 0;
break;
case TREE_LIST:
WALK_SUBTREE (TREE_PURPOSE (*tp));
break;
case OVERLOAD:
WALK_SUBTREE (OVL_FUNCTION (*tp));
WALK_SUBTREE (OVL_CHAIN (*tp));
*walk_subtrees_p = 0;
break;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (*tp))
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
break;
default:
input_location = save_locus;
return NULL_TREE;
}
out:
input_location = save_locus;
return result;
#undef WALK_SUBTREE
}
int
cp_cannot_inline_tree_fn (tree* fnp)
{
tree fn = *fnp;
if (DECL_TEMPLATE_INFO (fn)
&& TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
{
if (!DECL_INLINE (DECL_TEMPLATE_RESULT
(template_for_substitution (fn))))
return 1;
fn = *fnp = instantiate_decl (fn, 0, 0);
if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
return 1;
}
if (flag_really_no_inline
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
return 1;
if (!DECL_DECLARED_INLINE_P (fn) && DECL_REPLACEABLE_P (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
if (varargs_function_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
if (! function_attribute_inlinable_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
return 0;
}
tree
cp_add_pending_fn_decls (void* fns_p, tree prev_fn)
{
varray_type *fnsp = (varray_type *)fns_p;
struct saved_scope *s;
for (s = scope_chain; s; s = s->prev)
if (s->function_decl && s->function_decl != prev_fn)
{
VARRAY_PUSH_TREE (*fnsp, s->function_decl);
prev_fn = s->function_decl;
}
return prev_fn;
}
int
cp_auto_var_in_fn_p (tree var, tree fn)
{
return (DECL_P (var) && DECL_CONTEXT (var) == fn
&& nonstatic_local_decl_p (var));
}
tree
cp_save_expr (tree expr)
{
if (processing_template_decl)
return expr;
return save_expr (expr);
}
void
init_tree (void)
{
list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
special_function_kind
special_function_p (tree decl)
{
if (DECL_COPY_CONSTRUCTOR_P (decl))
return sfk_copy_constructor;
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
return sfk_assignment_operator;
if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
return sfk_destructor;
if (DECL_COMPLETE_DESTRUCTOR_P (decl))
return sfk_complete_destructor;
if (DECL_BASE_DESTRUCTOR_P (decl))
return sfk_base_destructor;
if (DECL_DELETING_DESTRUCTOR_P (decl))
return sfk_deleting_destructor;
if (DECL_CONV_FN_P (decl))
return sfk_conversion;
return sfk_none;
}
int
char_type_p (tree type)
{
return (same_type_p (type, char_type_node)
|| same_type_p (type, unsigned_char_type_node)
|| same_type_p (type, signed_char_type_node)
|| same_type_p (type, wchar_type_node));
}
linkage_kind
decl_linkage (tree decl)
{
if (!DECL_NAME (decl))
return lk_none;
if (TREE_PUBLIC (decl))
return lk_external;
if (TREE_CODE (decl) == NAMESPACE_DECL)
return lk_external;
if (TREE_CODE (decl) == CONST_DECL)
return decl_linkage (TYPE_NAME (TREE_TYPE (decl)));
if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl)
&& DECL_COMDAT (decl))
return lk_external;
if (decl_function_context (decl))
return lk_none;
if (TREE_CODE (decl) == TYPE_DECL
|| ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
&& !DECL_THIS_STATIC (decl)))
return lk_external;
return lk_internal;
}
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 = 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;
gcc_assert (!TREE_SIDE_EFFECTS (exp));
return exp;
}
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);
}
void
stabilize_call (tree call, tree *initp)
{
tree inits = NULL_TREE;
tree t;
if (call == error_mark_node)
return;
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);
inits = add_stmt_to_compound (inits, init);
}
*initp = inits;
}
bool
stabilize_init (tree init, tree *initp)
{
tree t = init;
*initp = NULL_TREE;
if (t == error_mark_node)
return true;
if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_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))
return true;
if (TREE_CODE (t) == COND_EXPR)
return false;
if (TREE_CODE (t) == CALL_EXPR
|| TREE_CODE (t) == AGGR_INIT_EXPR)
{
stabilize_call (t, initp);
return true;
}
return TREE_SIDE_EFFECTS (init);
}
tree
fold_if_not_in_template (tree expr)
{
if (processing_template_decl)
return expr;
if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
return fold (expr);
}
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);
}
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
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
#include "gt-cp-tree.h"