This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 29020


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();
+};
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]