diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 47 | ||||
-rw-r--r-- | gcc/cp/class.c | 177 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 391 | ||||
-rw-r--r-- | gcc/cp/decl.c | 41 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 1 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/lex.c | 30 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 65 | ||||
-rw-r--r-- | gcc/cp/method.c | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 27 | ||||
-rw-r--r-- | gcc/cp/ptree.c | 18 | ||||
-rw-r--r-- | gcc/cp/search.c | 8 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 |
13 files changed, 430 insertions, 380 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 17ac919..257dca4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,50 @@ +2009-07-03 Jason Merrill <jason@redhat.com> + + * cp-tree.h (struct lang_decl): Overhaul. + (struct lang_decl_flags): Remove. + (struct lang_decl_base): New. + (struct lang_decl_min): New. + (struct lang_decl_fn): New. + (struct lang_decl_ns): New. + (CAN_HAVE_FULL_LANG_DECL_P): Replace with LANG_DECL_HAS_MIN. + (LANG_DECL_MIN_CHECK): New. + (LANG_DECL_FN_CHECK): New. + (LANG_DECL_NS_CHECK): New. + (STRIP_TEMPLATE): New. + (NON_THUNK_FUNCTION_CHECK): Remove. + (DECL_DECLARES_FUNCTION_P): New. + (lots): Adjust. + * lex.c (retrofit_lang_decl, cxx_dup_lang_specific_decl): Adjust. + * decl.c (push_local_name, duplicate_decls): Adjust. + * decl2.c (start_objects): Don't set u2sel. + * semantics.c (finish_omp_threadprivate): Adjust. + * class.c (build_clone): Don't do much on TEMPLATE_DECLs. + (decl_cloned_function_p): Out-of-line implementation of macros. + (clone_function_decl, adjust_clone_args): Use DECL_CLONED_FUNCTION_P. + * mangle.c (write_unqualified_name): Don't check function flags + on non-functions. + * method.c (make_alias_for): Don't set DECL_CLONED_FUNCTION. + * pt.c (build_template_decl): Don't set function flags. + (check_default_tmpl_args): Check that it's a function. + (instantiate_template): Use DECL_ABSTRACT_ORIGIN to find the + cloned template. + + * pt.c (tsubst_decl) [FUNCTION_DECL]: Don't tsubst + DECL_CLONED_FUNCTION. + + * cp-tree.h (struct lang_type_class): Move sorted_fields here. + * class.c (finish_struct_1): Adjust. + * ptree.c (cxx_print_decl, cxx_print_type): Adjust. + * search.c (lookup_field_1): Adjust. + + * cp-tree.h (CLASSTYPE_INLINE_FRIENDS): Remove. + * decl.c (finish_method): Don't add to it. + * class.c (fixup_pending_inline): Remove. + (fixup_inline_methods): Remove. + (finish_struct_1): Don't call it. + + * error.c (dump_function_name): Handle null name. + 2009-07-02 Mark Mitchell <mark@codesourcery.com> * typeck.c (cp_build_binary_op): Move warnings about use of NULL diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 12192e6..4668c68 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -151,8 +151,6 @@ static void check_bases_and_members (tree); static tree create_vtable_ptr (tree, tree *); static void include_empty_classes (record_layout_info); static void layout_class_type (tree, tree *); -static void fixup_pending_inline (tree); -static void fixup_inline_methods (tree); static void propagate_binfo_offsets (tree, tree); static void layout_virtual_bases (record_layout_info, splay_tree); static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *); @@ -3799,12 +3797,27 @@ build_clone (tree fn, tree name) /* Copy the function. */ clone = copy_decl (fn); - /* Remember where this function came from. */ - DECL_CLONED_FUNCTION (clone) = fn; - DECL_ABSTRACT_ORIGIN (clone) = fn; /* Reset the function name. */ DECL_NAME (clone) = name; SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE); + /* Remember where this function came from. */ + DECL_ABSTRACT_ORIGIN (clone) = fn; + /* Make it easy to find the CLONE given the FN. */ + TREE_CHAIN (clone) = TREE_CHAIN (fn); + TREE_CHAIN (fn) = clone; + + /* If this is a template, do the rest on the DECL_TEMPLATE_RESULT. */ + if (TREE_CODE (clone) == TEMPLATE_DECL) + { + tree result = build_clone (DECL_TEMPLATE_RESULT (clone), name); + DECL_TEMPLATE_RESULT (clone) = result; + DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result)); + DECL_TI_TEMPLATE (result) = clone; + TREE_TYPE (clone) = TREE_TYPE (result); + return clone; + } + + DECL_CLONED_FUNCTION (clone) = fn; /* There's no pending inline data for this function. */ DECL_PENDING_INLINE_INFO (clone) = NULL; DECL_PENDING_INLINE_P (clone) = 0; @@ -3852,61 +3865,79 @@ build_clone (tree fn, tree name) TYPE_ATTRIBUTES (TREE_TYPE (fn))); } - /* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL - aren't function parameters; those are the template parameters. */ - if (TREE_CODE (clone) != TEMPLATE_DECL) + /* Copy the function parameters. */ + DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone)); + /* Remove the in-charge parameter. */ + if (DECL_HAS_IN_CHARGE_PARM_P (clone)) + { + TREE_CHAIN (DECL_ARGUMENTS (clone)) + = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone))); + DECL_HAS_IN_CHARGE_PARM_P (clone) = 0; + } + /* And the VTT parm, in a complete [cd]tor. */ + if (DECL_HAS_VTT_PARM_P (fn)) { - DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone)); - /* Remove the in-charge parameter. */ - if (DECL_HAS_IN_CHARGE_PARM_P (clone)) + if (DECL_NEEDS_VTT_PARM_P (clone)) + DECL_HAS_VTT_PARM_P (clone) = 1; + else { TREE_CHAIN (DECL_ARGUMENTS (clone)) = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone))); - DECL_HAS_IN_CHARGE_PARM_P (clone) = 0; - } - /* And the VTT parm, in a complete [cd]tor. */ - if (DECL_HAS_VTT_PARM_P (fn)) - { - if (DECL_NEEDS_VTT_PARM_P (clone)) - DECL_HAS_VTT_PARM_P (clone) = 1; - else - { - TREE_CHAIN (DECL_ARGUMENTS (clone)) - = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone))); - DECL_HAS_VTT_PARM_P (clone) = 0; - } + DECL_HAS_VTT_PARM_P (clone) = 0; } + } - for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms)) - { - DECL_CONTEXT (parms) = clone; - cxx_dup_lang_specific_decl (parms); - } + for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms)) + { + DECL_CONTEXT (parms) = clone; + cxx_dup_lang_specific_decl (parms); } /* Create the RTL for this function. */ SET_DECL_RTL (clone, NULL_RTX); rest_of_decl_compilation (clone, /*top_level=*/1, at_eof); - /* Make it easy to find the CLONE given the FN. */ - TREE_CHAIN (clone) = TREE_CHAIN (fn); - TREE_CHAIN (fn) = clone; + if (pch_file) + note_decl_for_pch (clone); - /* If this is a template, handle the DECL_TEMPLATE_RESULT as well. */ - if (TREE_CODE (clone) == TEMPLATE_DECL) - { - tree result; + return clone; +} - DECL_TEMPLATE_RESULT (clone) - = build_clone (DECL_TEMPLATE_RESULT (clone), name); - result = DECL_TEMPLATE_RESULT (clone); - DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result)); - DECL_TI_TEMPLATE (result) = clone; +/* Implementation of DECL_CLONED_FUNCTION and DECL_CLONED_FUNCTION_P, do + not invoke this function directly. + + For a non-thunk function, returns the address of the slot for storing + the function it is a clone of. Otherwise returns NULL_TREE. + + If JUST_TESTING, looks through TEMPLATE_DECL and returns NULL if + cloned_function is unset. This is to support the separate + DECL_CLONED_FUNCTION and DECL_CLONED_FUNCTION_P modes; using the latter + on a template makes sense, but not the former. */ + +tree * +decl_cloned_function_p (const_tree decl, bool just_testing) +{ + tree *ptr; + if (just_testing) + decl = STRIP_TEMPLATE (decl); + + if (TREE_CODE (decl) != FUNCTION_DECL + || !DECL_LANG_SPECIFIC (decl) + || DECL_LANG_SPECIFIC (decl)->u.fn.thunk_p) + { +#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) + if (!just_testing) + lang_check_failed (__FILE__, __LINE__, __FUNCTION__); + else +#endif + return NULL; } - else if (pch_file) - note_decl_for_pch (clone); - return clone; + ptr = &DECL_LANG_SPECIFIC (decl)->u.fn.u5.cloned_function; + if (just_testing && *ptr == NULL_TREE) + return NULL; + else + return ptr; } /* Produce declarations for all appropriate clones of FN. If @@ -3920,7 +3951,7 @@ clone_function_decl (tree fn, int update_method_vec_p) /* Avoid inappropriate cloning. */ if (TREE_CHAIN (fn) - && DECL_CLONED_FUNCTION (TREE_CHAIN (fn))) + && DECL_CLONED_FUNCTION_P (TREE_CHAIN (fn))) return; if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)) @@ -3977,7 +4008,7 @@ adjust_clone_args (tree decl) { tree clone; - for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION (clone); + for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION_P (clone); clone = TREE_CHAIN (clone)) { tree orig_clone_parms = TYPE_ARG_TYPES (TREE_TYPE (clone)); @@ -4447,54 +4478,6 @@ create_vtable_ptr (tree t, tree* virtuals_p) return NULL_TREE; } -/* Fixup the inline function given by INFO now that the class is - complete. */ - -static void -fixup_pending_inline (tree fn) -{ - if (DECL_PENDING_INLINE_INFO (fn)) - { - tree args = DECL_ARGUMENTS (fn); - while (args) - { - DECL_CONTEXT (args) = fn; - args = TREE_CHAIN (args); - } - } -} - -/* Fixup the inline methods and friends in TYPE now that TYPE is - complete. */ - -static void -fixup_inline_methods (tree type) -{ - tree method = TYPE_METHODS (type); - VEC(tree,gc) *friends; - unsigned ix; - - if (method && TREE_CODE (method) == TREE_VEC) - { - if (TREE_VEC_ELT (method, 1)) - method = TREE_VEC_ELT (method, 1); - else if (TREE_VEC_ELT (method, 0)) - method = TREE_VEC_ELT (method, 0); - else - method = TREE_VEC_ELT (method, 2); - } - - /* Do inline member functions. */ - for (; method; method = TREE_CHAIN (method)) - fixup_pending_inline (method); - - /* Do friends. */ - for (friends = CLASSTYPE_INLINE_FRIENDS (type), ix = 0; - VEC_iterate (tree, friends, ix, method); ix++) - fixup_pending_inline (method); - CLASSTYPE_INLINE_FRIENDS (type) = NULL; -} - /* Add OFFSET to all base types of BINFO which is a base in the hierarchy dominated by T. @@ -5219,8 +5202,6 @@ finish_struct_1 (tree t) TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE; - fixup_inline_methods (t); - /* Make assumptions about the class; we'll reset the flags if necessary. */ CLASSTYPE_EMPTY_P (t) = 1; @@ -5332,9 +5313,7 @@ finish_struct_1 (tree t) add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0); qsort (field_vec->elts, n_fields, sizeof (tree), field_decl_cmp); - if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t))) - retrofit_lang_decl (TYPE_MAIN_DECL (t)); - DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec; + CLASSTYPE_SORTED_FIELDS (t) = field_vec; } /* Complain if one of the field types requires lower visibility. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 03dad66..50ed2ea 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -199,21 +199,13 @@ framework extensions, you must include this file before toplev.h, not after. TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM) #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) -#define NON_THUNK_FUNCTION_CHECK(NODE) __extension__ \ -({ __typeof(NODE) const __t = (NODE); \ - if (TREE_CODE (__t) != FUNCTION_DECL && \ - TREE_CODE (__t) != TEMPLATE_DECL && __t->decl_common.lang_specific \ - && __t->decl_common.lang_specific->decl_flags.thunk_p) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \ - __t; }) #define THUNK_FUNCTION_CHECK(NODE) __extension__ \ ({ __typeof (NODE) const __t = (NODE); \ - if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl_common.lang_specific \ - || !__t->decl_common.lang_specific->decl_flags.thunk_p) \ + if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl_common.lang_specific \ + || !__t->decl_common.lang_specific->u.fn.thunk_p) \ tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \ __t; }) #else -#define NON_THUNK_FUNCTION_CHECK(NODE) (NODE) #define THUNK_FUNCTION_CHECK(NODE) (NODE) #endif @@ -1160,6 +1152,10 @@ struct GTY(()) lang_type_class { as a list of adopted protocols or a pointer to a corresponding @interface. See objc/objc-act.h for details. */ tree objc_info; + /* sorted_fields is sorted based on a pointer, so we need to be able + to resort it if pointers get rearranged. */ + struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) + sorted_fields; }; struct GTY(()) lang_type_ptrmem { @@ -1197,13 +1193,6 @@ struct GTY(()) lang_type { #endif /* ENABLE_TREE_CHECKING */ -/* Fields used for storing information before the class is defined. - After the class is defined, these fields hold other information. */ - -/* VEC(tree) of friends which were defined inline in this class - definition. */ -#define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE) - /* Nonzero for _CLASSTYPE means that operator delete is defined. */ #define TYPE_GETS_DELETE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->gets_delete) #define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1) @@ -1563,142 +1552,188 @@ struct GTY(()) lang_type { /* The binding level associated with the namespace. */ #define NAMESPACE_LEVEL(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.u.level) + (LANG_DECL_NS_CHECK (NODE)->level) +/* Flags shared by all forms of DECL_LANG_SPECIFIC. -/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or - a lang_decl (which has lang_decl_flags as its initial prefix). - This macro is nonzero for tree nodes whose DECL_LANG_SPECIFIC is - the full lang_decl, and not just lang_decl_flags. Keep these - checks in ascending code order. */ -#define CAN_HAVE_FULL_LANG_DECL_P(NODE) \ - (!(TREE_CODE (NODE) == FIELD_DECL \ - || TREE_CODE (NODE) == VAR_DECL \ - || TREE_CODE (NODE) == CONST_DECL \ - || TREE_CODE (NODE) == USING_DECL)) + Some of the flags live here only to make lang_decl_min/fn smaller. Do + not make this struct larger than 32 bits; instead, make sel smaller. */ -struct GTY(()) lang_decl_flags { +struct GTY(()) lang_decl_base { + unsigned selector : 16; /* Larger than necessary for faster access. */ ENUM_BITFIELD(languages) language : 4; + unsigned use_template : 2; + unsigned not_really_extern : 1; /* var or fn */ + unsigned initialized_in_class : 1; /* var or fn */ + unsigned repo_available_p : 1; /* var or fn */ + unsigned threadprivate_or_deleted_p : 1; /* var or fn */ + unsigned anticipated_p : 1; /* fn or type */ + unsigned friend_attr : 1; /* fn or type */ + unsigned template_conv_p : 1; /* template only? */ + unsigned u2sel : 1; + /* 2 spare bits */ +}; + +/* True for DECL codes which have template info and access. */ +#define LANG_DECL_HAS_MIN(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL \ + || TREE_CODE (NODE) == FIELD_DECL \ + || TREE_CODE (NODE) == VAR_DECL \ + || TREE_CODE (NODE) == CONST_DECL \ + || TREE_CODE (NODE) == TYPE_DECL \ + || TREE_CODE (NODE) == TEMPLATE_DECL \ + || TREE_CODE (NODE) == USING_DECL) + +/* DECL_LANG_SPECIFIC for the above codes. */ + +struct GTY(()) lang_decl_min { + struct lang_decl_base base; + + /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is + THUNK_ALIAS. + In a FUNCTION_DECL for which DECL_THUNK_P does not hold, + VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this is + DECL_TEMPLATE_INFO. */ + tree template_info; + + union lang_decl_u2 { + /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is + THUNK_VIRTUAL_OFFSET. + Otherwise this is DECL_ACCESS. */ + tree GTY ((tag ("0"))) access; + + /* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */ + int GTY ((tag ("1"))) discriminator; + } GTY ((desc ("%0.u.base.u2sel"))) u2; +}; + +/* Additional DECL_LANG_SPECIFIC information for functions. */ + +struct GTY(()) lang_decl_fn { + struct lang_decl_min min; + + /* In an overloaded operator, this is the value of + DECL_OVERLOADED_OPERATOR_P. */ + ENUM_BITFIELD (tree_code) operator_code : 16; + unsigned global_ctor_p : 1; unsigned global_dtor_p : 1; - unsigned anticipated_p : 1; - unsigned template_conv_p : 1; - - unsigned operator_attr : 1; unsigned constructor_attr : 1; unsigned destructor_attr : 1; - unsigned friend_attr : 1; + unsigned assignment_operator_p : 1; unsigned static_function : 1; unsigned pure_virtual : 1; + unsigned defaulted_p : 1; + unsigned has_in_charge_parm_p : 1; unsigned has_vtt_parm_p : 1; - - unsigned deferred : 1; - unsigned use_template : 2; + unsigned pending_inline_p : 1; unsigned nonconverting : 1; - unsigned not_really_extern : 1; - unsigned initialized_in_class : 1; - unsigned assignment_operator_p : 1; - unsigned u1sel : 1; - - unsigned u2sel : 1; - unsigned can_be_full : 1; unsigned thunk_p : 1; unsigned this_thunk_p : 1; - unsigned repo_available_p : 1; unsigned hidden_friend_p : 1; - unsigned threadprivate_or_deleted_p : 1; - unsigned defaulted_p : 1; + unsigned deferred : 1; + /* No spare bits; consider adding to lang_decl_base instead. */ - union lang_decl_u { - /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is - THUNK_ALIAS. - In a FUNCTION_DECL for which DECL_THUNK_P does not hold, - VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this is - DECL_TEMPLATE_INFO. */ - tree GTY ((tag ("0"))) template_info; + /* For a non-thunk function decl, this is a tree list of + friendly classes. For a thunk function decl, it is the + thunked to function decl. */ + tree befriending_classes; - /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */ - struct cp_binding_level * GTY ((tag ("1"))) level; - } GTY ((desc ("%1.u1sel"))) u; + /* For a non-virtual FUNCTION_DECL, this is + DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which + DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both + this pointer and result pointer adjusting thunks are + chained here. This pointer thunks to return pointer thunks + will be chained on the return pointer thunk. */ + tree context; - union lang_decl_u2 { - /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is - THUNK_VIRTUAL_OFFSET. - Otherwise this is DECL_ACCESS. */ - tree GTY ((tag ("0"))) access; + union lang_decl_u5 + { + /* In a non-thunk FUNCTION_DECL or TEMPLATE_DECL, this is + DECL_CLONED_FUNCTION. */ + tree GTY ((tag ("0"))) cloned_function; - /* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */ - int GTY ((tag ("1"))) discriminator; - } GTY ((desc ("%1.u2sel"))) u2; + /* In a FUNCTION_DECL for which THUNK_P holds this is the + THUNK_FIXED_OFFSET. */ + HOST_WIDE_INT GTY ((tag ("1"))) fixed_offset; + } GTY ((desc ("%1.thunk_p"))) u5; + + union lang_decl_u3 + { + struct cp_token_cache * GTY ((tag ("1"))) pending_inline_info; + struct language_function * GTY ((tag ("0"))) + saved_language_function; + } GTY ((desc ("%1.pending_inline_p"))) u; + +}; + +/* DECL_LANG_SPECIFIC for namespaces. */ + +struct GTY(()) lang_decl_ns { + struct lang_decl_base base; + struct cp_binding_level *level; }; -/* sorted_fields is sorted based on a pointer, so we need to be able - to resort it if pointers get rearranged. */ +/* DECL_LANG_SPECIFIC for all types. It would be nice to just make this a + union rather than a struct containing a union as its only field, but + tree.h declares it as a struct. */ struct GTY(()) lang_decl { - struct lang_decl_flags decl_flags; - - union lang_decl_u4 - { - struct full_lang_decl - { - /* In an overloaded operator, this is the value of - DECL_OVERLOADED_OPERATOR_P. */ - ENUM_BITFIELD (tree_code) operator_code : 16; - - unsigned u3sel : 1; - unsigned pending_inline_p : 1; - unsigned spare : 14; - - /* For a non-thunk function decl, this is a tree list of - friendly classes. For a thunk function decl, it is the - thunked to function decl. */ - tree befriending_classes; - - /* For a non-virtual FUNCTION_DECL, this is - DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which - DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both - this pointer and result pointer adjusting thunks are - chained here. This pointer thunks to return pointer thunks - will be chained on the return pointer thunk. */ - tree context; - - union lang_decl_u5 - { - /* In a non-thunk FUNCTION_DECL or TEMPLATE_DECL, this is - DECL_CLONED_FUNCTION. */ - tree GTY ((tag ("0"))) cloned_function; - - /* In a FUNCTION_DECL for which THUNK_P holds this is the - THUNK_FIXED_OFFSET. */ - HOST_WIDE_INT GTY ((tag ("1"))) fixed_offset; - } GTY ((desc ("%0.decl_flags.thunk_p"))) u5; - - union lang_decl_u3 - { - struct sorted_fields_type * GTY ((tag ("0"), reorder ("resort_sorted_fields"))) - sorted_fields; - struct cp_token_cache * GTY ((tag ("2"))) pending_inline_info; - struct language_function * GTY ((tag ("1"))) - saved_language_function; - } GTY ((desc ("%1.u3sel + %1.pending_inline_p"))) u; - } GTY ((tag ("1"))) f; - } GTY ((desc ("%1.decl_flags.can_be_full"))) u; + union GTY((desc ("%h.base.selector"))) lang_decl_u { + struct lang_decl_base GTY ((default)) base; + struct lang_decl_min GTY((tag ("0"))) min; + struct lang_decl_fn GTY ((tag ("1"))) fn; + struct lang_decl_ns GTY((tag ("2"))) ns; + } u; }; +/* Looks through a template (if present) to find what it declares. */ +#define STRIP_TEMPLATE(NODE) \ + (TREE_CODE (NODE) == TEMPLATE_DECL ? DECL_TEMPLATE_RESULT (NODE) : NODE) + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) +#define LANG_DECL_MIN_CHECK(NODE) __extension__ \ +({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ + if (!LANG_DECL_HAS_MIN (NODE)) \ + lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ + <->u.min; }) + +/* We want to be able to check DECL_CONSTRUCTOR_P and such on a function + template, not just on a FUNCTION_DECL. So when looking for things in + lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ +#define LANG_DECL_FN_CHECK(NODE) __extension__ \ +({ struct lang_decl *lt = DECL_LANG_SPECIFIC (STRIP_TEMPLATE (NODE)); \ + if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != 1) \ + lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ + <->u.fn; }) + +#define LANG_DECL_NS_CHECK(NODE) __extension__ \ +({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ + if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != 2) \ + lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ + <->u.ns; }) + #define LANG_DECL_U2_CHECK(NODE, TF) __extension__ \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ - if (lt->decl_flags.u2sel != TF) \ + if (lt->u.base.u2sel != TF) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ - <->decl_flags.u2; }) + <->u.min.u2; }) #else +#define LANG_DECL_MIN_CHECK(NODE) \ + (&DECL_LANG_SPECIFIC (NODE)->u.min) + +#define LANG_DECL_FN_CHECK(NODE) \ + (&DECL_LANG_SPECIFIC (NODE)->u.fn) + +#define LANG_DECL_NS_CHECK(NODE) \ + (&DECL_LANG_SPECIFIC (NODE)->u.ns) + #define LANG_DECL_U2_CHECK(NODE, TF) \ - (&DECL_LANG_SPECIFIC (NODE)->decl_flags.u2) + (&DECL_LANG_SPECIFIC (NODE)->u.min.u2) #endif /* ENABLE_TREE_CHECKING */ @@ -1713,17 +1748,17 @@ struct GTY(()) lang_decl { we do create DECL_LANG_SPECIFIC for variables with non-C++ linkage. */ #define DECL_LANGUAGE(NODE) \ (DECL_LANG_SPECIFIC (NODE) \ - ? DECL_LANG_SPECIFIC (NODE)->decl_flags.language \ + ? DECL_LANG_SPECIFIC (NODE)->u.base.language \ : (TREE_CODE (NODE) == FUNCTION_DECL \ ? lang_c : lang_cplusplus)) /* Set the language linkage for NODE to LANGUAGE. */ #define SET_DECL_LANGUAGE(NODE, LANGUAGE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.language = (LANGUAGE)) + (DECL_LANG_SPECIFIC (NODE)->u.base.language = (LANGUAGE)) /* For FUNCTION_DECLs: nonzero means that this function is a constructor. */ #define DECL_CONSTRUCTOR_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.constructor_attr) + (LANG_DECL_FN_CHECK (NODE)->constructor_attr) /* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a complete object. */ @@ -1741,7 +1776,8 @@ struct GTY(()) lang_decl { specialized in-charge constructor or the specialized not-in-charge constructor. */ #define DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P(NODE) \ - (DECL_CONSTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE)) + (DECL_DECLARES_FUNCTION_P (NODE) && DECL_CONSTRUCTOR_P (NODE) \ + && !DECL_CLONED_FUNCTION_P (NODE)) /* Nonzero if NODE (a FUNCTION_DECL) is a copy constructor. */ #define DECL_COPY_CONSTRUCTOR_P(NODE) \ @@ -1753,13 +1789,14 @@ struct GTY(()) lang_decl { /* Nonzero if NODE is a destructor. */ #define DECL_DESTRUCTOR_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.destructor_attr) + (LANG_DECL_FN_CHECK (NODE)->destructor_attr) /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the specialized in-charge constructor, in-charge deleting constructor, or the base destructor. */ #define DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P(NODE) \ - (DECL_DESTRUCTOR_P (NODE) && !DECL_CLONED_FUNCTION_P (NODE)) + (DECL_DECLARES_FUNCTION_P (NODE) && DECL_DESTRUCTOR_P (NODE) \ + && !DECL_CLONED_FUNCTION_P (NODE)) /* Nonzero if NODE (a FUNCTION_DECL) is a destructor for a complete object. */ @@ -1781,17 +1818,11 @@ struct GTY(()) lang_decl { /* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or destructor. */ -#define DECL_CLONED_FUNCTION_P(NODE) \ - ((TREE_CODE (NODE) == FUNCTION_DECL \ - || TREE_CODE (NODE) == TEMPLATE_DECL) \ - && DECL_LANG_SPECIFIC (NODE) \ - && !DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p \ - && DECL_CLONED_FUNCTION (NODE) != NULL_TREE) +#define DECL_CLONED_FUNCTION_P(NODE) (!!decl_cloned_function_p (NODE, true)) /* If DECL_CLONED_FUNCTION_P holds, this is the function that was cloned. */ -#define DECL_CLONED_FUNCTION(NODE) \ - (DECL_LANG_SPECIFIC (NON_THUNK_FUNCTION_CHECK(NODE))->u.f.u5.cloned_function) +#define DECL_CLONED_FUNCTION(NODE) (*decl_cloned_function_p (NODE, false)) /* Perform an action for each clone of FN, if FN is a function with clones. This macro should be used like: @@ -1818,7 +1849,7 @@ struct GTY(()) lang_decl { /* Nonzero if the VTT parm has been added to NODE. */ #define DECL_HAS_VTT_PARM_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.has_vtt_parm_p) + (LANG_DECL_FN_CHECK (NODE)->has_vtt_parm_p) /* Nonzero if NODE is a FUNCTION_DECL for which a VTT parameter is required. */ @@ -1840,11 +1871,11 @@ struct GTY(()) lang_decl { conversion operator to a type dependent on the innermost template args. */ #define DECL_TEMPLATE_CONV_FN_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.template_conv_p) + (DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE))->u.base.template_conv_p) /* Set the overloaded operator code for NODE to CODE. */ #define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.operator_code = (CODE)) + (LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE)) /* If NODE is an overloaded operator, then this returns the TREE_CODE associated with the overloaded operator. @@ -1855,17 +1886,17 @@ struct GTY(()) lang_decl { to test whether or not NODE is an overloaded operator. */ #define DECL_OVERLOADED_OPERATOR_P(NODE) \ (IDENTIFIER_OPNAME_P (DECL_NAME (NODE)) \ - ? DECL_LANG_SPECIFIC (NODE)->u.f.operator_code : ERROR_MARK) + ? LANG_DECL_FN_CHECK (NODE)->operator_code : ERROR_MARK) /* Nonzero if NODE is an assignment operator (including += and such). */ #define DECL_ASSIGNMENT_OPERATOR_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.assignment_operator_p) + (LANG_DECL_FN_CHECK (NODE)->assignment_operator_p) /* For FUNCTION_DECLs: nonzero means that this function is a constructor or a destructor with an extra in-charge parameter to control whether or not virtual bases are constructed. */ #define DECL_HAS_IN_CHARGE_PARM_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.has_in_charge_parm_p) + (LANG_DECL_FN_CHECK (NODE)->has_in_charge_parm_p) /* Nonzero if DECL is a declaration of __builtin_constant_p. */ #define DECL_IS_BUILTIN_CONSTANT_P(NODE) \ @@ -1917,20 +1948,21 @@ struct GTY(()) lang_decl { rather than outside the class. This is used for both static member VAR_DECLS, and FUNCTION_DECLS that are defined in the class. */ #define DECL_INITIALIZED_IN_CLASS_P(DECL) \ - (DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class) + (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \ + ->u.base.initialized_in_class) /* Nonzero for DECL means that this decl is just a friend declaration, and should not be added to the list of members for this class. */ -#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.friend_attr) +#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr) /* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */ #define DECL_BEFRIENDING_CLASSES(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) + (LANG_DECL_FN_CHECK (NODE)->befriending_classes) /* Nonzero for FUNCTION_DECL means that this decl is a static member function. */ #define DECL_STATIC_FUNCTION_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.static_function) + (LANG_DECL_FN_CHECK (NODE)->static_function) /* Nonzero for FUNCTION_DECL means that this decl is a non-static member function. */ @@ -1940,7 +1972,7 @@ struct GTY(()) lang_decl { /* Nonzero for FUNCTION_DECL means that this decl is a member function (static or non-static). */ #define DECL_FUNCTION_MEMBER_P(NODE) \ - (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE)) + (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE)) /* Nonzero for FUNCTION_DECL means that this member function has `this' as const X *const. */ @@ -1968,12 +2000,12 @@ struct GTY(()) lang_decl { /* Nonzero for _DECL means that this constructor or conversion function is non-converting. */ #define DECL_NONCONVERTING_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.nonconverting) + (LANG_DECL_FN_CHECK (NODE)->nonconverting) /* Nonzero for FUNCTION_DECL means that this member function is a pure virtual function. */ #define DECL_PURE_VIRTUAL_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.pure_virtual) + (LANG_DECL_FN_CHECK (NODE)->pure_virtual) /* True (in a FUNCTION_DECL) if NODE is a virtual function that is an invalid overrider for a function from a base class. Once we have @@ -1984,27 +2016,26 @@ struct GTY(()) lang_decl { /* The thunks associated with NODE, a FUNCTION_DECL. */ #define DECL_THUNKS(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.context) + (LANG_DECL_FN_CHECK (NODE)->context) /* Nonzero if NODE is a thunk, rather than an ordinary function. */ #define DECL_THUNK_P(NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \ && DECL_LANG_SPECIFIC (NODE) \ - && DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p) + && LANG_DECL_FN_CHECK (NODE)->thunk_p) /* Set DECL_THUNK_P for node. */ #define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p = 1, \ - DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \ - DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING)) + (LANG_DECL_FN_CHECK (NODE)->thunk_p = 1, \ + LANG_DECL_FN_CHECK (NODE)->this_thunk_p = (THIS_ADJUSTING)) /* Nonzero if NODE is a this pointer adjusting thunk. */ #define DECL_THIS_THUNK_P(NODE) \ - (DECL_THUNK_P (NODE) && DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p) + (DECL_THUNK_P (NODE) && LANG_DECL_FN_CHECK (NODE)->this_thunk_p) /* Nonzero if NODE is a result pointer adjusting thunk. */ #define DECL_RESULT_THUNK_P(NODE) \ - (DECL_THUNK_P (NODE) && !DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p) + (DECL_THUNK_P (NODE) && !LANG_DECL_FN_CHECK (NODE)->this_thunk_p) /* Nonzero if NODE is a FUNCTION_DECL, but not a thunk. */ #define DECL_NON_THUNK_FUNCTION_P(NODE) \ @@ -2021,7 +2052,7 @@ struct GTY(()) lang_decl { /* True iff DECL is an entity with vague linkage whose definition is available in this translation unit. */ #define DECL_REPO_AVAILABLE_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.repo_available_p) + (DECL_LANG_SPECIFIC (NODE)->u.base.repo_available_p) /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a template function. */ @@ -2040,13 +2071,14 @@ struct GTY(()) lang_decl { the DECL_FRIEND_CONTEXT for `f' will be `S'. */ #define DECL_FRIEND_CONTEXT(NODE) \ - ((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \ - ? DECL_LANG_SPECIFIC (NODE)->u.f.context \ + ((DECL_DECLARES_FUNCTION_P (NODE) \ + && DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \ + ? LANG_DECL_FN_CHECK (NODE)->context \ : NULL_TREE) /* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT. */ #define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.context = (CONTEXT)) + (LANG_DECL_FN_CHECK (NODE)->context = (CONTEXT)) /* NULL_TREE in DECL_CONTEXT represents the global namespace. */ #define CP_DECL_CONTEXT(NODE) \ @@ -2153,21 +2185,21 @@ extern void decl_shadowed_for_var_insert (tree, tree); the class definition. We have saved away the text of the function, but have not yet processed it. */ #define DECL_PENDING_INLINE_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.pending_inline_p) + (LANG_DECL_FN_CHECK (NODE)->pending_inline_p) /* If DECL_PENDING_INLINE_P holds, this is the saved text of the function. */ #define DECL_PENDING_INLINE_INFO(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.u.pending_inline_info) + (LANG_DECL_FN_CHECK (NODE)->u.pending_inline_info) -/* For a TYPE_DECL: if this structure has many fields, we'll sort them +/* For a class type: if this structure has many fields, we'll sort them and put them into a TREE_VEC. */ -#define DECL_SORTED_FIELDS(NODE) \ - (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.f.u.sorted_fields) +#define CLASSTYPE_SORTED_FIELDS(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->sorted_fields) /* True if on the deferred_fns (see decl2.c) list. */ #define DECL_DEFERRED_FN(DECL) \ - (DECL_LANG_SPECIFIC (DECL)->decl_flags.deferred) + (LANG_DECL_FN_CHECK (DECL)->deferred) /* If non-NULL for a VAR_DECL, FUNCTION_DECL, TYPE_DECL or TEMPLATE_DECL, the entity is either a template specialization (if @@ -2190,7 +2222,7 @@ extern void decl_shadowed_for_var_insert (tree, tree); will be non-NULL, but DECL_USE_TEMPLATE will be zero. */ #define DECL_TEMPLATE_INFO(NODE) \ (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \ - ->decl_flags.u.template_info) + ->u.min.template_info) /* For a VAR_DECL, indicates that the variable is actually a non-static data member of anonymous union that has been promoted to @@ -2440,8 +2472,8 @@ extern void decl_shadowed_for_var_insert (tree, tree); /* In a FUNCTION_DECL, the saved language-specific per-function data. */ #define DECL_SAVED_FUNCTION_DATA(NODE) \ - (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \ - ->u.f.u.saved_language_function) + (LANG_DECL_FN_CHECK (FUNCTION_DECL_CHECK (NODE)) \ + ->u.saved_language_function) /* Indicates an indirect_expr is for converting a reference. */ #define REFERENCE_REF_P(NODE) \ @@ -2617,26 +2649,26 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) declared inside a class. In the latter case DECL_HIDDEN_FRIEND_P will be set. */ #define DECL_ANTICIPATED(NODE) \ - (DECL_LANG_SPECIFIC (DECL_COMMON_CHECK (NODE))->decl_flags.anticipated_p) + (DECL_LANG_SPECIFIC (DECL_COMMON_CHECK (NODE))->u.base.anticipated_p) /* Nonzero if NODE is a FUNCTION_DECL which was declared as a friend within a class but has not been declared in the surrounding scope. The function is invisible except via argument dependent lookup. */ #define DECL_HIDDEN_FRIEND_P(NODE) \ - (DECL_LANG_SPECIFIC (DECL_COMMON_CHECK (NODE))->decl_flags.hidden_friend_p) + (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->hidden_friend_p) /* Nonzero if DECL has been declared threadprivate by #pragma omp threadprivate. */ #define CP_DECL_THREADPRIVATE_P(DECL) \ - (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->decl_flags.threadprivate_or_deleted_p) + (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->u.base.threadprivate_or_deleted_p) /* Nonzero if DECL was declared with '= delete'. */ #define DECL_DELETED_FN(DECL) \ - (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.threadprivate_or_deleted_p) + (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->u.base.threadprivate_or_deleted_p) /* Nonzero if DECL was declared with '= default'. */ #define DECL_DEFAULTED_FN(DECL) \ - (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.defaulted_p) + (LANG_DECL_FN_CHECK (DECL)->defaulted_p) /* Record whether a typedef for type `int' was actually `signed int'. */ #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP) @@ -3046,11 +3078,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* Nonzero if the FUNCTION_DECL is a global constructor. */ #define DECL_GLOBAL_CTOR_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.global_ctor_p) + (LANG_DECL_FN_CHECK (NODE)->global_ctor_p) /* Nonzero if the FUNCTION_DECL is a global destructor. */ #define DECL_GLOBAL_DTOR_P(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.global_dtor_p) + (LANG_DECL_FN_CHECK (NODE)->global_dtor_p) /* Accessor macros for C++ template decl nodes. */ @@ -3151,6 +3183,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_DECLARES_TYPE_P(NODE) \ (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE)) +/* Nonzero if NODE declares a function. */ +#define DECL_DECLARES_FUNCTION_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (NODE)) + /* Nonzero if NODE is the typedef implicitly generated for a type when the type is declared. In C++, `struct S {};' is roughly equivalent to `struct S {}; typedef struct S S;' in C. @@ -3204,7 +3240,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) If DECL_USE_TEMPLATE is nonzero, then DECL_TEMPLATE_INFO will also be non-NULL. */ -#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template) +#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.use_template) /* Like DECL_USE_TEMPLATE, but for class types. */ #define CLASSTYPE_USE_TEMPLATE(NODE) \ @@ -3277,7 +3313,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) current translation unit; it indicates whether or not we should emit the decl at the end of compilation if it is defined and needed. */ #define DECL_NOT_REALLY_EXTERN(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern) + (DECL_LANG_SPECIFIC (NODE)->u.base.not_really_extern) #define DECL_REALLY_EXTERN(NODE) \ (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE)) @@ -3324,7 +3360,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* An integer indicating how many bytes should be subtracted from the this or result pointer when this function is called. */ #define THUNK_FIXED_OFFSET(DECL) \ - (DECL_LANG_SPECIFIC (THUNK_FUNCTION_CHECK (DECL))->u.f.u5.fixed_offset) + (DECL_LANG_SPECIFIC (THUNK_FUNCTION_CHECK (DECL))->u.fn.u5.fixed_offset) /* A tree indicating how to perform the virtual adjustment. For a this adjusting thunk it is the number of bytes to be added to the vtable @@ -3341,12 +3377,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* A thunk which is equivalent to another thunk. */ #define THUNK_ALIAS(DECL) \ - (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.u.template_info) + (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->u.min.template_info) /* For thunk NODE, this is the FUNCTION_DECL thunked to. It is possible for the target to be a thunk too. */ #define THUNK_TARGET(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) + (LANG_DECL_FN_CHECK (NODE)->befriending_classes) /* True for a SCOPE_REF iff the "template" keyword was used to indicate that the qualified name denotes a template. */ @@ -4258,6 +4294,7 @@ extern bool type_has_user_provided_constructor (tree); extern bool type_has_user_provided_default_constructor (tree); extern bool defaultable_fn_p (tree); extern void fixup_type_variants (tree); +extern tree* decl_cloned_function_p (const_tree, bool); extern void clone_function_decl (tree, int); extern void adjust_clone_args (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 73c756f..dc2ef1e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -873,7 +873,7 @@ push_local_name (tree decl) { if (!DECL_LANG_SPECIFIC (decl)) retrofit_lang_decl (decl); - DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1; + DECL_LANG_SPECIFIC (decl)->u.base.u2sel = 1; if (DECL_LANG_SPECIFIC (t)) DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1; else @@ -1786,9 +1786,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) { DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl); - if (CAN_HAVE_FULL_LANG_DECL_P (newdecl) - && DECL_LANG_SPECIFIC (newdecl) - && DECL_LANG_SPECIFIC (olddecl)) + if (TREE_CODE (newdecl) == FUNCTION_DECL) { DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl); DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl); @@ -1894,24 +1892,27 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* Don't really know how much of the language-specific values we should copy from old to new. */ DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); - DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 = - DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2; - DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl); - if (DECL_TEMPLATE_INFO (newdecl)) - new_template_info = DECL_TEMPLATE_INFO (newdecl); - DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); DECL_INITIALIZED_IN_CLASS_P (newdecl) |= DECL_INITIALIZED_IN_CLASS_P (olddecl); - olddecl_friend = DECL_FRIEND_P (olddecl); - hidden_friend = (DECL_ANTICIPATED (olddecl) - && DECL_HIDDEN_FRIEND_P (olddecl) - && newdecl_is_friend); - /* Only functions have DECL_BEFRIENDING_CLASSES. */ + if (LANG_DECL_HAS_MIN (newdecl)) + { + DECL_LANG_SPECIFIC (newdecl)->u.min.u2 = + DECL_LANG_SPECIFIC (olddecl)->u.min.u2; + if (DECL_TEMPLATE_INFO (newdecl)) + new_template_info = DECL_TEMPLATE_INFO (newdecl); + DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); + } + /* Only functions have these fields. */ if (TREE_CODE (newdecl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (newdecl)) { + DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); + olddecl_friend = DECL_FRIEND_P (olddecl); + hidden_friend = (DECL_ANTICIPATED (olddecl) + && DECL_HIDDEN_FRIEND_P (olddecl) + && newdecl_is_friend); DECL_BEFRIENDING_CLASSES (newdecl) = chainon (DECL_BEFRIENDING_CLASSES (newdecl), DECL_BEFRIENDING_CLASSES (olddecl)); @@ -12582,16 +12583,6 @@ finish_method (tree decl) DECL_INITIAL (fndecl) = old_initial; - /* We used to check if the context of FNDECL was different from - current_class_type as another way to get inside here. This didn't work - for String.cc in libg++. */ - if (DECL_FRIEND_P (fndecl)) - { - VEC_safe_push (tree, gc, CLASSTYPE_INLINE_FRIENDS (current_class_type), - fndecl); - decl = void_type_node; - } - return decl; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 1191964..6be57a6 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2634,7 +2634,6 @@ start_objects (int method_type, int initp) DECL_GLOBAL_CTOR_P (current_function_decl) = 1; else DECL_GLOBAL_DTOR_P (current_function_decl) = 1; - DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1; body = begin_compound_stmt (BCS_FN_BODY); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index fa97a3b..850f406 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1406,7 +1406,7 @@ dump_function_name (tree t, int flags) pp_cxx_ws_string (cxx_pp, "operator"); dump_type (TREE_TYPE (TREE_TYPE (t)), flags); } - else if (IDENTIFIER_OPNAME_P (name)) + else if (name && IDENTIFIER_OPNAME_P (name)) pp_cxx_tree_identifier (cxx_pp, name); else dump_decl (name, flags); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index bf50741..5effd7a 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -532,19 +532,20 @@ retrofit_lang_decl (tree t) { struct lang_decl *ld; size_t size; - - if (CAN_HAVE_FULL_LANG_DECL_P (t)) - size = sizeof (struct lang_decl); + int sel; + + if (TREE_CODE (t) == FUNCTION_DECL) + sel = 1, size = sizeof (struct lang_decl_fn); + else if (TREE_CODE (t) == NAMESPACE_DECL) + sel = 2, size = sizeof (struct lang_decl_ns); + else if (LANG_DECL_HAS_MIN (t)) + sel = 0, size = sizeof (struct lang_decl_min); else - size = sizeof (struct lang_decl_flags); + gcc_unreachable (); ld = GGC_CNEWVAR (struct lang_decl, size); - ld->decl_flags.can_be_full = CAN_HAVE_FULL_LANG_DECL_P (t) ? 1 : 0; - ld->decl_flags.u1sel = TREE_CODE (t) == NAMESPACE_DECL ? 1 : 0; - ld->decl_flags.u2sel = 0; - if (ld->decl_flags.can_be_full) - ld->u.f.u3sel = TREE_CODE (t) == FUNCTION_DECL ? 1 : 0; + ld->u.base.selector = sel; DECL_LANG_SPECIFIC (t) = ld; if (current_lang_name == lang_name_cplusplus @@ -572,10 +573,15 @@ cxx_dup_lang_specific_decl (tree node) if (! DECL_LANG_SPECIFIC (node)) return; - if (!CAN_HAVE_FULL_LANG_DECL_P (node)) - size = sizeof (struct lang_decl_flags); + if (TREE_CODE (node) == FUNCTION_DECL) + size = sizeof (struct lang_decl_fn); + else if (TREE_CODE (node) == NAMESPACE_DECL) + size = sizeof (struct lang_decl_ns); + else if (LANG_DECL_HAS_MIN (node)) + size = sizeof (struct lang_decl_min); else - size = sizeof (struct lang_decl); + gcc_unreachable (); + ld = GGC_NEWVAR (struct lang_decl, size); memcpy (ld, DECL_LANG_SPECIFIC (node), size); DECL_LANG_SPECIFIC (node) = ld; diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index f7d9d41..fe2f6fd 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1088,43 +1088,54 @@ write_unqualified_name (const tree decl) { MANGLE_TRACE_TREE ("unqualified-name", decl); - if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_CONSTRUCTOR_P (decl)) - write_special_name_constructor (decl); - else if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_DESTRUCTOR_P (decl)) - write_special_name_destructor (decl); - else if (DECL_NAME (decl) == NULL_TREE) + if (DECL_NAME (decl) == NULL_TREE) { gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); write_source_name (DECL_ASSEMBLER_NAME (decl)); + return; } - else if (DECL_CONV_FN_P (decl)) + else if (DECL_DECLARES_FUNCTION_P (decl)) { - /* Conversion operator. Handle it right here. - <operator> ::= cv <type> */ - tree type; - if (decl_is_template_id (decl, NULL)) + bool found = true; + if (DECL_CONSTRUCTOR_P (decl)) + write_special_name_constructor (decl); + else if (DECL_DESTRUCTOR_P (decl)) + write_special_name_destructor (decl); + else if (DECL_CONV_FN_P (decl)) { - tree fn_type; - fn_type = get_mostly_instantiated_function_type (decl); - type = TREE_TYPE (fn_type); + /* Conversion operator. Handle it right here. + <operator> ::= cv <type> */ + tree type; + if (decl_is_template_id (decl, NULL)) + { + tree fn_type; + fn_type = get_mostly_instantiated_function_type (decl); + type = TREE_TYPE (fn_type); + } + else + type = DECL_CONV_FN_TYPE (decl); + write_conversion_operator_name (type); + } + else if (DECL_OVERLOADED_OPERATOR_P (decl)) + { + operator_name_info_t *oni; + if (DECL_ASSIGNMENT_OPERATOR_P (decl)) + oni = assignment_operator_name_info; + else + oni = operator_name_info; + + write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name); } else - type = DECL_CONV_FN_TYPE (decl); - write_conversion_operator_name (type); - } - else if (DECL_OVERLOADED_OPERATOR_P (decl)) - { - operator_name_info_t *oni; - if (DECL_ASSIGNMENT_OPERATOR_P (decl)) - oni = assignment_operator_name_info; - else - oni = operator_name_info; + found = false; - write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name); + if (found) + return; } - else if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl) - && DECL_NAMESPACE_SCOPE_P (decl) - && decl_linkage (decl) == lk_internal) + + if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl) + && DECL_NAMESPACE_SCOPE_P (decl) + && decl_linkage (decl) == lk_internal) { MANGLE_TRACE_TREE ("local-source-name", decl); write_char ('L'); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index af58afe..4e22a20 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -277,7 +277,6 @@ make_alias_for (tree function, tree newid) DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; - DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c65ffcd..b93c811 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3458,17 +3458,6 @@ build_template_decl (tree decl, tree parms, bool member_template_p) DECL_TEMPLATE_PARMS (tmpl) = parms; DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p; - if (DECL_LANG_SPECIFIC (decl)) - { - DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl); - DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl); - DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_P (decl); - DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl); - DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl); - if (DECL_OVERLOADED_OPERATOR_P (decl)) - SET_OVERLOADED_OPERATOR_CODE (tmpl, - DECL_OVERLOADED_OPERATOR_P (decl)); - } return tmpl; } @@ -3792,6 +3781,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, if (current_class_type && !TYPE_BEING_DEFINED (current_class_type) && DECL_LANG_SPECIFIC (decl) + && DECL_DECLARES_FUNCTION_P (decl) /* If this is either a friend defined in the scope of the class or a member function. */ && (DECL_FUNCTION_MEMBER_P (decl) @@ -8594,13 +8584,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) DECL_SAVED_TREE (r) = NULL_TREE; DECL_STRUCT_FUNCTION (r) = NULL; TREE_USED (r) = 0; - if (DECL_CLONED_FUNCTION (r)) - { - DECL_CLONED_FUNCTION (r) = tsubst (DECL_CLONED_FUNCTION (t), - args, complain, t); - TREE_CHAIN (r) = TREE_CHAIN (DECL_CLONED_FUNCTION (r)); - TREE_CHAIN (DECL_CLONED_FUNCTION (r)) = r; - } + /* We'll re-clone as appropriate in instantiate_template. */ + DECL_CLONED_FUNCTION (r) = NULL_TREE; /* Set up the DECL_TEMPLATE_INFO for R. There's no need to do this in the special friend case mentioned above where @@ -12330,8 +12315,10 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) tree spec; tree clone; - spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr, - complain); + /* Use DECL_ABSTRACT_ORIGIN because only FUNCTION_DECLs have + DECL_CLONED_FUNCTION. */ + spec = instantiate_template (DECL_ABSTRACT_ORIGIN (tmpl), + targ_ptr, complain); if (spec == error_mark_node) return error_mark_node; diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 2452abc..ec7a471 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -65,10 +65,6 @@ cxx_print_decl (FILE *file, tree node, int indent) && DECL_PENDING_INLINE_INFO (node)) fprintf (file, " pending-inline-info %p", (void *) DECL_PENDING_INLINE_INFO (node)); - if (TREE_CODE (node) == TYPE_DECL - && DECL_SORTED_FIELDS (node)) - fprintf (file, " sorted-fields %p", - (void *) DECL_SORTED_FIELDS (node)); if ((TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL) && DECL_TEMPLATE_INFO (node)) fprintf (file, " template-info %p", @@ -95,13 +91,6 @@ cxx_print_type (FILE *file, tree node, int indent) print_node (file, "throws", TYPE_RAISES_EXCEPTIONS (node), indent + 4); return; - case RECORD_TYPE: - case UNION_TYPE: - indent_to (file, indent + 4); - fprintf (file, "full-name \"%s\"", - type_as_string (node, TFF_CLASS_KEY_OR_ENUM)); - break; - default: return; } @@ -113,6 +102,10 @@ cxx_print_type (FILE *file, tree node, int indent) if (! CLASS_TYPE_P (node)) return; + indent_to (file, indent + 4); + fprintf (file, "full-name \"%s\"", + type_as_string (node, TFF_CLASS_KEY_OR_ENUM)); + indent_to (file, indent + 3); if (TYPE_NEEDS_CONSTRUCTING (node)) @@ -140,6 +133,9 @@ cxx_print_type (FILE *file, tree node, int indent) fputs (" delete[]", file); if (TYPE_HAS_ASSIGN_REF (node)) fputs (" this=(X&)", file); + if (CLASSTYPE_SORTED_FIELDS (node)) + fprintf (file, " sorted-fields %p", + (void *) CLASSTYPE_SORTED_FIELDS (node)); if (TREE_CODE (node) == RECORD_TYPE) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 4f36e64..c50cc4a 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -395,12 +395,10 @@ lookup_field_1 (tree type, tree name, bool want_type) The TYPE_FIELDS of TYPENAME_TYPE is its TYPENAME_TYPE_FULLNAME. */ return NULL_TREE; - if (TYPE_NAME (type) - && DECL_LANG_SPECIFIC (TYPE_NAME (type)) - && DECL_SORTED_FIELDS (TYPE_NAME (type))) + if (CLASSTYPE_SORTED_FIELDS (type)) { - tree *fields = &DECL_SORTED_FIELDS (TYPE_NAME (type))->elts[0]; - int lo = 0, hi = DECL_SORTED_FIELDS (TYPE_NAME (type))->len; + tree *fields = &CLASSTYPE_SORTED_FIELDS (type)->elts[0]; + int lo = 0, hi = CLASSTYPE_SORTED_FIELDS (type)->len; int i; while (lo < hi) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9a43863..59a5312 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3861,7 +3861,7 @@ finish_omp_threadprivate (tree vars) /* Make sure that DECL_DISCRIMINATOR_P continues to be true after the allocation of the lang_decl structure. */ if (DECL_DISCRIMINATOR_P (v)) - DECL_LANG_SPECIFIC (v)->decl_flags.u2sel = 1; + DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1; } if (! DECL_THREAD_LOCAL_P (v)) |