re PR c++/21903 (Default argument of template function causes a compile-time error)
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 6 Jun 2005 17:29:41 +0000 (17:29 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 6 Jun 2005 17:29:41 +0000 (17:29 +0000)
cp:
PR 21903
* cp-tree.def (DEFAULT_ARG): Document TREE_CHAIN use.
* parser.c (cp_parser_late_parsing_default_args): Propagate parsed
argument to any early instantiations.
* pt.c (tsubst_arg_types): Chain early instantiation of default arg.
testsuite:
PR 21903
* g++.dg/parse/defarg9.C: New.

From-SVN: r100669

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/defarg9.C [new file with mode: 0644]

index 758451c..e493e10 100644 (file)
@@ -1,5 +1,11 @@
 2005-06-06  Nathan Sidwell  <nathan@codesourcery.com>
 
+       PR 21903
+       * cp-tree.def (DEFAULT_ARG): Document TREE_CHAIN use.
+       * parser.c (cp_parser_late_parsing_default_args): Propagate parsed
+       argument to any early instantiations.
+       * pt.c (tsubst_arg_types): Chain early instantiation of default arg.
+
        PR c++/20637
        * cp-tree.h (add_method): Add using_decl parameter.
        * class.c (add_method): Add using_decl parameter.  Adjust error
index c42dbfb..2728467 100644 (file)
@@ -206,7 +206,9 @@ DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0)
 /* A using directive. The operand is USING_STMT_NAMESPACE.  */     
 DEFTREECODE (USING_STMT, "using_directive", tcc_statement, 1)
 
-/* An un-parsed default argument.  Looks like an IDENTIFIER_NODE.  */
+/* An un-parsed default argument.  Looks like an IDENTIFIER_NODE.
+   TREE_CHAIN is used to hold instantiations of functions that had to
+   be instantiated before the argument was parsed.  */
 DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0)
 
 /* A template-id, like foo<int>.  The first operand is the template.
index 65442c7..c0059d0 100644 (file)
@@ -15593,19 +15593,29 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
        parm = TREE_CHAIN (parm))
     {
       cp_token_cache *tokens;
-
-      if (!TREE_PURPOSE (parm)
-         || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG)
+      tree default_arg = TREE_PURPOSE (parm);
+      tree parsed_arg;
+      
+      if (!default_arg)
        continue;
 
+      gcc_assert (TREE_CODE (default_arg) == DEFAULT_ARG);
+
        /* Push the saved tokens for the default argument onto the parser's
          lexer stack.  */
-      tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
+      tokens = DEFARG_TOKENS (default_arg);
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser,
-                                                            /*cast_p=*/false);
+      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+
+      TREE_PURPOSE (parm) = parsed_arg;
+
+      /* Update any instantiations we've already created.  */
+      for (default_arg = TREE_CHAIN (default_arg);
+          default_arg;
+          default_arg = TREE_CHAIN (default_arg))
+       TREE_PURPOSE (TREE_PURPOSE (default_arg)) = parsed_arg;
 
       /* If the token stream has not been completely used up, then
         there was extra junk after the end of the default
index ad1e5f3..7924bbe 100644 (file)
@@ -6704,6 +6704,8 @@ tsubst_arg_types (tree arg_types,
 {
   tree remaining_arg_types;
   tree type;
+  tree default_arg;
+  tree result = NULL_TREE;
 
   if (!arg_types || arg_types == void_list_node)
     return arg_types;
@@ -6731,12 +6733,25 @@ tsubst_arg_types (tree arg_types,
      top-level qualifiers as required.  */
   type = TYPE_MAIN_VARIANT (type_decays_to (type));
 
-  /* Note that we do not substitute into default arguments here.  The
-     standard mandates that they be instantiated only when needed,
-     which is done in build_over_call.  */
-  return hash_tree_cons (TREE_PURPOSE (arg_types), type,
-                        remaining_arg_types);
-                        
+  /* We do not substitute into default arguments here.  The standard
+     mandates that they be instantiated only when needed, which is
+     done in build_over_call.  */
+  default_arg = TREE_PURPOSE (arg_types);
+  
+  if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
+    {
+      /* We've instantiated a template before its default arguments
+        have been parsed.  This can happen for a nested template
+        class, and is not an error unless we require the default
+        argument in a call of this function.  */
+      result = tree_cons (default_arg, type, remaining_arg_types);
+      TREE_CHAIN (default_arg) = tree_cons (result, NULL_TREE,
+                                           TREE_CHAIN (default_arg));
+    }
+  else
+    result = hash_tree_cons (default_arg, type, remaining_arg_types);
+  
+  return result;
 }
 
 /* Substitute into a FUNCTION_TYPE or METHOD_TYPE.  This routine does
index 9061d5f..a89b7fe 100644 (file)
@@ -1,5 +1,8 @@
 2005-06-06  Nathan Sidwell  <nathan@codesourcery.com>
 
+       PR 21903
+       * g++.dg/parse/defarg9.C: New.
+
        PR c++/20637
        * g++.dg/inherit/using4.C: New.
        * g++.dg/overload/error1.C: Adjust expected errors.
diff --git a/gcc/testsuite/g++.dg/parse/defarg9.C b/gcc/testsuite/g++.dg/parse/defarg9.C
new file mode 100644 (file)
index 0000000..8496cfb
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 6 Jun 2005 <nathan@codesourcery.com>
+
+// PR 21903:Reject legal with default arg confusion
+// Origin:  Wolfgang Bangerth <bangerth@dealii.org>
+
+
+struct O { 
+  template<typename T> struct B { 
+    void set (T, bool=true); 
+  }; 
+  
+  struct D : public B<int> {}; 
+}; 
+
+void x () 
+{ 
+  O::D d; 
+  d.set(1); 
+}