This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 29020
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 4 Oct 2006 00:02:51 -0700
- Subject: C++ PATCH: PR 29020
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/29020, a failure to accept a valid friend
declaration. Unfortunately, the meaning of qualified names in C++
depends on whether or not you are in a declaration; in
template <class T>
void S<T>::X::f() {}
you are supposed to look in to S<T> to make sure there really is a
type named X, whereas:
template <class T>
void f() {
return S<T>::X::f();
}
is erroneous; you need to use typename to refer to S<T>::X.
The C++ parser caches nested-name-specifiers; if it backtracks, it
doesn't reparse the nested-name-specifier. However, we were failing
to handle the difference between the two cases above when we
backtracked; fixed with this patch.
Tested on x86_64-unknown-linux-gnu, applied on the mainline. I will
apply to 4.1 after testing there.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-10-03 Mark Mitchell <mark@codesourcery.com>
PR c++/29020
* friend.c (do_friend): Improve comments; add assertion.
* parser.c (cp_parser_nested_name_specifier_opt): Resolve
typenames for qualified names used in declarations, even when
caching qualified name lookup.
2006-10-03 Mark Mitchell <mark@codesourcery.com>
PR c++/29020
* g++.dg/template/friend48.C: New test.
Index: gcc/cp/friend.c
===================================================================
--- gcc/cp/friend.c (revision 117408)
+++ gcc/cp/friend.c (working copy)
@@ -396,21 +396,21 @@ make_friend_class (tree type, tree frien
}
}
-/* Main friend processor.
-
- CTYPE is the class this friend belongs to.
-
- DECLARATOR is the name of the friend.
-
- DECL is the FUNCTION_DECL that the friend is.
-
- FLAGS is just used for `grokclassfn'. */
+/* Record DECL (a FUNCTION_DECL) as a friend of the
+ CURRENT_CLASS_TYPE. If DECL is a member function, CTYPE is the
+ class of which it is a member, as named in the friend declaration.
+ DECLARATOR is the name of the friend. FUNCDEF_FLAG is true if the
+ friend declaration is a definition of the function. FLAGS is as
+ for grokclass fn. */
tree
do_friend (tree ctype, tree declarator, tree decl,
tree attrlist, enum overload_flags flags,
bool funcdef_flag)
{
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ gcc_assert (!ctype || IS_AGGR_TYPE (ctype));
+
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
@@ -421,8 +421,6 @@ do_friend (tree ctype, tree declarator,
declarator = DECL_NAME (get_first_fn (declarator));
}
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-
if (ctype)
{
/* CLASS_TEMPLATE_DEPTH counts the number of template headers for
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 117409)
+++ gcc/cp/parser.c (working copy)
@@ -3632,6 +3632,17 @@ cp_parser_nested_name_specifier_opt (cp_
{
/* Grab the nested-name-specifier and continue the loop. */
cp_parser_pre_parsed_nested_name_specifier (parser);
+ /* If we originally encountered this nested-name-specifier
+ with IS_DECLARATION set to false, we will not have
+ resolved TYPENAME_TYPEs, so we must do so here. */
+ if (is_declaration
+ && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+ {
+ new_scope = resolve_typename_type (parser->scope,
+ /*only_current_p=*/false);
+ if (new_scope != error_mark_node)
+ parser->scope = new_scope;
+ }
success = true;
continue;
}
Index: gcc/testsuite/g++.dg/template/friend48.C
===================================================================
--- gcc/testsuite/g++.dg/template/friend48.C (revision 0)
+++ gcc/testsuite/g++.dg/template/friend48.C (revision 0)
@@ -0,0 +1,12 @@
+// PR c++/29020
+
+template<int> struct A
+{
+ void foo();
+};
+
+struct B
+{
+ template<int N> friend void A<N>::A::foo();
+};
+