Commit b0e0b31f by Mark Mitchell Committed by Mark Mitchell

cp-tree.h: Revert previous change.

	* cp-tree.h: Revert previous change.
	(finish_struct_methods): Remove declaration.
	* class.c: Revert previous change.
	(maybe_warn_about_overly_private_class): New function.
	(finish_struct_methods): Declare here, and make static.  Remove
	unnecessary parameters.  Tidy slightly.  Use
	maybe_warn_about_overly_private_class.
	(finish_struct_1): Adjust.  Remove check for private constructors,
	now done elsewhere.
	(finish_struct): Adjust.

From-SVN: r22426
parent bf71cd2e
1998-09-15 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h: Revert previous change.
(finish_struct_methods): Remove declaration.
* class.c: Revert previous change.
(maybe_warn_about_overly_private_class): New function.
(finish_struct_methods): Declare here, and make static. Remove
unnecessary parameters. Tidy slightly. Use
maybe_warn_about_overly_private_class.
(finish_struct_1): Adjust. Remove check for private constructors,
now done elsewhere.
(finish_struct): Adjust.
1998-09-15 Andrew MacLeod <amacleod@cygnus.com> 1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
* except.c (expand_start_catch_block): No need to check for new * except.c (expand_start_catch_block): No need to check for new
...@@ -15,6 +28,14 @@ ...@@ -15,6 +28,14 @@
1998-09-14 Mark Mitchell <mark@markmitchell.com> 1998-09-14 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (lang_type): Add has_non_private_static_mem_fn.
(CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN): New macro, to access it.
* class.c (maybe_class_too_private_p): New function.
(finish_struct_methods): Use it.
(finish_struct_1): Likewise.
(finish_struct): Set CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN if
appropriate.
* pt.c (check_specialization_scope): Fix spelling error. * pt.c (check_specialization_scope): Fix spelling error.
(check_explicit_specialization): Remove code to handle explicit (check_explicit_specialization): Remove code to handle explicit
specializations in class scope; they are now correctly diagnosed specializations in class scope; they are now correctly diagnosed
......
...@@ -100,7 +100,8 @@ static void modify_all_indirect_vtables PROTO((tree, int, int, tree, ...@@ -100,7 +100,8 @@ static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
tree, tree)); tree, tree));
static void build_class_init_list PROTO((tree)); static void build_class_init_list PROTO((tree));
static int finish_base_struct PROTO((tree, struct base_info *)); static int finish_base_struct PROTO((tree, struct base_info *));
static int maybe_class_too_private_p PROTO((tree)); static void finish_struct_methods PROTO((tree));
static void maybe_warn_about_overly_private_class PROTO ((tree));
/* Way of stacking language names. */ /* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack; tree *current_lang_base, *current_lang_stack;
...@@ -1898,32 +1899,145 @@ grow_method (fndecl, method_vec_ptr) ...@@ -1898,32 +1899,145 @@ grow_method (fndecl, method_vec_ptr)
} }
} }
/* Returns non-zero if T is the sort of class for which we should /* Issue warnings about T having private constructors, but no friends,
check issue warnings like "all constructors are private". */ and so forth.
static int HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or
maybe_class_too_private_p (t) static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any
tree t; non-private static member functions. */
static void
maybe_warn_about_overly_private_class (t)
tree t;
{ {
if (!warn_ctor_dtor_privacy) if (warn_ctor_dtor_privacy
/* The user doesn't want to here these warnings. */ /* If the class has friends, those entities might create and
return 0; access instances, so we should not warn. */
&& !(CLASSTYPE_FRIEND_CLASSES (t)
|| DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))
/* We will have warned when the template was declared; there's
no need to warn on every instantiation. */
&& !CLASSTYPE_TEMPLATE_INSTANTIATION (t))
{
/* We only issue one warning, if more than one applies, because
otherwise, on code like:
class A {
// Oops - forgot `public:'
A();
A(const A&);
~A();
};
we warn several times about essentially the same problem. */
int has_member_fn = 0;
int has_nonprivate_method = 0;
tree fn;
/* Check to see if all (non-constructor, non-destructor) member
functions are private. (Since there are no friends or
non-private statics, we can't ever call any of the private
member functions.) */
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
/* We're not interested in compiler-generated methods; they
don't provide any way to call private members. */
if (!DECL_ARTIFICIAL (fn))
{
if (!TREE_PRIVATE (fn))
{
if (DECL_STATIC_FUNCTION_P (fn))
/* A non-private static member function is just like a
friend; it can create and invoke private member
functions, and be accessed without a class
instance. */
return;
has_nonprivate_method = 1;
break;
}
else
has_member_fn = 1;
}
if (CLASSTYPE_FRIEND_CLASSES (t) if (!has_nonprivate_method && has_member_fn)
|| DECL_FRIENDLIST (TYPE_MAIN_DECL (t))) {
/* The class has friends. Maybe they can make use of the class, int i;
even though it's very private. */ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
return 0; for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
|| TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
{
has_nonprivate_method = 1;
break;
}
if (!has_nonprivate_method)
{
cp_warning ("all member functions in class `%T' are private", t);
return;
}
}
if (CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN (t)) /* Even if some of the member functions are non-private, the
/* The class has a non-private static member function. Such a class won't be useful for much if all the constructors or
thing might be used, like a friend, to create instances of the destructors are private: such an object can never be created
class. */ or destroyed. */
return 0; if (TYPE_HAS_DESTRUCTOR (t))
{
tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
if (TREE_PRIVATE (dtor))
{
cp_warning ("`%#T' only defines a private destructor and has no friends",
t);
return;
}
}
if (TYPE_HAS_CONSTRUCTOR (t))
{
int nonprivate_ctor = 0;
/* If a non-template class does not define a copy
constructor, one is defined for it, enabling it to avoid
this warning. For a template class, this does not
happen, and so we would normally get a warning on:
return 1; template <class T> class C { private: C(); };
To avoid this asymmetry, we check TYPE_HAS_INIT_REF. */
if (!TYPE_HAS_INIT_REF (t))
nonprivate_ctor = 1;
else
for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
fn;
fn = OVL_NEXT (fn))
{
tree ctor = OVL_CURRENT (fn);
/* Ideally, we wouldn't count copy constructors (or, in
fact, any constructor that takes an argument of the
class type as a parameter) because such things cannot
be used to construct an instance of the class unless
you already have one. But, for now at least, we're
more generous. */
if (! TREE_PRIVATE (ctor))
{
nonprivate_ctor = 1;
break;
}
}
if (nonprivate_ctor == 0)
{
cp_warning ("`%#T' only defines private constructors and has no friends",
t);
return;
}
}
}
} }
/* Warn about duplicate methods in fn_fields. Also compact method /* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster. lists so that lookup can be made faster.
...@@ -1945,16 +2059,14 @@ maybe_class_too_private_p (t) ...@@ -1945,16 +2059,14 @@ maybe_class_too_private_p (t)
We also link each field which has shares a name with its baseclass We also link each field which has shares a name with its baseclass
to the head of the list of fields for that base class. This allows to the head of the list of fields for that base class. This allows
us to reduce search time in places like `build_method_call' to us to reduce search time in places like `build_method_call' to
consider only reasonably likely functions. */ consider only reasonably likely functions. */
tree static void
finish_struct_methods (t, fn_fields, nonprivate_method) finish_struct_methods (t)
tree t; tree t;
tree fn_fields;
int nonprivate_method;
{ {
tree fn_fields;
tree method_vec; tree method_vec;
tree save_fn_fields = fn_fields;
tree ctor_name = constructor_name (t); tree ctor_name = constructor_name (t);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
...@@ -1972,8 +2084,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -1972,8 +2084,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
/* First fill in entry 0 with the constructors, entry 1 with destructors, /* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */ and the next few with type conversion operators (if any). */
for (fn_fields = TYPE_METHODS (t); fn_fields;
for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) fn_fields = TREE_CHAIN (fn_fields))
{ {
tree fn_name = DECL_NAME (fn_fields); tree fn_name = DECL_NAME (fn_fields);
...@@ -2021,8 +2133,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2021,8 +2133,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
grow_method (fn_fields, &method_vec); grow_method (fn_fields, &method_vec);
} }
fn_fields = save_fn_fields; for (fn_fields = TYPE_METHODS (t); fn_fields;
for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) fn_fields = TREE_CHAIN (fn_fields))
{ {
tree fn_name = DECL_NAME (fn_fields); tree fn_name = DECL_NAME (fn_fields);
...@@ -2050,33 +2162,14 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2050,33 +2162,14 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_finish (&class_obstack); obstack_finish (&class_obstack);
CLASSTYPE_METHOD_VEC (t) = method_vec; CLASSTYPE_METHOD_VEC (t) = method_vec;
if (nonprivate_method == 0 && maybe_class_too_private_p (t)) if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
{ /* We thought there was a destructor, but there wasn't. Some
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); parse errors cause this anomalous situation. */
for (i = 0; i < n_baseclasses; i++) TYPE_HAS_DESTRUCTOR (t) = 0;
if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
|| TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) /* Issue warnings about private constructors and such. If there are
{ no methods, then some public defaults are generated. */
nonprivate_method = 1; maybe_warn_about_overly_private_class (t);
break;
}
if (nonprivate_method == 0)
cp_warning ("all member functions in class `%T' are private", t);
}
/* Warn if all destructors are private (in which case this class is
effectively unusable. */
if (TYPE_HAS_DESTRUCTOR (t))
{
tree dtor = TREE_VEC_ELT (method_vec, 1);
/* Wild parse errors can cause this to happen. */
if (dtor == NULL_TREE)
TYPE_HAS_DESTRUCTOR (t) = 0;
else if (TREE_PRIVATE (dtor) && maybe_class_too_private_p (t))
cp_warning ("`%#T' only defines a private destructor and has no friends",
t);
}
/* Now for each member function (except for constructors and /* Now for each member function (except for constructors and
destructors), compute where member functions of the same destructors), compute where member functions of the same
...@@ -2102,8 +2195,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2102,8 +2195,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
else else
obstack_free (current_obstack, baselink_vec); obstack_free (current_obstack, baselink_vec);
} }
return method_vec;
} }
/* Emit error when a duplicate definition of a type is seen. Patch up. */ /* Emit error when a duplicate definition of a type is seen. Patch up. */
...@@ -3063,7 +3154,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3063,7 +3154,6 @@ finish_struct_1 (t, warn_anon)
int any_default_members = 0; int any_default_members = 0;
int const_sans_init = 0; int const_sans_init = 0;
int ref_sans_init = 0; int ref_sans_init = 0;
int nonprivate_method = 0;
tree access_decls = NULL_TREE; tree access_decls = NULL_TREE;
int aggregate = 1; int aggregate = 1;
int empty = 1; int empty = 1;
...@@ -3165,8 +3255,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3165,8 +3255,6 @@ finish_struct_1 (t, warn_anon)
{ {
GNU_xref_member (current_class_name, x); GNU_xref_member (current_class_name, x);
nonprivate_method |= ! TREE_PRIVATE (x);
/* If this was an evil function, don't keep it in class. */ /* If this was an evil function, don't keep it in class. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue; continue;
...@@ -3538,9 +3626,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3538,9 +3626,6 @@ finish_struct_1 (t, warn_anon)
/* Synthesize any needed methods. Note that methods will be synthesized /* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */ for anonymous unions; grok_x_components undoes that. */
if (! fn_fields)
nonprivate_method = 1;
if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
&& !IS_SIGNATURE (t)) && !IS_SIGNATURE (t))
{ {
...@@ -3561,7 +3646,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3561,7 +3646,6 @@ finish_struct_1 (t, warn_anon)
if (DECL_VINDEX (dtor)) if (DECL_VINDEX (dtor))
add_virtual_function (&pending_virtuals, &pending_hard_virtuals, add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, dtor, t); &has_virtual, dtor, t);
nonprivate_method = 1;
} }
} }
...@@ -3632,28 +3716,8 @@ finish_struct_1 (t, warn_anon) ...@@ -3632,28 +3716,8 @@ finish_struct_1 (t, warn_anon)
if (fn_fields) if (fn_fields)
{ {
TYPE_METHODS (t) = fn_fields; TYPE_METHODS (t) = fn_fields;
method_vec = finish_struct_methods (t, fn_fields, nonprivate_method); finish_struct_methods (t);
method_vec = CLASSTYPE_METHOD_VEC (t);
if (TYPE_HAS_CONSTRUCTOR (t)
&& CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
&& DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
{
int nonprivate_ctor = 0;
tree ctor;
for (ctor = TREE_VEC_ELT (method_vec, 0);
ctor;
ctor = OVL_NEXT (ctor))
if (! TREE_PRIVATE (OVL_CURRENT (ctor)))
{
nonprivate_ctor = 1;
break;
}
if (nonprivate_ctor == 0 && maybe_class_too_private_p (t))
cp_warning ("`%#T' only defines private constructors and has no friends",
t);
}
} }
else else
{ {
...@@ -4229,12 +4293,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4229,12 +4293,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
TREE_PRIVATE (x) = access == access_private_node; TREE_PRIVATE (x) = access == access_private_node;
TREE_PROTECTED (x) = access == access_protected_node; TREE_PROTECTED (x) = access == access_protected_node;
if (!TREE_PRIVATE (x)
&& TREE_CODE (x) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (x)
&& DECL_STATIC_FUNCTION_P (x))
CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN (t) = 1;
if (TREE_CODE (x) == TEMPLATE_DECL) if (TREE_CODE (x) == TEMPLATE_DECL)
{ {
TREE_PRIVATE (DECL_RESULT (x)) = TREE_PRIVATE (x); TREE_PRIVATE (DECL_RESULT (x)) = TREE_PRIVATE (x);
...@@ -4363,8 +4421,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4363,8 +4421,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
= tree_cons (NULL_TREE, d, = tree_cons (NULL_TREE, d,
DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))); DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
} }
CLASSTYPE_METHOD_VEC (t) finish_struct_methods (t);
= finish_struct_methods (t, TYPE_METHODS (t), 1);
TYPE_SIZE (t) = integer_zero_node; TYPE_SIZE (t) = integer_zero_node;
} }
else else
......
...@@ -621,12 +621,11 @@ struct lang_type ...@@ -621,12 +621,11 @@ struct lang_type
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1; unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1; unsigned non_aggregate : 1;
unsigned has_non_private_static_mem_fn : 1;
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */ member `dummy' with new bits if you go over the edge. */
unsigned dummy : 10; unsigned dummy : 11;
} type_flags; } type_flags;
int n_ancestors; int n_ancestors;
...@@ -1452,10 +1451,6 @@ extern int flag_new_for_scope; ...@@ -1452,10 +1451,6 @@ extern int flag_new_for_scope;
#define TYPE_NON_AGGREGATE_CLASS(NODE) \ #define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE)) (IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if NODE has a non-private static member function. */
#define CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN(NODE) \
(TYPE_LANG_SPECIFIC (NODE)->type_flags.has_non_private_static_mem_fn)
/* Nonzero if there is a user-defined X::op=(x&) for this class. */ /* Nonzero if there is a user-defined X::op=(x&) for this class. */
#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref) #define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref) #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
...@@ -2414,7 +2409,6 @@ extern tree get_vfield_offset PROTO((tree)); ...@@ -2414,7 +2409,6 @@ extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree)); extern void duplicate_tag_error PROTO((tree));
extern tree finish_struct PROTO((tree, tree, tree, int)); extern tree finish_struct PROTO((tree, tree, tree, int));
extern tree finish_struct_1 PROTO((tree, int)); extern tree finish_struct_1 PROTO((tree, int));
extern tree finish_struct_methods PROTO((tree, tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *)); extern int resolves_to_fixed_type_p PROTO((tree, int *));
extern void init_class_processing PROTO((void)); extern void init_class_processing PROTO((void));
extern int is_empty_class PROTO((tree)); extern int is_empty_class PROTO((tree));
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
// 04 // 04
// local names (14.6.1 p 4) // local names (14.6.1 p 4)
template <class T10, int i> class Xfour {// ERROR - .* template <class T10, int i> struct Xfour {// ERROR - .*
int T10; // ERROR - .* int T10; // ERROR - .*
void f(){ void f(){
char T10; // ERROR - .* char T10; // ERROR - .*
...@@ -90,7 +90,7 @@ template <class T10, int i> class Xfour {// ERROR - .* ...@@ -90,7 +90,7 @@ template <class T10, int i> class Xfour {// ERROR - .*
// 05 // 05
// using different tempate-parms for out-of-line defs // using different tempate-parms for out-of-line defs
template <class T12, int i> class Xfive { template <class T12, int i> struct Xfive {
void f(); void f();
}; };
...@@ -189,7 +189,7 @@ public: ...@@ -189,7 +189,7 @@ public:
// 13 // 13
// member templates, non-type parameters // member templates, non-type parameters
template <long l>// ERROR - .* template <long l>// ERROR - .*
class Xthirteen { struct Xthirteen {
template <long l> long comp_ge(long test) {// ERROR - . template <long l> long comp_ge(long test) {// ERROR - .
long local_value; long local_value;
if (local_value > value) if (local_value > value)
......
...@@ -112,7 +112,7 @@ protected: ...@@ -112,7 +112,7 @@ protected:
// 20 // 20
// local names (14.6.1 p 4) part two, variable names as template param // local names (14.6.1 p 4) part two, variable names as template param
template <class T17, int i> class Xtwenty { template <class T17, int i> struct Xtwenty {
void f(){ void f(){
T17 my_type; //ok T17 my_type; //ok
for (int j = 0; j < 5; ++l) for (int j = 0; j < 5; ++l)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Build don't link: // Build don't link:
template <class T> template <class T>
class A { struct A {
int i; int i;
Blarg () : i(0) { } // ERROR - Blarg () : i(0) { } // ERROR -
}; };
// Build don't link:
class A {
};
class B {
public:
void f();
private:
B ();
B (const B&);
}; // WARNING - only private constructors
class C {
public:
void f();
private:
~C ();
}; // WARNING - only private destructors
class D {
private:
void f();
}; // WARNING - all member functions are private
template <class T>
class X {
private:
~X ();
}; // WARNING - only private destructors
template class X<int>;
template class X<double>;
template <class T>
class Y {
private:
Y ();
Y (const Y&);
}; // WARNING - only private constructors
template <class T>
class Z {
private:
void f();
}; // WARNING - all member functions are private
...@@ -4,7 +4,7 @@ template <class T> ...@@ -4,7 +4,7 @@ template <class T>
class S class S
{ {
template <class U> template <class U>
class S2 { struct S2 {
S2(const S2<U>& s2u) {} S2(const S2<U>& s2u) {}
}; };
}; };
......
// Build don't link: // Build don't link:
// GROUPS passed membertemplates // GROUPS passed membertemplates
template <class T> template <class T>
class S struct S
{ {
S(const S<T>& x) {} S(const S<T>& x) {}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Build don't link: // Build don't link:
template <class T> template <class T>
class A struct A
{ {
typedef enum typedef enum
{ {
......
...@@ -6,7 +6,7 @@ class a ...@@ -6,7 +6,7 @@ class a
vector<s> vs; vector<s> vs;
friend class b; friend class b;
}; };
class b struct b
{ {
vector<a> va; vector<a> va;
operator vector< vector<s> >() operator vector< vector<s> >()
......
...@@ -6,7 +6,7 @@ class a ...@@ -6,7 +6,7 @@ class a
vector<s> vs; vector<s> vs;
friend class b; friend class b;
}; };
class b struct b
{ {
vector<a> va; vector<a> va;
operator vector< vector<s> >() operator vector< vector<s> >()
......
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