diff options
Diffstat (limited to 'contrib/gcc/cp/tree.c')
-rw-r--r-- | contrib/gcc/cp/tree.c | 2811 |
1 files changed, 0 insertions, 2811 deletions
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c deleted file mode 100644 index 866aa271acdd..000000000000 --- a/contrib/gcc/cp/tree.c +++ /dev/null @@ -1,2811 +0,0 @@ -/* Language-dependent node constructors for parse phase of GNU compiler. - Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc. - Hacked by Michael Tiemann (tiemann@cygnus.com) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "obstack.h" -#include "tree.h" -#include "cp-tree.h" -#include "flags.h" -#include "rtl.h" -#include "toplev.h" - -static tree bot_manip PROTO((tree)); -static tree perm_manip PROTO((tree)); -static tree build_cplus_array_type_1 PROTO((tree, tree)); -static void list_hash_add PROTO((int, tree)); -static int list_hash PROTO((tree, tree, tree)); -static tree list_hash_lookup PROTO((int, tree, tree, tree)); -static void propagate_binfo_offsets PROTO((tree, tree)); -static int avoid_overlap PROTO((tree, tree)); -static int lvalue_p_1 PROTO((tree, int)); -static int equal_functions PROTO((tree, tree)); -static tree no_linkage_helper PROTO((tree)); -static tree build_srcloc PROTO((char *, int)); - -#define CEIL(x,y) (((x) + (y) - 1) / (y)) - -/* Returns non-zero if REF is an lvalue. If - TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type - are considered lvalues. */ - -static int -lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) - tree ref; - int treat_class_rvalues_as_lvalues; -{ - if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) - return 1; - - if (ref == current_class_ptr && flag_this_is_variable <= 0) - return 0; - - switch (TREE_CODE (ref)) - { - /* preincrements and predecrements are valid lvals, provided - what they refer to are valid lvals. */ - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case COMPONENT_REF: - case SAVE_EXPR: - case UNSAVE_EXPR: - case TRY_CATCH_EXPR: - case WITH_CLEANUP_EXPR: - case REALPART_EXPR: - case IMAGPART_EXPR: - case NOP_EXPR: - return lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues); - - case STRING_CST: - return 1; - - case VAR_DECL: - if (TREE_READONLY (ref) && ! TREE_STATIC (ref) - && DECL_LANG_SPECIFIC (ref) - && DECL_IN_AGGR_P (ref)) - return 0; - case INDIRECT_REF: - case ARRAY_REF: - case PARM_DECL: - case RESULT_DECL: - if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) - return 1; - break; - - /* A currently unresolved scope ref. */ - case SCOPE_REF: - my_friendly_abort (103); - case OFFSET_REF: - if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) - return 1; - return (lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues) - && lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues)); - break; - - case COND_EXPR: - return (lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues) - && lvalue_p_1 (TREE_OPERAND (ref, 2), - treat_class_rvalues_as_lvalues)); - - case MODIFY_EXPR: - return 1; - - case COMPOUND_EXPR: - return lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues); - - case MAX_EXPR: - case MIN_EXPR: - return (lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues) - && lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues)); - - case TARGET_EXPR: - return treat_class_rvalues_as_lvalues; - - case CALL_EXPR: - return (treat_class_rvalues_as_lvalues - && IS_AGGR_TYPE (TREE_TYPE (ref))); - - case FUNCTION_DECL: - /* All functions (except non-static-member functions) are - lvalues. */ - return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref); - - default: - break; - } - - return 0; -} - -/* Return nonzero if REF is an lvalue valid for this language. - Lvalues can be assigned, unless they have TREE_READONLY, or unless - they are FUNCTION_DECLs. Lvalues can have their address taken, - unless they have DECL_REGISTER. */ - -int -real_lvalue_p (ref) - tree ref; -{ - return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0); -} - -/* This differs from real_lvalue_p in that class rvalues are considered - lvalues. */ - -int -lvalue_p (ref) - tree ref; -{ - return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1); -} - -/* Return nonzero if REF is an lvalue valid for this language; - otherwise, print an error message and return zero. */ - -int -lvalue_or_else (ref, string) - tree ref; - const char *string; -{ - int win = lvalue_p (ref); - if (! win) - error ("non-lvalue in %s", string); - return win; -} - -/* INIT is a CALL_EXPR which needs info about its target. - TYPE is the type that this initialization should appear to have. - - Build an encapsulation of the initialization to perform - and return it so that it can be processed by language-independent - and language-specific expression expanders. */ - -tree -build_cplus_new (type, init) - tree type; - tree init; -{ - tree slot; - tree rval; - - 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; - layout_decl (slot, 0); - rval = build (AGGR_INIT_EXPR, type, - TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); - TREE_SIDE_EFFECTS (rval) = 1; - rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE); - TREE_SIDE_EFFECTS (rval) = 1; - - return rval; -} - -/* Encapsulate the expression INIT in a TARGET_EXPR. */ - -tree -get_target_expr (init) - tree init; -{ - tree slot; - tree rval; - - slot = build (VAR_DECL, TREE_TYPE (init)); - DECL_ARTIFICIAL (slot) = 1; - layout_decl (slot, 0); - rval = build (TARGET_EXPR, TREE_TYPE (init), slot, init, - NULL_TREE, NULL_TREE); - TREE_SIDE_EFFECTS (rval) = 1; - - return rval; -} - -/* Recursively search EXP for CALL_EXPRs that need cleanups and replace - these CALL_EXPRs with tree nodes that will perform the cleanups. */ - -tree -break_out_cleanups (exp) - tree exp; -{ - tree tmp = exp; - - if (TREE_CODE (tmp) == CALL_EXPR - && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp))) - return build_cplus_new (TREE_TYPE (tmp), tmp); - - while (TREE_CODE (tmp) == NOP_EXPR - || TREE_CODE (tmp) == CONVERT_EXPR - || TREE_CODE (tmp) == NON_LVALUE_EXPR) - { - if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR - && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0)))) - { - TREE_OPERAND (tmp, 0) - = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)), - TREE_OPERAND (tmp, 0)); - break; - } - else - tmp = TREE_OPERAND (tmp, 0); - } - return exp; -} - -/* Recursively perform a preorder search EXP for CALL_EXPRs, making - copies where they are found. Returns a deep copy all nodes transitively - containing CALL_EXPRs. */ - -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); - - /* Don't try and defeat a save_expr, as it should only be done once. */ - if (code == SAVE_EXPR) - return exp; - - switch (TREE_CODE_CLASS (code)) - { - default: - abort (); - - case 'c': /* a constant */ - case 't': /* a type node */ - case 'x': /* something random, like an identifier or an ERROR_MARK. */ - return exp; - - case 'd': /* A decl node */ -#if 0 /* This is bogus. jason 9/21/94 */ - - 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': /* A block node */ - { - /* Don't know how to handle these correctly yet. Must do a - break_out_calls on all DECL_INITIAL values for local variables, - and also break_out_calls on all sub-blocks and sub-statements. */ - abort (); - } - return exp; - - case 'e': /* an expression */ - case 'r': /* a reference */ - case 's': /* an expression with side effects */ - for (i = tree_code_length[(int) 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 '<': /* a comparison expression */ - case '2': /* a binary arithmetic expression */ - t2 = break_out_calls (TREE_OPERAND (exp, 1)); - if (t2 != TREE_OPERAND (exp, 1)) - changed = 1; - case '1': /* a unary arithmetic expression */ - t1 = break_out_calls (TREE_OPERAND (exp, 0)); - if (t1 != TREE_OPERAND (exp, 0)) - changed = 1; - if (changed) - { - if (tree_code_length[(int) code] == 1) - return build1 (code, TREE_TYPE (exp), t1); - else - return build (code, TREE_TYPE (exp), t1, t2); - } - return exp; - } - -} - -extern struct obstack *current_obstack; -extern struct obstack permanent_obstack, class_obstack; -extern struct obstack *saveable_obstack; -extern struct obstack *expression_obstack; - -/* Here is how primitive or already-canonicalized types' hash - codes are made. MUST BE CONSISTENT WITH tree.c !!! */ -#define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777) - -/* Construct, lay out and return the type of methods belonging to class - BASETYPE and whose arguments are described by ARGTYPES and whose values - are described by RETTYPE. If each type exists already, reuse it. */ - -tree -build_cplus_method_type (basetype, rettype, argtypes) - tree basetype, rettype, argtypes; -{ - register tree t; - tree ptype; - int hashcode; - - /* Make a node of the sort we want. */ - t = make_node (METHOD_TYPE); - - TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); - TREE_TYPE (t) = rettype; - if (IS_SIGNATURE (basetype)) - ptype = build_signature_pointer_type (basetype); - else - ptype = build_pointer_type (basetype); - - /* The actual arglist for this function includes a "hidden" argument - which is "this". Put it into the list of argument types. */ - - argtypes = tree_cons (NULL_TREE, ptype, argtypes); - TYPE_ARG_TYPES (t) = argtypes; - TREE_SIDE_EFFECTS (argtypes) = 1; /* Mark first argtype as "artificial". */ - - /* If we already have such a type, use the old one and free this one. - Note that it also frees up the above cons cell if found. */ - hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes); - t = type_hash_canon (hashcode, t); - - if (TYPE_SIZE (t) == 0) - layout_type (t); - - return t; -} - -static tree -build_cplus_array_type_1 (elt_type, index_type) - tree elt_type; - tree index_type; -{ - register struct obstack *ambient_obstack = current_obstack; - register struct obstack *ambient_saveable_obstack = saveable_obstack; - tree t; - - /* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent, - make this permanent too. */ - if (TREE_PERMANENT (elt_type) - && (index_type == 0 || TREE_PERMANENT (index_type))) - { - current_obstack = &permanent_obstack; - saveable_obstack = &permanent_obstack; - } - - if (processing_template_decl - || uses_template_parms (elt_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); - - /* Push these needs up so that initialization takes place - more easily. */ - TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type)); - TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type)); - current_obstack = ambient_obstack; - saveable_obstack = ambient_saveable_obstack; - 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); - - elt_type = TYPE_MAIN_VARIANT (elt_type); - - 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; -} - -/* Make a variant type in the proper way for C/C++, propagating qualifiers - down to the element type of an array. */ - -tree -cp_build_qualified_type (type, type_quals) - tree type; - int type_quals; -{ - if (type == error_mark_node) - return type; - - /* A restrict-qualified pointer type must be a pointer (or reference) - to object or incomplete type. */ - if ((type_quals & TYPE_QUAL_RESTRICT) - && (!POINTER_TYPE_P (type) - || TYPE_PTRMEM_P (type) - || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)) - { - cp_error ("`%T' cannot be `restrict'-qualified", type); - type_quals &= ~TYPE_QUAL_RESTRICT; - } - - if (TREE_CODE (type) == ARRAY_TYPE) - { - tree real_main_variant = TYPE_MAIN_VARIANT (type); - - push_obstacks (TYPE_OBSTACK (real_main_variant), - TYPE_OBSTACK (real_main_variant)); - type = build_cplus_array_type_1 (cp_build_qualified_type - (TREE_TYPE (type), type_quals), - TYPE_DOMAIN (type)); - - /* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not, - make a copy. (TYPE might have come from the hash table and - REAL_MAIN_VARIANT might be in some function's obstack.) */ - - if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant)) - { - type = copy_node (type); - TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0; - } - - TYPE_MAIN_VARIANT (type) = real_main_variant; - pop_obstacks (); - return type; - } - return build_qualified_type (type, type_quals); -} - -/* Returns the canonical version of TYPE. In other words, if TYPE is - a typedef, returns the underlying type. The cv-qualification of - the type returned matches the type input; they will always be - compatible types. */ - -tree -canonical_type_variant (t) - tree t; -{ - return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), CP_TYPE_QUALS (t)); -} - -/* Add OFFSET to all base types of T. - - OFFSET, which is a type offset, is number of bytes. - - Note that we don't have to worry about having two paths to the - same base type, since this type owns its association list. */ - -static void -propagate_binfo_offsets (binfo, offset) - tree binfo; - tree offset; -{ - tree binfos = BINFO_BASETYPES (binfo); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - - for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - - if (TREE_VIA_VIRTUAL (base_binfo)) - i += 1; - else - { - int j; - tree delta = NULL_TREE; - - for (j = i+1; j < n_baselinks; j++) - if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) - { - /* The next basetype offset must take into account the space - between the classes, not just the size of each class. */ - delta = size_binop (MINUS_EXPR, - BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), - BINFO_OFFSET (base_binfo)); - break; - } - -#if 0 - if (BINFO_OFFSET_ZEROP (base_binfo)) - BINFO_OFFSET (base_binfo) = offset; - else - BINFO_OFFSET (base_binfo) - = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset); -#else - BINFO_OFFSET (base_binfo) = offset; -#endif - - propagate_binfo_offsets (base_binfo, offset); - - /* Go to our next class that counts for offset propagation. */ - i = j; - if (i < n_baselinks) - offset = size_binop (PLUS_EXPR, offset, delta); - } - } -} - -/* Makes new binfos for the indirect bases under BINFO, and updates - BINFO_OFFSET for them and their bases. */ - -void -unshare_base_binfos (binfo) - tree binfo; -{ - tree binfos = BINFO_BASETYPES (binfo); - tree new_binfo; - int j; - - if (binfos == NULL_TREE) - return; - - /* Now unshare the structure beneath BINFO. */ - 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; - unshare_base_binfos (new_binfo); - } -} - -/* Finish the work of layout_record, now taking virtual bases into account. - Also compute the actual offsets that our base classes will have. - This must be performed after the fields are laid out, since virtual - baseclasses must lay down at the end of the record. - - Returns the maximum number of virtual functions any of the - baseclasses provide. */ - -int -layout_basetypes (rec, max) - tree rec; - int max; -{ - tree binfos = TYPE_BINFO_BASETYPES (rec); - int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - - tree vbase_types; - - unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); - unsigned int desired_align; - - /* Record size so far is CONST_SIZE bits, where CONST_SIZE is an integer. */ - register unsigned int const_size = 0; - unsigned int nonvirtual_const_size; - -#ifdef STRUCTURE_SIZE_BOUNDARY - /* Packed structures don't need to have minimum size. */ - if (! TYPE_PACKED (rec)) - record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY); -#endif - - /* Get all the virtual base types that this type uses. The - TREE_VALUE slot holds the virtual baseclass type. Note that - get_vbase_types makes copies of the virtual base BINFOs, so that - the vbase_types are unshared. */ - vbase_types = CLASSTYPE_VBASECLASSES (rec); - - my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302); - const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec)); - - nonvirtual_const_size = const_size; - - while (vbase_types) - { - tree basetype = BINFO_TYPE (vbase_types); - tree offset; - - desired_align = TYPE_ALIGN (basetype); - record_align = MAX (record_align, desired_align); - - if (const_size == 0) - offset = integer_zero_node; - else - { - /* Give each virtual base type the alignment it wants. */ - const_size = CEIL (const_size, desired_align) * desired_align; - offset = size_int (CEIL (const_size, BITS_PER_UNIT)); - } - - if (CLASSTYPE_VSIZE (basetype) > max) - max = CLASSTYPE_VSIZE (basetype); - BINFO_OFFSET (vbase_types) = offset; - - /* Every virtual baseclass takes a least a UNIT, so that we can - take it's address and get something different for each base. */ - const_size += MAX (BITS_PER_UNIT, - TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype))); - - vbase_types = TREE_CHAIN (vbase_types); - } - - if (const_size) - { - /* Because a virtual base might take a single byte above, - we have to re-adjust the total size to make sure it is - a multiple of the alignment. */ - /* Give the whole object the alignment it wants. */ - const_size = CEIL (const_size, record_align) * record_align; - } - - /* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN - here, as that is for this class, without any virtual base classes. */ - TYPE_ALIGN (rec) = record_align; - if (const_size != nonvirtual_const_size) - { - TYPE_SIZE (rec) = size_int (const_size); - TYPE_SIZE_UNIT (rec) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (rec), - size_int (BITS_PER_UNIT)); - } - - /* Now propagate offset information throughout the lattice. */ - for (i = 0; i < n_baseclasses; i++) - { - register tree base_binfo = TREE_VEC_ELT (binfos, i); - register tree basetype = BINFO_TYPE (base_binfo); - tree field = TYPE_FIELDS (rec); - - if (TREE_VIA_VIRTUAL (base_binfo)) - continue; - - my_friendly_assert (TREE_TYPE (field) == basetype, 23897); - - if (get_base_distance (basetype, rec, 0, (tree*)0) == -2) - cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", - basetype, rec); - - BINFO_OFFSET (base_binfo) - = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)), - BITS_PER_UNIT)); - propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo)); - TYPE_FIELDS (rec) = TREE_CHAIN (field); - } - - for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types; - vbase_types = TREE_CHAIN (vbase_types)) - { - BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); - unshare_base_binfos (vbase_types); - propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); - - if (extra_warnings) - { - tree basetype = BINFO_TYPE (vbase_types); - if (get_base_distance (basetype, rec, 0, (tree*)0) == -2) - cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", - basetype, rec); - } - } - - return max; -} - -/* If the empty base field in DECL overlaps with a base of the same type in - NEWDECL, which is either another base field or the first data field of - the class, pad the base just before NEWDECL and return 1. Otherwise, - return 0. */ - -static int -avoid_overlap (decl, newdecl) - tree decl, newdecl; -{ - tree field; - - if (newdecl == NULL_TREE - || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl))) - return 0; - - for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl; - field = TREE_CHAIN (field)) - ; - - DECL_SIZE (field) = integer_one_node; - - return 1; -} - -/* Returns a list of fields to stand in for the base class subobjects - of REC. These fields are later removed by layout_basetypes. */ - -tree -build_base_fields (rec) - tree rec; -{ - /* Chain to hold all the new FIELD_DECLs which stand in for base class - subobjects. */ - tree base_decls = NULL_TREE; - tree binfos = TYPE_BINFO_BASETYPES (rec); - int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - tree decl, nextdecl; - int i, saw_empty = 0; - unsigned int base_align = 0; - - for (i = 0; i < n_baseclasses; ++i) - { - register tree base_binfo = TREE_VEC_ELT (binfos, i); - register tree basetype = BINFO_TYPE (base_binfo); - - if (TYPE_SIZE (basetype) == 0) - /* This error is now reported in xref_tag, thus giving better - location information. */ - continue; - - if (TREE_VIA_VIRTUAL (base_binfo)) - continue; - - decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, basetype); - DECL_ARTIFICIAL (decl) = 1; - DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec; - DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype); - DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype); - TREE_CHAIN (decl) = base_decls; - base_decls = decl; - - if (! flag_new_abi) - { - /* Brain damage for backwards compatibility. For no good reason, - the old layout_basetypes made every base at least as large as - the alignment for the bases up to that point, gratuitously - wasting space. So we do the same thing here. */ - base_align = MAX (base_align, DECL_ALIGN (decl)); - DECL_SIZE (decl) - = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)), - (int) base_align)); - } - else if (DECL_SIZE (decl) == integer_zero_node) - saw_empty = 1; - } - - /* Reverse the list of fields so we allocate the bases in the proper - order. */ - base_decls = nreverse (base_decls); - - /* In the presence of empty base classes, we run the risk of allocating - two objects of the same class on top of one another. Avoid that. */ - if (flag_new_abi && saw_empty) - for (decl = base_decls; decl; decl = TREE_CHAIN (decl)) - { - if (DECL_SIZE (decl) == integer_zero_node) - { - /* First step through the following bases until we find - an overlap or a non-empty base. */ - for (nextdecl = TREE_CHAIN (decl); nextdecl; - nextdecl = TREE_CHAIN (nextdecl)) - { - if (avoid_overlap (decl, nextdecl) - || DECL_SIZE (nextdecl) != integer_zero_node) - goto nextbase; - } - - /* If we're still looking, also check against the first - field. */ - for (nextdecl = TYPE_FIELDS (rec); - nextdecl && TREE_CODE (nextdecl) != FIELD_DECL; - nextdecl = TREE_CHAIN (nextdecl)) - /* keep looking */; - avoid_overlap (decl, nextdecl); - } - nextbase:; - } - - return base_decls; -} - -/* Returns list of virtual base class pointers in a FIELD_DECL chain. */ - -tree -build_vbase_pointer_fields (rec) - tree rec; -{ - /* Chain to hold all the new FIELD_DECLs which point at virtual - base classes. */ - tree vbase_decls = NULL_TREE; - tree binfos = TYPE_BINFO_BASETYPES (rec); - int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - tree decl; - int i; - - /* Handle basetypes almost like fields, but record their - offsets differently. */ - - for (i = 0; i < n_baseclasses; i++) - { - register tree base_binfo = TREE_VEC_ELT (binfos, i); - register tree basetype = BINFO_TYPE (base_binfo); - - if (TYPE_SIZE (basetype) == 0) - /* This error is now reported in xref_tag, thus giving better - location information. */ - continue; - - /* All basetypes are recorded in the association list of the - derived type. */ - - if (TREE_VIA_VIRTUAL (base_binfo)) - { - int j; - const char *name; - - /* The offset for a virtual base class is only used in computing - virtual function tables and for initializing virtual base - pointers. It is built once `get_vbase_types' is called. */ - - /* If this basetype can come from another vbase pointer - without an additional indirection, we will share - that pointer. If an indirection is involved, we - make our own pointer. */ - for (j = 0; j < n_baseclasses; j++) - { - tree other_base_binfo = TREE_VEC_ELT (binfos, j); - if (! TREE_VIA_VIRTUAL (other_base_binfo) - && binfo_member (basetype, - CLASSTYPE_VBASECLASSES (BINFO_TYPE - (other_base_binfo)) - )) - goto got_it; - } - FORMAT_VBASE_NAME (name, basetype); - decl = build_lang_field_decl (FIELD_DECL, get_identifier (name), - build_pointer_type (basetype)); - /* If you change any of the below, take a look at all the - other VFIELD_BASEs and VTABLE_BASEs in the code, and change - them too. */ - DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE); - DECL_VIRTUAL_P (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - DECL_FIELD_CONTEXT (decl) = rec; - DECL_CLASS_CONTEXT (decl) = rec; - DECL_FCONTEXT (decl) = basetype; - DECL_SAVED_INSNS (decl) = NULL_RTX; - DECL_FIELD_SIZE (decl) = 0; - DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node); - TREE_CHAIN (decl) = vbase_decls; - BINFO_VPTR_FIELD (base_binfo) = decl; - vbase_decls = decl; - - got_it: - /* The space this decl occupies has already been accounted for. */ - ; - } - } - - return vbase_decls; -} - -/* Hashing of lists so that we don't make duplicates. - The entry point is `list_hash_canon'. */ - -/* Each hash table slot is a bucket containing a chain - of these structures. */ - -struct list_hash -{ - struct list_hash *next; /* Next structure in the bucket. */ - int hashcode; /* Hash code of this list. */ - tree list; /* The list recorded here. */ -}; - -/* Now here is the hash table. When recording a list, it is added - to the slot whose index is the hash code mod the table size. - Note that the hash table is used for several kinds of lists. - While all these live in the same table, they are completely independent, - and the hash code is computed differently for each of these. */ - -#define TYPE_HASH_SIZE 59 -static struct list_hash *list_hash_table[TYPE_HASH_SIZE]; - -/* Compute a hash code for a list (chain of TREE_LIST nodes - with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the - TREE_COMMON slots), by adding the hash codes of the individual entries. */ - -static int -list_hash (purpose, value, chain) - tree purpose, value, chain; -{ - register int 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; -} - -/* Look in the type hash table for a type isomorphic to TYPE. - If one is found, return it. Otherwise return 0. */ - -static tree -list_hash_lookup (hashcode, purpose, value, chain) - int hashcode; - tree purpose, value, chain; -{ - register struct list_hash *h; - - for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) - if (h->hashcode == hashcode - && TREE_PURPOSE (h->list) == purpose - && TREE_VALUE (h->list) == value - && TREE_CHAIN (h->list) == chain) - return h->list; - return 0; -} - -/* Add an entry to the list-hash-table - for a list TYPE whose hash code is HASHCODE. */ - -static void -list_hash_add (hashcode, list) - int hashcode; - tree list; -{ - register struct list_hash *h; - - h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash)); - h->hashcode = hashcode; - h->list = list; - h->next = list_hash_table[hashcode % TYPE_HASH_SIZE]; - list_hash_table[hashcode % TYPE_HASH_SIZE] = h; -} - -/* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical - object for an identical list if one already exists. Otherwise, build a - new one, and record it as the canonical object. */ - -/* Set to 1 to debug without canonicalization. Never set by program. */ - -static int debug_no_list_hash = 0; - -tree -hash_tree_cons (purpose, value, chain) - tree purpose, value, chain; -{ - struct obstack *ambient_obstack = current_obstack; - tree t; - int hashcode = 0; - - if (! debug_no_list_hash) - { - hashcode = list_hash (purpose, value, chain); - t = list_hash_lookup (hashcode, purpose, value, chain); - if (t) - return t; - } - - current_obstack = &class_obstack; - - t = tree_cons (purpose, value, chain); - - /* If this is a new list, record it for later reuse. */ - if (! debug_no_list_hash) - list_hash_add (hashcode, t); - - current_obstack = ambient_obstack; - return t; -} - -/* Constructor for hashed lists. */ - -tree -hash_tree_chain (value, chain) - tree value, chain; -{ - return hash_tree_cons (NULL_TREE, value, chain); -} - -/* Similar, but used for concatenating two lists. */ - -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)); -} - -/* Build an association between TYPE and some parameters: - - OFFSET is the offset added to `this' to convert it to a pointer - of type `TYPE *' - - BINFO is the base binfo to use, if we are deriving from one. This - is necessary, as we want specialized parent binfos from base - classes, so that the VTABLE_NAMEs of bases are for the most derived - type, instead of the simple type. - - VTABLE is the virtual function table with which to initialize - sub-objects of type TYPE. - - VIRTUALS are the virtual functions sitting in VTABLE. */ - -tree -make_binfo (offset, binfo, vtable, virtuals) - tree offset, binfo; - tree vtable, virtuals; -{ - tree new_binfo = make_tree_vec (7); - 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; - BINFO_VPTR_FIELD (new_binfo) = NULL_TREE; - - if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE) - BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo)); - return new_binfo; -} - -/* Return the binfo value for ELEM in TYPE. */ - -tree -binfo_value (elem, type) - tree elem; - tree type; -{ - if (get_base_distance (elem, type, 0, (tree *)0) == -2) - compiler_error ("base class `%s' ambiguous in binfo_value", - TYPE_NAME_STRING (elem)); - if (elem == type) - return TYPE_BINFO (type); - if (TREE_CODE (elem) == RECORD_TYPE && TYPE_BINFO (elem) == type) - return type; - return get_binfo (elem, type, 0); -} - -/* Return a reversed copy of the BINFO-chain given by PATH. (If the - BINFO_INHERITANCE_CHAIN points from base classes to derived - classes, it will instead point from derived classes to base - classes.) Returns the first node in the reversed chain. */ - -tree -reverse_path (path) - tree path; -{ - register tree prev = NULL_TREE, cur; - push_expression_obstack (); - for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur)) - { - tree r = copy_node (cur); - BINFO_INHERITANCE_CHAIN (r) = prev; - prev = r; - } - pop_obstacks (); - return prev; -} - -void -debug_binfo (elem) - tree elem; -{ - unsigned HOST_WIDE_INT n; - tree virtuals; - - fprintf (stderr, "type \"%s\"; offset = %ld\n", - TYPE_NAME_STRING (BINFO_TYPE (elem)), - (long) TREE_INT_CST_LOW (BINFO_OFFSET (elem))); - fprintf (stderr, "vtable type:\n"); - debug_tree (BINFO_TYPE (elem)); - if (BINFO_VTABLE (elem)) - fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); - else - fprintf (stderr, "no vtable decl yet\n"); - fprintf (stderr, "virtuals:\n"); - virtuals = BINFO_VIRTUALS (elem); - - n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem)); - - while (virtuals) - { - tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); - 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); - } -} - -/* Initialize an CPLUS_BINDING node that does not live on an obstack. */ - -tree -binding_init (node) - struct tree_binding* node; -{ - static struct tree_binding* source; - if (!source) - { - extern struct obstack permanent_obstack; - push_obstacks (&permanent_obstack, &permanent_obstack); - source = (struct tree_binding*)make_node (CPLUS_BINDING); - pop_obstacks (); - } - *node = *source; - TREE_PERMANENT ((tree)node) = 0; - return (tree)node; -} - -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; - } - - my_friendly_abort (359); - return 0; -} - -int -is_overloaded_fn (x) - tree x; -{ - /* A baselink is also considered an overloaded function. */ - if (TREE_CODE (x) == OFFSET_REF) - x = TREE_OPERAND (x, 1); - if (BASELINK_P (x)) - x = TREE_VALUE (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; -{ - /* A baselink is also considered an overloaded function. */ - if (TREE_CODE (x) == OFFSET_REF) - x = TREE_OPERAND (x, 1); - if (BASELINK_P (x)) - x = TREE_VALUE (x); - return (TREE_CODE (x) == OVERLOAD - && (TREE_CHAIN (x) != NULL_TREE - || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x)))); -} - -tree -get_first_fn (from) - tree from; -{ - my_friendly_assert (is_overloaded_fn (from), 9); - /* A baselink is also considered an overloaded function. */ - if (BASELINK_P (from)) - from = TREE_VALUE (from); - return OVL_CURRENT (from); -} - -/* Returns nonzero if T is a ->* or .* expression that refers to a - member function. */ - -int -bound_pmf_p (t) - 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 -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; -} - -/* Same as ovl_cons, but on the scratch_obstack. */ - -tree -scratch_ovl_cons (value, chain) - tree value, chain; -{ - register tree node; - register struct obstack *ambient_obstack = current_obstack; - extern struct obstack *expression_obstack; - current_obstack = expression_obstack; - node = ovl_cons (value, chain); - current_obstack = ambient_obstack; - return node; -} - -/* Build a new overloaded function. If this is the first one, - just return it; otherwise, ovl_cons the _DECLs */ - -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); -} - -/* Returns true iff functions are equivalent. Equivalent functions are - not identical only if one is a function-local extern function. - This assumes that function-locals don't have TREE_PERMANENT. */ - -static int -equal_functions (fn1, fn2) - tree fn1; - tree fn2; -{ - if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2)) - return decls_match (fn1, fn2); - return fn1 == fn2; -} - -/* True if fn is in ovl. */ - -int -ovl_member (fn, ovl) - tree fn; - tree ovl; -{ - if (ovl == NULL_TREE) - return 0; - if (TREE_CODE (ovl) != OVERLOAD) - return equal_functions (ovl, fn); - for (; ovl; ovl = OVL_CHAIN (ovl)) - if (equal_functions (OVL_FUNCTION (ovl), fn)) - return 1; - return 0; -} - -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); -} - -#define PRINT_RING_SIZE 4 - -char * -lang_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; - - /* Only cache functions. */ - if (v < 2 - || TREE_CODE (decl) != FUNCTION_DECL - || DECL_LANG_SPECIFIC (decl) == 0) - return lang_decl_name (decl, v); - - /* See if this print name is lying around. */ - for (i = 0; i < PRINT_RING_SIZE; i++) - if (decl_ring[i] == decl) - /* yes, so return it. */ - 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) - my_friendly_abort (106); - } - - 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]; -} - -/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions - listed in RAISES. */ - -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)) - { - tree t; - tree u; - - if (TYPE_QUALS (v) != type_quals) - continue; - - for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises; - t != NULL_TREE && u != NULL_TREE; - t = TREE_CHAIN (t), u = TREE_CHAIN (u)) - if (((TREE_VALUE (t) != NULL_TREE) - != (TREE_VALUE (u) != NULL_TREE)) - || !same_type_p (TREE_VALUE (t), TREE_VALUE (u))) - break; - - if (!t && !u) - /* There's a memory leak here; RAISES is not freed. */ - return v; - } - - /* Need to build a new variant. */ - v = build_type_copy (type); - - if (raises && ! TREE_PERMANENT (raises)) - raises = copy_to_permanent (raises); - - TYPE_RAISES_EXCEPTIONS (v) = raises; - return v; -} - -/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its - lang_specific field and its corresponding TEMPLATE_DECL node */ - -tree -copy_template_template_parm (t) - tree t; -{ - tree template = TYPE_NAME (t); - tree t2; - - /* Make sure these end up on the permanent_obstack. */ - push_obstacks_nochange (); - end_temporary_allocation (); - - t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM); - template = copy_node (template); - copy_lang_decl (template); - - pop_obstacks (); - - TREE_TYPE (template) = t2; - TYPE_NAME (t2) = template; - TYPE_STUB_DECL (t2) = template; - - /* No need to copy these */ - TYPE_FIELDS (t2) = TYPE_FIELDS (t); - TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2) - = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); - return t2; -} - -/* Walk through the tree structure T, applying func. If func ever returns - non-null, return that value. */ - -tree -search_tree (t, func) - tree t; - tree (*func) PROTO((tree)); -{ -#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp - - tree tmp; - - if (t == NULL_TREE) - return t; - - if (tmp = func (t), tmp != NULL_TREE) - return tmp; - - switch (TREE_CODE (t)) - { - case ERROR_MARK: - break; - - case IDENTIFIER_NODE: - break; - - case VAR_DECL: - case FUNCTION_DECL: - case CONST_DECL: - case TEMPLATE_DECL: - case NAMESPACE_DECL: - break; - - case TYPE_DECL: - TRY (TREE_TYPE (t)); - break; - - case PARM_DECL: - TRY (TREE_TYPE (t)); - TRY (TREE_CHAIN (t)); - break; - - case TREE_LIST: - TRY (TREE_PURPOSE (t)); - TRY (TREE_VALUE (t)); - TRY (TREE_CHAIN (t)); - break; - - case OVERLOAD: - TRY (OVL_FUNCTION (t)); - TRY (OVL_CHAIN (t)); - break; - - case TREE_VEC: - { - int len = TREE_VEC_LENGTH (t); - - t = copy_node (t); - while (len--) - TRY (TREE_VEC_ELT (t, len)); - } - break; - - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - case DEFAULT_ARG: - break; - - case PTRMEM_CST: - TRY (TREE_TYPE (t)); - break; - - case COND_EXPR: - case TARGET_EXPR: - case AGGR_INIT_EXPR: - case NEW_EXPR: - TRY (TREE_OPERAND (t, 0)); - TRY (TREE_OPERAND (t, 1)); - TRY (TREE_OPERAND (t, 2)); - break; - - case MODIFY_EXPR: - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case TRUNC_MOD_EXPR: - case MIN_EXPR: - case MAX_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case BIT_AND_EXPR: - case BIT_ANDTC_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case CEIL_MOD_EXPR: - case FLOOR_MOD_EXPR: - case ROUND_MOD_EXPR: - case COMPOUND_EXPR: - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case ARRAY_REF: - case SCOPE_REF: - case TRY_CATCH_EXPR: - case WITH_CLEANUP_EXPR: - case CALL_EXPR: - TRY (TREE_OPERAND (t, 0)); - TRY (TREE_OPERAND (t, 1)); - break; - - case SAVE_EXPR: - case CONVERT_EXPR: - case ADDR_EXPR: - case INDIRECT_REF: - case NEGATE_EXPR: - case BIT_NOT_EXPR: - case TRUTH_NOT_EXPR: - case NOP_EXPR: - case NON_LVALUE_EXPR: - case COMPONENT_REF: - case CLEANUP_POINT_EXPR: - case LOOKUP_EXPR: - case SIZEOF_EXPR: - case ALIGNOF_EXPR: - TRY (TREE_OPERAND (t, 0)); - break; - - case MODOP_EXPR: - case CAST_EXPR: - case REINTERPRET_CAST_EXPR: - case CONST_CAST_EXPR: - case STATIC_CAST_EXPR: - case DYNAMIC_CAST_EXPR: - case ARROW_EXPR: - case DOTSTAR_EXPR: - case TYPEID_EXPR: - break; - - case COMPLEX_CST: - TRY (TREE_REALPART (t)); - TRY (TREE_IMAGPART (t)); - break; - - case CONSTRUCTOR: - TRY (CONSTRUCTOR_ELTS (t)); - break; - - case TEMPLATE_TEMPLATE_PARM: - case TEMPLATE_PARM_INDEX: - case TEMPLATE_TYPE_PARM: - break; - - case BIND_EXPR: - break; - - case REAL_TYPE: - case COMPLEX_TYPE: - case VOID_TYPE: - case BOOLEAN_TYPE: - case TYPENAME_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - case TYPEOF_TYPE: - break; - - case POINTER_TYPE: - case REFERENCE_TYPE: - TRY (TREE_TYPE (t)); - break; - - case FUNCTION_TYPE: - case METHOD_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_ARG_TYPES (t)); - break; - - case ARRAY_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_DOMAIN (t)); - break; - - case INTEGER_TYPE: - TRY (TYPE_MAX_VALUE (t)); - break; - - case OFFSET_TYPE: - TRY (TREE_TYPE (t)); - TRY (TYPE_OFFSET_BASETYPE (t)); - break; - - case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - TRY (TYPE_PTRMEMFUNC_FN_TYPE (t)); - break; - - /* This list is incomplete, but should suffice for now. - It is very important that `sorry' not call - `report_error_function'. That could cause an infinite loop. */ - default: - sorry ("initializer contains unrecognized tree code"); - return error_mark_node; - - } - - return NULL_TREE; - -#undef TRY -} - -/* Passed to search_tree. Checks for the use of types with no linkage. */ - -static tree -no_linkage_helper (t) - tree t; -{ - if (TYPE_P (t) - && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE) - && (decl_function_context (TYPE_MAIN_DECL (t)) - || ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))) - return t; - return NULL_TREE; -} - -/* Check if the type T depends on a type with no linkage and if so, return - it. */ - -tree -no_linkage_check (t) - tree t; -{ - t = search_tree (t, no_linkage_helper); - if (t != error_mark_node) - return t; - return NULL_TREE; -} - - -/* Make copies of all the nodes below T. If FUNC is non-NULL, call it - for each node. */ - -tree -mapcar (t, func) - tree t; - tree (*func) PROTO((tree)); -{ - tree tmp; - - if (t == NULL_TREE) - return t; - - if (func) - { - tmp = func (t); - if (tmp) - return tmp; - } - - switch (TREE_CODE (t)) - { - case ERROR_MARK: - return error_mark_node; - - case VAR_DECL: - case FUNCTION_DECL: - case CONST_DECL: - /* Rather than aborting, return error_mark_node. This allows us - to report a sensible error message on code like this: - - void g() { int i; f<i>(7); } - - In a case like: - - void g() { const int i = 7; f<i>(7); } - - however, we must actually return the constant initializer. */ - if (TREE_READONLY_DECL_P (t)) - { - tmp = decl_constant_value (t); - if (tmp != t) - return mapcar (tmp, func); - } - return error_mark_node; - - case PARM_DECL: - { - tree chain = TREE_CHAIN (t); - t = copy_node (t); - TREE_CHAIN (t) = mapcar (chain, func); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - DECL_INITIAL (t) = mapcar (DECL_INITIAL (t), func); - DECL_SIZE (t) = mapcar (DECL_SIZE (t), func); - return t; - } - - case TREE_LIST: - { - tree chain = TREE_CHAIN (t); - t = copy_node (t); - TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func); - TREE_VALUE (t) = mapcar (TREE_VALUE (t), func); - TREE_CHAIN (t) = mapcar (chain, func); - return t; - } - - case OVERLOAD: - { - tree chain = OVL_CHAIN (t); - t = copy_node (t); - OVL_FUNCTION (t) = mapcar (OVL_FUNCTION (t), func); - OVL_CHAIN (t) = mapcar (chain, func); - return t; - } - - case TREE_VEC: - { - int len = TREE_VEC_LENGTH (t); - - t = copy_node (t); - while (len--) - TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func); - return t; - } - - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - return copy_node (t); - - case PTRMEM_CST: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func); - return t; - - case COND_EXPR: - case TARGET_EXPR: - case AGGR_INIT_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - return t; - - case SAVE_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - - case MODIFY_EXPR: - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case TRUNC_MOD_EXPR: - case MIN_EXPR: - case MAX_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case BIT_AND_EXPR: - case BIT_ANDTC_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case CEIL_MOD_EXPR: - case FLOOR_MOD_EXPR: - case ROUND_MOD_EXPR: - case COMPOUND_EXPR: - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case ARRAY_REF: - case SCOPE_REF: - case TRY_CATCH_EXPR: - case WITH_CLEANUP_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - return t; - - case CALL_EXPR: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - - /* tree.def says that operand two is RTL, but - make_call_declarator puts trees in there. */ - if (TREE_OPERAND (t, 2) - && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST) - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - else - TREE_OPERAND (t, 2) = NULL_TREE; - return t; - - case CONVERT_EXPR: - case ADDR_EXPR: - case INDIRECT_REF: - case NEGATE_EXPR: - case BIT_NOT_EXPR: - case TRUTH_NOT_EXPR: - case NOP_EXPR: - case COMPONENT_REF: - case CLEANUP_POINT_EXPR: - case NON_LVALUE_EXPR: - t = copy_node (t); - TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - - case POINTER_TYPE: - tmp = build_pointer_type (mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case REFERENCE_TYPE: - tmp = build_reference_type (mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case FUNCTION_TYPE: - tmp = build_function_type (mapcar (TREE_TYPE (t), func), - mapcar (TYPE_ARG_TYPES (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case ARRAY_TYPE: - tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func), - mapcar (TYPE_DOMAIN (t), func)); - return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t)); - case INTEGER_TYPE: - tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case OFFSET_TYPE: - tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func), - mapcar (TREE_TYPE (t), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - case METHOD_TYPE: - tmp = build_cplus_method_type - (mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func), - mapcar (TREE_TYPE (t), func), - mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func)); - return cp_build_qualified_type (tmp, TYPE_QUALS (t)); - - case COMPLEX_CST: - t = copy_node (t); - TREE_REALPART (t) = mapcar (TREE_REALPART (t), func); - TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func); - return t; - - case CONSTRUCTOR: - t = copy_node (t); - CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func); - return t; - - case TEMPLATE_TEMPLATE_PARM: - return copy_template_template_parm (t); - - case BIND_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = NULL_TREE; - return t; - - case NEW_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); - TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); - return t; - - case LOOKUP_EXPR: - t = copy_node (t); - TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); - return t; - - case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - return build_ptrmemfunc_type - (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); - /* else fall through */ - - /* This list is incomplete, but should suffice for now. - It is very important that `sorry' not call - `report_error_function'. That could cause an infinite loop. */ - default: - sorry ("initializer contains unrecognized tree code"); - return error_mark_node; - - } - my_friendly_abort (107); - /* NOTREACHED */ - return NULL_TREE; -} - -/* Returns T if T is allocated on the permanent obstack, NULL_TREE - otherwise. */ - -tree -permanent_p (t) - tree t; -{ - return TREE_PERMANENT (t) ? t : NULL_TREE; -} - -static tree -perm_manip (t) - tree t; -{ - if (TREE_PERMANENT (t)) - return t; - - /* Support `void f () { extern int i; A<&i> a; }' */ - if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) - && TREE_PUBLIC (t)) - { - t = copy_node (t); - - /* copy_rtx won't make a new SYMBOL_REF, so call make_decl_rtl again. */ - DECL_RTL (t) = 0; - make_decl_rtl (t, NULL_PTR, 1); - - return t; - } - return NULL_TREE; -} - -/* Assuming T is a node built bottom-up, make it all exist on - permanent obstack, if it is not permanent already. */ - -tree -copy_to_permanent (t) - tree t; -{ - if (t == NULL_TREE || TREE_PERMANENT (t)) - return t; - - push_obstacks_nochange (); - end_temporary_allocation (); - - t = mapcar (t, perm_manip); - - pop_obstacks (); - - return t; -} - -#ifdef GATHER_STATISTICS -extern int depth_reached; -#endif - -void -print_lang_statistics () -{ - extern struct obstack decl_obstack; - print_obstack_statistics ("class_obstack", &class_obstack); - print_obstack_statistics ("decl_obstack", &decl_obstack); - print_search_statistics (); - print_class_statistics (); -#ifdef GATHER_STATISTICS - fprintf (stderr, "maximum template instantiation depth reached: %d\n", - depth_reached); -#endif -} - -/* This is used by the `assert' macro. It is provided in libgcc.a, - which `cc' doesn't know how to link. Note that the C++ front-end - no longer actually uses the `assert' macro (instead, it calls - my_friendly_assert). But all of the back-end files still need this. */ - -void -__eprintf (string, expression, line, filename) - const char *string; - const char *expression; - unsigned line; - const char *filename; -{ - fprintf (stderr, string, expression, line, filename); - fflush (stderr); - abort (); -} - -/* Return, as an INTEGER_CST node, the number of elements for TYPE - (which is an ARRAY_TYPE). This counts only elements of the top - array. */ - -tree -array_type_nelts_top (type) - tree type; -{ - return fold (build (PLUS_EXPR, sizetype, - array_type_nelts (type), - integer_one_node)); -} - -/* Return, as an INTEGER_CST node, the number of elements for TYPE - (which is an ARRAY_TYPE). This one is a recursive count of all - ARRAY_TYPEs that are clumped together. */ - -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 (t) - tree t; -{ - if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t)) - return t; - else if (TREE_CODE (t) == TARGET_EXPR) - { - if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR) - { - mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0)); - return build_cplus_new - (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1))); - } - t = copy_node (t); - TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t)); - layout_decl (TREE_OPERAND (t, 0), 0); - return t; - } - else if (TREE_CODE (t) == CALL_EXPR) - mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); - - return NULL_TREE; -} - -/* Actually, we'll just clean out the target exprs for the moment. */ - -tree -break_out_target_exprs (t) - tree t; -{ - return mapcar (t, bot_manip); -} - -/* Obstack used for allocating nodes in template function and variable - definitions. */ - -/* Similar to `build_nt', except we build - on the permanent_obstack, regardless. */ - -tree -build_min_nt VPROTO((enum tree_code code, ...)) -{ -#ifndef __STDC__ - enum tree_code code; -#endif - register struct obstack *ambient_obstack = expression_obstack; - va_list p; - register tree t; - register int length; - register int i; - - VA_START (p, code); - -#ifndef __STDC__ - code = va_arg (p, enum tree_code); -#endif - - expression_obstack = &permanent_obstack; - - t = make_node (code); - length = tree_code_length[(int) code]; - TREE_COMPLEXITY (t) = lineno; - - for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = copy_to_permanent (x); - } - - va_end (p); - expression_obstack = ambient_obstack; - return t; -} - -/* Similar to `build', except we build - on the permanent_obstack, regardless. */ - -tree -build_min VPROTO((enum tree_code code, tree tt, ...)) -{ -#ifndef __STDC__ - enum tree_code code; - tree tt; -#endif - register struct obstack *ambient_obstack = expression_obstack; - va_list p; - register tree t; - register int length; - register int i; - - VA_START (p, tt); - -#ifndef __STDC__ - code = va_arg (p, enum tree_code); - tt = va_arg (p, tree); -#endif - - expression_obstack = &permanent_obstack; - - t = make_node (code); - length = tree_code_length[(int) code]; - TREE_TYPE (t) = copy_to_permanent (tt); - TREE_COMPLEXITY (t) = lineno; - - for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = copy_to_permanent (x); - } - - va_end (p); - expression_obstack = ambient_obstack; - return t; -} - -/* Same as `tree_cons' but make a permanent object. */ - -tree -min_tree_cons (purpose, value, chain) - tree purpose, value, chain; -{ - register tree node; - register struct obstack *ambient_obstack = current_obstack; - current_obstack = &permanent_obstack; - - node = tree_cons (copy_to_permanent (purpose), - copy_to_permanent (value), chain); - current_obstack = ambient_obstack; - return node; -} - -tree -get_type_decl (t) - tree t; -{ - if (TREE_CODE (t) == TYPE_DECL) - return t; - if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') - return TYPE_STUB_DECL (t); - - my_friendly_abort (42); - - /* Stop compiler from complaining control reaches end of non-void function. */ - return 0; -} - -int -can_free (obstack, t) - struct obstack *obstack; - tree t; -{ - int size = 0; - - if (TREE_CODE (t) == TREE_VEC) - size = (TREE_VEC_LENGTH (t)-1) * sizeof (tree) + sizeof (struct tree_vec); - else - my_friendly_abort (42); - -#define ROUND(x) ((x + obstack_alignment_mask (obstack)) \ - & ~ obstack_alignment_mask (obstack)) - if ((char *)t + ROUND (size) == obstack_next_free (obstack)) - return 1; -#undef ROUND - - return 0; -} - -/* Return first vector element whose BINFO_TYPE is ELEM. - Return 0 if ELEM is not in VEC. VEC may be NULL_TREE. */ - -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; -} - -/* Kludge around the fact that DECL_CONTEXT for virtual functions returns - the wrong thing for decl_function_context. Hopefully the uses in the - backend won't matter, since we don't need a static chain for local class - methods. FIXME! */ - -tree -hack_decl_function_context (decl) - tree decl; -{ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (decl)) - return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl))); - return decl_function_context (decl); -} - -/* Returns the namespace that contains DECL, whether directly or - indirectly. */ - -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); - } -} - -/* Return truthvalue of whether T1 is the same tree structure as T2. - Return 1 if they are the same. - Return 0 if they are understandably different. - Return -1 if either contains tree structure not understood by - this function. */ - -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) - && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2), - TREE_STRING_LENGTH (t1)); - - case CONSTRUCTOR: - /* We need to do this when determining whether or not two - non-type pointer to member function template arguments - are the same. */ - if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) - /* The first operand is RTL. */ - && 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: - /* Special case: if either target is an unallocated VAR_DECL, - it means that it's going to be unified with whatever the - TARGET_EXPR is really supposed to initialize, so treat it - as being equivalent to anything. */ - if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL - && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE - && DECL_RTL (TREE_OPERAND (t1, 0)) == 0) - || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL - && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE - && DECL_RTL (TREE_OPERAND (t2, 0)) == 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, 2), TREE_OPERAND (t1, 2)); - - 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); - - case SIZEOF_EXPR: - case ALIGNOF_EXPR: - if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0))) - return 0; - if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't') - return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); - break; - - case PTRMEM_CST: - /* Two pointer-to-members are the same if they point to the same - field or function in the same class. */ - 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)) - { - int i; - case '1': - case '2': - case '<': - case 'e': - case 'r': - case 's': - cmp = 1; - for (i=0; i<tree_code_length[(int) code1]; ++i) - { - cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)); - if (cmp <= 0) - return cmp; - } - return cmp; - } - - return -1; -} - -/* Similar to make_tree_vec, but build on the momentary_obstack. - Thus, these vectors are really and truly temporary. */ - -tree -make_temp_vec (len) - int len; -{ - register tree node; - push_expression_obstack (); - node = make_tree_vec (len); - pop_obstacks (); - return node; -} - -/* Build a wrapper around some pointer PTR so we can use it as a tree. */ - -tree -build_ptr_wrapper (ptr) - void *ptr; -{ - tree t = make_node (WRAPPER); - WRAPPER_PTR (t) = ptr; - return t; -} - -/* Same, but on the expression_obstack. */ - -tree -build_expr_ptr_wrapper (ptr) - void *ptr; -{ - tree t; - push_expression_obstack (); - t = build_ptr_wrapper (ptr); - pop_obstacks (); - return t; -} - -/* Build a wrapper around some integer I so we can use it as a tree. */ - -tree -build_int_wrapper (i) - int i; -{ - tree t = make_node (WRAPPER); - WRAPPER_INT (t) = i; - return t; -} - -static tree -build_srcloc (file, line) - char *file; - int line; -{ - tree t; - - /* Make sure that we put these on the permanent obstack; up in - add_pending_template, we pass this return value into perm_tree_cons, - which also puts it on the permanent_obstack. However, this wasn't - explicitly doing the same. */ - register struct obstack *ambient_obstack = current_obstack; - current_obstack = &permanent_obstack; - - t = make_node (SRCLOC); - SRCLOC_FILE (t) = file; - SRCLOC_LINE (t) = line; - - current_obstack = ambient_obstack; - - return t; -} - -tree -build_srcloc_here () -{ - return build_srcloc (input_filename, lineno); -} - -void -push_expression_obstack () -{ - push_obstacks_nochange (); - current_obstack = expression_obstack; -} - -/* The type of ARG when used as an lvalue. */ - -tree -lvalue_type (arg) - tree arg; -{ - tree type = TREE_TYPE (arg); - if (TREE_CODE (arg) == OVERLOAD) - type = unknown_type_node; - return type; -} - -/* The type of ARG for printing error messages; denote lvalues with - reference types. */ - -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; -} - -/* Does FUNCTION use a variable-length argument list? */ - -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; -} - -/* Returns 1 if decl is a member of a class. */ - -int -member_p (decl) - tree decl; -{ - tree ctx = DECL_CONTEXT (decl); - return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't'); -} - -/* Create a placeholder for member access where we don't actually have an - object that the access is against. */ - -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_PTR); -} - -/* We've gotten a reference to a member of TYPE. Return *this if appropriate, - or a dummy object otherwise. If BINFOP is non-0, it is filled with the - binfo path from current_class_type to TYPE, or 0. */ - -tree -maybe_dummy_object (type, binfop) - tree type; - tree *binfop; -{ - tree decl, context; - - if (current_class_type - && get_base_distance (type, current_class_type, 0, binfop) != -1) - context = current_class_type; - else - { - /* Reference from a nested class member function. */ - context = type; - if (binfop) - *binfop = TYPE_BINFO (type); - } - - if (current_class_ref && context == current_class_type) - decl = current_class_ref; - else - decl = build_dummy_object (context); - - return decl; -} - -/* Returns 1 if OB is a placeholder object, or a pointer to one. */ - -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); -} - -/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */ - -int -pod_type_p (t) - tree t; -{ - tree f; - - while (TREE_CODE (t) == ARRAY_TYPE) - t = TREE_TYPE (t); - - if (! IS_AGGR_TYPE (t)) - return 1; - - if (CLASSTYPE_NON_AGGREGATE (t) - || TYPE_HAS_COMPLEX_ASSIGN_REF (t) - || TYPE_HAS_DESTRUCTOR (t)) - return 0; - - for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f)) - { - if (TREE_CODE (f) != FIELD_DECL) - continue; - - if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE - || TYPE_PTRMEMFUNC_P (TREE_TYPE (f)) - || TYPE_PTRMEM_P (TREE_TYPE (f))) - return 0; - } - - return 1; -} - -/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific - attribute for either declaration DECL or type TYPE and 0 otherwise. - Plugged into valid_lang_attribute. */ - -int -cp_valid_lang_attribute (attr_name, attr_args, decl, type) - tree attr_name; - tree attr_args ATTRIBUTE_UNUSED; - tree decl ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; -{ - if (is_attribute_p ("com_interface", attr_name)) - { - if (! flag_vtable_thunks) - { - error ("`com_interface' only supported with -fvtable-thunks"); - return 0; - } - - if (attr_args != NULL_TREE - || decl != NULL_TREE - || ! CLASS_TYPE_P (type) - || type != TYPE_MAIN_VARIANT (type)) - { - warning ("`com_interface' attribute can only be applied to class definitions"); - return 0; - } - - CLASSTYPE_COM_INTERFACE (type) = 1; - return 1; - } - else if (is_attribute_p ("init_priority", attr_name)) - { - tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE); - int pri; - - if (initp_expr) - STRIP_NOPS (initp_expr); - - if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST) - { - error ("requested init_priority is not an integer constant"); - return 0; - } - - pri = TREE_INT_CST_LOW (initp_expr); - - while (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (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) - /* Static objects in functions are initialized the - first time control passes through that - function. This is not precise enough to pin down an - init_priority value, so don't allow it. */ - || current_function_decl) - { - error ("can only use init_priority attribute on file-scope definitions of objects of class type"); - return 0; - } - - if (pri > MAX_INIT_PRIORITY || pri <= 0) - { - error ("requested init_priority is out of range"); - return 0; - } - - /* Check for init_priorities that are reserved for - language and runtime support implementations.*/ - if (pri <= MAX_RESERVED_INIT_PRIORITY) - { - warning - ("requested init_priority is reserved for internal use"); - } - - DECL_INIT_PRIORITY (decl) = pri; - return 1; - } - - return 0; -} - -/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the - thing pointed to by the constant. */ - -tree -make_ptrmem_cst (type, member) - tree type; - tree member; -{ - tree ptrmem_cst = make_node (PTRMEM_CST); - /* If would seem a great convenience if make_node would set - TREE_CONSTANT for things of class `c', but it does not. */ - TREE_CONSTANT (ptrmem_cst) = 1; - TREE_TYPE (ptrmem_cst) = type; - PTRMEM_CST_MEMBER (ptrmem_cst) = member; - return ptrmem_cst; -} - |