aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2002-10-30 15:54:10 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2002-10-30 15:54:10 +0000
commit7088fca94118e4e68a80f349ee55cda4930823b1 (patch)
treede9d8ee4f80351fcf0257caba03bc679119f5b27 /gcc
parentd2d199a3e6103b6cd2e0088cbcfdd0047d2c631e (diff)
downloadgcc-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/ChangeLog19
-rw-r--r--gcc/cp/class.c34
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/friend.c7
-rw-r--r--gcc/cp/pt.c294
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/g++.dg/template/instantiate1.C8
-rw-r--r--gcc/testsuite/g++.dg/template/instantiate3.C17
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash10.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/derived3.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec28.C2
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>