This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix 21903


this patch fixes 21903, a regression with default arguments and template instantiations. We can instantiate nested template class before we've done the late parsing for default arguments. When we parse the default arguments we should propagate that information to the instantiations.

built & tested on i686-pc-linux-gnu, installed mainline.

I'll install on 4.0 when it is unfrozen.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

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.

2005-06-06  Nathan Sidwell  <nathan@codesourcery.com>

	PR 21903
	* g++.dg/parse/defarg9.C: New.

Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.102
diff -c -3 -p -r1.102 cp-tree.def
*** cp/cp-tree.def	27 May 2005 23:17:07 -0000	1.102
--- cp/cp-tree.def	6 Jun 2005 15:55:44 -0000
*************** DEFTREECODE (USING_DECL, "using_decl", t
*** 206,212 ****
  /* 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.  */
  DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0)
  
  /* A template-id, like foo<int>.  The first operand is the template.
--- 206,214 ----
  /* 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.
!    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: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.336
diff -c -3 -p -r1.336 parser.c
*** cp/parser.c	5 Jun 2005 16:33:36 -0000	1.336
--- cp/parser.c	6 Jun 2005 15:56:22 -0000
*************** cp_parser_late_parsing_default_args (cp_
*** 15593,15611 ****
         parm = TREE_CHAIN (parm))
      {
        cp_token_cache *tokens;
! 
!       if (!TREE_PURPOSE (parm)
! 	  || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG)
  	continue;
  
         /* Push the saved tokens for the default argument onto the parser's
  	  lexer stack.  */
!       tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
        cp_parser_push_lexer_for_tokens (parser, tokens);
  
        /* Parse the assignment-expression.  */
!       TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser,
! 							     /*cast_p=*/false);
  
        /* If the token stream has not been completely used up, then
  	 there was extra junk after the end of the default
--- 15593,15621 ----
         parm = TREE_CHAIN (parm))
      {
        cp_token_cache *tokens;
!       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 (default_arg);
        cp_parser_push_lexer_for_tokens (parser, tokens);
  
        /* Parse the assignment-expression.  */
!       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: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.1001
diff -c -3 -p -r1.1001 pt.c
*** cp/pt.c	3 Jun 2005 16:16:15 -0000	1.1001
--- cp/pt.c	6 Jun 2005 15:56:47 -0000
*************** tsubst_arg_types (tree arg_types, 
*** 6704,6709 ****
--- 6704,6711 ----
  {
    tree remaining_arg_types;
    tree type;
+   tree default_arg;
+   tree result = NULL_TREE;
  
    if (!arg_types || arg_types == void_list_node)
      return arg_types;
*************** tsubst_arg_types (tree arg_types, 
*** 6731,6742 ****
       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);
! 			 
  }
  
  /* Substitute into a FUNCTION_TYPE or METHOD_TYPE.  This routine does
--- 6733,6757 ----
       top-level qualifiers as required.  */
    type = TYPE_MAIN_VARIANT (type_decays_to (type));
  
!   /* 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: testsuite/g++.dg/parse/defarg9.C
===================================================================
RCS file: testsuite/g++.dg/parse/defarg9.C
diff -N testsuite/g++.dg/parse/defarg9.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/defarg9.C	6 Jun 2005 17:26:11 -0000
***************
*** 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); 
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]