aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2005-03-14 14:51:25 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2005-03-14 14:51:25 +0000
commit5a24482e72fb06ef2e93050cdb056002f99bb226 (patch)
treeebe96dca1d08f5e123696a21d05cb1a03baaae0f /gcc
parent184107932d56261a7786e3086212cfa32db6acd0 (diff)
downloadgcc-5a24482e72fb06ef2e93050cdb056002f99bb226.zip
gcc-5a24482e72fb06ef2e93050cdb056002f99bb226.tar.gz
gcc-5a24482e72fb06ef2e93050cdb056002f99bb226.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/name-lookup.c26
-rw-r--r--gcc/cp/pt.c39
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/template/friend34.C16
-rw-r--r--gcc/testsuite/g++.dg/template/friend35.C28
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/inherit2.C8
7 files changed, 116 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e2a7de3..0ac2a84 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
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
PR c++/1016
* cp-tree.h (pushtag): Adjust declaration.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4a5429c..fda7d34 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1147f79..51d32b3 100644
--- a/gcc/cp/pt.c
+++ b/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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 993b95b..841c733 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,13 @@
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
PR c++/1016
* g++.dg/lookup/hidden-class1.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/friend34.C b/gcc/testsuite/g++.dg/template/friend34.C
new file mode 100644
index 0000000..555cf35
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend34.C
@@ -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 *) {}
diff --git a/gcc/testsuite/g++.dg/template/friend35.C b/gcc/testsuite/g++.dg/template/friend35.C
new file mode 100644
index 0000000..b150ccd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend35.C
@@ -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;
+ }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/inherit2.C b/gcc/testsuite/g++.old-deja/g++.pt/inherit2.C
index 2ae5672..136050d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/inherit2.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/inherit2.C
@@ -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 "" "" } -
}
};