re PR c++/9162 ([New parser] Problem with default argument in a friend function)
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 3 Jul 2003 16:10:52 +0000 (16:10 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 3 Jul 2003 16:10:52 +0000 (16:10 +0000)
cp:
PR c++/9162
* decl.c (grokdeclarator): Return friend decls, not
void_type_node.
* decl2.c (grokfield): Alter friend decl check.
* parser.c (struct cp_parser): Document default_arg chain on
unparsed_functions_queue.
(cp_parser_save_default_args): New.
(cp_parser_init_declarator, cp_parser_function_definition,
cp_parser_member_declaration): Call it.
(cp_parser_class_specifier): Remove unused variable. Alter
processing of unparsed_functions_queue.
testsuite:
PR c++/9162
* g++.dg/parse/defarg4.C: New.

From-SVN: r68886

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/friend.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/defarg4.C [new file with mode: 0644]

index c0b47dc970b844086c52f9ca7f7dbb780b8e0e61..f75b8ac4a4f4d1c72f6df09c9607d419f72aeb64 100644 (file)
@@ -1,3 +1,17 @@
+2003-07-03  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9162
+       * decl.c (grokdeclarator): Return friend decls, not
+       void_type_node.
+       * decl2.c (grokfield): Alter friend decl check.
+       * parser.c (struct cp_parser): Document default_arg chain on
+       unparsed_functions_queue.
+       (cp_parser_save_default_args): New.
+       (cp_parser_init_declarator, cp_parser_function_definition,
+       cp_parser_member_declaration): Call it.
+       (cp_parser_class_specifier): Remove unused variable. Alter
+       processing of unparsed_functions_queue.
+
 2003-07-03  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * class.c (add_method, check_field_decl): Fix format specifier.
index 732ada291b4d2ae502364bfef95cd591ea9582dd..219c65996fd3f974ad5ac1687b329e45d50af799 100644 (file)
@@ -10779,9 +10779,6 @@ grokdeclarator (tree declarator,
 
            declarator = TREE_OPERAND (declarator, 0);
 
-           /* FIXME: This is where default args should be fully
-              processed.  */
-
            arg_types = grokparms (inner_parms);
 
            if (declarator && flags == DTOR_FLAG)
@@ -11536,30 +11533,24 @@ grokdeclarator (tree declarator,
            /* Friends are treated specially.  */
            if (ctype == current_class_type)
              warning ("member functions are implicitly friends of their class");
-           else
-             {
-               tree t = NULL_TREE;
-               if (decl && DECL_NAME (decl))
-                 {
-                   if (template_class_depth (current_class_type) == 0)
-                     {
-                       decl
-                         = check_explicit_specialization
-                         (declarator, decl,
-                          template_count, 2 * (funcdef_flag != 0) + 4);
-                       if (decl == error_mark_node)
-                         return error_mark_node;
-                     }
-                   
-                   t = do_friend (ctype, declarator, decl,
-                                  last_function_parms, *attrlist,
-                                  flags, quals, funcdef_flag);
-                 }
-               if (t && funcdef_flag)
-                 return t;
-  
-               return void_type_node;
-             }
+           else if (decl && DECL_NAME (decl))
+             {
+               if (template_class_depth (current_class_type) == 0)
+                 {
+                   decl = check_explicit_specialization
+                     (declarator, decl, template_count,
+                      2 * (funcdef_flag != 0) + 4);
+                   if (decl == error_mark_node)
+                     return error_mark_node;
+                 }
+               
+               decl = do_friend (ctype, declarator, decl,
+                                 last_function_parms, *attrlist,
+                                 flags, quals, funcdef_flag);
+               return decl;
+             }
+           else
+             return void_type_node;
          }
 
        /* Structure field.  It may not be a function, except for C++ */
index faa36f58b3cd99644099c0b034b2824c807ff688..ab29aeed45d1dd275189e067105e6344c348d483 100644 (file)
@@ -889,8 +889,14 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
     }
 
   /* Pass friendly classes back.  */
-  if (TREE_CODE (value) == VOID_TYPE)
-    return void_type_node;
+  if (value == void_type_node)
+    return value;
+
+  /* Pass friend decls back. */
+  if ((TREE_CODE (value) == FUNCTION_DECL
+       || TREE_CODE (value) == TEMPLATE_DECL)
+      && DECL_CONTEXT (value) != current_class_type)
+    return value;
 
   if (DECL_NAME (value) != NULL_TREE
       && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
index 0a0e82c7fcdbd522c7f18337b2c080e69c1ad541..e458a14bf1a478ac1f53a19c47fc161c63124cff 100644 (file)
@@ -306,10 +306,7 @@ make_friend_class (type, friend_type)
     }
 }
 
