diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2002-10-30 15:54:10 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2002-10-30 15:54:10 +0000 |
commit | 7088fca94118e4e68a80f349ee55cda4930823b1 (patch) | |
tree | de9d8ee4f80351fcf0257caba03bc679119f5b27 /gcc | |
parent | d2d199a3e6103b6cd2e0088cbcfdd0047d2c631e (diff) | |
download | gcc-7088fca94118e4e68a80f349ee55cda4930823b1.zip gcc-7088fca94118e4e68a80f349ee55cda4930823b1.tar.gz gcc-7088fca94118e4e68a80f349ee55cda4930823b1.tar.bz2 |
Core issue 287, PR c++/7639
Core issue 287, PR c++/7639
* cp-tree.h (lang_type_class): Add decl_list field.
(CLASSTYPE_DECL_LIST): New macro.
(maybe_add_class_template_decl_list): Add declaration.
* class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST.
(unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST.
(maybe_add_class_template_decl_list): New function.
(add_implicitly_declared_members): Use it.
* decl.c (maybe_process_template_type_declaration): Likewise.
(pushtag): Likewise.
* friend.c (add_friend): Likewise.
(make_friend_class): Likewise.
* semantics.c (finish_member_declaration): Likewise.
(begin_class_definition): Initialize CLASSTYPE_DECL_LIST.
* pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST
to process members and friends in the order of declaration.
Core issue 287, PR c++/7639
* g++.dg/template/instantiate1.C: Adjust error location.
* g++.dg/template/instantiate3.C: New test.
* g++.old-deja/g++.pt/crash10.C: Adjust error location.
* g++.old-deja/g++.pt/derived3.C: Adjust error location.
* g++.old-deja/g++.pt/spec28.C: Reorder declaration.
From-SVN: r58654
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/class.c | 34 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 12 | ||||
-rw-r--r-- | gcc/cp/friend.c | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 294 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/instantiate1.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/instantiate3.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/crash10.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/derived3.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/spec28.C | 2 |
13 files changed, 261 insertions, 162 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dba4a0d..1dc2487 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2002-10-30 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> + + Core issue 287, PR c++/7639 + * cp-tree.h (lang_type_class): Add decl_list field. + (CLASSTYPE_DECL_LIST): New macro. + (maybe_add_class_template_decl_list): Add declaration. + * class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST. + (unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST. + (maybe_add_class_template_decl_list): New function. + (add_implicitly_declared_members): Use it. + * decl.c (maybe_process_template_type_declaration): Likewise. + (pushtag): Likewise. + * friend.c (add_friend): Likewise. + (make_friend_class): Likewise. + * semantics.c (finish_member_declaration): Likewise. + (begin_class_definition): Initialize CLASSTYPE_DECL_LIST. + * pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST + to process members and friends in the order of declaration. + 2002-10-29 Mark Mitchell <mark@codesourcery.com> PR c++/8287 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 8263161..d189686 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2093,6 +2093,7 @@ duplicate_tag_error (t) TYPE_REDEFINED (t) = 1; CLASSTYPE_TEMPLATE_INFO (t) = template_info; CLASSTYPE_USE_TEMPLATE (t) = use_template; + CLASSTYPE_DECL_LIST (t) = NULL_TREE; } TYPE_SIZE (t) = NULL_TREE; TYPE_MODE (t) = VOIDmode; @@ -2744,6 +2745,29 @@ finish_struct_anon (t) } } +/* Add T to CLASSTYPE_DECL_LIST of current_class_type which + will be used later during class template instantiation. + When FRIEND_P is zero, T can be a static member data (VAR_DECL), + a non-static member data (FIELD_DECL), a member function + (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE), + a typedef (TYPE_DECL) or a member class template (TEMPLATE_DECL) + When FRIEND_P is nonzero, T is either a friend class + (RECORD_TYPE, TEMPLATE_DECL) or a friend function + (FUNCTION_DECL, TEMPLATE_DECL). */ + +void +maybe_add_class_template_decl_list (type, t, friend_p) + tree type; + tree t; + int friend_p; +{ + /* Save some memory by not creating TREE_LIST if TYPE is not template. */ + if (CLASSTYPE_TEMPLATE_INFO (type)) + CLASSTYPE_DECL_LIST (type) + = tree_cons (friend_p ? NULL_TREE : type, + t, CLASSTYPE_DECL_LIST (type)); +} + /* Create default constructors, assignment operators, and so forth for the type indicated by T, if they are needed. CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and @@ -2824,7 +2848,10 @@ add_implicitly_declared_members (t, cant_have_default_ctor, /* Now, hook all of the new functions on to TYPE_METHODS, and add them to the CLASSTYPE_METHOD_VEC. */ for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f)) - add_method (t, *f, /*error_p=*/0); + { + add_method (t, *f, /*error_p=*/0); + maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0); + } *f = TYPE_METHODS (t); TYPE_METHODS (t) = implicit_fns; @@ -5305,10 +5332,11 @@ unreverse_member_declarations (t) tree prev; tree x; - /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in - reverse order. Put them in declaration order now. */ + /* The following lists are all in reverse order. Put them in + declaration order now. */ TYPE_METHODS (t) = nreverse (TYPE_METHODS (t)); CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t)); + CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t)); /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in reverse order, so we can't just use nreverse. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e1544fd..d9bde84 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1159,6 +1159,7 @@ struct lang_type_class GTY(()) tree friend_classes; tree rtti; tree methods; + tree decl_list; tree template_info; tree befriending_classes; }; @@ -1295,6 +1296,12 @@ struct lang_type GTY(()) functions are sorted, once the class is complete. */ #define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods) +/* For class templates, this is a TREE_LIST of all member data, + functions, types, and friends in the order of declaration. + The TREE_PURPOSE of each TREE_LIST is NULL_TREE for a friend, + and the RECORD_TYPE for the class template otherwise. */ +#define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list) + /* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */ #define CLASSTYPE_CONSTRUCTOR_SLOT 0 @@ -3572,6 +3579,7 @@ extern void cxx_print_error_function PARAMS ((struct diagnostic_context *, extern void build_self_reference PARAMS ((void)); extern int same_signature_p PARAMS ((tree, tree)); extern void warn_hidden PARAMS ((tree)); +extern void maybe_add_class_template_decl_list PARAMS ((tree, tree, int)); extern tree get_enclosing_class PARAMS ((tree)); int is_base_of_enclosing_class PARAMS ((tree, tree)); extern void unreverse_member_declarations PARAMS ((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f42c8d3..4fcb363 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2617,7 +2617,11 @@ maybe_process_template_type_declaration (type, globalize, b) b->level_chain->tags = tree_cons (name, type, b->level_chain->tags); if (!COMPLETE_TYPE_P (current_class_type)) - CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags; + { + maybe_add_class_template_decl_list (current_class_type, + type, /*friend_p=*/0); + CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags; + } } } } @@ -2781,7 +2785,11 @@ pushtag (name, type, globalize) if (b->parm_flag == 2) { if (!COMPLETE_TYPE_P (current_class_type)) - CLASSTYPE_TAGS (current_class_type) = b->tags; + { + maybe_add_class_template_decl_list (current_class_type, + type, /*friend_p=*/0); + CLASSTYPE_TAGS (current_class_type) = b->tags; + } } } diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index b71baa5..7b718ac 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -159,6 +159,9 @@ add_friend (type, decl) return; } } + + maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); + TREE_VALUE (list) = tree_cons (error_mark_node, decl, TREE_VALUE (list)); return; @@ -166,6 +169,8 @@ add_friend (type, decl) list = TREE_CHAIN (list); } + maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); + DECL_FRIENDLIST (typedecl) = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), DECL_FRIENDLIST (typedecl)); @@ -267,6 +272,8 @@ make_friend_class (type, friend_type) TREE_VALUE (classes), type); else { + maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1); + CLASSTYPE_FRIEND_CLASSES (type) = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); if (is_template_friend) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 183a360..09e225a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4975,7 +4975,7 @@ tree instantiate_class_template (type) tree type; { - tree template, args, pattern, t; + tree template, args, pattern, t, member; tree typedecl; if (type == error_mark_node) @@ -5070,6 +5070,7 @@ instantiate_class_template (type) TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern); TYPE_FIELDS (type) = TYPE_FIELDS (pattern); TYPE_METHODS (type) = TYPE_METHODS (pattern); + CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern); CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern); CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern); @@ -5223,175 +5224,174 @@ instantiate_class_template (type) class. */ pushclass (type, 1); - for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t)) + /* Now members are processed in the order of declaration. */ + for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member)) { - tree tag = TREE_VALUE (t); - tree name = TYPE_IDENTIFIER (tag); - tree newtag; + tree t = TREE_VALUE (member); - newtag = tsubst (tag, args, tf_error, NULL_TREE); - my_friendly_assert (newtag != error_mark_node, 20010206); - if (TREE_CODE (newtag) != ENUMERAL_TYPE) + if (TREE_PURPOSE (member)) { - if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag)) - /* Unfortunately, lookup_template_class sets - CLASSTYPE_IMPLICIT_INSTANTIATION for a partial - instantiation (i.e., for the type of a member template - class nested within a template class.) This behavior is - required for maybe_process_partial_specialization to work - correctly, but is not accurate in this case; the TAG is not - an instantiation of anything. (The corresponding - TEMPLATE_DECL is an instantiation, but the TYPE is not.) */ - CLASSTYPE_USE_TEMPLATE (newtag) = 0; - - /* Now, we call pushtag to put this NEWTAG into the scope of - TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid - pushtag calling push_template_decl. We don't have to do - this for enums because it will already have been done in - tsubst_enum. */ - if (name) - SET_IDENTIFIER_TYPE_VALUE (name, newtag); - pushtag (name, newtag, /*globalize=*/0); - } - } + if (TYPE_P (t)) + { + /* Build new CLASSTYPE_TAGS. */ - /* Don't replace enum constants here. */ - for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t)) - if (TREE_CODE (t) != CONST_DECL) - { - tree r; + tree tag = t; + tree name = TYPE_IDENTIFIER (tag); + tree newtag; - /* The the file and line for this declaration, to assist in - error message reporting. Since we called push_tinst_level - above, we don't need to restore these. */ - lineno = DECL_SOURCE_LINE (t); - input_filename = DECL_SOURCE_FILE (t); + newtag = tsubst (tag, args, tf_error, NULL_TREE); + my_friendly_assert (newtag != error_mark_node, 20010206); + if (TREE_CODE (newtag) != ENUMERAL_TYPE) + { + if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag)) + /* Unfortunately, lookup_template_class sets + CLASSTYPE_IMPLICIT_INSTANTIATION for a partial + instantiation (i.e., for the type of a member template + class nested within a template class.) This behavior is + required for maybe_process_partial_specialization to work + correctly, but is not accurate in this case; the TAG is not + an instantiation of anything. (The corresponding + TEMPLATE_DECL is an instantiation, but the TYPE is not.) */ + CLASSTYPE_USE_TEMPLATE (newtag) = 0; + + /* Now, we call pushtag to put this NEWTAG into the scope of + TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid + pushtag calling push_template_decl. We don't have to do + this for enums because it will already have been done in + tsubst_enum. */ + if (name) + SET_IDENTIFIER_TYPE_VALUE (name, newtag); + pushtag (name, newtag, /*globalize=*/0); + } + } + else if (TREE_CODE (t) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (t)) + { + /* Build new TYPE_METHODS. */ - r = tsubst (t, args, tf_error | tf_warning, NULL_TREE); - if (TREE_CODE (r) == VAR_DECL) - { - tree init; + tree r = tsubst (t, args, tf_error, NULL_TREE); + set_current_access_from_decl (r); + grok_special_member_properties (r); + finish_member_declaration (r); + } + else + { + /* Build new TYPE_FIELDS. */ - if (DECL_INITIALIZED_IN_CLASS_P (r)) - init = tsubst_expr (DECL_INITIAL (t), args, - tf_error | tf_warning, NULL_TREE); - else - init = NULL_TREE; + if (TREE_CODE (t) != CONST_DECL) + { + tree r; - finish_static_data_member_decl (r, init, - /*asmspec_tree=*/NULL_TREE, - /*flags=*/0); + /* The the file and line for this declaration, to assist + in error message reporting. Since we called + push_tinst_level above, we don't need to restore these. */ + lineno = DECL_SOURCE_LINE (t); + input_filename = DECL_SOURCE_FILE (t); - if (DECL_INITIALIZED_IN_CLASS_P (r)) - check_static_variable_definition (r, TREE_TYPE (r)); - } - else if (TREE_CODE (r) == FIELD_DECL) - { - /* Determine whether R has a valid type and can be - completed later. If R is invalid, then it is replaced - by error_mark_node so that it will not be added to - TYPE_FIELDS. */ - tree rtype = TREE_TYPE (r); - if (!can_complete_type_without_circularity (rtype)) - { - cxx_incomplete_type_error (r, rtype); - r = error_mark_node; - } - } + r = tsubst (t, args, tf_error | tf_warning, NULL_TREE); + if (TREE_CODE (r) == VAR_DECL) + { + tree init; - /* R will have a TREE_CHAIN if and only if it has already been - processed by finish_member_declaration. This can happen - if, for example, it is a TYPE_DECL for a class-scoped - ENUMERAL_TYPE; such a thing will already have been added to - the field list by tsubst_enum above. */ - if (!TREE_CHAIN (r)) - { - set_current_access_from_decl (r); - finish_member_declaration (r); - } - } + if (DECL_INITIALIZED_IN_CLASS_P (r)) + init = tsubst_expr (DECL_INITIAL (t), args, + tf_error | tf_warning, NULL_TREE); + else + init = NULL_TREE; - /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC) - for this instantiation. */ - for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t)) - { - tree r = tsubst (t, args, tf_error, NULL_TREE); - set_current_access_from_decl (r); - grok_special_member_properties (r); - finish_member_declaration (r); - } + finish_static_data_member_decl (r, init, + /*asmspec_tree=*/NULL_TREE, + /*flags=*/0); - /* Construct the DECL_FRIENDLIST for the new class type. */ - typedecl = TYPE_MAIN_DECL (type); - for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)); - t != NULL_TREE; - t = TREE_CHAIN (t)) - { - tree friends; - - for (friends = TREE_VALUE (t); - friends != NULL_TREE; - friends = TREE_CHAIN (friends)) - if (TREE_PURPOSE (friends) == error_mark_node) - add_friend (type, - tsubst_friend_function (TREE_VALUE (friends), - args)); - else - abort (); - } - - for (t = CLASSTYPE_FRIEND_CLASSES (pattern); - t != NULL_TREE; - t = TREE_CHAIN (t)) - { - tree friend_type = TREE_VALUE (t); - tree new_friend_type; + if (DECL_INITIALIZED_IN_CLASS_P (r)) + check_static_variable_definition (r, TREE_TYPE (r)); + } + else if (TREE_CODE (r) == FIELD_DECL) + { + /* Determine whether R has a valid type and can be + completed later. If R is invalid, then it is + replaced by error_mark_node so that it will not be + added to TYPE_FIELDS. */ + tree rtype = TREE_TYPE (r); + if (can_complete_type_without_circularity (rtype)) + complete_type (rtype); + + if (!COMPLETE_TYPE_P (rtype)) + { + cxx_incomplete_type_error (r, rtype); + r = error_mark_node; + } + } - if (TREE_CODE (friend_type) == TEMPLATE_DECL) - new_friend_type = tsubst_friend_class (friend_type, args); - else if (uses_template_parms (friend_type)) - new_friend_type = tsubst (friend_type, args, - tf_error | tf_warning, NULL_TREE); - else - { - tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type)); - - /* The call to xref_tag_from_type does injection for friend - classes. */ - push_nested_namespace (ns); - new_friend_type = - xref_tag_from_type (friend_type, NULL_TREE, 1); - pop_nested_namespace (ns); + /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE, + such a thing will already have been added to the field + list by tsubst_enum in finish_member_declaration in the + CLASSTYPE_TAGS case above. */ + if (!(TREE_CODE (r) == TYPE_DECL + && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE + && TYPE_CONTEXT (TREE_TYPE (r)) == type)) + { + set_current_access_from_decl (r); + finish_member_declaration (r); + } + } + } } + else + { + if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t)) + { + /* Build new CLASSTYPE_FRIEND_CLASSES. */ - if (TREE_CODE (friend_type) == TEMPLATE_DECL) - /* Trick make_friend_class into realizing that the friend - we're adding is a template, not an ordinary class. It's - important that we use make_friend_class since it will - perform some error-checking and output cross-reference - information. */ - ++processing_template_decl; + tree friend_type = t; + tree new_friend_type; - if (new_friend_type != error_mark_node) - make_friend_class (type, new_friend_type); + if (TREE_CODE (friend_type) == TEMPLATE_DECL) + new_friend_type = tsubst_friend_class (friend_type, args); + else if (uses_template_parms (friend_type)) + new_friend_type = tsubst (friend_type, args, + tf_error | tf_warning, NULL_TREE); + else + { + tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type)); + + /* The call to xref_tag_from_type does injection for friend + classes. */ + push_nested_namespace (ns); + new_friend_type = + xref_tag_from_type (friend_type, NULL_TREE, 1); + pop_nested_namespace (ns); + } - if (TREE_CODE (friend_type) == TEMPLATE_DECL) - --processing_template_decl; - } + if (TREE_CODE (friend_type) == TEMPLATE_DECL) + /* Trick make_friend_class into realizing that the friend + we're adding is a template, not an ordinary class. It's + important that we use make_friend_class since it will + perform some error-checking and output cross-reference + information. */ + ++processing_template_decl; - /* Now that TYPE_FIELDS and TYPE_METHODS are set up. We can - instantiate templates used by this class. */ - for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) - if (TREE_CODE (t) == FIELD_DECL) - { - TREE_TYPE (t) = complete_type (TREE_TYPE (t)); - require_complete_type (t); - } + if (new_friend_type != error_mark_node) + make_friend_class (type, new_friend_type); + + if (TREE_CODE (friend_type) == TEMPLATE_DECL) + --processing_template_decl; + } + else + { + /* Build new DECL_FRIENDLIST. */ + + add_friend (type, + tsubst_friend_function (t, args)); + } + } + } /* Set the file and line number information to whatever is given for the class itself. This puts error messages involving generated implicit functions at a predictable point, and the same point that would be used for non-template classes. */ + typedecl = TYPE_MAIN_DECL (type); lineno = DECL_SOURCE_LINE (typedecl); input_filename = DECL_SOURCE_FILE (typedecl); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e2428a9..81b4ccf 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1754,6 +1754,7 @@ begin_class_definition (t) TYPE_BINFO_BASETYPES (t) = NULL_TREE; TYPE_FIELDS (t) = NULL_TREE; TYPE_METHODS (t) = NULL_TREE; + CLASSTYPE_DECL_LIST (t) = NULL_TREE; CLASSTYPE_TAGS (t) = NULL_TREE; CLASSTYPE_VBASECLASSES (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE; @@ -1835,6 +1836,8 @@ finish_member_declaration (decl) if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c) SET_DECL_LANGUAGE (decl, lang_cplusplus); + maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0); + /* Put functions on the TYPE_METHODS list and everything else on the TYPE_FIELDS list. Note that these are built up in reverse order. We reverse them (to obtain declaration order) in finish_struct. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ed1f82e..2c0826d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2002-10-30 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> + + Core issue 287, PR c++/7639 + * g++.dg/template/instantiate1.C: Adjust error location. + * g++.dg/template/instantiate3.C: New test. + * g++.old-deja/g++.pt/crash10.C: Adjust error location. + * g++.old-deja/g++.pt/derived3.C: Adjust error location. + * g++.old-deja/g++.pt/spec28.C: Reorder declaration. + 2002-10-29 Hans-Peter Nilsson <hp@bitrange.com> * lib/compat.exp (compat-execute): Don't clean out a gluefile. diff --git a/gcc/testsuite/g++.dg/template/instantiate1.C b/gcc/testsuite/g++.dg/template/instantiate1.C index e96bcd2..e4e7bc9 100644 --- a/gcc/testsuite/g++.dg/template/instantiate1.C +++ b/gcc/testsuite/g++.dg/template/instantiate1.C @@ -8,12 +8,12 @@ template <class T> struct X { T t; // { dg-error "incomplete" } }; -template <class T> struct Y { // { dg-error "instantiated" } - X<T> x; +template <class T> struct Y { + X<T> x; // { dg-error "instantiated" } }; -template <class T> struct Z { // { dg-error "instantiated|declaration" } - Y<Z<T> > y; +template <class T> struct Z { // { dg-error "declaration" } + Y<Z<T> > y; // { dg-error "instantiated" } }; struct ZZ : Z<int> diff --git a/gcc/testsuite/g++.dg/template/instantiate3.C b/gcc/testsuite/g++.dg/template/instantiate3.C new file mode 100644 index 0000000..e75b570 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/instantiate3.C @@ -0,0 +1,17 @@ +// { dg-do compile } +// Origin: Scott Snyder <snyder@fnal.gov> + +// PR c++/7639 +// ICE when accessing member with incomplete type. + +class ACE_Null_Mutex; // { dg-error "forward declaration" } + +template <class TYPE> +struct ACE_Cleanup_Adapter +{ + TYPE &object () + { return object_; } // { dg-error "no member" } + TYPE object_; // { dg-error "incomplete type" } +}; + +template class ACE_Cleanup_Adapter<ACE_Null_Mutex>; // { dg-error "instantiated from here" } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C index 033e234..a7633a0 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash10.C @@ -3,9 +3,9 @@ template<int M, int N> class GCD { public: - enum { val = (N == 0) ? M : GCD<N, M % N>::val }; + enum { val = (N == 0) ? M : GCD<N, M % N>::val }; // ERROR - division }; int main() { - GCD< 1, 0 >::val; // ERROR - division + GCD< 1, 0 >::val; // ERROR - instantiated } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/derived3.C b/gcc/testsuite/g++.old-deja/g++.pt/derived3.C index fa807da..262c1c7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/derived3.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/derived3.C @@ -6,10 +6,10 @@ template<class T> class X { - class Y : public T {}; // ERROR - invalid base type - Y y; + class Y : public T {}; + Y y; // ERROR - invalid base type }; int main() { - X<int> x; + X<int> x; // ERROR - instantiated } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec28.C b/gcc/testsuite/g++.old-deja/g++.pt/spec28.C index d63e796..cb07380 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec28.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec28.C @@ -2,8 +2,8 @@ template <class T> struct S1 { - friend bool f<>(const S1&); typedef T X; + friend bool f<>(const S1&); }; template <class T> |