From: Mark Mitchell Date: Mon, 30 Sep 2002 16:52:19 +0000 (+0000) Subject: store-layout.c (finish_record_layout): Add free_p parameter. X-Git-Tag: releases/gcc-3.3.0~2548 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=17bbb839f1270db8e2f99a8f173f38188ad176f3;p=gcc.git store-layout.c (finish_record_layout): Add free_p parameter. * store-layout.c (finish_record_layout): Add free_p parameter. (layout_type): Pass it. * tree.h (finish_record_layout): Update prototype. * class.c (walk_subobject_offsets): Correct the calculation of offsets for virtual bases. Correct the counting of array elements. (layout_nonempty_base_or_field): Simplify. Correct the calculation of offsets to be propagated through the binfo hierarchy. (build_base_field): Avoid creating a FIELD_DECL for empty bases. Add the FIELD_DECL to TYPE_FIELDS. (build_base_fields): Adjust accordingly. (layout_virtual_bases): Use build_base_field. (end_of_class): Return a tree, not an integer. (warn_about_ambiguous_direct_bases): Rename to ... (warn_about_ambiguous_bases): ... this. (include_empty_classes): New function. (layout_class_type): Create an alternative version of the type to be used when as a base class type. Do not call finish_record_layout until we are done laying out the class. * cp-tree.h (lang_type_class): Remove size, size_unit. Add as_base. (CLASSTYPE_SIZE): Reimplement. (CLASSTYPE_SIZE_UNIT): Likewise. (CLASSTYPE_ALIGN): Likweise. (CLASSTYPE_USER_ALIGN): Likewise. (CLASSTYPE_AS_BASE): New macro. (DECL_INITIALIZED_P): Likewise. (extract_init): Remove prototype. (build_forced_zero_init): Rename to ... (build_zero_init): ... this. (force_store_init_value): Remove. * decl.c (obscure_complex_init): Remove. (duplicate_decls): Copy DECL_INITIALIZED_P. (check_initializer): Do not leave junk in DECL_INITIAL. (cp_finish_decl): Handle zero-initialization of entities with static storage duration. * expr.c (extract_init): Remove. * init.c (build_forced_zero_init): Remove. (build_zero_init): New function. (build_default_init): Use it. (build_field_list): Skip FIELD_DECLs for base subobjects. (push_base_cleanups): Likewise. * method.c (do_build_assign_ref): Likewise. (synthesize_exception_spec): Likewise. * pt.c (tsubst_decl): Clear DECL_INITIALIZED_P. (regenerate_decl_from_template): To not set DECL_INITIAL for a static data member whose initialization took place in its class. (instantiate_decl): Do not pass an initializer to cp_finish_decl in that situation. * search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects. (dfs_unuse_fields): Likewise. * tree.c (pod_type_p): Handle error_mark_node. (zero_init_p): Likewise. * typeck.c (lookup_anon_field): Skip FIELD_DECLs for base subobjects. * typeck2.c (store_init_value): Remove #if 0'd code. (force_store_init_value): Remove. (process_init_constructor): Use build_zero_init. * g++.dg/abi/empty7.C: New test. * g++.dg/init/pm2.C: Likewise. From-SVN: r57654 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76793fb896f0..f1a6964664b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2002-09-30 Mark Mitchell + + * store-layout.c (finish_record_layout): Add free_p parameter. + (layout_type): Pass it. + * tree.h (finish_record_layout): Update prototype. + Mon Sep 30 14:57:18 CEST 2002 Jan Hubicka * i386.h (TARGET_CPP_CPU_BUILTINS): Define __SSE_MATH__. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 792ce89cd613..1fef98d22b82 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,62 @@ +2002-09-30 Mark Mitchell + + * class.c (walk_subobject_offsets): Correct the calculation of + offsets for virtual bases. Correct the counting of array + elements. + (layout_nonempty_base_or_field): Simplify. Correct the + calculation of offsets to be propagated through the binfo + hierarchy. + (build_base_field): Avoid creating a FIELD_DECL for empty bases. + Add the FIELD_DECL to TYPE_FIELDS. + (build_base_fields): Adjust accordingly. + (layout_virtual_bases): Use build_base_field. + (end_of_class): Return a tree, not an integer. + (warn_about_ambiguous_direct_bases): Rename to ... + (warn_about_ambiguous_bases): ... this. + (include_empty_classes): New function. + (layout_class_type): Create an alternative version of the type to + be used when as a base class type. Do not call + finish_record_layout until we are done laying out the class. + * cp-tree.h (lang_type_class): Remove size, size_unit. Add + as_base. + (CLASSTYPE_SIZE): Reimplement. + (CLASSTYPE_SIZE_UNIT): Likewise. + (CLASSTYPE_ALIGN): Likweise. + (CLASSTYPE_USER_ALIGN): Likewise. + (CLASSTYPE_AS_BASE): New macro. + (DECL_INITIALIZED_P): Likewise. + (extract_init): Remove prototype. + (build_forced_zero_init): Rename to ... + (build_zero_init): ... this. + (force_store_init_value): Remove. + * decl.c (obscure_complex_init): Remove. + (duplicate_decls): Copy DECL_INITIALIZED_P. + (check_initializer): Do not leave junk in DECL_INITIAL. + (cp_finish_decl): Handle zero-initialization of entities with + static storage duration. + * expr.c (extract_init): Remove. + * init.c (build_forced_zero_init): Remove. + (build_zero_init): New function. + (build_default_init): Use it. + (build_field_list): Skip FIELD_DECLs for base subobjects. + (push_base_cleanups): Likewise. + * method.c (do_build_assign_ref): Likewise. + (synthesize_exception_spec): Likewise. + * pt.c (tsubst_decl): Clear DECL_INITIALIZED_P. + (regenerate_decl_from_template): To not set DECL_INITIAL for a + static data member whose initialization took place in its class. + (instantiate_decl): Do not pass an initializer to cp_finish_decl + in that situation. + * search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects. + (dfs_unuse_fields): Likewise. + * tree.c (pod_type_p): Handle error_mark_node. + (zero_init_p): Likewise. + * typeck.c (lookup_anon_field): Skip FIELD_DECLs for base + subobjects. + * typeck2.c (store_init_value): Remove #if 0'd code. + (force_store_init_value): Remove. + (process_init_constructor): Use build_zero_init. + 2002-09-29 Nathan Sidwell PR c++/7788 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7532c5d8e21d..b97b2683ee16 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -137,21 +137,22 @@ static void check_bitfield_decl PARAMS ((tree)); static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *)); static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, int *)); -static bool build_base_field PARAMS ((record_layout_info, tree, int *, - splay_tree, tree)); -static bool build_base_fields PARAMS ((record_layout_info, int *, - splay_tree, tree)); +static tree *build_base_field PARAMS ((record_layout_info, tree, int *, + splay_tree, tree *)); +static void build_base_fields PARAMS ((record_layout_info, int *, + splay_tree, tree *)); static void check_methods PARAMS ((tree)); static void remove_zero_width_bit_fields PARAMS ((tree)); static void check_bases PARAMS ((tree, int *, int *, int *)); static void check_bases_and_members PARAMS ((tree, int *)); static tree create_vtable_ptr PARAMS ((tree, int *, tree *)); +static void include_empty_classes (record_layout_info); static void layout_class_type PARAMS ((tree, int *, int *, tree *)); static void fixup_pending_inline PARAMS ((tree)); static void fixup_inline_methods PARAMS ((tree)); static void set_primary_base PARAMS ((tree, tree, int *)); static void propagate_binfo_offsets PARAMS ((tree, tree, tree)); -static void layout_virtual_bases PARAMS ((tree, splay_tree)); +static void layout_virtual_bases (record_layout_info, splay_tree); static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *)); static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *)); static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *)); @@ -171,9 +172,8 @@ static tree build_vtable PARAMS ((tree, tree, tree)); static void initialize_vtable PARAMS ((tree, tree)); static void initialize_array PARAMS ((tree, tree)); static void layout_nonempty_base_or_field PARAMS ((record_layout_info, - tree, tree, - splay_tree, tree)); -static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); + tree, tree, splay_tree)); +static tree end_of_class PARAMS ((tree, int)); static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree)); static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, @@ -208,7 +208,7 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int)); static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int)); static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, splay_tree_key k2)); -static void warn_about_ambiguous_direct_bases PARAMS ((tree)); +static void warn_about_ambiguous_bases PARAMS ((tree)); static bool type_requires_array_cookie PARAMS ((tree)); static bool contains_empty_class_p (tree); @@ -3512,6 +3512,7 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) if (CLASS_TYPE_P (type)) { tree field; + tree binfo; int i; /* Record the location of TYPE. */ @@ -3522,7 +3523,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) /* Iterate through the direct base classes of TYPE. */ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i) { - tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i); + binfo = BINFO_BASETYPE (TYPE_BINFO (type), i); + + if (abi_version_at_least (2) + && TREE_VIA_VIRTUAL (binfo)) + continue; if (!vbases_p && TREE_VIA_VIRTUAL (binfo) @@ -3536,14 +3541,40 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) BINFO_OFFSET (binfo)), offsets, max_offset, - vbases_p); + (abi_version_at_least (2) + ? /*vbases_p=*/0 : vbases_p)); if (r) return r; } + /* Iterate through the virtual base classes of TYPE. In G++ + 3.2, we included virtual bases in the direct base class loop + above, which results in incorrect results; the correct + offsets for virtual bases are only known when working with + the most derived type. */ + if (abi_version_at_least (2) && vbases_p) + { + tree vbase; + + for (vbase = CLASSTYPE_VBASECLASSES (type); + vbase; + vbase = TREE_CHAIN (vbase)) + { + binfo = TREE_VALUE (vbase); + r = walk_subobject_offsets (BINFO_TYPE (binfo), + f, + size_binop (PLUS_EXPR, + offset, + BINFO_OFFSET (binfo)), + offsets, + max_offset, + /*vbases_p=*/0); + } + } + /* Iterate through the fields of TYPE. */ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL) + if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field)) { tree field_offset; @@ -3571,8 +3602,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) tree index; /* Step through each of the elements in the array. */ - for (index = size_zero_node; - INT_CST_LT (index, TYPE_MAX_VALUE (domain)); + for (index = size_zero_node; + /* G++ 3.2 had an off-by-one error here. */ + (abi_version_at_least (2) + ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index) + : INT_CST_LT (index, TYPE_MAX_VALUE (domain))); index = size_binop (PLUS_EXPR, index, size_one_node)) { r = walk_subobject_offsets (TREE_TYPE (type), @@ -3640,22 +3674,34 @@ layout_conflict_p (type, offset, offsets, vbases_p) /* DECL is a FIELD_DECL corresponding either to a base subobject of a non-static data member of the type indicated by RLI. BINFO is the binfo corresponding to the base subobject, OFFSETS maps offsets to - types already located at those offsets. T is the most derived - type. This function determines the position of the DECL. */ + types already located at those offsets. This function determines + the position of the DECL. */ static void -layout_nonempty_base_or_field (rli, decl, binfo, offsets, t) - record_layout_info rli; - tree decl; - tree binfo; - splay_tree offsets; - tree t; +layout_nonempty_base_or_field (record_layout_info rli, + tree decl, + tree binfo, + splay_tree offsets) { + tree t = rli->t; tree offset = NULL_TREE; - tree type = TREE_TYPE (decl); - /* If we are laying out a base class, rather than a field, then - DECL_ARTIFICIAL will be set on the FIELD_DECL. */ - int field_p = !DECL_ARTIFICIAL (decl); + bool field_p; + tree type; + + if (binfo) + { + /* For the purposes of determining layout conflicts, we want to + use the class type of BINFO; TREE_TYPE (DECL) will be the + CLASSTYPE_AS_BASE version, which does not contain entries for + zero-sized bases. */ + type = TREE_TYPE (binfo); + field_p = false; + } + else + { + type = TREE_TYPE (decl); + field_p = true; + } /* Try to place the field. It may take more than one try if we have a hard time placing the field without putting two objects of the @@ -3683,10 +3729,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t) empty class, have nonzero size, any overlap can happen only with a direct or indirect base-class -- it can't happen with a data member. */ - if (layout_conflict_p (TREE_TYPE (decl), - offset, - offsets, - field_p)) + if (layout_conflict_p (type, offset, offsets, field_p)) { /* Strip off the size allocated to this field. That puts us at the first place we could have put the field with @@ -3709,8 +3752,15 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t) /* Now that we know where it will be placed, update its BINFO_OFFSET. */ if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo))) + /* Indirect virtual bases may have a non-zero BINFO_OFFSET at + this point because their BINFO_OFFSET is copied from another + hierarchy. Therefore, we may not need to add the entire + OFFSET. */ propagate_binfo_offsets (binfo, - convert (ssizetype, offset), t); + size_diffop (convert (ssizetype, offset), + convert (ssizetype, + BINFO_OFFSET (binfo))), + t); } /* Layout the empty base BINFO. EOC indicates the byte currently just @@ -3768,60 +3818,74 @@ layout_empty_base (binfo, eoc, offsets, t) return atend; } -/* Build a FIELD_DECL for the base given by BINFO in the class - indicated by RLI. If the new object is non-empty, clear *EMPTY_P. - *BASE_ALIGN is a running maximum of the alignments of any base - class. OFFSETS gives the location of empty base subobjects. T is - the most derived type. Return nonzero if the new object cannot be - nearly-empty. */ +/* Layout the the base given by BINFO in the class indicated by RLI. + If the new object is non-empty, and EMPTY_P is non-NULL, clear + *EMPTY_P. *BASE_ALIGN is a running maximum of the alignments of + any base class. OFFSETS gives the location of empty base + subobjects. T is the most derived type. Return nonzero if the new + object cannot be nearly-empty. A new FIELD_DECL is inserted at + *NEXT_FIELD, unless BINFO is for an empty base class. -static bool -build_base_field (rli, binfo, empty_p, offsets, t) - record_layout_info rli; - tree binfo; - int *empty_p; - splay_tree offsets; - tree t; + Returns the location at which the next field should be inserted. */ + +static tree * +build_base_field (record_layout_info rli, tree binfo, int *empty_p, + splay_tree offsets, tree *next_field) { + tree t = rli->t; tree basetype = BINFO_TYPE (binfo); - tree decl; - bool atend = false; if (!COMPLETE_TYPE_P (basetype)) /* This error is now reported in xref_tag, thus giving better location information. */ - return atend; - - decl = build_decl (FIELD_DECL, NULL_TREE, basetype); - DECL_ARTIFICIAL (decl) = 1; - DECL_FIELD_CONTEXT (decl) = rli->t; - DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype); - DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype); - DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype); - DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype); - /* Tell the backend not to round up to TYPE_ALIGN. */ - DECL_PACKED (decl) = 1; + return next_field; - if (!integer_zerop (DECL_SIZE (decl))) + /* Place the base class. */ + if (!is_empty_class (basetype)) { + tree decl; + /* The containing class is non-empty because it has a non-empty base class. */ - *empty_p = 0; - + if (empty_p) + *empty_p = 0; + + /* Create the FIELD_DECL. */ + decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype)); + DECL_ARTIFICIAL (decl) = 1; + DECL_FIELD_CONTEXT (decl) = t; + DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype); + DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype); + DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype); + DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype); + /* Tell the backend not to round up to TYPE_ALIGN. */ + DECL_PACKED (decl) = 1; + /* Try to place the field. It may take more than one try if we have a hard time placing the field without putting two objects of the same type at the same address. */ - layout_nonempty_base_or_field (rli, decl, binfo, offsets, t); + layout_nonempty_base_or_field (rli, decl, binfo, offsets); + /* Add the new FIELD_DECL to the list of fields for T. */ + TREE_CHAIN (decl) = *next_field; + *next_field = decl; + next_field = &TREE_CHAIN (decl); } else { - unsigned HOST_WIDE_INT eoc; + tree eoc; /* On some platforms (ARM), even empty classes will not be byte-aligned. */ - eoc = tree_low_cst (rli_size_unit_so_far (rli), 0); - eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl); - atend |= layout_empty_base (binfo, size_int (eoc), offsets, t); + eoc = round_up (rli_size_unit_so_far (rli), + CLASSTYPE_ALIGN_UNIT (basetype)); + if (layout_empty_base (binfo, eoc, offsets, t)) + CLASSTYPE_NEARLY_EMPTY_P (t) = 0; + + /* We do not create a FIELD_DECL for empty base classes because + it might overlap some other field. We want to be able to + create CONSTRUCTORs for the class by iterating over the + FIELD_DECLs, and the back end does not handle overlapping + FIELD_DECLs. */ } /* Record the offsets of BINFO and its base subobjects. */ @@ -3829,42 +3893,41 @@ build_base_field (rli, binfo, empty_p, offsets, t) BINFO_OFFSET (binfo), offsets, /*vbases_p=*/0); - return atend; + + return next_field; } /* Layout all of the non-virtual base classes. Record empty - subobjects in OFFSETS. T is the most derived type. Return - nonzero if the type cannot be nearly empty. */ + subobjects in OFFSETS. T is the most derived type. Return nonzero + if the type cannot be nearly empty. The fields created + corresponding to the base classes will be inserted at + *NEXT_FIELD. */ -static bool -build_base_fields (rli, empty_p, offsets, t) - record_layout_info rli; - int *empty_p; - splay_tree offsets; - tree t; +static void +build_base_fields (record_layout_info rli, int *empty_p, + splay_tree offsets, tree *next_field) { /* Chain to hold all the new FIELD_DECLs which stand in for base class subobjects. */ - tree rec = rli->t; - int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec); + tree t = rli->t; + int n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i; - bool atend = 0; /* The primary base class is always allocated first. */ - if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec)) - build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), - empty_p, offsets, t); + if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) + next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t), + empty_p, offsets, next_field); /* Now allocate the rest of the bases. */ for (i = 0; i < n_baseclasses; ++i) { tree base_binfo; - base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i); + base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i); /* The primary base was already allocated above, so we don't need to allocate it again here. */ - if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec)) + if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t)) continue; /* A primary virtual base class is allocated just like any other @@ -3874,9 +3937,9 @@ build_base_fields (rli, empty_p, offsets, t) && !BINFO_PRIMARY_P (base_binfo)) continue; - atend |= build_base_field (rli, base_binfo, empty_p, offsets, t); + next_field = build_base_field (rli, base_binfo, empty_p, + offsets, next_field); } - return atend; } /* Go through the TYPE_METHODS of T issuing any appropriate @@ -4567,36 +4630,41 @@ dfs_set_offset_for_unshared_vbases (binfo, data) return NULL_TREE; } -/* Set BINFO_OFFSET for all of the virtual bases for T. Update +/* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of empty subobjects of T. */ static void -layout_virtual_bases (t, offsets) - tree t; - splay_tree offsets; +layout_virtual_bases (record_layout_info rli, splay_tree offsets) { - tree vbases, dsize; - unsigned HOST_WIDE_INT eoc; + tree vbases; + tree t = rli->t; bool first_vbase = true; + tree *next_field; if (CLASSTYPE_N_BASECLASSES (t) == 0) return; + if (!abi_version_at_least(2)) + { + /* In G++ 3.2, we incorrectly rounded the size before laying out + the virtual bases. */ + finish_record_layout (rli, /*free_p=*/false); #ifdef STRUCTURE_SIZE_BOUNDARY - /* Packed structures don't need to have minimum size. */ - if (! TYPE_PACKED (t)) - TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY); + /* Packed structures don't need to have minimum size. */ + if (! TYPE_PACKED (t)) + TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY); #endif + rli->offset = TYPE_SIZE_UNIT (t); + rli->bitpos = bitsize_zero_node; + rli->record_align = TYPE_ALIGN (t); + } - /* DSIZE is the size of the class without the virtual bases. */ - if (abi_version_at_least(2)) - dsize = CLASSTYPE_SIZE (t); - else - dsize = TYPE_SIZE (t); - - /* Make every class have alignment of at least one. */ - TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT); + /* Find the last field. The artificial fields created for virtual + bases will go after the last extant field to date. */ + next_field = &TYPE_FIELDS (t); + while (*next_field) + next_field = &TREE_CHAIN (*next_field); /* Go through the virtual bases, allocating space for each virtual base that is not already a primary base class. These are @@ -4614,45 +4682,12 @@ layout_virtual_bases (t, offsets) if (!BINFO_PRIMARY_P (vbase)) { + tree basetype = TREE_TYPE (vbase); + /* This virtual base is not a primary base of any class in the hierarchy, so we have to add space for it. */ - tree basetype, usize; - unsigned int desired_align; - - basetype = BINFO_TYPE (vbase); - - desired_align = CLASSTYPE_ALIGN (basetype); - TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align); - - /* Add padding so that we can put the virtual base class at an - appropriately aligned offset. */ - dsize = round_up (dsize, desired_align); - usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node); - - /* We try to squish empty virtual bases in just like - ordinary empty bases. */ - if (is_empty_class (basetype)) - layout_empty_base (vbase, - convert (sizetype, usize), - offsets, t); - else - { - tree offset; - - offset = convert (ssizetype, usize); - offset = size_diffop (offset, - convert (ssizetype, - BINFO_OFFSET (vbase))); - - /* And compute the offset of the virtual base. */ - propagate_binfo_offsets (vbase, offset, t); - /* Every virtual baseclass takes a least a UNIT, so that - we can take it's address and get something different - for each base. */ - dsize = size_binop (PLUS_EXPR, dsize, - size_binop (MAX_EXPR, bitsize_unit_node, - CLASSTYPE_SIZE (basetype))); - } + next_field = build_base_field (rli, vbase, /*empty_p=*/NULL, + offsets, next_field); /* If the first virtual base might have been placed at a lower address, had we started from CLASSTYPE_SIZE, rather @@ -4663,20 +4698,15 @@ layout_virtual_bases (t, offsets) the results which is not particularly tractable. */ if (warn_abi && first_vbase - && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR, - round_up (CLASSTYPE_SIZE (t), - desired_align), - bitsize_unit_node), - BINFO_OFFSET (vbase))) + && (tree_int_cst_lt + (size_binop (CEIL_DIV_EXPR, + round_up (CLASSTYPE_SIZE (t), + CLASSTYPE_ALIGN (basetype)), + bitsize_unit_node), + BINFO_OFFSET (vbase)))) warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC", basetype); - /* Keep track of the offsets assigned to this virtual base. */ - record_subobject_offsets (BINFO_TYPE (vbase), - BINFO_OFFSET (vbase), - offsets, - /*vbases_p=*/0); - first_vbase = false; } } @@ -4687,45 +4717,18 @@ layout_virtual_bases (t, offsets) in lookup_base depend on the BINFO_OFFSETs being set correctly. */ dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t); - - /* If we had empty base classes that protruded beyond the end of the - class, we didn't update DSIZE above; we were hoping to overlay - multiple such bases at the same location. */ - eoc = end_of_class (t, /*include_virtuals_p=*/1); - dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT)); - - /* Now, make sure that the total size of the type is a multiple of - its alignment. */ - dsize = round_up (dsize, TYPE_ALIGN (t)); - TYPE_SIZE (t) = dsize; - TYPE_SIZE_UNIT (t) = convert (sizetype, - size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t), - bitsize_unit_node)); - - /* Check for ambiguous virtual bases. */ - if (extra_warnings) - for (vbases = CLASSTYPE_VBASECLASSES (t); - vbases; - vbases = TREE_CHAIN (vbases)) - { - tree basetype = BINFO_TYPE (TREE_VALUE (vbases)); - - if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL)) - warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", - basetype, t); - } } /* Returns the offset of the byte just past the end of the base class with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then only non-virtual bases are included. */ -static unsigned HOST_WIDE_INT +static tree end_of_class (t, include_virtuals_p) tree t; int include_virtuals_p; { - unsigned HOST_WIDE_INT result = 0; + tree result = size_zero_node; int i; for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i) @@ -4733,7 +4736,6 @@ end_of_class (t, include_virtuals_p) tree base_binfo; tree offset; tree size; - unsigned HOST_WIDE_INT end_of_base; base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i); @@ -4752,15 +4754,14 @@ end_of_class (t, include_virtuals_p) offset = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), size); - end_of_base = tree_low_cst (offset, /*pos=*/1); - if (end_of_base > result) - result = end_of_base; + if (INT_CST_LT_UNSIGNED (result, offset)) + result = offset; } return result; } -/* Warn about direct bases of T that are inaccessible because they are +/* Warn about bases of T that are inaccessible because they are ambiguous. For example: struct S {}; @@ -4771,19 +4772,35 @@ end_of_class (t, include_virtuals_p) subobjects of U. */ static void -warn_about_ambiguous_direct_bases (t) +warn_about_ambiguous_bases (t) tree t; { int i; + tree vbases; + tree basetype; + /* Check direct bases. */ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i) { - tree basetype = TYPE_BINFO_BASETYPE (t, i); + basetype = TYPE_BINFO_BASETYPE (t, i); if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL)) warning ("direct base `%T' inaccessible in `%T' due to ambiguity", - basetype, t); + basetype, t); } + + /* Check for ambiguous virtual bases. */ + if (extra_warnings) + for (vbases = CLASSTYPE_VBASECLASSES (t); + vbases; + vbases = TREE_CHAIN (vbases)) + { + basetype = BINFO_TYPE (TREE_VALUE (vbases)); + + if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL)) + warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", + basetype, t); + } } /* Compare two INTEGER_CSTs K1 and K2. */ @@ -4796,6 +4813,29 @@ splay_tree_compare_integer_csts (k1, k2) return tree_int_cst_compare ((tree) k1, (tree) k2); } +/* Increase the size indicated in RLI to account for empty classes + that are "off the end" of the class. */ + +static void +include_empty_classes (record_layout_info rli) +{ + tree eoc; + + /* It might be the case that we grew the class to allocate a + zero-sized base class. That won't be reflected in RLI, yet, + because we are willing to overlay multiple bases at the same + offset. However, now we need to make sure that RLI is big enough + to reflect the entire class. */ + eoc = end_of_class (rli->t, + CLASSTYPE_AS_BASE (rli->t) != NULL_TREE); + if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST + && INT_CST_LT_UNSIGNED (rli_size_unit_so_far (rli), eoc)) + { + rli->offset = size_binop (MAX_EXPR, rli->offset, eoc); + rli->bitpos = bitsize_zero_node; + } +} + /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate BINFO_OFFSETs for all of the base-classes. Position the vtable pointer. Accumulate declared virtual functions on VIRTUALS_P. */ @@ -4811,12 +4851,15 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) tree field; tree vptr; record_layout_info rli; - unsigned HOST_WIDE_INT eoc; /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of types that appear at that offset. */ splay_tree empty_base_offsets; /* True if the last field layed out was a bit-field. */ bool last_field_was_bitfield = false; + /* The location at which the next field should be inserted. */ + tree *next_field; + /* T, as a base class. */ + tree base_t; /* Keep track of the first non-static data member. */ non_static_data_members = TYPE_FIELDS (t); @@ -4834,15 +4877,18 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) /* The vptr is always the first thing in the class. */ if (vptr) { - TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t)); + TREE_CHAIN (vptr) = TYPE_FIELDS (t); + TYPE_FIELDS (t) = vptr; + next_field = &TREE_CHAIN (vptr); place_field (rli, vptr); } + else + next_field = &TYPE_FIELDS (t); /* Build FIELD_DECLs for all of the non-virtual base-types. */ empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts, NULL, NULL); - if (build_base_fields (rli, empty_p, empty_base_offsets, t)) - CLASSTYPE_NEARLY_EMPTY_P (t) = 0; + build_base_fields (rli, empty_p, empty_base_offsets, next_field); /* Layout the non-static data members. */ for (field = non_static_data_members; field; field = TREE_CHAIN (field)) @@ -4917,7 +4963,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) padding = NULL_TREE; layout_nonempty_base_or_field (rli, field, NULL_TREE, - empty_base_offsets, t); + empty_base_offsets); /* If a bit-field does not immediately follow another bit-field, and yet it starts in the middle of a byte, we have failed to @@ -4957,76 +5003,59 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) DECL_USER_ALIGN (padding_field) = 0; layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, - empty_base_offsets, t); + empty_base_offsets); } last_field_was_bitfield = DECL_C_BIT_FIELD (field); } - /* It might be the case that we grew the class to allocate a - zero-sized base class. That won't be reflected in RLI, yet, - because we are willing to overlay multiple bases at the same - offset. However, now we need to make sure that RLI is big enough - to reflect the entire class. */ - eoc = end_of_class (t, /*include_virtuals_p=*/0); - if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST - && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0) - { - rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc)); - rli->bitpos = bitsize_zero_node; - } - - /* We make all structures have at least one element, so that they - have nonzero size. The class may be empty even if it has - basetypes. Therefore, we add the fake field after all the other - fields; if there are already FIELD_DECLs on the list, their - offsets will not be disturbed. */ - if (!eoc && *empty_p) - { - tree padding; - - padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node); - place_field (rli, padding); - } - else if (abi_version_at_least (2) - && !integer_zerop (rli->bitpos)) + if (abi_version_at_least (2) && !integer_zerop (rli->bitpos)) /* Make sure that we are on a byte boundary so that the size of the class without virtual bases will always be a round number of bytes. */ rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT); - - /* Let the back-end lay out the type. Note that at this point we - have only included non-virtual base-classes; we will lay out the - virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after - this call are not necessarily correct; they are just the size and - alignment when no virtual base clases are used. */ - finish_record_layout (rli); + + /* Make sure that empty classes are reflected in RLI at this + point. */ + include_empty_classes(rli); /* Delete all zero-width bit-fields from the list of fields. Now that the type is laid out they are no longer important. */ remove_zero_width_bit_fields (t); - /* Remember the size and alignment of the class before adding - the virtual bases. */ - if (*empty_p) + /* Create the version of T used for virtual bases. We do not use + make_aggr_type for this version; this is an artificial type. For + a POD type, we just reuse T. */ + if (CLASSTYPE_NON_POD_P (t) || *empty_p) { - CLASSTYPE_SIZE (t) = bitsize_zero_node; - CLASSTYPE_SIZE_UNIT (t) = size_zero_node; - } - /* If this is a POD, we can't reuse its tail padding. */ - else if (!CLASSTYPE_NON_POD_P (t)) - { - CLASSTYPE_SIZE (t) = TYPE_SIZE (t); - CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t); + base_t = make_node (TREE_CODE (t)); + + /* Set the size and alignment for the new type. */ + TYPE_SIZE (base_t) = rli_size_so_far (rli); + TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli); + TYPE_ALIGN (base_t) = rli->record_align; + TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t); + + /* Copy the fields from T. */ + next_field = &TYPE_FIELDS (base_t); + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + { + *next_field = build_decl (FIELD_DECL, + DECL_NAME (field), + TREE_TYPE (field)); + DECL_CONTEXT (*next_field) = base_t; + DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field); + DECL_FIELD_BIT_OFFSET (*next_field) + = DECL_FIELD_BIT_OFFSET (field); + next_field = &TREE_CHAIN (*next_field); + } + + /* Record the base version of the type. */ + CLASSTYPE_AS_BASE (t) = base_t; } else - { - CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t); - CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t); - } - - CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t); - CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t); + CLASSTYPE_AS_BASE (t) = t; /* Set the TYPE_DECL for this type to contain the right value for DECL_OFFSET, so that we can use it as part @@ -5037,11 +5066,22 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) around. We must get these done before we try to lay out the virtual function table. As a side-effect, this will remove the base subobject fields. */ - layout_virtual_bases (t, empty_base_offsets); + layout_virtual_bases (rli, empty_base_offsets); + + /* Make sure that empty classes are reflected in RLI at this + point. */ + include_empty_classes(rli); + + /* Make sure not to create any structures with zero size. */ + if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p) + place_field (rli, + build_decl (FIELD_DECL, NULL_TREE, char_type_node)); + + /* Let the back-end lay out the type. */ + finish_record_layout (rli, /*free_p=*/true); - /* Warn about direct bases that can't be talked about due to - ambiguity. */ - warn_about_ambiguous_direct_bases (t); + /* Warn about bases that can't be talked about due to ambiguity. */ + warn_about_ambiguous_bases (t); /* Clean up. */ splay_tree_delete (empty_base_offsets); @@ -6414,7 +6454,9 @@ contains_empty_class_p (tree type) if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i))) return true; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (contains_empty_class_p (TREE_TYPE (field))) + if (TREE_CODE (field) == FIELD_DECL + && !DECL_ARTIFICIAL (field) + && is_empty_class (TREE_TYPE (field))) return true; } else if (TREE_CODE (type) == ARRAY_TYPE) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7e40937bed64..3a9c7e76d710 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -59,6 +59,7 @@ struct diagnostic_context; INHERITED_VALUE_BINDING_P (in CPLUS_BINDING) ICS_ELLIPSIS_FLAG (in _CONV) BINFO_ACCESS (in BINFO) + DECL_INITIALIZED_P (in VAR_DECL) 2: IDENTIFIER_OPNAME_P. TYPE_POLYMORPHIC_P (in _TYPE) ICS_THIS_FLAG (in _CONV) @@ -96,11 +97,10 @@ struct diagnostic_context; DECL_MUTABLE_P (in FIELD_DECL) 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL). DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL) - DECL_C_BITFIELD (in FIELD_DECL) 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) 3: DECL_IN_AGGR_P. - 4: DECL_C_BIT_FIELD + 4: DECL_C_BIT_FIELD (in a FIELD_DECL) 5: DECL_INTERFACE_KNOWN. 6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL). 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL). @@ -1150,8 +1150,7 @@ struct lang_type_class GTY(()) tree vfields; tree vbases; tree tags; - tree size; - tree size_unit; + tree as_base; tree pure_virtuals; tree friend_classes; tree rtti; @@ -1396,12 +1395,17 @@ struct lang_type GTY(()) #define CLASSTYPE_N_BASECLASSES(NODE) \ (BINFO_N_BASETYPES (TYPE_BINFO (NODE))) +/* The type corresponding to NODE when NODE is used as a base class, + i.e., NODE without virtual base classes. */ + +#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base) + /* These are the size and alignment of the type without its virtual base classes, for when we use this type as a base itself. */ -#define CLASSTYPE_SIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size) -#define CLASSTYPE_SIZE_UNIT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size_unit) -#define CLASSTYPE_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->align) -#define CLASSTYPE_USER_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->user_align) +#define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE)) +#define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE)) +#define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE)) +#define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE)) /* The alignment of NODE, without its virtual bases, in bytes. */ #define CLASSTYPE_ALIGN_UNIT(NODE) \ @@ -1954,6 +1958,11 @@ struct lang_decl GTY(()) should be allocated. */ #define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE)) +/* Nonzero for a VAR_DECL means that the variable's initialization has + been processed. */ +#define DECL_INITIALIZED_P(NODE) \ + (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE))) + /* Nonzero if the DECL was initialized in the class definition itself, rather than outside the class. */ #define DECL_INITIALIZED_IN_CLASS_P(DECL) \ @@ -3850,7 +3859,6 @@ extern void check_handlers PARAMS ((tree)); extern void choose_personality_routine PARAMS ((enum languages)); /* in expr.c */ -extern int extract_init PARAMS ((tree, tree)); extern rtx cxx_expand_expr PARAMS ((tree, rtx, enum machine_mode, int)); @@ -3870,7 +3878,7 @@ extern tree build_init PARAMS ((tree, tree, int)); extern int is_aggr_type PARAMS ((tree, int)); extern tree get_aggr_from_typedef PARAMS ((tree, int)); extern tree get_type_value PARAMS ((tree)); -extern tree build_forced_zero_init PARAMS ((tree)); +extern tree build_zero_init (tree, bool); extern tree build_member_call PARAMS ((tree, tree, tree)); extern tree build_offset_ref PARAMS ((tree, tree)); extern tree resolve_offset_ref PARAMS ((tree)); @@ -4344,7 +4352,6 @@ extern tree binfo_or_else PARAMS ((tree, tree)); extern void readonly_error PARAMS ((tree, const char *, int)); extern int abstract_virtuals_error PARAMS ((tree, tree)); -extern tree force_store_init_value PARAMS ((tree, tree)); extern tree store_init_value PARAMS ((tree, tree)); extern tree digest_init PARAMS ((tree, tree, tree *)); extern tree build_scoped_ref PARAMS ((tree, tree, tree *)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 980a38a4e3ba..fb6c776e65fe 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -67,7 +67,6 @@ static int ambi_op_p PARAMS ((enum tree_code)); static int unary_op_p PARAMS ((enum tree_code)); static tree store_bindings PARAMS ((tree, tree)); static tree lookup_tag_reverse PARAMS ((tree, tree)); -static tree obscure_complex_init PARAMS ((tree, tree)); static tree lookup_name_real PARAMS ((tree, int, int, int)); static void push_local_name PARAMS ((tree)); static void warn_extern_redeclared_static PARAMS ((tree, tree)); @@ -3460,7 +3459,11 @@ duplicate_decls (newdecl, olddecl) newtype = oldtype; if (TREE_CODE (newdecl) == VAR_DECL) - DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); + { + DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); + DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl); + } + /* Do this after calling `merge_types' so that default parameters don't confuse us. */ else if (TREE_CODE (newdecl) == FUNCTION_DECL @@ -7548,45 +7551,6 @@ grok_reference_init (decl, type, init) return NULL_TREE; } -/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from - mucking with forces it does not comprehend (i.e. initialization with a - constructor). If we are at global scope and won't go into COMMON, fill - it in with a dummy CONSTRUCTOR to force the variable into .data; - otherwise we can use error_mark_node. */ - -static tree -obscure_complex_init (decl, init) - tree decl, init; -{ - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) - { - error ("run-time initialization of thread-local storage"); - return NULL_TREE; - } - - if (! flag_no_inline && TREE_STATIC (decl)) - { - if (extract_init (decl, init)) - return NULL_TREE; - } - -#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) - if (toplevel_bindings_p () && ! DECL_COMMON (decl)) - DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, - NULL_TREE); - else -#endif - { - if (zero_init_p (TREE_TYPE (decl))) - DECL_INITIAL (decl) = error_mark_node; - /* Otherwise, force_store_init_value will have already stored a - zero-init initializer in DECL_INITIAL, that should be - retained. */ - } - - return init; -} - /* When parsing `int a[] = {1, 2};' we don't know the size of the array until we finish parsing the initializer. If that's the situation we're in, update DECL accordingly. */ @@ -7773,17 +7737,18 @@ check_initializer (decl, init) tree decl; tree init; { - tree type; - - if (TREE_CODE (decl) == FIELD_DECL) - return init; - - type = TREE_TYPE (decl); + tree type = TREE_TYPE (decl); /* If `start_decl' didn't like having an initialization, ignore it now. */ if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE) init = NULL_TREE; + /* If an initializer is present, DECL_INITIAL has been + error_mark_node, to indicate that an as-of-yet unevaluated + initialization will occur. From now on, DECL_INITIAL reflects + the static initialization -- if any -- of DECL. */ + DECL_INITIAL (decl) = NULL_TREE; + /* Check the initializer. */ if (init) { @@ -7823,21 +7788,9 @@ check_initializer (decl, init) init = NULL_TREE; } else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE) - { - init = grok_reference_init (decl, type, init); - if (init) - init = obscure_complex_init (decl, init); - } - else if (!DECL_EXTERNAL (decl) && !zero_init_p (type)) - { - force_store_init_value (decl, build_forced_zero_init (type)); - - if (init) - goto process_init; - } + init = grok_reference_init (decl, type, init); else if (init) { - process_init: if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) { if (TREE_CODE (type) == ARRAY_TYPE) @@ -7861,11 +7814,6 @@ check_initializer (decl, init) if (TREE_CODE (init) != TREE_VEC) init = store_init_value (decl, init); } - - if (init) - /* We must hide the initializer so that expand_decl - won't try to do something it does not understand. */ - init = obscure_complex_init (decl, init); } else if (DECL_EXTERNAL (decl)) ; @@ -7884,10 +7832,6 @@ check_initializer (decl, init) } check_for_uninitialized_const_var (decl); - - if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type)) - init = obscure_complex_init (decl, NULL_TREE); - } else check_for_uninitialized_const_var (decl); @@ -8255,10 +8199,54 @@ cp_finish_decl (decl, init, asmspec_tree, flags) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec)); make_decl_rtl (decl, asmspec); } - - /* Deduce size of array from initialization, if not already known. */ - init = check_initializer (decl, init); - maybe_deduce_size_from_array_init (decl, init); + else if (TREE_CODE (decl) == RESULT_DECL) + init = check_initializer (decl, init); + else if (TREE_CODE (decl) == VAR_DECL) + { + /* Only PODs can have thread-local storage. Other types may require + various kinds of non-trivial initialization. */ + if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl))) + error ("`%D' cannot be thread-local because it has non-POD type `%T'", + decl, TREE_TYPE (decl)); + /* Convert the initializer to the type of DECL, if we have not + already initialized DECL. */ + if (!DECL_INITIALIZED_P (decl) + /* If !DECL_EXTERNAL then DECL is being defined. In the + case of a static data memberm initialized inside the + class-specifier, there can be an initializer even if DECL + is *not* defined. */ + && (!DECL_EXTERNAL (decl) || init)) + { + init = check_initializer (decl, init); + /* If DECL has an array type without a specific bound, deduce the + array size from the initializer. Note that this must be done + after check_initializer is called because of cases like this: + + struct S { int a; int b; }; + struct S a[] = { 1, 2 }; + + which creates a one-element array, not a two-element array. */ + maybe_deduce_size_from_array_init (decl, init); + /* Handle: + + [dcl.init] + + The memory occupied by any object of static storage + duration is zero-initialized at program startup before + any other initialization takes place. + + We cannot create an appropriate initializer until after + the type of DECL is finalized. If DECL_INITIAL is set, + then the DECL is statically initialized, and any + necessary zero-initialization has already been performed. */ + if (TREE_STATIC (decl) && !DECL_INITIAL (decl)) + DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl), + /*static_storage_p=*/true); + /* Remember that the initialization for this variable has + taken place. */ + DECL_INITIALIZED_P (decl) = 1; + } + } /* Add this declaration to the statement-tree. This needs to happen after the call to check_initializer so that the DECL_STMT for a diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 3cc6551ee52f..e5b0439c93d2 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -127,11 +127,3 @@ cxx_expand_expr (exp, target, tmode, modifier) /* NOTREACHED */ return NULL; } - -int -extract_init (decl, init) - tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED; -{ - return 0; -} - diff --git a/gcc/cp/init.c b/gcc/cp/init.c index c2110d1c8006..ec74a2566391 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -156,70 +156,151 @@ initialize_vtbl_ptrs (addr) dfs_marked_real_bases_queue_p, type); } -/* Types containing pointers to data members cannot be - zero-initialized with zeros, because the NULL value for such - pointers is -1. - - TYPE is a type that requires such zero initialization. The - returned value is the initializer. */ +/* Return an expression for the zero-initialization of an object with + type T. This expression will either be a constant (in the case + that T is a scalar), or a CONSTRUCTOR (in the case that T is an + aggregate). In either case, the value can be used as DECL_INITIAL + for a decl of the indicated TYPE; it is a valid static initializer. + If STATIC_STORAGE_P is TRUE, initializers are only generated for + entities for which zero-initialization does not simply mean filling + the storage with zero bytes. */ tree -build_forced_zero_init (type) - tree type; +build_zero_init (tree type, bool static_storage_p) { - tree init = NULL; + tree init = NULL_TREE; + + /* [dcl.init] + + To zero-initialization storage for an object of type T means: + + -- if T is a scalar type, the storage is set to the value of zero + converted to T. + + -- if T is a non-union class type, the storage for each nonstatic + data member and each base-class subobject is zero-initialized. + + -- if T is a union type, the storage for its first data member is + zero-initialized. + + -- if T is an array type, the storage for each element is + zero-initialized. + + -- if T is a reference type, no initialization is performed. */ - if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type)) + if (type == error_mark_node) + ; + else if (static_storage_p && zero_init_p (type)) + /* In order to save space, we do not explicitly build initializers + for items that do not need them. GCC's semantics are that + items with static storage duration that are not otherwise + initialized are initialized to zero. */ + ; + else if (SCALAR_TYPE_P (type)) + init = convert (type, integer_zero_node); + else if (CLASS_TYPE_P (type)) + { + tree field; + tree inits; + + /* Build a constructor to contain the initializations. */ + init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + /* Iterate over the fields, building initializations. */ + inits = NULL_TREE; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + + /* Note that for class types there will be FIELD_DECLs + corresponding to base classes as well. Thus, iterating + over TYPE_FIELDs will result in correct initialization of + all of the subobjects. */ + if (static_storage_p && !zero_init_p (TREE_TYPE (field))) + inits = tree_cons (field, + build_zero_init (TREE_TYPE (field), + static_storage_p), + inits); + + /* For unions, only the first field is initialized. */ + if (TREE_CODE (type) == UNION_TYPE) + break; + } + CONSTRUCTOR_ELTS (init) = nreverse (inits); + } + else if (TREE_CODE (type) == ARRAY_TYPE) { - /* This is a default initialization of an aggregate, but not one of - non-POD class type. We cleverly notice that the initialization - rules in such a case are the same as for initialization with an - empty brace-initialization list. */ - init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); + tree index; + tree max_index; + tree inits; + + /* Build a constructor to contain the initializations. */ + init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + /* Iterate over the array elements, building initializations. */ + inits = NULL_TREE; + for (index = size_zero_node, max_index = array_type_nelts (type); + !tree_int_cst_lt (max_index, index); + index = size_binop (PLUS_EXPR, index, size_one_node)) + inits = tree_cons (index, + build_zero_init (TREE_TYPE (type), + static_storage_p), + inits); + CONSTRUCTOR_ELTS (init) = nreverse (inits); } else if (TREE_CODE (type) == REFERENCE_TYPE) - /* --if T is a reference type, no initialization is performed. */ - return NULL_TREE; + ; else - { - init = integer_zero_node; - - if (TREE_CODE (type) == ENUMERAL_TYPE) - /* We must make enumeral types the right type. */ - init = fold (build1 (NOP_EXPR, type, init)); - } + abort (); - init = digest_init (type, init, 0); + /* In all cases, the initializer is a constant. */ + if (init) + TREE_CONSTANT (init) = 1; return init; } -/* [dcl.init]: +/* Build an expression for the default-initialization of an object + with type T. If initialization T requires calling constructors, + this function returns NULL_TREE; the caller is responsible for + arranging for the constructors to be called. */ - To default-initialize an object of type T means: +static tree +build_default_init (type) + tree type; +{ + /* [dcl.init]: - --if T is a non-POD class type (clause _class_), the default construc- - tor for T is called (and the initialization is ill-formed if T has - no accessible default constructor); + To default-initialize an object of type T means: - --if T is an array type, each element is default-initialized; + --if T is a non-POD class type (clause _class_), the default construc- + tor for T is called (and the initialization is ill-formed if T has + no accessible default constructor); - --otherwise, the storage for the object is zero-initialized. + --if T is an array type, each element is default-initialized; - A program that calls for default-initialization of an entity of refer- - ence type is ill-formed. */ + --otherwise, the storage for the object is zero-initialized. -static tree -build_default_init (type) - tree type; -{ + A program that calls for default-initialization of an entity of refer- + ence type is ill-formed. */ + + /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for + performing the initialization. This is confusing in that some + non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example, + a class with a pointer-to-data member as a non-static data member + does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up + passing non-PODs to build_zero_init below, which is contrary to + the semantics quoted above from [dcl.init]. + + It happens, however, that the behavior of the constructor the + standard says we should have generated would be precisely the + same as that obtained by calling build_zero_init below, so things + work out OK. */ if (TYPE_NEEDS_CONSTRUCTING (type)) - /* Other code will handle running the default constructor. We can't do - anything with a CONSTRUCTOR for arrays here, as that would imply - copy-initialization. */ return NULL_TREE; - - return build_forced_zero_init (type); + + /* At this point, TYPE is either a POD class type, an array of POD + classes, or something even more inoccuous. */ + return build_zero_init (type, /*static_storage_p=*/false); } /* Subroutine of emit_base_init. */ @@ -335,7 +416,7 @@ build_field_list (t, list, uses_unions_p) for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields)) { /* Skip CONST_DECLs for enumeration constants and so forth. */ - if (TREE_CODE (fields) != FIELD_DECL) + if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) continue; /* Keep track of whether or not any fields are unions. */ @@ -3337,7 +3418,7 @@ push_base_cleanups () for (member = TYPE_FIELDS (current_class_type); member; member = TREE_CHAIN (member)) { - if (TREE_CODE (member) != FIELD_DECL) + if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member)) continue; if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member))) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 0689a7d44074..6b4b79524fbc 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -668,7 +668,7 @@ do_build_assign_ref (fndecl) tree comp, init, t; tree field = fields; - if (TREE_CODE (field) != FIELD_DECL) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; if (CP_TYPE_CONST_P (TREE_TYPE (field))) @@ -824,7 +824,7 @@ synthesize_exception_spec (type, extractor, client) tree type = TREE_TYPE (fields); tree fn; - if (TREE_CODE (fields) != FIELD_DECL) + if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) continue; while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 53787d6d6c20..47421a0b09d6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6141,7 +6141,10 @@ tsubst_decl (t, args, type, complain) /* Even if the original location is out of scope, the newly substituted one is not. */ if (TREE_CODE (r) == VAR_DECL) - DECL_DEAD_FOR_LOCAL (r) = 0; + { + DECL_DEAD_FOR_LOCAL (r) = 0; + DECL_INITIALIZED_P (r) = 0; + } if (!local_p) { @@ -9860,9 +9863,10 @@ regenerate_decl_from_template (decl, tmpl) if (TREE_CODE (decl) == VAR_DECL) { /* Set up DECL_INITIAL, since tsubst doesn't. */ - DECL_INITIAL (new_decl) = - tsubst_expr (DECL_INITIAL (code_pattern), args, - tf_error, DECL_TI_TEMPLATE (decl)); + if (!DECL_INITIALIZED_IN_CLASS_P (decl)) + DECL_INITIAL (new_decl) = + tsubst_expr (DECL_INITIAL (code_pattern), args, + tf_error, DECL_TI_TEMPLATE (decl)); } else if (TREE_CODE (decl) == FUNCTION_DECL) { @@ -10142,7 +10146,10 @@ instantiate_decl (d, defer_ok) DECL_EXTERNAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; } - cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0); + cp_finish_decl (d, + (!DECL_INITIALIZED_IN_CLASS_P (d) + ? DECL_INITIAL (d) : NULL_TREE), + NULL_TREE, 0); } else if (TREE_CODE (d) == FUNCTION_DECL) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index ae3b1023dad9..3b06a0a0cced 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2536,7 +2536,8 @@ dfs_push_decls (binfo, data) for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) if (DECL_NAME (fields) && TREE_CODE (fields) != TYPE_DECL - && TREE_CODE (fields) != USING_DECL) + && TREE_CODE (fields) != USING_DECL + && !DECL_ARTIFICIAL (fields)) setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0); else if (TREE_CODE (fields) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (fields))) @@ -2597,7 +2598,7 @@ dfs_unuse_fields (binfo, data) for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) { - if (TREE_CODE (fields) != FIELD_DECL) + if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) continue; TREE_USED (fields) = 0; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index ea2e0e1ede06..588b7108095e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1937,6 +1937,8 @@ pod_type_p (t) { t = strip_array_types (t); + if (t == error_mark_node) + return 1; if (INTEGRAL_TYPE_P (t)) return 1; /* integral, character or enumeral type */ if (FLOAT_TYPE_P (t)) @@ -1964,6 +1966,9 @@ zero_init_p (t) { t = strip_array_types (t); + if (t == error_mark_node) + return 1; + /* NULL pointers to data members are initialized with -1. */ if (TYPE_PTRMEM_P (t)) return 0; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d32d81cceb86..ae78dbfee4e0 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1811,7 +1811,7 @@ lookup_anon_field (t, type) { if (TREE_STATIC (field)) continue; - if (TREE_CODE (field) != FIELD_DECL) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; /* If we find it directly, return the field. */ diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index fb55c8b55658..fa7f705019d6 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -320,12 +320,6 @@ store_init_value (decl, init) if (TREE_CODE (type) == ERROR_MARK) return NULL_TREE; -#if 0 - /* This breaks arrays, and should not have any effect for other decls. */ - /* Take care of C++ business up here. */ - type = TYPE_MAIN_VARIANT (type); -#endif - if (IS_AGGR_TYPE (type)) { if (! TYPE_HAS_TRIVIAL_INIT_REF (type) @@ -337,35 +331,6 @@ store_init_value (decl, init) error ("constructor syntax used, but no constructor declared for type `%T'", type); init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init)); } -#if 0 - if (TREE_CODE (init) == CONSTRUCTOR) - { - tree field; - - /* Check that we're really an aggregate as ARM 8.4.1 defines it. */ - if (CLASSTYPE_N_BASECLASSES (type)) - cp_error_at ("initializer list construction invalid for derived class object `%D'", decl); - if (CLASSTYPE_VTBL_PTR (type)) - cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl); - if (TYPE_NEEDS_CONSTRUCTING (type)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - error ("due to the presence of a constructor"); - } - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - cp_error_at ("due to non-public access of member `%D'", field); - } - for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field)) - if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - cp_error_at ("due to non-public access of member `%D'", field); - } - } -#endif } else if (TREE_CODE (init) == TREE_LIST && TREE_TYPE (init) != unknown_type_node) @@ -457,27 +422,6 @@ store_init_value (decl, init) return NULL_TREE; } -/* Same as store_init_value, but used for known-to-be-valid static - initializers. Used to introduce a static initializer even in data - structures that may require dynamic initialization. */ - -tree -force_store_init_value (decl, init) - tree decl, init; -{ - tree type = TREE_TYPE (decl); - int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type); - - TYPE_NEEDS_CONSTRUCTING (type) = 0; - - init = store_init_value (decl, init); - if (init) - abort (); - - TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing; - - return init; -} /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. @@ -791,7 +735,8 @@ process_init_constructor (type, init, elts) next1 = digest_init (TREE_TYPE (type), next1, 0); } else if (! zero_init_p (TREE_TYPE (type))) - next1 = build_forced_zero_init (TREE_TYPE (type)); + next1 = build_zero_init (TREE_TYPE (type), + /*static_storage_p=*/false); else /* The default zero-initialization is fine for us; don't add anything to the CONSTRUCTOR. */ @@ -840,7 +785,7 @@ process_init_constructor (type, init, elts) continue; } - if (TREE_CODE (field) != FIELD_DECL) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; if (tail) @@ -909,7 +854,8 @@ process_init_constructor (type, init, elts) warning ("missing initializer for member `%D'", field); if (! zero_init_p (TREE_TYPE (field))) - next1 = build_forced_zero_init (TREE_TYPE (field)); + next1 = build_zero_init (TREE_TYPE (field), + /*static_storage_p=*/false); else /* The default zero-initialization is fine for us; don't add anything to the CONSTRUCTOR. */ @@ -933,8 +879,7 @@ process_init_constructor (type, init, elts) /* Find the first named field. ANSI decided in September 1990 that only named fields count here. */ - while (field && (DECL_NAME (field) == 0 - || TREE_CODE (field) != FIELD_DECL)) + while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL)) field = TREE_CHAIN (field); /* If this element specifies a field, initialize via that field. */ diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index e468a2b8ebec..953d58f75ca8 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1484,11 +1484,14 @@ finalize_type_size (type) /* Do all of the work required to layout the type indicated by RLI, once the fields have been laid out. This function will call `free' - for RLI. */ + for RLI, unless FREE_P is false. Passing a value other than false + for FREE_P is bad practice; this option only exists to support the + G++ 3.2 ABI. */ void -finish_record_layout (rli) +finish_record_layout (rli, free_p) record_layout_info rli; + int free_p; { /* Compute the final size. */ finalize_record_size (rli); @@ -1508,7 +1511,8 @@ finish_record_layout (rli) } /* Clean up. */ - free (rli); + if (free_p) + free (rli); } /* Calculate the mode, size, and alignment for TYPE. @@ -1763,7 +1767,7 @@ layout_type (type) (*lang_adjust_rli) (rli); /* Finish laying out the record. */ - finish_record_layout (rli); + finish_record_layout (rli, /*free_p=*/true); } break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cc3219be00fe..d444eea27d56 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-09-30 Mark Mitchell + + * g++.dg/abi/empty7.C: New test. + * g++.dg/init/pm2.C: Likewise. + 2002-09-29 Nathan Sidwell * g++.dg/rtti/crash1.C: New test. diff --git a/gcc/testsuite/g++.dg/abi/empty7.C b/gcc/testsuite/g++.dg/abi/empty7.C new file mode 100644 index 000000000000..4b1ac3b2c2cf --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/empty7.C @@ -0,0 +1,18 @@ +// { dg-do run { target i?86-*-* } } +// { dg-options "-fabi-version=0" } + +struct S1 {}; +struct S2 { virtual void f () {} S1 s1[4]; }; +struct S3 : virtual public S2 {}; +struct S4 : virtual public S2 { int i; }; +struct S5 : public S3, virtual public S4 {}; +struct S6 { S5 s5; }; +struct S7 { S1 s1[5]; }; +struct S8 : public S1, public S6, virtual public S7 { }; + +S8 s8; + +int main () { + if ((char *)(S7 *)&s8 - (char *)&s8 != 24) + return 1; +} diff --git a/gcc/testsuite/g++.dg/init/pm2.C b/gcc/testsuite/g++.dg/init/pm2.C new file mode 100644 index 000000000000..35b9b32fea13 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/pm2.C @@ -0,0 +1,7 @@ +struct S { + S (); + int S::* sp; + int i; +}; + +S s[2] = {}; diff --git a/gcc/tree.h b/gcc/tree.h index 1c16c83dbe4f..1d0941c323ba 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2434,7 +2434,7 @@ extern tree rli_size_so_far PARAMS ((record_layout_info)); extern void normalize_rli PARAMS ((record_layout_info)); extern void place_field PARAMS ((record_layout_info, tree)); extern void compute_record_mode PARAMS ((tree)); -extern void finish_record_layout PARAMS ((record_layout_info)); +extern void finish_record_layout PARAMS ((record_layout_info, int)); /* Given a hashcode and a ..._TYPE node (for which the hashcode was made), return a canonicalized ..._TYPE node, so that duplicates are not made.