#include "config.h"
#include "system.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 "target.h"
#ifdef ENABLE_DMP_TREE
#include "dmp-tree.h"
extern int cp_dump_tree_p PARAMS ((FILE *, const char *, tree, int));
extern lang_dump_tree_p_t cp_prev_lang_dump_tree_p;
extern int c_dump_tree_p PARAMS ((FILE *, const char *, tree, int));
extern lang_dump_tree_p_t c_prev_lang_dump_tree_p;
#endif
static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *));
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, 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 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 *));
static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code));
static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree handle_link_name_attribute PARAMS ((tree *, tree, tree, int, bool *));
static cp_lvalue_kind
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;
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 UNSAVE_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,
allow_cast_as_lvalue);
case NOP_EXPR:
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,
allow_cast_as_lvalue);
if (op1_lvalue_kind
&& TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
&& DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
op1_lvalue_kind &= ~clk_ordinary;
op1_lvalue_kind |= clk_bitfield;
}
return op1_lvalue_kind;
case STRING_CST:
return clk_ordinary;
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:
abort ();
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return clk_ordinary;
case MAX_EXPR:
case MIN_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
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,
allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue);
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue);
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
case CALL_EXPR:
case VA_ARG_EXPR:
return ((treat_class_rvalues_as_lvalues
&& IS_AGGR_TYPE (TREE_TYPE (ref)))
? clk_class : clk_none);
case FUNCTION_DECL:
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : 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 (ref)
tree ref;
{
return lvalue_p_1 (ref, 0, 1);
}
cp_lvalue_kind
real_non_cast_lvalue_p (tree ref)
{
return lvalue_p_1 (ref,
0,
0);
}
int
lvalue_p (ref)
tree ref;
{
return
(lvalue_p_1 (ref, 1, 1) != clk_none);
}
int
non_cast_lvalue_p (ref)
tree ref;
{
return
(lvalue_p_1 (ref, 1, 0) != clk_none);
}
int
lvalue_or_else (ref, string)
tree ref;
const char *string;
{
int ret = lvalue_p_1 (ref, 1, 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, 1, 0);
int win = (ret != clk_none);
if (! win)
error ("non-lvalue in %s", string);
return win;
}
static tree
build_target_expr (decl, value)
tree decl;
tree value;
{
tree t;
t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value,
cxx_maybe_build_cleanup (decl), NULL_TREE);
TREE_SIDE_EFFECTS (t) = 1;
return t;
}
tree
build_cplus_new (type, init)
tree type;
tree init;
{
tree fn;
tree slot;
tree rval;
abstract_virtuals_error (NULL_TREE, type);
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init);
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
layout_decl (slot, 0);
fn = TREE_OPERAND (init, 0);
rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval)
= (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
rval = build_target_expr (slot, rval);
return rval;
}
tree
build_target_expr_with_type (init, type)
tree init;
tree type;
{
tree slot;
tree rval;
if (TREE_CODE (init) == TARGET_EXPR)
return init;
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
layout_decl (slot, 0);
rval = build_target_expr (slot, init);
return rval;
}
tree
get_target_expr (init)
tree init;
{
return build_target_expr_with_type (init, TREE_TYPE (init));
}
tree
break_out_calls (exp)
tree exp;
{
register tree t1, t2 = NULL_TREE;
register enum tree_code code;
register int changed = 0;
register int i;
if (exp == NULL_TREE)
return exp;
code = TREE_CODE (exp);
if (code == CALL_EXPR)
return copy_node (exp);
if (code == SAVE_EXPR)
return exp;
switch (TREE_CODE_CLASS (code))
{
default:
abort ();
case 'c':
case 't':
case 'x':
return exp;
case 'd':
#if 0
t1 = break_out_calls (DECL_INITIAL (exp));
if (t1 != DECL_INITIAL (exp))
{
exp = copy_node (exp);
DECL_INITIAL (exp) = t1;
}
#endif
return exp;
case 'b':
{
abort ();
}
return exp;
case 'e':
case 'r':
case 's':
for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; i--)
{
t1 = break_out_calls (TREE_OPERAND (exp, i));
if (t1 != TREE_OPERAND (exp, i))
{
exp = copy_node (exp);
TREE_OPERAND (exp, i) = t1;
}
}
return exp;
case '<':
case '2':
t2 = break_out_calls (TREE_OPERAND (exp, 1));
if (t2 != TREE_OPERAND (exp, 1))
changed = 1;
case '1':
t1 = break_out_calls (TREE_OPERAND (exp, 0));
if (t1 != TREE_OPERAND (exp, 0))
changed = 1;
if (changed)
{
if (TREE_CODE_LENGTH (code) == 1)
return build1 (code, TREE_TYPE (exp), t1);
else
return build (code, TREE_TYPE (exp), t1, t2);
}
return exp;
}
}
tree
build_cplus_method_type (basetype, rettype, argtypes)
tree basetype, rettype, argtypes;
{
register tree t;
tree ptype;
int hashcode;
t = make_node (METHOD_TYPE);
TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
TREE_TYPE (t) = rettype;
ptype = build_pointer_type (basetype);
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
TREE_SIDE_EFFECTS (argtypes) = 1;
hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
type_hash_list (argtypes);
t = type_hash_canon (hashcode, t);
if (!COMPLETE_TYPE_P (t))
layout_type (t);
return t;
}
static tree
build_cplus_array_type_1 (elt_type, index_type)
tree elt_type;
tree index_type;
{
tree t;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
if ((processing_template_decl
&& index_type && TYPE_MAX_VALUE (index_type)
&& TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
|| uses_template_parms (elt_type)
|| (index_type && uses_template_parms (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 (elt_type, index_type)
tree elt_type;
tree 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 (cv_quals)
elt_type = cp_build_qualified_type (elt_type, other_quals);
t = build_cplus_array_type_1 (elt_type, index_type);
if (cv_quals)
t = cp_build_qualified_type (t, cv_quals);
return t;
}
tree
cp_build_qualified_type_real (type, type_quals, complain)
tree type;
int type_quals;
tsubst_flags_t complain;
{
tree result;
int bad_quals = TYPE_UNQUALIFIED;
int bad_func_quals = TYPE_UNQUALIFIED;
if (type == error_mark_node)
return type;
if (type_quals == cp_type_quals (type))
return type;
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
if (TREE_CODE (type) != REFERENCE_TYPE)
bad_func_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
&& !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 (bad_func_quals && !(complain & tf_error))
return error_mark_node;
else
{
if (complain & tf_ignore_bad_quals)
bad_quals &= ~TYPE_QUAL_CONST;
bad_quals |= bad_func_quals;
if (bad_quals)
{
tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
if (!(complain & tf_ignore_bad_quals)
|| bad_func_quals)
error ("`%V' qualifiers cannot be applied to `%T'",
bad_type, 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_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);
}
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 (t)
tree t;
{
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
}
void
unshare_base_binfos (binfo)
tree binfo;
{
tree binfos = BINFO_BASETYPES (binfo);
tree new_binfo;
int j;
if (binfos == NULL_TREE)
return;
for (j = TREE_VEC_LENGTH (binfos)-1;
j >= 0; j--)
{
tree base_binfo = TREE_VEC_ELT (binfos, j);
new_binfo = TREE_VEC_ELT (binfos, j)
= make_binfo (BINFO_OFFSET (base_binfo),
base_binfo,
BINFO_VTABLE (base_binfo),
BINFO_VIRTUALS (base_binfo));
TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
BINFO_PRIMARY_BASE_OF (new_binfo) = NULL_TREE;
unshare_base_binfos (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 (entry, data)
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 (purpose, value, chain)
tree purpose;
tree value;
tree chain;
{
hashval_t hashcode = 0;
if (chain)
hashcode += TYPE_HASH (chain);
if (value)
hashcode += TYPE_HASH (value);
else
hashcode += 1007;
if (purpose)
hashcode += TYPE_HASH (purpose);
else
hashcode += 1009;
return hashcode;
}
static hashval_t
list_hash (p)
const void *p;
{
tree t = (tree) p;
return list_hash_pieces (TREE_PURPOSE (t),
TREE_VALUE (t),
TREE_CHAIN (t));
}
tree
hash_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
int hashcode = 0;
PTR* 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 = (PTR) tree_cons (purpose, value, chain);
return *slot;
}
tree
hash_tree_chain (value, chain)
tree value, chain;
{
return hash_tree_cons (NULL_TREE, value, chain);
}
tree
hash_chainon (list1, list2)
tree list1, 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));
}
tree
make_binfo (offset, binfo, vtable, virtuals)
tree offset, binfo;
tree vtable, virtuals;
{
tree new_binfo = make_tree_vec (11);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else
{
type = binfo;
binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
}
TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
BINFO_VIRTUALS (new_binfo) = virtuals;
if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));
return new_binfo;
}
tree
reverse_path (binfo)
tree binfo;
{
tree reversed_path;
reversed_path = NULL_TREE;
while (binfo)
{
reversed_path = tree_cons (NULL_TREE, binfo, reversed_path);
binfo = BINFO_INHERITANCE_CHAIN (binfo);
}
return reversed_path;
}
void
debug_binfo (elem)
tree elem;
{
HOST_WIDE_INT n;
tree virtuals;
fprintf (stderr, "type \"%s\", offset = ",
TYPE_NAME_STRING (BINFO_TYPE (elem)));
fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
fprintf (stderr, "\nvtable type:\n");
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);
}
}
int
count_functions (t)
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 (x)
tree x;
{
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
|| TREE_CODE (x) == OVERLOAD);
}
int
really_overloaded_fn (x)
tree x;
{
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (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);
}
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
get_first_fn (from)
tree from;
{
my_friendly_assert (is_overloaded_fn (from), 9);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
int
bound_pmf_p (t)
tree t;
{
return (TREE_CODE (t) == OFFSET_REF
&& TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
}
tree
ovl_cons (decl, chain)
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 (decl, chain)
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);
}
int
is_aggr_type_2 (t1, t2)
tree t1, t2;
{
if (TREE_CODE (t1) != TREE_CODE (t2))
return 0;
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
int
cp_statement_code_p (code)
enum tree_code code;
{
switch (code)
{
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:
case HANDLER:
case EH_SPEC_BLOCK:
case USING_STMT:
case TAG_DEFN:
return 1;
default:
return 0;
}
}
#define PRINT_RING_SIZE 4
const char *
cxx_printable_name (decl, v)
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;
if (decl_ring[ring_counter] == current_function_decl)
abort ();
}
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 (type, raises)
tree type;
tree raises;
{
tree v = TYPE_MAIN_VARIANT (type);
int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
if (TYPE_QUALS (v) == type_quals
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
return v;
v = build_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
}
tree
bind_template_template_parm (t, newargs)
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 (tp, walk_subtrees, data)
tree *tp ATTRIBUTE_UNUSED;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data;
{
++ *((int*) data);
return NULL_TREE;
}
int
count_trees (t)
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 (tp, walk_subtrees, data)
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;
if (htab_find (*statements, t))
abort ();
slot = htab_find_slot (*statements, t, INSERT);
*slot = t;
return NULL_TREE;
}
void
verify_stmt_tree (t)
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);
}
static tree
find_tree_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data;
{
if (*tp == (tree) data)
return (tree) data;
return NULL_TREE;
}
tree
find_tree (t, x)
tree t;
tree x;
{
return walk_tree_without_duplicates (&t, find_tree_r, x);
}
static tree
no_linkage_helper (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
tree t = *tp;
if (TYPE_P (t)
&& (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
&& (decl_function_context (TYPE_MAIN_DECL (t))
|| TYPE_ANONYMOUS_P (t)))
return t;
return NULL_TREE;
}
tree
no_linkage_check (t)
tree t;
{
if (processing_template_decl)
return NULL_TREE;
t = walk_tree_without_duplicates (&t, no_linkage_helper, NULL);
if (t != error_mark_node)
return t;
return NULL_TREE;
}
#ifdef GATHER_STATISTICS
extern int depth_reached;
#endif
void
cxx_print_statistics ()
{
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 (type)
tree type;
{
return fold (build (PLUS_EXPR, sizetype,
array_type_nelts (type),
integer_one_node));
}
tree
array_type_nelts_total (type)
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 (build (MULT_EXPR, sizetype, sz, n));
type = TREE_TYPE (type);
}
return sz;
}
static tree
bot_manip (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
void *data;
{
splay_tree target_remap = ((splay_tree) data);
tree t = *tp;
if (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)
{
mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
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;
}
else if (TREE_CODE (t) == CALL_EXPR)
mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
return copy_tree_r (tp, walk_subtrees, NULL);
}
static tree
bot_replace (t, walk_subtrees, data)
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 (t)
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 VPARAMS ((enum tree_code code, ...))
{
register tree t;
register int length;
register int i;
VA_OPEN (p, code);
VA_FIXEDARG (p, enum tree_code, code);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
}
VA_CLOSE (p);
return t;
}
tree
build_min VPARAMS ((enum tree_code code, tree tt, ...))
{
register tree t;
register int length;
register int i;
VA_OPEN (p, tt);
VA_FIXEDARG (p, enum tree_code, code);
VA_FIXEDARG (p, tree, tt);
t = make_node (code);
length = TREE_CODE_LENGTH (code);
TREE_TYPE (t) = tt;
TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
}
VA_CLOSE (p);
return t;
}
static GTY(()) tree shared_int_cache[256];
tree
build_shared_int_cst (i)
int i;
{
if (i >= 256)
return build_int_2 (i, 0);
if (!shared_int_cache[i])
shared_int_cache[i] = build_int_2 (i, 0);
return shared_int_cache[i];
}
tree
get_type_decl (t)
tree t;
{
if (TREE_CODE (t) == TYPE_DECL)
return t;
if (TYPE_P (t))
return TYPE_STUB_DECL (t);
if (t == error_mark_node)
return t;
abort ();
return 0;
}
tree
vec_binfo_member (elem, vec)
tree elem, vec;
{
int i;
if (vec)
for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
return TREE_VEC_ELT (vec, i);
return NULL_TREE;
}
tree
decl_namespace_context (decl)
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);
}
}
int
cp_tree_equal (t1, t2)
tree t1, t2;
{
register enum tree_code code1, code2;
int cmp;
if (t1 == t2)
return 1;
if (t1 == 0 || t2 == 0)
return 0;
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
{
if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
else
return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
}
else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
|| code2 == NON_LVALUE_EXPR)
return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
if (code1 != code2)
return 0;
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 CONSTRUCTOR:
if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
return 0;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TREE_LIST:
cmp = cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
if (cmp <= 0)
return cmp;
cmp = cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2));
if (cmp <= 0)
return cmp;
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:
cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
if (cmp <= 0)
return cmp;
return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TARGET_EXPR:
if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
&& DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
&& !DECL_RTL_SET_P (TREE_OPERAND (t1, 0)))
|| (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
&& DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
&& !DECL_RTL_SET_P (TREE_OPERAND (t2, 0))))
cmp = 1;
else
cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
if (cmp <= 0)
return cmp;
return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case WITH_CLEANUP_EXPR:
cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
if (cmp <= 0)
return cmp;
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 cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
return 0;
case VAR_DECL:
case PARM_DECL:
case CONST_DECL:
case FUNCTION_DECL:
return 0;
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 SIZEOF_EXPR:
case ALIGNOF_EXPR:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
return 0;
if (TYPE_P (TREE_OPERAND (t1, 0)))
return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
break;
case PTRMEM_CST:
return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
&& same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
default:
break;
}
switch (TREE_CODE_CLASS (code1))
{
case '1':
case '2':
case '<':
case 'e':
case 'r':
case 's':
{
int i;
cmp = 1;
for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
{
cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
if (cmp <= 0)
return cmp;
}
return cmp;
}
case 't':
return same_type_p (t1, t2) ? 1 : 0;
}
return -1;
}
tree
build_zc_wrapper (ptr)
struct z_candidate *ptr;
{
tree t = make_node (WRAPPER);
WRAPPER_ZC (t) = ptr;
return t;
}
static tree
build_srcloc (file, line)
const char *file;
int line;
{
tree t;
t = make_node (SRCLOC);
SRCLOC_FILE (t) = file;
SRCLOC_LINE (t) = line;
return t;
}
tree
build_srcloc_here ()
{
return build_srcloc (input_filename, lineno);
}
tree
lvalue_type (arg)
tree arg;
{
tree type = TREE_TYPE (arg);
if (TREE_CODE (arg) == OVERLOAD)
type = unknown_type_node;
return type;
}
tree
error_type (arg)
tree arg;
{
tree type = TREE_TYPE (arg);
if (TREE_CODE (type) == ARRAY_TYPE)
;
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 (function)
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 (decl)
tree decl;
{
const tree ctx = DECL_CONTEXT (decl);
return (ctx && TYPE_P (ctx));
}
tree
build_dummy_object (type)
tree type;
{
tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
return build_indirect_ref (decl, NULL);
}
tree
maybe_dummy_object (type, binfop)
tree type;
tree *binfop;
{
tree decl, context;
tree binfo;
if (current_class_type
&& (binfo = lookup_base (current_class_type, type,
ba_ignore | 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 (ob)
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 (t)
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_PTRMEM_P (t))
return 1;
if (TYPE_PTRMEMFUNC_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 (t)
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 },
{ "link_name", 1, 1, false, true, false, handle_link_name_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
static tree
handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
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 ("`%s' attribute can only be applied to Java class definitions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
return NULL_TREE;
}
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
*node = build_type_copy (*node);
TYPE_JAVA_INTERFACE (*node) = 1;
return NULL_TREE;
}
static tree
handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
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 ("`%s' attribute can only be applied to class definitions",
IDENTIFIER_POINTER (name));
return NULL_TREE;
}
if (!warned++)
warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
IDENTIFIER_POINTER (name));
return NULL_TREE;
}
static tree
handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
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 `%s' attribute on file-scope definitions of objects of class type",
IDENTIFIER_POINTER (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
("requested init_priority is reserved for internal use");
}
if (SUPPORTS_INIT_PRIORITY)
{
DECL_INIT_PRIORITY (decl) = pri;
return NULL_TREE;
}
else
{
error ("`%s' attribute is not supported on this platform",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
return NULL_TREE;
}
}
static tree
handle_link_name_attribute (node, name, args, flags, no_add_attrs)
tree *node ATTRIBUTE_UNUSED;
tree name;
tree args;
int flags ATTRIBUTE_UNUSED;
bool *no_add_attrs;
{
tree name_expr = TREE_VALUE (args);
if (!name_expr || TREE_CODE(name_expr) != STRING_CST)
{
error ("`%s' attribute requires a string literal",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
return NULL_TREE;
}
return NULL_TREE;
}
tree
make_ptrmem_cst (type, member)
tree type;
tree member;
{
tree ptrmem_cst = make_node (PTRMEM_CST);
TREE_CONSTANT (ptrmem_cst) = 1;
TREE_TYPE (ptrmem_cst) = type;
PTRMEM_CST_MEMBER (ptrmem_cst) = member;
return ptrmem_cst;
}
tree
cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
tree *tp;
int *walk_subtrees_p;
walk_tree_fn func;
void *data;
void *htab;
{
enum tree_code code = TREE_CODE (*tp);
tree result;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_tree (&(NODE), func, data, htab); \
if (result) \
return result; \
} \
while (0)
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:
*walk_subtrees_p = 0;
break;
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
*walk_subtrees_p = 0;
break;
case TREE_LIST:
if (!BASELINK_P (*tp))
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:
break;
}
return NULL_TREE;
#undef WALK_SUBTREE
}
int
cp_cannot_inline_tree_fn (fnp)
tree *fnp;
{
tree fn = *fnp;
if (flag_really_no_inline
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
return 1;
if (DECL_TEMPLATE_INFO (fn)
&& TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
{
fn = *fnp = instantiate_decl (fn, 0);
if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
return 1;
}
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;
return 1;
}
if (! function_attribute_inlinable_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
return 1;
}
return 0;
}
tree
cp_add_pending_fn_decls (fns_p, prev_fn)
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_is_overload_p (t)
tree t;
{
return TREE_CODE (t) == OVERLOAD;
}
int
cp_auto_var_in_fn_p (var, fn)
tree var, fn;
{
return (DECL_P (var) && DECL_CONTEXT (var) == fn
&& nonstatic_local_decl_p (var));
}
tree
cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
need_decl, target_exprs)
tree result, fn, caller;
void *decl_map_;
int *need_decl;
void *target_exprs;
{
splay_tree decl_map = (splay_tree)decl_map_;
varray_type *texps = (varray_type *)target_exprs;
tree var;
int aggregate_return_p;
aggregate_return_p = IS_AGGR_TYPE (TREE_TYPE (result));
*need_decl = ! aggregate_return_p;
if (aggregate_return_p)
{
if (VARRAY_ACTIVE_SIZE (*texps) == 0)
abort ();
var = TREE_OPERAND (VARRAY_TOP_TREE (*texps), 0);
if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
TREE_TYPE (result)))
abort ();
}
else
var = copy_decl_for_inlining (result, fn, caller);
if (DECL_SAVED_FUNCTION_DATA (fn))
{
tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
if (nrv)
{
DECL_NAME (var) = DECL_NAME (nrv);
DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
DECL_INITIAL (var) = DECL_INITIAL (nrv);
TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
splay_tree_insert (decl_map,
(splay_tree_key) nrv,
(splay_tree_value) var);
}
}
return var;
}
int
cp_start_inlining (fn)
tree fn;
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
return push_tinst_level (fn);
else
return 1;
}
void
cp_end_inlining (fn)
tree fn ATTRIBUTE_UNUSED;
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
pop_tinst_level ();
}
void
init_tree ()
{
lang_statement_code_p = cp_statement_code_p;
#ifdef ENABLE_DMP_TREE
cp_prev_lang_dump_tree_p = set_dump_tree_p (cp_dump_tree_p);
c_prev_lang_dump_tree_p = set_dump_tree_p (c_dump_tree_p);
SET_MAX_DMP_TREE_CODE(LAST_CPLUS_TREE_CODE);
#endif
list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
static tree
mark_local_for_remap_r (tp, walk_subtrees, data)
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_STMT
&& nonstatic_local_decl_p (DECL_STMT_DECL (t)))
decl = DECL_STMT_DECL (t);
else if (TREE_CODE (t) == LABEL_STMT)
decl = LABEL_STMT_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)
decl = CASE_LABEL_DECL (t);
else
decl = NULL_TREE;
if (decl)
{
tree copy;
copy = copy_decl_for_inlining (decl,
DECL_CONTEXT (decl),
DECL_CONTEXT (decl));
splay_tree_insert (st,
(splay_tree_key) decl,
(splay_tree_value) copy);
}
return NULL_TREE;
}
static tree
cp_unsave_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
void *data;
{
splay_tree st = (splay_tree) data;
splay_tree_node n;
if (nonstatic_local_decl_p (*tp))
{
n = splay_tree_lookup (st, (splay_tree_key) *tp);
if (n)
*tp = (tree) n->value;
}
else if (TREE_CODE (*tp) == SAVE_EXPR)
remap_save_expr (tp, st, current_function_decl, walk_subtrees);
else
{
copy_tree_r (tp, walk_subtrees, NULL);
unsave_expr_1 (*tp);
}
return NULL_TREE;
}
tree
cxx_unsave_expr_now (tp)
tree tp;
{
splay_tree st;
st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
walk_tree (&tp, mark_local_for_remap_r, st, NULL);
walk_tree (&tp, cp_unsave_r, st, NULL);
splay_tree_delete (st);
return tp;
}
special_function_kind
special_function_p (decl)
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;
}
bool
name_p (tree node)
{
if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
node = TREE_OPERAND (node, 0);
return (
TREE_CODE (node) == IDENTIFIER_NODE
|| TREE_CODE (node) == BIT_NOT_EXPR
|| TREE_CODE (node) == SCOPE_REF);
}
int
char_type_p (type)
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 (decl)
tree decl;
{
if (!DECL_NAME (decl))
return lk_none;
if (TREE_PUBLIC (decl))
return lk_external;
if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
return lk_external;
if (decl_function_context (decl))
return lk_none;
return lk_internal;
}
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)
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
#include "gt-cp-tree.h"