--- gcc/cp/tree.c 2018/04/24 18:20:22 1.1 +++ gcc/cp/tree.c 2018/04/24 18:27:17 1.1.1.2 @@ -1,5 +1,5 @@ /* Language-dependent node constructors for parse phase of GNU compiler. - Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more deta 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include "config.h" #include @@ -24,6 +25,7 @@ the Free Software Foundation, 675 Mass A #include "tree.h" #include "cp-tree.h" #include "flags.h" +#include "rtl.h" #define CEIL(x,y) (((x) + (y) - 1) / (y)) @@ -32,6 +34,79 @@ the Free Software Foundation, 675 Mass A Lvalues can have their address taken, unless they have DECL_REGISTER. */ int +real_lvalue_p (ref) + tree ref; +{ + if (! language_lvalue_valid (ref)) + return 0; + + if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + return 1; + + if (ref == current_class_decl && 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: + return real_lvalue_p (TREE_OPERAND (ref, 0)); + + 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: + case ERROR_MARK: + if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) + return 1; + break; + + case WITH_CLEANUP_EXPR: + return real_lvalue_p (TREE_OPERAND (ref, 0)); + + /* 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 real_lvalue_p (TREE_OPERAND (ref, 0)) + && real_lvalue_p (TREE_OPERAND (ref, 1)); + break; + + case COND_EXPR: + return (real_lvalue_p (TREE_OPERAND (ref, 1)) + && real_lvalue_p (TREE_OPERAND (ref, 2))); + + case MODIFY_EXPR: + return 1; + + case COMPOUND_EXPR: + return real_lvalue_p (TREE_OPERAND (ref, 1)); + + case MAX_EXPR: + case MIN_EXPR: + return (real_lvalue_p (TREE_OPERAND (ref, 0)) + && real_lvalue_p (TREE_OPERAND (ref, 1))); + } + + return 0; +} + +int lvalue_p (ref) tree ref; { @@ -79,7 +154,7 @@ lvalue_p (ref) return 1; case CALL_EXPR: - if (TREE_ADDRESSABLE (TREE_TYPE (ref))) + if (IS_AGGR_TYPE (TREE_TYPE (ref))) return 1; break; @@ -102,6 +177,11 @@ lvalue_p (ref) case COMPOUND_EXPR: return lvalue_p (TREE_OPERAND (ref, 1)); + + case MAX_EXPR: + case MIN_EXPR: + return (lvalue_p (TREE_OPERAND (ref, 0)) + && lvalue_p (TREE_OPERAND (ref, 1))); } return 0; @@ -138,9 +218,13 @@ build_cplus_new (type, init, with_cleanu tree init; int with_cleanup_p; { - tree slot = build (VAR_DECL, type); - tree rval = build (NEW_EXPR, type, - TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); + tree slot; + tree rval; + + slot = build (VAR_DECL, type); + layout_decl (slot, 0); + rval = build (NEW_EXPR, type, + TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); TREE_SIDE_EFFECTS (rval) = 1; TREE_ADDRESSABLE (rval) = 1; rval = build (TARGET_EXPR, type, slot, rval, 0); @@ -152,7 +236,7 @@ build_cplus_new (type, init, with_cleanu { TREE_OPERAND (rval, 2) = error_mark_node; rval = build (WITH_CLEANUP_EXPR, type, rval, 0, - build_delete (TYPE_POINTER_TO (type), + build_delete (build_pointer_type (type), build_unary_op (ADDR_EXPR, slot, 0), integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0)); @@ -314,10 +398,8 @@ build_cplus_method_type (basetype, retty TYPE_READONLY (basetype), TYPE_VOLATILE (basetype)); else - { - ptype = build_pointer_type (basetype); - ptype = build_type_variant (ptype, 1, 0); - } + 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. */ @@ -491,6 +573,7 @@ propagate_binfo_offsets (binfo, offset) chain = TREE_VEC_ELT (base_binfos, k); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Now propagate the offset to the base types. */ propagate_binfo_offsets (base_binfo, offset); @@ -570,9 +653,13 @@ layout_vbasetypes (rec, max) BINFO_OFFSET (vbase_types) = offset; if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST) - const_size += MAX (BITS_PER_UNIT, - TREE_INT_CST_LOW (TYPE_SIZE (basetype)) - - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); + { + /* 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 (TYPE_SIZE (basetype)) + - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); + } else if (var_size == 0) var_size = TYPE_SIZE (basetype); else @@ -581,6 +668,15 @@ layout_vbasetypes (rec, max) 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 it + 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; @@ -598,6 +694,8 @@ layout_vbasetypes (rec, max) { tree base_binfos = BINFO_BASETYPES (vbase_types); + BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); + if (base_binfos) { tree chain = NULL_TREE; @@ -618,6 +716,7 @@ layout_vbasetypes (rec, max) chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = vbase_types; } propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); @@ -654,7 +753,7 @@ layout_basetypes (rec, binfos) /* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using - VAR_SIZE. And so far, we've been sucessful. */ + VAR_SIZE. And so far, we've been successful. */ #if 0 register tree var_size = 0; #endif @@ -731,6 +830,7 @@ layout_basetypes (rec, binfos) 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; @@ -1151,22 +1251,6 @@ make_binfo (offset, binfo, vtable, virtu return new_binfo; } -tree -copy_binfo (list) - tree list; -{ - tree binfo = copy_list (list); - tree rval = binfo; - while (binfo) - { - TREE_USED (binfo) = 0; - if (BINFO_BASETYPES (binfo)) - BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo)); - binfo = TREE_CHAIN (binfo); - } - return rval; -} - /* Return the binfo value for ELEM in TYPE. */ tree @@ -1234,7 +1318,7 @@ void debug_binfo (elem) tree elem; { - int i; + unsigned HOST_WIDE_INT n; tree virtuals; fprintf (stderr, "type \"%s\"; offset = %d\n", @@ -1248,21 +1332,17 @@ debug_binfo (elem) fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "virtuals:\n"); virtuals = BINFO_VIRTUALS (elem); - if (virtuals != 0) - { - virtuals = TREE_CHAIN (virtuals); - if (flag_dossier) - virtuals = TREE_CHAIN (virtuals); - } - i = 1; + + n = skip_rtti_stuff (&virtuals); + while (virtuals) { tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); fprintf (stderr, "%s [%d =? %d]\n", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), - i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); + n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); + ++n; virtuals = TREE_CHAIN (virtuals); - i += 1; } } @@ -1484,11 +1564,11 @@ id_cmp (p1, p2) return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2); } -/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions +/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions listed in RAISES. */ tree -build_exception_variant (ctype, type, raises) - tree ctype, type; +build_exception_variant (type, raises) + tree type; tree raises; { int i; @@ -1504,24 +1584,13 @@ build_exception_variant (ctype, type, ra || TYPE_VOLATILE (v) != volatilep) continue; - t = raises; - t2 = TYPE_RAISES_EXCEPTIONS (v); - while (t && t2) - { - if (TREE_TYPE (t) == TREE_TYPE (t2)) - { - t = TREE_CHAIN (t); - t2 = TREE_CHAIN (t2); - } - else break; - } - if (t || t2) - continue; - /* List of exceptions raised matches previously found list. - - @@ Nice to free up storage used in consing up the - @@ list of exceptions raised. */ - return v; + /* @@ This should do set equality, not exact match. */ + if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises)) + /* List of exceptions raised matches previously found list. + + @@ Nice to free up storage used in consing up the + @@ list of exceptions raised. */ + return v; } /* Need to build a new variant. */ @@ -1543,15 +1612,21 @@ build_exception_variant (ctype, type, ra Assuming T is a node build bottom-up, make it all exist on permanent obstack, if it is not permanent already. */ -static tree -make_deep_copy (t) + +tree +mapcar (t, func) tree t; + tree (*func)(); { enum tree_code code; + tree tmp; - if (t == NULL_TREE || TREE_PERMANENT (t)) + if (t == NULL_TREE) return t; + if (tmp = func (t), tmp != NULL_TREE) + return tmp; + switch (code = TREE_CODE (t)) { case ERROR_MARK: @@ -1566,10 +1641,10 @@ make_deep_copy (t) { tree chain = TREE_CHAIN (t); t = copy_node (t); - TREE_CHAIN (t) = make_deep_copy (chain); - TREE_TYPE (t) = make_deep_copy (TREE_TYPE (t)); - DECL_INITIAL (t) = make_deep_copy (DECL_INITIAL (t)); - DECL_SIZE (t) = make_deep_copy (DECL_SIZE (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; } @@ -1577,9 +1652,9 @@ make_deep_copy (t) { tree chain = TREE_CHAIN (t); t = copy_node (t); - TREE_PURPOSE (t) = make_deep_copy (TREE_PURPOSE (t)); - TREE_VALUE (t) = make_deep_copy (TREE_VALUE (t)); - TREE_CHAIN (t) = make_deep_copy (chain); + TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func); + TREE_VALUE (t) = mapcar (TREE_VALUE (t), func); + TREE_CHAIN (t) = mapcar (chain, func); return t; } @@ -1589,7 +1664,7 @@ make_deep_copy (t) t = copy_node (t); while (len--) - TREE_VEC_ELT (t, len) = make_deep_copy (TREE_VEC_ELT (t, len)); + TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func); return t; } @@ -1602,14 +1677,14 @@ make_deep_copy (t) case TARGET_EXPR: case NEW_EXPR: t = copy_node (t); - TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); - TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1)); - TREE_OPERAND (t, 2) = make_deep_copy (TREE_OPERAND (t, 2)); + 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) = make_deep_copy (TREE_OPERAND (t, 0)); + TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); return t; case MODIFY_EXPR: @@ -1647,8 +1722,8 @@ make_deep_copy (t) case POSTINCREMENT_EXPR: case CALL_EXPR: t = copy_node (t); - TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); - TREE_OPERAND (t, 1) = make_deep_copy (TREE_OPERAND (t, 1)); + TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); + TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); return t; case CONVERT_EXPR: @@ -1660,32 +1735,36 @@ make_deep_copy (t) case NOP_EXPR: case COMPONENT_REF: t = copy_node (t); - TREE_OPERAND (t, 0) = make_deep_copy (TREE_OPERAND (t, 0)); + TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); return t; case POINTER_TYPE: - return build_pointer_type (make_deep_copy (TREE_TYPE (t))); + return build_pointer_type (mapcar (TREE_TYPE (t), func)); case REFERENCE_TYPE: - return build_reference_type (make_deep_copy (TREE_TYPE (t))); + return build_reference_type (mapcar (TREE_TYPE (t), func)); case FUNCTION_TYPE: - return build_function_type (make_deep_copy (TREE_TYPE (t)), - make_deep_copy (TYPE_ARG_TYPES (t))); + return build_function_type (mapcar (TREE_TYPE (t), func), + mapcar (TYPE_ARG_TYPES (t), func)); case ARRAY_TYPE: - return build_array_type (make_deep_copy (TREE_TYPE (t)), - make_deep_copy (TYPE_DOMAIN (t))); + return build_array_type (mapcar (TREE_TYPE (t), func), + mapcar (TYPE_DOMAIN (t), func)); + case INTEGER_TYPE: + return build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); + case OFFSET_TYPE: - return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)), - make_deep_copy (TREE_TYPE (t))); + return build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func), + mapcar (TREE_TYPE (t), func)); case METHOD_TYPE: return build_method_type - (make_deep_copy (TYPE_METHOD_BASETYPE (t)), + (mapcar (TYPE_METHOD_BASETYPE (t), func), build_function_type - (make_deep_copy (TREE_TYPE (t)), - make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t))))); + (mapcar (TREE_TYPE (t), func), + mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func))); + case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) return build_ptrmemfunc_type - (make_deep_copy (TYPE_PTRMEMFUNC_FN_TYPE (t))); + (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); /* else fall through */ /* This list is incomplete, but should suffice for now. @@ -1701,6 +1780,15 @@ make_deep_copy (t) return NULL_TREE; } +static tree +perm_manip (t) + tree t; +{ + if (TREE_PERMANENT (t)) + 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 @@ -1709,15 +1797,18 @@ copy_to_permanent (t) { register struct obstack *ambient_obstack = current_obstack; register struct obstack *ambient_saveable_obstack = saveable_obstack; + int resume; if (t == NULL_TREE || TREE_PERMANENT (t)) return t; saveable_obstack = &permanent_obstack; current_obstack = saveable_obstack; + resume = suspend_momentary (); - t = make_deep_copy (t); + t = mapcar (t, perm_manip); + resume_momentary (resume); current_obstack = ambient_obstack; saveable_obstack = ambient_saveable_obstack; @@ -1788,3 +1879,117 @@ array_type_nelts_total (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) + return build_cplus_new (TREE_TYPE (t), + break_out_target_exprs (TREE_OPERAND (t, 1)), 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); +} + +tree +unsave_expr (expr) + tree expr; +{ + tree t; + + t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr); + TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr); + return t; +} + +/* Modify a tree in place so that all the evaluate only once things + are cleared out. Return the EXPR given. */ +tree +unsave_expr_now (expr) + tree expr; +{ + enum tree_code code; + register int i; + + if (expr == NULL_TREE) + return expr; + + code = TREE_CODE (expr); + switch (code) + { + case SAVE_EXPR: + SAVE_EXPR_RTL (expr) = NULL_RTX; + break; + + case TARGET_EXPR: + sorry ("TARGET_EXPR reused inside UNSAVE_EXPR"); + break; + + case RTL_EXPR: + warning ("RTL_EXPR reused inside UNSAVE_EXPR"); + RTL_EXPR_SEQUENCE (expr) = NULL_RTX; + break; + + case CALL_EXPR: + CALL_EXPR_RTL (expr) = NULL_RTX; + if (TREE_OPERAND (expr, 1) + && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST) + { + tree exp = TREE_OPERAND (expr, 1); + while (exp) + { + unsave_expr_now (TREE_VALUE (exp)); + exp = TREE_CHAIN (exp); + } + } + break; + + case WITH_CLEANUP_EXPR: + warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR"); + RTL_EXPR_RTL (expr) = NULL_RTX; + break; + } + + switch (TREE_CODE_CLASS (code)) + { + case 'c': /* a constant */ + case 't': /* a type node */ + case 'x': /* something random, like an identifier or an ERROR_MARK. */ + case 'd': /* A decl node */ + case 'b': /* A block node */ + return expr; + + case 'e': /* an expression */ + case 'r': /* a reference */ + case 's': /* an expression with side effects */ + case '<': /* a comparison expression */ + case '2': /* a binary arithmetic expression */ + case '1': /* a unary arithmetic expression */ + for (i = tree_code_length[(int) code] - 1; i >= 0; i--) + unsave_expr_now (TREE_OPERAND (expr, i)); + return expr; + + default: + my_friendly_abort (999); + } +} + +/* Since cleanup may have SAVE_EXPRs in it, we protect it with an + UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups + by itself. */ +int +cp_expand_decl_cleanup (decl, cleanup) + tree decl, cleanup; +{ + return expand_decl_cleanup (decl, unsave_expr (cleanup)); +}