-/* Main friend processor.  This is large, and for modularity purposes,
-   has been removed from grokdeclarator.  It returns `void_type_node'
-   to indicate that something happened, though a FIELD_DECL is
-   not returned.
+/* Main friend processor. 
 
    CTYPE is the class this friend belongs to.
 
index 3654adbe0a84509d9a41eb4cd2e199a821e6a7a5..6155af404cdd74c57fa2008a53fe39bb03dc9bda 100644 (file)
@@ -1295,16 +1295,20 @@ typedef struct cp_parser GTY(())
      issued as an error message if a type is defined.  */
   const char *type_definition_forbidden_message;
 
-  /* A TREE_LIST of queues of functions whose bodies have been lexed,
-     but may not have been parsed.  These functions are friends of
-     members defined within a class-specification; they are not
-     procssed until the class is complete.  The active queue is at the
-     front of the list.
-
-     Within each queue, functions appear in the reverse order that
-     they appeared in the source.  Each TREE_VALUE is a
-     FUNCTION_DECL of TEMPLATE_DECL corresponding to a member
-     function.  */
+  /* A list of lists. The outer list is a stack, used for member
+     functions of local classes. At each level there are two sub-list,
+     one on TREE_VALUE and one on TREE_PURPOSE. Each of those
+     sub-lists has a FUNCTION_DECL or TEMPLATE_DECL on their
+     TREE_VALUE's. The functions are chained in reverse declaration
+     order.
+
+     The TREE_PURPOSE sublist contains those functions with default
+     arguments that need post processing, and the TREE_VALUE sublist
+     contains those functions with definitions that need post
+     processing.
+
+     These lists can only be processed once the outermost class being
+     defined is complete. */
   tree unparsed_functions_queues;
 
   /* The number of classes whose definitions are currently in
@@ -1679,6 +1683,8 @@ static tree cp_parser_single_declaration
   (cp_parser *, bool, bool *);
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
+static void cp_parser_save_default_args
+  (cp_parser *, tree);
 static void cp_parser_late_parsing_for_member
   (cp_parser *, tree);
 static void cp_parser_late_parsing_default_args
@@ -9735,10 +9741,14 @@ cp_parser_init_declarator (cp_parser* parser,
   /* For an in-class declaration, use `grokfield' to create the
      declaration.  */
   if (member_p)
-    decl = grokfield (declarator, decl_specifiers,
-                     initializer, /*asmspec=*/NULL_TREE,
+    {
+      decl = grokfield (declarator, decl_specifiers,
+                       initializer, /*asmspec=*/NULL_TREE,
                        /*attributes=*/NULL_TREE);
-
+      if (decl && TREE_CODE (decl) == FUNCTION_DECL)
+       cp_parser_save_default_args (parser, decl);
+    }
+  
   /* Finish processing the declaration.  But, skip friend
      declarations.  */
   if (!friend_p && decl)
@@ -11031,6 +11041,9 @@ cp_parser_function_definition (cp_parser* parser, bool* friend_p)
          return error_mark_node;
        }
 
+      /* Remember it, if there default args to post process.  */
+      cp_parser_save_default_args (parser, fn);
+      
       /* Create a token cache.  */
       cache = cp_token_cache_new ();
       /* Save away the tokens that make up the body of the 
@@ -11505,14 +11518,9 @@ cp_parser_class_specifier (cp_parser* parser)
      there is no need to delay the parsing of `A::B::f'.  */
   if (--parser->num_classes_being_defined == 0) 
     {
-      tree last_scope = NULL_TREE;
       tree queue_entry;
       tree fn;
 
-      /* Reverse the queue, so that we process it in the order the
-        functions were declared.  */
-      TREE_VALUE (parser->unparsed_functions_queues)
-       = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
         This two-phased approach handles cases like:
@@ -11523,13 +11531,13 @@ cp_parser_class_specifier (cp_parser* parser)
             };
 
          */
-      for (queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
-          queue_entry;
-          queue_entry = TREE_CHAIN (queue_entry))
+      for (TREE_PURPOSE (parser->unparsed_functions_queues)
+            = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
+          (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
+          TREE_PURPOSE (parser->unparsed_functions_queues)
+            = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
        {
          fn = TREE_VALUE (queue_entry);
-         if (DECL_FUNCTION_TEMPLATE_P (fn))
-           fn = DECL_TEMPLATE_RESULT (fn);
          /* Make sure that any template parameters are in scope.  */
          maybe_begin_member_template_processing (fn);
          /* If there are default arguments that have not yet been processed,
@@ -11539,24 +11547,19 @@ cp_parser_class_specifier (cp_parser* parser)
          maybe_end_member_template_processing ();
        }
       /* Now parse the body of the functions.  */
-      while (TREE_VALUE (parser->unparsed_functions_queues))
-
+      for (TREE_VALUE (parser->unparsed_functions_queues)
+            = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
+          (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));
+          TREE_VALUE (parser->unparsed_functions_queues)
+            = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues)))
        {
          /* Figure out which function we need to process.  */
-         queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
          fn = TREE_VALUE (queue_entry);
 
          /* Parse the function.  */
          cp_parser_late_parsing_for_member (parser, fn);
-
-         TREE_VALUE (parser->unparsed_functions_queues)
-           = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues));
        }
 
-      /* If LAST_SCOPE is non-NULL, then we have pushed scopes one
-        more time than we have popped, so me must pop here.  */
-      if (last_scope)
-       pop_scope (last_scope);
     }
 
   /* Put back any saved access checks.  */
@@ -12268,13 +12271,8 @@ cp_parser_member_declaration (cp_parser* parser)
              if (!friend_p)
                finish_member_declaration (decl);
 
-             /* If DECL is a function, we must return
-                to parse it later.  (Even though there is no definition,
-                there might be default arguments that need handling.)  */
              if (TREE_CODE (decl) == FUNCTION_DECL)
-               TREE_VALUE (parser->unparsed_functions_queues)
-                 = tree_cons (NULL_TREE, decl, 
-                              TREE_VALUE (parser->unparsed_functions_queues));
+               cp_parser_save_default_args (parser, decl);
            }
        }
     }
@@ -14129,6 +14127,27 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
     = TREE_CHAIN (parser->unparsed_functions_queues);
 }
 
+/* If DECL contains any default args, remeber it on the unparsed
+   functions queue.  */
+
+static void
+cp_parser_save_default_args (cp_parser* parser, tree decl)
+{
+  tree probe;
+
+  for (probe = TYPE_ARG_TYPES (TREE_TYPE (decl));
+       probe;
+       probe = TREE_CHAIN (probe))
+    if (TREE_PURPOSE (probe))
+      {
+       TREE_PURPOSE (parser->unparsed_functions_queues)
+         = tree_cons (NULL_TREE, decl, 
+                      TREE_PURPOSE (parser->unparsed_functions_queues));
+       break;
+      }
+  return;
+}
+
 /* FN is a FUNCTION_DECL which may contains a parameter with an
    unparsed DEFAULT_ARG.  Parse the default args now.  */
 
index 70bc1834e9ab8f76f3f0c08aa6596b85e446a3bf..c158b78539d58d438a93f26875944797092963c0 100644 (file)
@@ -1,3 +1,8 @@
+2003-07-03  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9162
+       * g++.dg/parse/defarg4.C: New.
+
 2003-07-03  Roger Sayle  <roger@eyesopen.com>
 
        PR target/10700
diff --git a/gcc/testsuite/g++.dg/parse/defarg4.C b/gcc/testsuite/g++.dg/parse/defarg4.C
new file mode 100644 (file)
index 0000000..39d0a89
--- /dev/null
@@ -0,0 +1,31 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 3 Jul 2003 <nathan@codesourcery.com>
+
+// PR c++ 9162. default args got left unprocessed
+
+struct S {
+  friend int foo (int = 100);
+};
+int i = foo ();
+
+struct R
+{
+  template <typename T> R (T, int = 0);
+};
+
+int Foo ()
+{
+  R s (1);
+}
+
+template <typename T> struct Q
+{
+  int Foo (T, int = 0);
+};
+
+int Foo (Q<int> *s)
+{
+  s->Foo (1);
+}