decl.c (grokfndecl): Undo COMPONENT_REF damage caused by bison parser ickiness.
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 27 Nov 2000 12:53:38 +0000 (12:53 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 27 Nov 2000 12:53:38 +0000 (12:53 +0000)
cp:
* decl.c (grokfndecl): Undo COMPONENT_REF damage caused by
bison parser ickiness.
* pt.c (tsubst_friend_function): Enter namespace scope when
tsubsting the function name.
* cp-tree.h (DECL_TI_TEMPLATE): Update comment to reflect reality.
testsuite:
* g++.old-deja/g++.other/friend46.C: New test.

From-SVN: r37793

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.pt/friend46.C [new file with mode: 0644]

index f2b1adc92ec094d05424663f2b9c506bec03ea7d..438f29a13dc5523d54998c0c599efd605930593a 100644 (file)
@@ -1,3 +1,11 @@
+2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * decl.c (grokfndecl): Undo COMPONENT_REF damage caused by
+       bison parser ickiness.
+       * pt.c (tsubst_friend_function): Enter namespace scope when
+       tsubsting the function name.
+       * cp-tree.h (DECL_TI_TEMPLATE): Update comment to reflect reality.
+
 2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
 
        * cp-tree.h (binfo_from_vbase): Return the virtual base's binfo.
index ab10f46c2ec714cc5f00a2d901ea153d71a284bc..c8cfa2556535155fa9b0772617bf5fb22908b982 100644 (file)
@@ -2362,8 +2362,9 @@ struct lang_decl
 
    As a special case, for a member friend template of a template
    class, this value will not be a TEMPLATE_DECL, but rather a
-   LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template
-   and any explicit template arguments provided.  For example, in:
+   LOOKUP_EXPR, IDENTIFIER_NODE or OVERLOAD indicating the name of
+   the template and any explicit template arguments provided.  For
+   example, in:
 
      template <class T> struct S { friend void f<int>(int, double); }
 
index 380b734551e322b02def3fea98424f4daccc3b34..3ca4ff6308487c4c5bdcb6d804dfa31ed5a544e9 100644 (file)
@@ -8944,6 +8944,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
           orig_declarator);
       else
        {
+         tree fns = TREE_OPERAND (orig_declarator, 0);
+         tree args = TREE_OPERAND (orig_declarator, 1);
+         
          if (PROCESSING_REAL_TEMPLATE_DECL_P ())
            {
              /* Something like `template <class T> friend void f<T>()'.  */
@@ -8956,10 +8959,22 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
          /* A friend declaration of the form friend void f<>().  Record
             the information in the TEMPLATE_ID_EXPR.  */
          SET_DECL_IMPLICIT_INSTANTIATION (decl);
-         DECL_TEMPLATE_INFO (decl)
-           = tree_cons (TREE_OPERAND (orig_declarator, 0),
-                        TREE_OPERAND (orig_declarator, 1),
-                        NULL_TREE);
+
+          if (TREE_CODE (fns) == COMPONENT_REF)
+            {
+              /* Due to bison parser ickiness, we will have already looked
+                 up an operator_name or PFUNCNAME within the current class
+                 (see template_id in parse.y). If the current class contains
+                 such a name, we'll get a COMPONENT_REF here. Undo that. */
+              
+              my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+                                  == current_class_type, 20001120);
+              fns = TREE_OPERAND (fns, 1);
+            }
+         my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+                             || TREE_CODE (fns) == LOOKUP_EXPR
+                             || TREE_CODE (fns) == OVERLOAD, 20001120);
+         DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
 
          if (has_default_arg)
            {
index bbc67009509156faac3a4f3a4d6ec4b83b81e6b9..5827c28ae7d55381db2ce65cf93a397404816f52 100644 (file)
@@ -4422,17 +4422,22 @@ tsubst_friend_function (decl, args)
        function declaration.  Now, we have to figure out what
        instantiation of what template.  */
     {
-      tree template_id;
+      tree template_id, arglist, fns;
       tree new_args;
       tree tmpl;
-
-      template_id
-       = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
-                                                args, /*complain=*/1, 
-                                                NULL_TREE),
-                                   tsubst (DECL_TI_ARGS (decl),
-                                           args, /*complain=*/1, 
-                                           NULL_TREE));
+      tree ns = CP_DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
+      
+      /* Friend functions are looked up in the containing namespace scope.
+         We must enter that scope, to avoid finding member functions of the
+         current cless with same name.  */
+      push_nested_namespace (ns);
+      fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
+                         /*complain=*/1, NULL_TREE);
+      pop_nested_namespace (ns);
+      arglist = tsubst (DECL_TI_ARGS (decl), args,
+                        /*complain=*/1, NULL_TREE);
+      template_id = lookup_template_function (fns, arglist);
+      
       new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
       tmpl = determine_specialization (template_id, new_friend,
                                       &new_args, 
index 1aeaf03a9dd2cbdf154477237bde4ded0a451c27..0fce517ce3bdc3071428d35924d39e0b3dd43593 100644 (file)
@@ -1,3 +1,7 @@
+2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/friend46.C: New test.
+
 2000-11-27  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.old-deja/g++.other/ptrmem8.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend46.C b/gcc/testsuite/g++.old-deja/g++.pt/friend46.C
new file mode 100644 (file)
index 0000000..58c87c4
--- /dev/null
@@ -0,0 +1,29 @@
+// Build don't link:
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 17 Nov 2000 <nathan@codesourcery.com>
+
+// bug 43. Two failings, bison parser ickiness caused us to find the member
+// named the same as a friend, and then when instantiating, we'd lookup in
+// the wrong scope.
+
+namespace X {
+  template <class T> class P;
+  
+  template <class T> void operator- (const P<T>&);
+  
+  template <class T>
+  struct V
+  {
+    V (const T&);
+  
+    void operator- ();
+    friend void operator-<> (const P<T>& a);
+  };
+}
+
+int main()
+{
+  X::V<double> b(1.0);
+
+  return 0;
+}