]> gcc.gnu.org Git - gcc.git/commitdiff
call.c (convert_default_arg): Check for unprocessed DEFAULT_ARG.
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 11 Jan 2001 12:29:20 +0000 (12:29 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 11 Jan 2001 12:29:20 +0000 (12:29 +0000)
cp:
* call.c (convert_default_arg): Check for unprocessed
DEFAULT_ARG.
* cp-tree.h (replace_defarg): Move to spew.c.
(maybe_snarf_defarg, add_defarg_fn, do_pending_defargs): Move to
spew.c, which is where they really are.
(done_pending_defargs): Declare.
(unprocessed_defarg_fn): Declare.
* decl.c (replace_defarg): Move to spew.c
* parse.y (structsp): Call done_pending_defargs.
* spew.c (defarg_fns): Rearrange list structure.
(defarg_fnsdone): New static variable.
(defarg_depfns): New static variable.
(init_spew): Adjust.
(add_defarg_fn): Store the type in TREE_TYPE.
(do_pending_defargs): Detect and deal with ordering constraints
and circularity.
(done_pending_defargs): New function.
(unprocessed_defarg_fn): New function.
(replace_defarg): Moved from decl.c. Robustify. Don't save
if circularity detected.
testsuite:
* g++.old-deja/g++.other/defarg7.C: New test.
* g++.old-deja/g++.other/defarg8.C: New test.

From-SVN: r38903

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parse.y
gcc/cp/spew.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/defarg7.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/defarg8.C [new file with mode: 0644]

index d72b8b0d56ef6117a5fe8a01045d09a461502462..0981c7eab9b68eae34c9bb825b85dae0928583aa 100644 (file)
@@ -1,3 +1,26 @@
+2001-01-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * call.c (convert_default_arg): Check for unprocessed
+       DEFAULT_ARG.
+       * cp-tree.h (replace_defarg): Move to spew.c.
+       (maybe_snarf_defarg, add_defarg_fn, do_pending_defargs): Move to
+       spew.c, which is where they really are.
+       (done_pending_defargs): Declare.
+       (unprocessed_defarg_fn): Declare.
+       * decl.c (replace_defarg): Move to spew.c
+       * parse.y (structsp): Call done_pending_defargs.
+       * spew.c (defarg_fns): Rearrange list structure.
+       (defarg_fnsdone): New static variable.
+       (defarg_depfns): New static variable.
+       (init_spew): Adjust.
+       (add_defarg_fn): Store the type in TREE_TYPE.
+       (do_pending_defargs): Detect and deal with ordering constraints
+       and circularity.
+       (done_pending_defargs): New function.
+       (unprocessed_defarg_fn): New function.
+       (replace_defarg): Moved from decl.c. Robustify. Don't save
+       if circularity detected.
+
 2001-01-11  Nathan Sidwell  <nathan@codesourcery.com>
 
        * pt.c (unify): Check array has a domain, before checking
index a855963c82971e9ee84849ab1a1f48d8a219655a..5f12f7efe2002e57555f8cd08a8b3ffb73120f51 100644 (file)
@@ -3953,6 +3953,26 @@ convert_default_arg (type, arg, fn, parmnum)
      tree fn;
      int parmnum;
 {
+  if (TREE_CODE (arg) == DEFAULT_ARG)
+    {
+      /* When processing the default args for a class, we can find that
+         there is an ordering constraint, and we call a function who's
+         default args have not yet been converted. For instance,
+          class A {
+              A (int = 0);
+              void Foo (A const & = A ());
+          };
+         We must process A::A before A::Foo's default arg can be converted.
+         Remember the dependent function, so do_pending_defargs can retry,
+         and check loops.  */
+      unprocessed_defarg_fn (fn);
+      
+      /* Don't return error_mark node, as we won't be able to distinguish
+         genuine errors from this case, and that would lead to repeated
+         diagnostics.  Just make something of the right type.  */
+      return build1 (NOP_EXPR, type, integer_zero_node);
+    }
+
   if (fn && DECL_TEMPLATE_INFO (fn))
     arg = tsubst_default_argument (fn, type, arg);
 
index 2c229540f8bbfc928dfb5c825eef4fcca0c6d706..eea27e0233f83e3998e943cc3c8299858a7b38e8 100644 (file)
@@ -3874,7 +3874,6 @@ extern tree finish_method                 PARAMS ((tree));
 extern void hack_incomplete_structures         PARAMS ((tree));
 extern tree maybe_build_cleanup                        PARAMS ((tree));
 extern void finish_stmt                                PARAMS ((void));
-extern void replace_defarg                     PARAMS ((tree, tree));
 extern void print_other_binding_stack          PARAMS ((struct binding_level *));
 extern void revert_static_member_fn             PARAMS ((tree));
 extern void fixup_anonymous_aggr                PARAMS ((tree));
@@ -4085,9 +4084,6 @@ extern void compiler_error                        PARAMS ((const char *, ...))
   ATTRIBUTE_PRINTF_1;
 extern void yyerror                            PARAMS ((const char *));
 extern void clear_inline_text_obstack          PARAMS ((void));
-extern void maybe_snarf_defarg                 PARAMS ((void));
-extern void add_defarg_fn                      PARAMS ((tree));
-extern void do_pending_defargs                 PARAMS ((void));
 extern void yyhook                             PARAMS ((int));
 extern int cp_type_qual_from_rid                PARAMS ((tree));
 
@@ -4345,6 +4341,12 @@ extern int peekyylex                             PARAMS ((void));
 extern int yylex                               PARAMS ((void));
 extern tree arbitrate_lookup                   PARAMS ((tree, tree, tree));
 extern tree frob_opname                         PARAMS ((tree));
+extern void maybe_snarf_defarg                 PARAMS ((void));
+extern void add_defarg_fn                      PARAMS ((tree));
+extern void do_pending_defargs                 PARAMS ((void));
+extern void done_pending_defargs               PARAMS ((void));
+extern void unprocessed_defarg_fn               PARAMS ((tree));
+extern void replace_defarg                     PARAMS ((tree, tree));
 
 /* in tree.c */
 extern void init_tree                          PARAMS ((void));
index 66a285c670951272b306387acda3d8dff8b12d5e..ff3084e8dfe38aa399620e1b5033f2e62a3ad82c 100644 (file)
@@ -11950,20 +11950,6 @@ grokparms (first_parm)
   return result;
 }
 
-/* Called from the parser to update an element of TYPE_ARG_TYPES for some
-   FUNCTION_TYPE with the newly parsed version of its default argument, which
-   was previously digested as text.  See snarf_defarg et al in lex.c.  */
-
-void
-replace_defarg (arg, init)
-     tree arg, init;
-{
-  if (! processing_template_decl
-      && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
-    cp_pedwarn ("invalid type `%T' for default argument to `%T'",
-               TREE_TYPE (init), TREE_VALUE (arg));
-  TREE_PURPOSE (arg) = init;
-}
 \f
 /* D is a constructor or overloaded `operator='.  Returns non-zero if
    D's arguments allow it to be a copy constructor, or copy assignment
index f74fae4b1adabdfe42191d24b61bf7708ccf7767..dca09921a2d809498f96f6b520fb5f290548797a 100644 (file)
@@ -2271,6 +2271,7 @@ structsp:
                }
          pending_defargs
                 {
+                 done_pending_defargs ();
                  begin_inline_definitions ();
                }
          pending_inlines
index 3fc146968f61a034a19ce9cd453a32c6c8a5726e..d7fd78e33f4009619f02f987e85d792a3b4a737e 100644 (file)
@@ -164,10 +164,14 @@ char *inline_text_firstobj;
    through and parse all of them using do_pending_defargs.  Since yacc
    parsers are not reentrant, we retain defargs state in these two
    variables so that subsequent calls to do_pending_defargs can resume
-   where the previous call left off.  */
+   where the previous call left off. DEFARG_FNS is a tree_list where 
+   the TREE_TYPE is the current_class_type, TREE_VALUE is the FUNCTION_DECL,
+   and TREE_PURPOSE is the list unprocessed dependent functions.  */
 
-static tree defarg_fns;
-static tree defarg_parm;
+static tree defarg_fns;     /* list of functions with unprocessed defargs */
+static tree defarg_parm;    /* current default parameter */
+static tree defarg_depfns;  /* list of unprocessed fns met during current fn. */
+static tree defarg_fnsdone; /* list of fns with circular defargs */
 
 /* Initialize obstacks. Called once, from init_parse.  */
 
@@ -180,6 +184,8 @@ init_spew ()
   gcc_obstack_init (&feed_obstack);
   ggc_add_tree_root (&defarg_fns, 1);
   ggc_add_tree_root (&defarg_parm, 1);
+  ggc_add_tree_root (&defarg_depfns, 1);
+  ggc_add_tree_root (&defarg_fnsdone, 1);
 
   ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *),
                mark_pending_inlines);
@@ -1267,7 +1273,10 @@ add_defarg_fn (decl)
   if (TREE_CODE (decl) == FUNCTION_DECL)
     TREE_VALUE (defarg_fns) = decl;
   else
-    defarg_fns = tree_cons (current_class_type, decl, defarg_fns);  
+    {
+      defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);  
+      TREE_TYPE (defarg_fns) = current_class_type;
+    }
 }
 
 /* Helper for do_pending_defargs.  Starts the parsing of a default arg.  */
@@ -1305,12 +1314,14 @@ do_pending_defargs ()
   if (defarg_parm)
     finish_defarg ();
 
-  for (; defarg_fns; defarg_fns = TREE_CHAIN (defarg_fns))
+  for (; defarg_fns;)
     {
+      tree current = defarg_fns;
+      
       tree defarg_fn = TREE_VALUE (defarg_fns);
       if (defarg_parm == NULL_TREE)
        {
-         push_nested_class (TREE_PURPOSE (defarg_fns), 1);
+         push_nested_class (TREE_TYPE (defarg_fns), 1);
          pushlevel (0);
          if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
            maybe_begin_member_template_processing (defarg_fn);
@@ -1324,8 +1335,12 @@ do_pending_defargs ()
        defarg_parm = TREE_CHAIN (defarg_parm);
 
       for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm))
-       if (TREE_PURPOSE (defarg_parm)
-           && TREE_CODE (TREE_PURPOSE (defarg_parm)) == DEFAULT_ARG)
+       if (!TREE_PURPOSE (defarg_parm)
+           || TREE_CODE (TREE_PURPOSE (defarg_parm)) != DEFAULT_ARG)
+         ;/* OK */
+       else if (TREE_PURPOSE (current) == error_mark_node)
+         DEFARG_POINTER (TREE_PURPOSE (defarg_parm)) = NULL;
+       else
          {
            feed_defarg (defarg_parm);
 
@@ -1342,6 +1357,96 @@ do_pending_defargs ()
 
       poplevel (0, 0, 0);
       pop_nested_class ();
+      
+      defarg_fns = TREE_CHAIN (defarg_fns);
+      if (defarg_depfns)
+        {
+          /* This function's default args depend on unprocessed default args
+             of defarg_fns. We will need to reprocess this function, and
+             check for circular dependancies.  */
+          tree a, b;
+          
+          for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b; 
+               a = TREE_CHAIN (a), b = TREE_CHAIN (b))
+            if (TREE_VALUE (a) != TREE_VALUE (b))
+              goto different;
+          if (a || b)
+            {
+            different:;
+              TREE_CHAIN (current) = NULL_TREE;
+              defarg_fns = chainon (defarg_fns, current);
+              TREE_PURPOSE (current) = defarg_depfns;
+            }
+          else
+            {
+              cp_warning_at ("circular dependency in default args of `%#D'", defarg_fn);
+              /* No need to say what else is dependent, as they will be
+                 picked up in another pass.  */
+              
+              /* Immediately repeat, but marked so that we break the loop. */
+              defarg_fns = current;
+              TREE_PURPOSE (current) = error_mark_node;
+            }
+          defarg_depfns = NULL_TREE;
+        }
+      else if (TREE_PURPOSE (current) == error_mark_node)
+        defarg_fnsdone = tree_cons (NULL_TREE, defarg_fn, defarg_fnsdone);
+    }
+}
+
+/* After parsing all the default arguments, we must clear any that remain,
+   which will be part of a circular dependency. */
+void
+done_pending_defargs ()
+{
+  for (; defarg_fnsdone; defarg_fnsdone = TREE_CHAIN (defarg_fnsdone))
+    {
+      tree fn = TREE_VALUE (defarg_fnsdone);
+      tree parms;
+      
+      if (TREE_CODE (fn) == FUNCTION_DECL)
+        parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
+      else
+        parms = TYPE_ARG_TYPES (fn);
+      for (; parms; parms = TREE_CHAIN (parms))
+       if (TREE_PURPOSE (parms)
+           && TREE_CODE (TREE_PURPOSE (parms)) == DEFAULT_ARG)
+         {
+            my_friendly_assert (!DEFARG_POINTER (TREE_PURPOSE (parms)), 20010107);
+           TREE_PURPOSE (parms) = NULL_TREE;
+         }
+    }
+}
+
+/* In processing the current default arg, we called FN, but that call
+   required a default argument of FN, and that had not yet been processed.
+   Remember FN.  */
+
+void
+unprocessed_defarg_fn (fn)
+     tree fn;
+{
+  defarg_depfns = tree_cons (NULL_TREE, fn, defarg_depfns);
+}
+
+/* Called from the parser to update an element of TYPE_ARG_TYPES for some
+   FUNCTION_TYPE with the newly parsed version of its default argument, which
+   was previously digested as text.  */
+
+void
+replace_defarg (arg, init)
+     tree arg, init;
+{
+  if (init == error_mark_node)
+    TREE_PURPOSE (arg) = error_mark_node;
+  else
+    {
+      if (! processing_template_decl
+          && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
+        cp_pedwarn ("invalid type `%T' for default argument to `%T'",
+                   TREE_TYPE (init), TREE_VALUE (arg));
+      if (!defarg_depfns)
+        TREE_PURPOSE (arg) = init;
     }
 }
 
index a87cf8850d7f6d3844ce80e452b35f33643179ce..4e44d8e95e92d45b40cd43fe50829414b6dc0b78 100644 (file)
@@ -1,3 +1,12 @@
+2001-01-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/defarg7.C: New test.
+       * g++.old-deja/g++.other/defarg8.C: New test.
+
+2001-01-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.pt/crash64.C: New test.
+
 2001-01-11  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.old-deja/g++.pt/crash63.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/defarg7.C b/gcc/testsuite/g++.old-deja/g++.other/defarg7.C
new file mode 100644 (file)
index 0000000..cb5a6da
--- /dev/null
@@ -0,0 +1,41 @@
+// Build don't link:
+
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 7 Jan 2001 <nathan@codesourcery.com>
+
+// Bug 1038. Default args on class members can produce circular dependencies.
+// Make sure we spot them, and don't depend on a particular ordering.
+
+struct A
+{
+  static int Foo (int = Baz ());    // WARNING - circular
+  static int Baz (int = Foo ());    // WARNING - circular
+};
+
+struct Test
+{
+  Test (void * = 0);
+  void set (const Test &arg = Test ());
+};
+
+struct B
+{
+  static int Bar (int = Foo (1));
+  static int Foo (int = Baz ());
+  static int Baz (int = Foo (1));
+};
+
+int main ()
+{
+  Test t;
+  t.set ();
+  t.set (t);
+  B::Bar ();
+  B::Bar (1);
+  B::Baz ();
+  B::Baz (1);
+  B::Foo ();
+  B::Foo (1);
+  
+  return 0;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/defarg8.C b/gcc/testsuite/g++.old-deja/g++.other/defarg8.C
new file mode 100644 (file)
index 0000000..7188209
--- /dev/null
@@ -0,0 +1,24 @@
+// Build don't link:
+// Special g++ options: -pedantic-errors -ansi -w
+
+// Copyright (C) 2000 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 7 Jan 2001 <nathan@codesourcery.com>
+
+// Bug 1038. Default args on class members can produce circular dependencies.
+// Make sure we spot them, and don't depend on a particular ordering.
+
+struct AA
+{
+  static int Foo (int = Baz ());    // ERROR - candidate
+  static int Baz (int = Foo ());    // ERROR - candidate
+};
+
+int main ()
+{
+  AA::Foo ();   // ERROR - no candidate
+  AA::Foo (1);
+  AA::Baz ();   // ERROR - no candidate
+  AA::Baz (1);
+  
+  return 0;
+}
This page took 0.09637 seconds and 5 git commands to generate.