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> 2002-10-29 Mark Mitchell <mark@codesourcery.com>
PR c++/8287 PR c++/8287
......
...@@ -2093,6 +2093,7 @@ duplicate_tag_error (t) ...@@ -2093,6 +2093,7 @@ duplicate_tag_error (t)
TYPE_REDEFINED (t) = 1; TYPE_REDEFINED (t) = 1;
CLASSTYPE_TEMPLATE_INFO (t) = template_info; CLASSTYPE_TEMPLATE_INFO (t) = template_info;
CLASSTYPE_USE_TEMPLATE (t) = use_template; CLASSTYPE_USE_TEMPLATE (t) = use_template;
CLASSTYPE_DECL_LIST (t) = NULL_TREE;
} }
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
TYPE_MODE (t) = VOIDmode; TYPE_MODE (t) = VOIDmode;
...@@ -2744,6 +2745,29 @@ finish_struct_anon (t) ...@@ -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 /* Create default constructors, assignment operators, and so forth for
the type indicated by T, if they are needed. the type indicated by T, if they are needed.
CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
...@@ -2824,7 +2848,10 @@ add_implicitly_declared_members (t, cant_have_default_ctor, ...@@ -2824,7 +2848,10 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
/* Now, hook all of the new functions on to TYPE_METHODS, /* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */ and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f)) 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); *f = TYPE_METHODS (t);
TYPE_METHODS (t) = implicit_fns; TYPE_METHODS (t) = implicit_fns;
...@@ -5305,10 +5332,11 @@ unreverse_member_declarations (t) ...@@ -5305,10 +5332,11 @@ unreverse_member_declarations (t)
tree prev; tree prev;
tree x; tree x;
/* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in /* The following lists are all in reverse order. Put them in
reverse order. Put them in declaration order now. */ declaration order now. */
TYPE_METHODS (t) = nreverse (TYPE_METHODS (t)); TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (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 /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
reverse order, so we can't just use nreverse. */ reverse order, so we can't just use nreverse. */
......
...@@ -1159,6 +1159,7 @@ struct lang_type_class GTY(()) ...@@ -1159,6 +1159,7 @@ struct lang_type_class GTY(())
tree friend_classes; tree friend_classes;
tree rtti; tree rtti;
tree methods; tree methods;
tree decl_list;
tree template_info; tree template_info;
tree befriending_classes; tree befriending_classes;
}; };
...@@ -1295,6 +1296,12 @@ struct lang_type GTY(()) ...@@ -1295,6 +1296,12 @@ struct lang_type GTY(())
functions are sorted, once the class is complete. */ functions are sorted, once the class is complete. */
#define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods) #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. */ /* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
#define CLASSTYPE_CONSTRUCTOR_SLOT 0 #define CLASSTYPE_CONSTRUCTOR_SLOT 0
...@@ -3572,6 +3579,7 @@ extern void cxx_print_error_function PARAMS ((struct diagnostic_context *, ...@@ -3572,6 +3579,7 @@ extern void cxx_print_error_function PARAMS ((struct diagnostic_context *,
extern void build_self_reference PARAMS ((void)); extern void build_self_reference PARAMS ((void));
extern int same_signature_p PARAMS ((tree, tree)); extern int same_signature_p PARAMS ((tree, tree));
extern void warn_hidden PARAMS ((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)); extern tree get_enclosing_class PARAMS ((tree));
int is_base_of_enclosing_class PARAMS ((tree, tree)); int is_base_of_enclosing_class PARAMS ((tree, tree));
extern void unreverse_member_declarations PARAMS ((tree)); extern void unreverse_member_declarations PARAMS ((tree));
......
...@@ -2617,10 +2617,14 @@ maybe_process_template_type_declaration (type, globalize, b) ...@@ -2617,10 +2617,14 @@ maybe_process_template_type_declaration (type, globalize, b)
b->level_chain->tags = b->level_chain->tags =
tree_cons (name, type, b->level_chain->tags); tree_cons (name, type, b->level_chain->tags);
if (!COMPLETE_TYPE_P (current_class_type)) 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; CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
} }
} }
} }
}
return decl; return decl;
} }
...@@ -2781,9 +2785,13 @@ pushtag (name, type, globalize) ...@@ -2781,9 +2785,13 @@ pushtag (name, type, globalize)
if (b->parm_flag == 2) if (b->parm_flag == 2)
{ {
if (!COMPLETE_TYPE_P (current_class_type)) 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; CLASSTYPE_TAGS (current_class_type) = b->tags;
} }
} }
}
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
/* Use the canonical TYPE_DECL for this node. */ /* Use the canonical TYPE_DECL for this node. */
......
...@@ -159,6 +159,9 @@ add_friend (type, decl) ...@@ -159,6 +159,9 @@ add_friend (type, decl)
return; return;
} }
} }
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
TREE_VALUE (list) = tree_cons (error_mark_node, decl, TREE_VALUE (list) = tree_cons (error_mark_node, decl,
TREE_VALUE (list)); TREE_VALUE (list));
return; return;
...@@ -166,6 +169,8 @@ add_friend (type, decl) ...@@ -166,6 +169,8 @@ add_friend (type, decl)
list = TREE_CHAIN (list); list = TREE_CHAIN (list);
} }
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
DECL_FRIENDLIST (typedecl) DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
DECL_FRIENDLIST (typedecl)); DECL_FRIENDLIST (typedecl));
...@@ -267,6 +272,8 @@ make_friend_class (type, friend_type) ...@@ -267,6 +272,8 @@ make_friend_class (type, friend_type)
TREE_VALUE (classes), type); TREE_VALUE (classes), type);
else else
{ {
maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
CLASSTYPE_FRIEND_CLASSES (type) CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
if (is_template_friend) if (is_template_friend)
......
...@@ -4975,7 +4975,7 @@ tree ...@@ -4975,7 +4975,7 @@ tree
instantiate_class_template (type) instantiate_class_template (type)
tree type; tree type;
{ {
tree template, args, pattern, t; tree template, args, pattern, t, member;
tree typedecl; tree typedecl;
if (type == error_mark_node) if (type == error_mark_node)
...@@ -5070,6 +5070,7 @@ instantiate_class_template (type) ...@@ -5070,6 +5070,7 @@ instantiate_class_template (type)
TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern); TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
TYPE_FIELDS (type) = TYPE_FIELDS (pattern); TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
TYPE_METHODS (type) = TYPE_METHODS (pattern); TYPE_METHODS (type) = TYPE_METHODS (pattern);
CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern); CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern); CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
...@@ -5223,9 +5224,18 @@ instantiate_class_template (type) ...@@ -5223,9 +5224,18 @@ instantiate_class_template (type)
class. */ class. */
pushclass (type, 1); 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 name = TYPE_IDENTIFIER (tag);
tree newtag; tree newtag;
...@@ -5254,16 +5264,27 @@ instantiate_class_template (type) ...@@ -5254,16 +5264,27 @@ instantiate_class_template (type)
pushtag (name, newtag, /*globalize=*/0); 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) if (TREE_CODE (t) != CONST_DECL)
{ {
tree r; tree r;
/* The the file and line for this declaration, to assist in /* The the file and line for this declaration, to assist
error message reporting. Since we called push_tinst_level in error message reporting. Since we called
above, we don't need to restore these. */ push_tinst_level above, we don't need to restore these. */
lineno = DECL_SOURCE_LINE (t); lineno = DECL_SOURCE_LINE (t);
input_filename = DECL_SOURCE_FILE (t); input_filename = DECL_SOURCE_FILE (t);
...@@ -5288,63 +5309,41 @@ instantiate_class_template (type) ...@@ -5288,63 +5309,41 @@ instantiate_class_template (type)
else if (TREE_CODE (r) == FIELD_DECL) else if (TREE_CODE (r) == FIELD_DECL)
{ {
/* Determine whether R has a valid type and can be /* Determine whether R has a valid type and can be
completed later. If R is invalid, then it is replaced completed later. If R is invalid, then it is
by error_mark_node so that it will not be added to replaced by error_mark_node so that it will not be
TYPE_FIELDS. */ added to TYPE_FIELDS. */
tree rtype = TREE_TYPE (r); 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); cxx_incomplete_type_error (r, rtype);
r = error_mark_node; r = error_mark_node;
} }
} }
/* R will have a TREE_CHAIN if and only if it has already been /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
processed by finish_member_declaration. This can happen such a thing will already have been added to the field
if, for example, it is a TYPE_DECL for a class-scoped list by tsubst_enum in finish_member_declaration in the
ENUMERAL_TYPE; such a thing will already have been added to CLASSTYPE_TAGS case above. */
the field list by tsubst_enum above. */ if (!(TREE_CODE (r) == TYPE_DECL
if (!TREE_CHAIN (r)) && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
&& TYPE_CONTEXT (TREE_TYPE (r)) == type))
{ {
set_current_access_from_decl (r); set_current_access_from_decl (r);
finish_member_declaration (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 ();
} }
else
for (t = CLASSTYPE_FRIEND_CLASSES (pattern); {
t != NULL_TREE; if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
t = TREE_CHAIN (t))
{ {
tree friend_type = TREE_VALUE (t); /* Build new CLASSTYPE_FRIEND_CLASSES. */
tree friend_type = t;
tree new_friend_type; tree new_friend_type;
if (TREE_CODE (friend_type) == TEMPLATE_DECL) if (TREE_CODE (friend_type) == TEMPLATE_DECL)
...@@ -5378,20 +5377,21 @@ instantiate_class_template (type) ...@@ -5378,20 +5377,21 @@ instantiate_class_template (type)
if (TREE_CODE (friend_type) == TEMPLATE_DECL) if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl; --processing_template_decl;
} }
else
/* 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)); /* Build new DECL_FRIENDLIST. */
require_complete_type (t);
add_friend (type,
tsubst_friend_function (t, args));
}
}
} }
/* Set the file and line number information to whatever is given for /* Set the file and line number information to whatever is given for
the class itself. This puts error messages involving generated the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point implicit functions at a predictable point, and the same point
that would be used for non-template classes. */ that would be used for non-template classes. */
typedecl = TYPE_MAIN_DECL (type);
lineno = DECL_SOURCE_LINE (typedecl); lineno = DECL_SOURCE_LINE (typedecl);
input_filename = DECL_SOURCE_FILE (typedecl); input_filename = DECL_SOURCE_FILE (typedecl);
......
...@@ -1754,6 +1754,7 @@ begin_class_definition (t) ...@@ -1754,6 +1754,7 @@ begin_class_definition (t)
TYPE_BINFO_BASETYPES (t) = NULL_TREE; TYPE_BINFO_BASETYPES (t) = NULL_TREE;
TYPE_FIELDS (t) = NULL_TREE; TYPE_FIELDS (t) = NULL_TREE;
TYPE_METHODS (t) = NULL_TREE; TYPE_METHODS (t) = NULL_TREE;
CLASSTYPE_DECL_LIST (t) = NULL_TREE;
CLASSTYPE_TAGS (t) = NULL_TREE; CLASSTYPE_TAGS (t) = NULL_TREE;
CLASSTYPE_VBASECLASSES (t) = NULL_TREE; CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
...@@ -1835,6 +1836,8 @@ finish_member_declaration (decl) ...@@ -1835,6 +1836,8 @@ finish_member_declaration (decl)
if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c) if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
SET_DECL_LANGUAGE (decl, lang_cplusplus); 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 /* Put functions on the TYPE_METHODS list and everything else on the
TYPE_FIELDS list. Note that these are built up in reverse order. TYPE_FIELDS list. Note that these are built up in reverse order.
We reverse them (to obtain declaration order) in finish_struct. */ 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> 2002-10-29 Hans-Peter Nilsson <hp@bitrange.com>
* lib/compat.exp (compat-execute): Don't clean out a gluefile. * lib/compat.exp (compat-execute): Don't clean out a gluefile.
......
...@@ -8,12 +8,12 @@ template <class T> struct X { ...@@ -8,12 +8,12 @@ template <class T> struct X {
T t; // { dg-error "incomplete" } T t; // { dg-error "incomplete" }
}; };
template <class T> struct Y { // { dg-error "instantiated" } template <class T> struct Y {
X<T> x; X<T> x; // { dg-error "instantiated" }
}; };
template <class T> struct Z { // { dg-error "instantiated|declaration" } template <class T> struct Z { // { dg-error "declaration" }
Y<Z<T> > y; Y<Z<T> > y; // { dg-error "instantiated" }
}; };
struct ZZ : Z<int> 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 @@ ...@@ -3,9 +3,9 @@
template<int M, int N> template<int M, int N>
class GCD { class GCD {
public: 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() { int main() {
GCD< 1, 0 >::val; // ERROR - division GCD< 1, 0 >::val; // ERROR - instantiated
} }
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
template<class T> template<class T>
class X { class X {
class Y : public T {}; // ERROR - invalid base type class Y : public T {};
Y y; Y y; // ERROR - invalid base type
}; };
int main() { int main() {
X<int> x; X<int> x; // ERROR - instantiated
} }
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
template <class T> template <class T>
struct S1 { struct S1 {
friend bool f<>(const S1&);
typedef T X; typedef T X;
friend bool f<>(const S1&);
}; };
template <class T> 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