diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2005-03-14 14:51:25 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2005-03-14 14:51:25 +0000 |
commit | 5a24482e72fb06ef2e93050cdb056002f99bb226 (patch) | |
tree | ebe96dca1d08f5e123696a21d05cb1a03baaae0f /gcc | |
parent | 184107932d56261a7786e3086212cfa32db6acd0 (diff) | |
download | gcc-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/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 26 | ||||
-rw-r--r-- | gcc/cp/pt.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend34.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend35.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/inherit2.C | 8 |
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 "" "" } - } }; |