Commit 7088fca9 by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

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
parent d2d199a3
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
......
......@@ -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);
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. */
......
......@@ -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));
......
......@@ -2617,10 +2617,14 @@ 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))
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
}
}
}
return decl;
}
......@@ -2781,9 +2785,13 @@ pushtag (name, type, globalize)
if (b->parm_flag == 2)
{
if (!COMPLETE_TYPE_P (current_class_type))
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
CLASSTYPE_TAGS (current_class_type) = b->tags;
}
}
}
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
/* Use the canonical TYPE_DECL for this node. */
......
......@@ -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)
......
......@@ -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,9 +5224,18 @@ 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 t = TREE_VALUE (member);
if (TREE_PURPOSE (member))
{
if (TYPE_P (t))
{
/* Build new CLASSTYPE_TAGS. */
tree tag = t;
tree name = TYPE_IDENTIFIER (tag);
tree newtag;
......@@ -5254,16 +5264,27 @@ instantiate_class_template (type)
pushtag (name, newtag, /*globalize=*/0);
}
}
else if (TREE_CODE (t) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (t))
{
/* Build new TYPE_METHODS. */
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. */
/* Don't replace enum constants here. */
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
tree r;
/* 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. */
/* 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);
......@@ -5288,63 +5309,41 @@ instantiate_class_template (type)
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. */
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))
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;
}
}
/* 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))
/* 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);
}
}
/* 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);
}
/* 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))
else
{
if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
{
tree friend_type = TREE_VALUE (t);
/* Build new CLASSTYPE_FRIEND_CLASSES. */
tree friend_type = t;
tree new_friend_type;
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
......@@ -5378,20 +5377,21 @@ instantiate_class_template (type)
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--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)
else
{
TREE_TYPE (t) = complete_type (TREE_TYPE (t));
require_complete_type (t);
/* 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);
......
......@@ -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. */
......
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.
......
......@@ -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>
......
// { 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" }
......@@ -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
}
......@@ -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
}
......@@ -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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment