OSDN Git Service

PR c++/29020
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Oct 2006 06:53:55 +0000 (06:53 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Oct 2006 06:53:55 +0000 (06:53 +0000)
* 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.
PR c++/29020
* g++.dg/template/friend48.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117425 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/friend.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/friend48.C [new file with mode: 0644]

index 835aabb..3d7ccc0 100644 (file)
@@ -1,5 +1,11 @@
 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.
+
        PR c++/29138
        * decl2.c (grokfield): Don't handle access declarations here.
        * parser.c (cp_parser_using_declaration): Handle access
index 0c9712e..d92df5f 100644 (file)
@@ -396,21 +396,21 @@ make_friend_class (tree type, tree friend_type, bool complain)
     }
 }
 
-/* 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, tree decl,
        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 05151cd..2672f15 100644 (file)
@@ -3632,10 +3632,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
        {
          /* 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)
-           parser->scope = resolve_typename_type (parser->scope,
-                                                  /*only_current_p=*/false);
+           {
+             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 7cc0dd2..d819ac3 100644 (file)
@@ -1,3 +1,8 @@
+2006-10-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/29020
+       * g++.dg/template/friend48.C: New test.
+
 2006-10-04  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/29098
diff --git a/gcc/testsuite/g++.dg/template/friend48.C b/gcc/testsuite/g++.dg/template/friend48.C
new file mode 100644 (file)
index 0000000..604697d
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/29020
+
+template<int> struct A
+{
+  void foo();
+};
+
+struct B
+{
+  template<int N> friend void A<N>::A::foo();
+};
+