From 508a1c9c6d5d84df1207ff6d1e849e104b41694b Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 17 Jul 2004 07:31:08 +0000 Subject: [PATCH] class.c (finish_struct_methods): Remove unncessary code. * class.c (finish_struct_methods): Remove unncessary code. (add_implicitly_declared_members): Create declarations for default constructors and copy constructors lazily. * cp-tree.h (lang_type_class): Remove lazy_default_ctor and lazy_copy_ctor. (CLASSTYPE_LAZY_DEFAULT_CTOR): New macro. (CLASSTYPE_LAZY_COPY_CTOR): Likewise. * decl2.c (check_classfn): Robustify. (locate_dtor): Handle empty CLASSTYPE_METHOD_VEC. (locate_ctor): Handle lazy default constructors. (locate_copy): Handle lazy copy constructors. (implicitly_declare_fn): Make sure we're looking at the TYPE_MAIN_VARIANT for a class before creating functions. Don't set TYPE_HAS_CONSTRUCTOR. (lazily_declare_fn): New function. * name-lookup.c (constructor_name_full): Simplify. * search.c (lookup_fnfields_1): Lazily create methods, as necessary. (lookup_for_overrides): Handle empty CLASSTYPE_METHOD_VEC. From-SVN: r84851 --- gcc/cp/ChangeLog | 22 +++++++++++++ gcc/cp/class.c | 30 ++++++------------ gcc/cp/cp-tree.h | 15 ++++++++- gcc/cp/decl2.c | 3 +- gcc/cp/method.c | 75 +++++++++++++++++++++++++++++++++++++------- gcc/cp/name-lookup.c | 7 +---- gcc/cp/search.c | 42 ++++++++++++++----------- 7 files changed, 134 insertions(+), 60 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 472b101436e..a67bfc37713 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +2004-07-16 Mark Mitchell + + * class.c (finish_struct_methods): Remove unncessary code. + (add_implicitly_declared_members): Create declarations for default + constructors and copy constructors lazily. + * cp-tree.h (lang_type_class): Remove lazy_default_ctor and + lazy_copy_ctor. + (CLASSTYPE_LAZY_DEFAULT_CTOR): New macro. + (CLASSTYPE_LAZY_COPY_CTOR): Likewise. + * decl2.c (check_classfn): Robustify. + (locate_dtor): Handle empty CLASSTYPE_METHOD_VEC. + (locate_ctor): Handle lazy default constructors. + (locate_copy): Handle lazy copy constructors. + (implicitly_declare_fn): Make sure we're looking at the + TYPE_MAIN_VARIANT for a class before creating functions. Don't + set TYPE_HAS_CONSTRUCTOR. + (lazily_declare_fn): New function. + * name-lookup.c (constructor_name_full): Simplify. + * search.c (lookup_fnfields_1): Lazily create methods, as + necessary. + (lookup_for_overrides): Handle empty CLASSTYPE_METHOD_VEC. + 2004-07-16 Steven Bosscher * cp-tree.h (struct lang_type): Don't have three GTY options on a diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c916d5fba21..cc1dc763900 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1714,18 +1714,10 @@ finish_struct_methods (tree t) VEC(tree) *method_vec; int slot, len; - if (!TYPE_METHODS (t)) - { - /* Clear these for safety; perhaps some parsing error could set - these incorrectly. */ - TYPE_HAS_CONSTRUCTOR (t) = 0; - TYPE_HAS_DESTRUCTOR (t) = 0; - CLASSTYPE_METHOD_VEC (t) = NULL; - return; - } - method_vec = CLASSTYPE_METHOD_VEC (t); - my_friendly_assert (method_vec, 19991215); + if (!method_vec) + return; + len = VEC_length (tree, method_vec); /* First fill in entry 0 with the constructors, entry 1 with destructors, @@ -2554,21 +2546,17 @@ add_implicitly_declared_members (tree t, /* Default constructor. */ if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor) { - default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0); - TREE_CHAIN (default_fn) = implicit_fns; - implicit_fns = default_fn; + TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1; + CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1; } /* Copy constructor. */ if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t)) { - /* ARM 12.18: You get either X(X&) or X(const X&), but - not both. --Chip */ - default_fn - = implicitly_declare_fn (sfk_copy_constructor, t, - /*const_p=*/!cant_have_const_cctor); - TREE_CHAIN (default_fn) = implicit_fns; - implicit_fns = default_fn; + TYPE_HAS_INIT_REF (t) = 1; + TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor; + CLASSTYPE_LAZY_COPY_CTOR (t) = 1; + TYPE_HAS_CONSTRUCTOR (t) = 1; } /* If there is no assignment operator, one will be created if and diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e7069ba51e8..a7d35d46ecd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -991,6 +991,8 @@ struct lang_type_class GTY(()) unsigned ptrmemfunc_flag : 1; unsigned was_anonymous : 1; + unsigned lazy_default_ctor : 1; + unsigned lazy_copy_ctor : 1; unsigned has_const_init_ref : 1; unsigned has_complex_init_ref : 1; unsigned has_complex_assign_ref : 1; @@ -1004,7 +1006,7 @@ struct lang_type_class GTY(()) /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 11; + unsigned dummy : 9; tree primary_base; tree vfields; @@ -1089,6 +1091,16 @@ struct lang_type GTY(()) #define TYPE_HAS_CONVERSION(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion) +/* Nonzero means that NODE (a class type) has a default constructor -- + but that it has not yet been declared. */ +#define CLASSTYPE_LAZY_DEFAULT_CTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_default_ctor) + +/* Nonzero means that NODE (a class type) has a copy constructor -- + but that it has not yet been declared. */ +#define CLASSTYPE_LAZY_COPY_CTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->lazy_copy_ctor) + /* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */ #define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref) @@ -3884,6 +3896,7 @@ extern void finish_thunk (tree); extern void use_thunk (tree, bool); extern void synthesize_method (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool); +extern tree lazily_declare_fn (special_function_kind, tree); extern tree skip_artificial_parms_for (tree, tree); /* In optimize.c */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 8467ad62e7b..7257f696952 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -693,9 +693,8 @@ check_classfn (tree ctype, tree function, tree template_parms) if (!fndecls && is_conv_op) { - if (VEC_length (tree, methods) > (size_t) ix) + if (VEC_length (tree, methods) > (size_t) ++ix) { - ix++; fndecls = VEC_index (tree, methods, ix); if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls))) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 1a9ecadbd77..984e0e90557 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -825,7 +825,9 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*), static tree locate_dtor (tree type, void *client ATTRIBUTE_UNUSED) { - return CLASSTYPE_DESTRUCTORS (type); + return (CLASSTYPE_METHOD_VEC (type) + ? CLASSTYPE_DESTRUCTORS (type) + : NULL_TREE); } /* Locate the default ctor of TYPE. */ @@ -838,6 +840,11 @@ locate_ctor (tree type, void *client ATTRIBUTE_UNUSED) if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) return NULL_TREE; + /* Call lookup_fnfields_1 to create the constructor declarations, if + necessary. */ + if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) + return lazily_declare_fn (sfk_constructor, type); + for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -864,21 +871,27 @@ locate_copy (tree type, void *client_) { struct copy_data *client = (struct copy_data *)client_; tree fns; - int ix = -1; tree best = NULL_TREE; bool excess_p = false; if (client->name) { - if (TYPE_HAS_ASSIGN_REF (type)) - ix = lookup_fnfields_1 (type, client->name); + int ix; + ix = lookup_fnfields_1 (type, client->name); + if (ix < 0) + return NULL_TREE; + fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix); } else if (TYPE_HAS_INIT_REF (type)) - ix = CLASSTYPE_CONSTRUCTOR_SLOT; - if (ix < 0) + { + /* If construction of the copy constructor was postponed, create + it now. */ + if (CLASSTYPE_LAZY_COPY_CTOR (type)) + lazily_declare_fn (sfk_copy_constructor, type); + fns = CLASSTYPE_CONSTRUCTORS (type); + } + else return NULL_TREE; - fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix); - for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -927,6 +940,8 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) tree rhs_parm_type = NULL_TREE; tree name; + type = TYPE_MAIN_VARIANT (type); + switch (kind) { case sfk_destructor: @@ -939,12 +954,9 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) /* Default constructor. */ name = constructor_name (type); raises = synthesize_exception_spec (type, &locate_ctor, 0); - TYPE_HAS_CONSTRUCTOR (type) = 1; break; case sfk_copy_constructor: - TYPE_HAS_CONSTRUCTOR (type) = 1; - /* Fall through. */ case sfk_assignment_operator: { struct copy_data data; @@ -1019,6 +1031,47 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) return fn; } +/* Add an implicit declaration to TYPE for the kind of function + indicated by SFK. Return the FUNCTION_DECL for the new implicit + declaration. */ + +tree +lazily_declare_fn (special_function_kind sfk, tree type) +{ + tree fn; + bool const_p; + + /* Figure out whether or not the argument has a const reference + type. */ + if (sfk == sfk_copy_constructor) + const_p = TYPE_HAS_CONST_INIT_REF (type); + else if (sfk == sfk_assignment_operator) + const_p = TYPE_HAS_CONST_ASSIGN_REF (type); + else + /* In this case, CONST_P will be ignored. */ + const_p = false; + /* Declare the function. */ + fn = implicitly_declare_fn (sfk, type, const_p); + /* Add it to CLASSTYPE_METHOD_VEC. */ + add_method (type, fn); + /* Add it to TYPE_METHODS. */ + TREE_CHAIN (fn) = TYPE_METHODS (type); + TYPE_METHODS (type) = fn; + maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); + if (sfk == sfk_constructor || sfk == sfk_copy_constructor) + { + /* Remember that the function has been created. */ + if (sfk == sfk_constructor) + CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; + else + CLASSTYPE_LAZY_COPY_CTOR (type) = 0; + /* Create appropriate clones. */ + clone_function_decl (fn, /*update_method_vec=*/true); + } + + return fn; +} + /* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST as there are artificial parms in FN. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index fd3776faf51..3a2f71ccaf7 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1794,12 +1794,7 @@ set_identifier_type_value (tree id, tree decl) tree constructor_name_full (tree type) { - type = TYPE_MAIN_VARIANT (type); - if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type) - && TYPE_HAS_CONSTRUCTOR (type)) - return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type))); - else - return TYPE_IDENTIFIER (type); + return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type)); } /* Return the name for the constructor (or destructor) for the diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 97b97899e4f..ceefa3cd05f 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1368,8 +1368,24 @@ lookup_fnfields_1 (tree type, tree name) if (!CLASS_TYPE_P (type)) return -1; - method_vec = CLASSTYPE_METHOD_VEC (type); + if (COMPLETE_TYPE_P (type)) + { + if ((name == ctor_identifier + || name == base_ctor_identifier + || name == complete_ctor_identifier)) + { + if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) + lazily_declare_fn (sfk_constructor, type); + if (CLASSTYPE_LAZY_COPY_CTOR (type)) + lazily_declare_fn (sfk_copy_constructor, type); + } + else if (name == ansi_assopname(NOP_EXPR) + && !TYPE_HAS_ASSIGN_REF (type) + && !TYPE_FOR_JAVA (type)) + lazily_declare_fn (sfk_assignment_operator, type); + } + method_vec = CLASSTYPE_METHOD_VEC (type); if (!method_vec) return -1; @@ -1405,24 +1421,6 @@ lookup_fnfields_1 (tree type, tree name) int lo; int hi; - /* All non-Java classes have "operator=" -- but we do not - actually create the declaration until it is needed. */ - if (name == ansi_assopname(NOP_EXPR) - && !TYPE_HAS_ASSIGN_REF (type) - && !TYPE_FOR_JAVA (type)) - { - tree fn; - - /* Declare the function. */ - fn = implicitly_declare_fn (sfk_assignment_operator, type, - TYPE_HAS_CONST_ASSIGN_REF (type)); - add_method (type, fn); - TREE_CHAIN (fn) = TYPE_METHODS (type); - TYPE_METHODS (type) = fn; - maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); - method_vec = CLASSTYPE_METHOD_VEC (type); - } - lo = i; hi = VEC_length (tree, method_vec); while (lo < hi) @@ -1789,6 +1787,12 @@ look_for_overrides_here (tree type, tree fndecl) { int ix; + /* If there are no methods in TYPE (meaning that only implicitly + declared methods will ever be provided for TYPE), then there are + no virtual functions. */ + if (!CLASSTYPE_METHOD_VEC (type)) + return NULL_TREE; + if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl)) ix = CLASSTYPE_DESTRUCTOR_SLOT; else -- 2.30.2