re PR c++/4403 (incorrect class becomes a friend in template)
PR c++/4403 PR c++/9783, DR433 * name-lookup.c (pushtag): Skip template parameter scope when scope is ts_global. Don't push tag into template parameter scope. * pt.c (instantiate_class_template): Reorder friend class template substitution to handle non-dependent friend class that hasn't been previously declared. * g++.dg/template/friend34.C: New test. * g++.dg/template/friend35.C: Likewise. * g++.old-deja/g++.pt/inherit2.C: Remove XFAIL's. From-SVN: r96432
This commit is contained in:
parent
184107932d
commit
5a24482e72
@ -1,3 +1,14 @@
|
||||
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/4403
|
||||
PR c++/9783, DR433
|
||||
* name-lookup.c (pushtag): Skip template parameter scope when
|
||||
scope is ts_global. Don't push tag into template parameter
|
||||
scope.
|
||||
* pt.c (instantiate_class_template): Reorder friend class
|
||||
template substitution to handle non-dependent friend class
|
||||
that hasn't been previously declared.
|
||||
|
||||
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
Friend class name lookup 5/n
|
||||
|
@ -4571,10 +4571,19 @@ maybe_process_template_type_declaration (tree type, int is_friend,
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Push a tag name NAME for struct/class/union/enum type TYPE.
|
||||
Normally put it into the inner-most non-sk_cleanup scope,
|
||||
but if GLOBALIZE is true, put it in the inner-most non-class scope.
|
||||
The latter is needed for implicit declarations.
|
||||
/* Push a tag name NAME for struct/class/union/enum type TYPE. In case
|
||||
that the NAME is a class template, the tag is processed but not pushed.
|
||||
|
||||
The pushed scope depend on the SCOPE parameter:
|
||||
- When SCOPE is TS_CURRENT, put it into the inner-most non-sk_cleanup
|
||||
scope.
|
||||
- When SCOPE is TS_GLOBAL, put it in the inner-most non-class and
|
||||
non-template-parameter scope. This case is needed for forward
|
||||
declarations.
|
||||
- When SCOPE is TS_WITHIN_ENCLOSING_NON_CLASS, this is similar to
|
||||
TS_GLOBAL case except that names within template-parameter scopes
|
||||
are not pushed at all.
|
||||
|
||||
Returns TYPE upon success and ERROR_MARK_NODE otherwise. */
|
||||
|
||||
tree
|
||||
@ -4590,10 +4599,9 @@ pushtag (tree name, tree type, tag_scope scope)
|
||||
/* Neither are the scopes used to hold template parameters
|
||||
for an explicit specialization. For an ordinary template
|
||||
declaration, these scopes are not scopes from the point of
|
||||
view of the language -- but we need a place to stash
|
||||
things that will go in the containing namespace when the
|
||||
template is instantiated. */
|
||||
|| (b->kind == sk_template_parms && b->explicit_spec_p)
|
||||
view of the language. */
|
||||
|| (b->kind == sk_template_parms
|
||||
&& (b->explicit_spec_p || scope == ts_global))
|
||||
|| (b->kind == sk_class
|
||||
&& (scope != ts_current
|
||||
/* We may be defining a new type in the initializer
|
||||
@ -4666,7 +4674,7 @@ pushtag (tree name, tree type, tag_scope scope)
|
||||
else
|
||||
pushdecl_class_level (d);
|
||||
}
|
||||
else
|
||||
else if (b->kind != sk_template_parms)
|
||||
d = pushdecl_with_scope (d, b);
|
||||
|
||||
if (d == error_mark_node)
|
||||
|
39
gcc/cp/pt.c
39
gcc/cp/pt.c
@ -5781,11 +5781,13 @@ instantiate_class_template (tree type)
|
||||
|
||||
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
|
||||
{
|
||||
/* template <class T> friend class C; */
|
||||
friend_type = tsubst_friend_class (friend_type, args);
|
||||
adjust_processing_template_decl = true;
|
||||
}
|
||||
else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
|
||||
{
|
||||
/* template <class T> friend class C::D; */
|
||||
friend_type = tsubst (friend_type, args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
|
||||
@ -5794,6 +5796,15 @@ instantiate_class_template (tree type)
|
||||
}
|
||||
else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
|
||||
{
|
||||
/* This could be either
|
||||
|
||||
friend class T::C;
|
||||
|
||||
when dependent_type_p is false or
|
||||
|
||||
template <class U> friend class T::C;
|
||||
|
||||
otherwise. */
|
||||
friend_type = tsubst (friend_type, args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
/* Bump processing_template_decl for correct
|
||||
@ -5803,13 +5814,14 @@ instantiate_class_template (tree type)
|
||||
adjust_processing_template_decl = true;
|
||||
--processing_template_decl;
|
||||
}
|
||||
else if (uses_template_parms (friend_type))
|
||||
friend_type = tsubst (friend_type, args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
else if (CLASSTYPE_USE_TEMPLATE (friend_type))
|
||||
friend_type = friend_type;
|
||||
else
|
||||
else if (!CLASSTYPE_USE_TEMPLATE (friend_type)
|
||||
&& hidden_name_p (TYPE_NAME (friend_type)))
|
||||
{
|
||||
/* friend class C;
|
||||
|
||||
where C hasn't been declared yet. Let's lookup name
|
||||
from namespace scope directly, bypassing any name that
|
||||
come from dependent base class. */
|
||||
tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
|
||||
|
||||
/* The call to xref_tag_from_type does injection for friend
|
||||
@ -5817,9 +5829,22 @@ instantiate_class_template (tree type)
|
||||
push_nested_namespace (ns);
|
||||
friend_type =
|
||||
xref_tag_from_type (friend_type, NULL_TREE,
|
||||
/*tag_scope=*/ts_global);
|
||||
/*tag_scope=*/ts_current);
|
||||
pop_nested_namespace (ns);
|
||||
}
|
||||
else if (uses_template_parms (friend_type))
|
||||
/* friend class C<T>; */
|
||||
friend_type = tsubst (friend_type, args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
/* Otherwise it's
|
||||
|
||||
friend class C;
|
||||
|
||||
where C is already declared or
|
||||
|
||||
friend class C<int>;
|
||||
|
||||
We don't have to do anything in these cases. */
|
||||
|
||||
if (adjust_processing_template_decl)
|
||||
/* Trick make_friend_class into realizing that the friend
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/4403
|
||||
PR c++/9783, DR433
|
||||
* g++.dg/template/friend34.C: New test.
|
||||
* g++.dg/template/friend35.C: Likewise.
|
||||
* g++.old-deja/g++.pt/inherit2.C: Remove XFAIL's.
|
||||
|
||||
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
Friend class name lookup 5/n
|
||||
|
16
gcc/testsuite/g++.dg/template/friend34.C
Normal file
16
gcc/testsuite/g++.dg/template/friend34.C
Normal file
@ -0,0 +1,16 @@
|
||||
// { dg-do compile }
|
||||
|
||||
// Origin: mleone@pixar.com
|
||||
// Wolfgang Bangerth <bangerth@ticam.utexas.edu>
|
||||
|
||||
// PR c++/9783: Forward declaration of class in template.
|
||||
|
||||
template <typename T>
|
||||
struct C {
|
||||
void foo (struct X *);
|
||||
};
|
||||
|
||||
struct X {};
|
||||
|
||||
template <typename T>
|
||||
void C<T>::foo(struct X *) {}
|
28
gcc/testsuite/g++.dg/template/friend35.C
Normal file
28
gcc/testsuite/g++.dg/template/friend35.C
Normal file
@ -0,0 +1,28 @@
|
||||
// { dg-do compile }
|
||||
|
||||
// Origin: Giovanni Bajo <giovannibajo@libero.it>
|
||||
|
||||
// PR c++/4403: Incorrect friend class chosen during instantiation.
|
||||
|
||||
template <typename T>
|
||||
struct A
|
||||
{
|
||||
struct F;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct B : A<T>
|
||||
{
|
||||
friend struct F;
|
||||
private:
|
||||
int priv;
|
||||
};
|
||||
|
||||
struct F
|
||||
{
|
||||
void func(void)
|
||||
{
|
||||
B<int> b;
|
||||
b.priv = 0;
|
||||
}
|
||||
};
|
@ -24,8 +24,8 @@ template <class T> class B
|
||||
static T value_AC;
|
||||
};
|
||||
template <typename T> T B<T>::valueA_AA;
|
||||
template <typename T> T B<T>::valueA_AC;// { dg-error "" "" { xfail *-*-* } } private -
|
||||
template <typename T> T B<T>::value_AC; // { dg-bogus "" "" { xfail *-*-* } } -
|
||||
template <typename T> T B<T>::valueA_AC;// { dg-error "" "" } private -
|
||||
template <typename T> T B<T>::value_AC; // { dg-bogus "" "" } -
|
||||
|
||||
// this one is a friend
|
||||
template <class T> struct A<T>::AA
|
||||
@ -41,7 +41,7 @@ template <class T> struct A<T>::AC
|
||||
{
|
||||
T M ()
|
||||
{
|
||||
return B<T>::valueA_AC; // { dg-error "" "" { xfail *-*-* } } within this context -
|
||||
return B<T>::valueA_AC; // { dg-error "" "" } within this context -
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ struct AC
|
||||
{
|
||||
int M ()
|
||||
{
|
||||
return B<int>::value_AC; // { dg-bogus "" "" { xfail *-*-* } } -
|
||||
return B<int>::value_AC; // { dg-bogus "" "" } -
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user