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 for c++/37302 (using parameters in late-specified return type)


Just pushing the parameter decls as we see them and then popping them again when we're done with the function declarator wasn't too complicated. I needed to delay deprecated warnings until grokparms time so that we don't warn about deprecated types as arguments to a deprecated function.

The one oddity is that parms don't get DECL_CONTEXT set until we actually start to compile the function. But this doesn't seem to hurt anything, and I kept running into problems when I tried to set it up sooner.

This patch also adds proposed mangling for decltype(function call) and decltype(type()), which I expect to be useful for late-specified return types.

Tested x86_64-pc-linux-gnu, applied to trunk.

2008-09-06  Jason Merrill  <jason@redhat.com>

	PR c++/37302
	* parser.c (cp_parser_parameter_declaration_list): Process the
	PARM_DECLs as we go and push them.  Return a TREE_LIST.
	(cp_parser_parameter_declaration_clause): Return a TREE_LIST.
	(cp_parser_direct_declarator): Create a binding level and
	suppress deprecated warnings in the parameter list.
	(make_call_declarator): PARMS is now a tree.
	* cp-tree.h (struct cp_declarator): Function parms are now a tree.
	* decl.h (enum deprecated_states, deprecated_state): Move here.
	* decl.c: From here.
	(type_is_deprecated): New fn.
	(grokparms): PARMLIST is a tree now.  Warn about parms that
	use deprecated types.
	* mangle.c (write_expression): Handle PARM_DECL, CALL_EXPR and
	0-operand cast.
	* pt.c (tsubst) [DECLTYPE_TYPE]: Set skip_evaluation.
	(tsubst_copy) [PARM_DECL]: Handle a PARM_DECL used outside of a 
	function.
	* name-lookup.c (pushtag): Look through function parameter scopes.
	(pushdecl_maybe_friend): Don't set DECL_CONTEXT on a PARM_DECL 
	when we're parsing a function declarator.

Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 140075)
--- cp/cp-tree.h	(working copy)
*************** struct cp_declarator {
*** 4108,4115 ****
      } id;
      /* For functions.  */
      struct {
!       /* The parameters to the function.  */
!       cp_parameter_declarator *parameters;
        /* The cv-qualifiers for the function.  */
        cp_cv_quals qualifiers;
        /* The exception-specification for the function.  */
--- 4108,4115 ----
      } id;
      /* For functions.  */
      struct {
!       /* The parameters to the function as a TREE_LIST of decl/default.  */
!       tree parameters;
        /* The cv-qualifiers for the function.  */
        cp_cv_quals qualifiers;
        /* The exception-specification for the function.  */
Index: cp/decl.c
===================================================================
*** cp/decl.c	(revision 140075)
--- cp/decl.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 54,60 ****
  #include "tree-flow.h"
  #include "pointer-set.h"
  
! static tree grokparms (cp_parameter_declarator *, tree *);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
--- 54,60 ----
  #include "tree-flow.h"
  #include "pointer-set.h"
  
! static tree grokparms (tree parmlist, tree *);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
*************** VEC(tree, gc) *deferred_mark_used_calls;
*** 236,248 ****
     with __attribute__((deprecated)).  An object declared as
     __attribute__((deprecated)) suppresses warnings of uses of other
     deprecated items.  */
! 
! enum deprecated_states {
!   DEPRECATED_NORMAL,
!   DEPRECATED_SUPPRESS
! };
! 
! static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
  
  
  /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
--- 236,242 ----
     with __attribute__((deprecated)).  An object declared as
     __attribute__((deprecated)) suppresses warnings of uses of other
     deprecated items.  */
! enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
  
  
  /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
*************** check_default_argument (tree decl, tree 
*** 9494,9499 ****
--- 9488,9519 ----
    return arg;
  }
  
+ /* Returns a deprecated type used within TYPE, or NULL_TREE if none.  */
+ 
+ static tree
+ type_is_deprecated (tree type)
+ {
+   enum tree_code code;
+   if (TREE_DEPRECATED (type))
+     return type;
+   if (TYPE_NAME (type)
+       && TREE_DEPRECATED (TYPE_NAME (type)))
+     return type;
+ 
+   code = TREE_CODE (type);
+ 
+   if (code == POINTER_TYPE || code == REFERENCE_TYPE
+       || code == OFFSET_TYPE || code == FUNCTION_TYPE
+       || code == METHOD_TYPE || code == ARRAY_TYPE)
+     return type_is_deprecated (TREE_TYPE (type));
+ 
+   if (TYPE_PTRMEMFUNC_P (type))
+     return type_is_deprecated
+       (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+ 
+   return NULL_TREE;
+ }
+ 
  /* Decode the list of parameter types for a function type.
     Given the list of things declared inside the parens,
     return a list of types.
*************** check_default_argument (tree decl, tree 
*** 9504,9544 ****
     *PARMS is set to the chain of PARM_DECLs created.  */
  
  static tree
! grokparms (cp_parameter_declarator *first_parm, tree *parms)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
!   int ellipsis = !first_parm || first_parm->ellipsis_p;
!   cp_parameter_declarator *parm;
    int any_error = 0;
-   struct pointer_set_t *unique_decls = pointer_set_create ();
  
!   for (parm = first_parm; parm != NULL; parm = parm->next)
      {
        tree type = NULL_TREE;
!       tree init = parm->default_argument;
!       tree attrs;
!       tree decl;
  
!       if (parm == no_parameters)
  	break;
  
-       attrs = parm->decl_specifiers.attributes;
-       parm->decl_specifiers.attributes = NULL_TREE;
-       decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
- 			     PARM, init != NULL_TREE, &attrs);
        if (! decl || TREE_TYPE (decl) == error_mark_node)
  	continue;
  
-       if (attrs)
- 	cplus_decl_attributes (&decl, attrs, 0);
- 
        type = TREE_TYPE (decl);
        if (VOID_TYPE_P (type))
  	{
  	  if (same_type_p (type, void_type_node)
  	      && DECL_SELF_REFERENCE_P (type)
! 	      && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
  	    /* this is a parmlist of `(void)', which is ok.  */
  	    break;
  	  cxx_incomplete_type_error (decl, type);
--- 9524,9554 ----
     *PARMS is set to the chain of PARM_DECLs created.  */
  
  static tree
! grokparms (tree parmlist, tree *parms)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
!   tree parm;
    int any_error = 0;
  
!   for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm))
      {
        tree type = NULL_TREE;
!       tree init = TREE_PURPOSE (parm);
!       tree decl = TREE_VALUE (parm);
  
!       if (parm == void_list_node)
  	break;
  
        if (! decl || TREE_TYPE (decl) == error_mark_node)
  	continue;
  
        type = TREE_TYPE (decl);
        if (VOID_TYPE_P (type))
  	{
  	  if (same_type_p (type, void_type_node)
  	      && DECL_SELF_REFERENCE_P (type)
! 	      && !DECL_NAME (decl) && !result && TREE_CHAIN (parm) == void_list_node)
  	    /* this is a parmlist of `(void)', which is ok.  */
  	    break;
  	  cxx_incomplete_type_error (decl, type);
*************** grokparms (cp_parameter_declarator *firs
*** 9561,9566 ****
--- 9571,9583 ----
  
        if (type != error_mark_node)
  	{
+ 	  if (deprecated_state != DEPRECATED_SUPPRESS)
+ 	    {
+ 	      tree deptype = type_is_deprecated (type);
+ 	      if (deptype)
+ 		warn_deprecated_use (deptype);
+ 	    }
+ 
  	  /* Top-level qualifiers on the parameters are
  	     ignored for function types.  */
  	  type = cp_build_qualified_type (type, 0);
*************** grokparms (cp_parameter_declarator *firs
*** 9603,9630 ****
  
        if (TREE_CODE (decl) == PARM_DECL
            && FUNCTION_PARAMETER_PACK_P (decl)
!           && parm->next)
          error ("parameter packs must be at the end of the parameter list");
  
-       if (DECL_NAME (decl))
-         {
-           if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
-             error ("multiple parameters named %qE", DECL_NAME (decl));
-           else
-             pointer_set_insert (unique_decls, DECL_NAME (decl));
-         }
- 
        TREE_CHAIN (decl) = decls;
        decls = decl;
        result = tree_cons (init, type, result);
      }
    decls = nreverse (decls);
    result = nreverse (result);
!   if (!ellipsis)
      result = chainon (result, void_list_node);
    *parms = decls;
  
-   pointer_set_destroy (unique_decls);
    return result;
  }
  
--- 9620,9639 ----
  
        if (TREE_CODE (decl) == PARM_DECL
            && FUNCTION_PARAMETER_PACK_P (decl)
!           && TREE_CHAIN (parm)
!           && TREE_CHAIN (parm) != void_list_node)
          error ("parameter packs must be at the end of the parameter list");
  
        TREE_CHAIN (decl) = decls;
        decls = decl;
        result = tree_cons (init, type, result);
      }
    decls = nreverse (decls);
    result = nreverse (result);
!   if (parm)
      result = chainon (result, void_list_node);
    *parms = decls;
  
    return result;
  }
  
Index: cp/decl.h
===================================================================
*** cp/decl.h	(revision 140075)
--- cp/decl.h	(working copy)
*************** enum decl_context
*** 34,36 ****
--- 34,49 ----
  extern tree grokdeclarator (const cp_declarator *,
  			    const cp_decl_specifier_seq *,
  			    enum decl_context, int, tree*);
+ 
+ /* States indicating how grokdeclarator() should handle declspecs marked
+    with __attribute__((deprecated)).  An object declared as
+    __attribute__((deprecated)) suppresses warnings of uses of other
+    deprecated items.  */
+ 
+ enum deprecated_states {
+   DEPRECATED_NORMAL,
+   DEPRECATED_SUPPRESS
+ };
+ 
+ extern enum deprecated_states deprecated_state;
+ 
Index: cp/mangle.c
===================================================================
*** cp/mangle.c	(revision 140075)
--- cp/mangle.c	(working copy)
*************** write_template_args (tree args)
*** 2016,2022 ****
     <expr-primary> ::= <template-param>
  		  ::= L <type> <value number> E		# literal
  		  ::= L <mangled-name> E		# external name
! 		  ::= sr <type> <unqualified-name>
  		  ::= sr <type> <unqualified-name> <template-args> */
  
  static void
--- 2016,2023 ----
     <expr-primary> ::= <template-param>
  		  ::= L <type> <value number> E		# literal
  		  ::= L <mangled-name> E		# external name
! 		  ::= st <type>				# sizeof
! 		  ::= sr <type> <unqualified-name>	# dependent name
  		  ::= sr <type> <unqualified-name> <template-args> */
  
  static void
*************** write_expression (tree expr)
*** 2042,2047 ****
--- 2043,2054 ----
        code = TREE_CODE (expr);
      }
  
+   if (code == OVERLOAD)
+     {
+       expr = OVL_FUNCTION (expr);
+       code = TREE_CODE (expr);
+     }
+ 
    /* Handle pointers-to-members by making them look like expression
       nodes.  */
    if (code == PTRMEM_CST)
*************** write_expression (tree expr)
*** 2064,2069 ****
--- 2071,2083 ----
    else if (TREE_CODE_CLASS (code) == tcc_constant
  	   || (abi_version_at_least (2) && code == CONST_DECL))
      write_template_arg_literal (expr);
+   else if (code == PARM_DECL)
+     {
+       /* A function parameter used under decltype in a late-specified
+ 	 return type.  Represented with a type placeholder.  */
+       write_string ("sT");
+       write_type (non_reference (TREE_TYPE (expr)));
+     }
    else if (DECL_P (expr))
      {
        /* G++ 3.2 incorrectly mangled non-type template arguments of
*************** write_expression (tree expr)
*** 2175,2190 ****
        switch (code)
  	{
  	case CALL_EXPR:
! 	  sorry ("call_expr cannot be mangled due to a defect in the C++ ABI");
  	  break;
  
  	case CAST_EXPR:
  	  write_type (TREE_TYPE (expr));
- 	  /* There is no way to mangle a zero-operand cast like
- 	     "T()".  */
  	  if (!TREE_OPERAND (expr, 0))
! 	    sorry ("zero-operand casts cannot be mangled due to a defect "
! 		   "in the C++ ABI");
  	  else
  	    write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
  	  break;
--- 2189,2205 ----
        switch (code)
  	{
  	case CALL_EXPR:
! 	  write_expression (CALL_EXPR_FN (expr));
! 	  for (i = 0; i < call_expr_nargs (expr); ++i)
! 	    write_expression (CALL_EXPR_ARG (expr, i));
! 	  write_char ('E');
  	  break;
  
  	case CAST_EXPR:
  	  write_type (TREE_TYPE (expr));
  	  if (!TREE_OPERAND (expr, 0))
! 	  /* "T()" is mangled as "T(void)".  */
! 	    write_char ('v');
  	  else
  	    write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
  	  break;
*************** write_expression (tree expr)
*** 2195,2201 ****
  	  write_expression (TREE_OPERAND (expr, 0));
  	  break;
  
- 
  	/* Handle pointers-to-members specially.  */
  	case SCOPE_REF:
  	  write_type (TREE_OPERAND (expr, 0));
--- 2210,2215 ----
Index: cp/name-lookup.c
===================================================================
*** cp/name-lookup.c	(revision 140075)
--- cp/name-lookup.c	(working copy)
*************** pushdecl_maybe_friend (tree x, bool is_f
*** 604,609 ****
--- 604,616 ----
  	     scope of the current namespace, not the current
  	     function.  */
  	  && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
+ 	  /* When parsing the parameter list of a function declarator,
+ 	     don't set DECL_CONTEXT to an enclosing function.  When we
+ 	     push the PARM_DECLs in order to process the function body,
+ 	     current_binding_level->this_entity will be set.  */
+ 	  && !(TREE_CODE (x) == PARM_DECL
+ 	       && current_binding_level->kind == sk_function_parms
+ 	       && current_binding_level->this_entity == NULL)
  	  && !DECL_CONTEXT (x))
  	DECL_CONTEXT (x) = current_function_decl;
  
*************** pushdecl_maybe_friend (tree x, bool is_f
*** 712,719 ****
  	    }
  	  else if (TREE_CODE (t) == PARM_DECL)
  	    {
- 	      gcc_assert (DECL_CONTEXT (t));
- 
  	      /* Check for duplicate params.  */
  	      if (duplicate_decls (x, t, is_friend))
  		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
--- 719,724 ----
*************** pushtag (tree name, tree type, tag_scope
*** 4987,4992 ****
--- 4992,4999 ----
    while (/* Cleanup scopes are not scopes from the point of view of
  	    the language.  */
  	 b->kind == sk_cleanup
+ 	 /* Neither are function parameter scopes.  */
+ 	 || b->kind == sk_function_parms
  	 /* Neither are the scopes used to hold template parameters
  	    for an explicit specialization.  For an ordinary template
  	    declaration, these scopes are not scopes from the point of
Index: cp/parser.c
===================================================================
*** cp/parser.c	(revision 140075)
--- cp/parser.c	(working copy)
*************** clear_decl_specs (cp_decl_specifier_seq 
*** 853,859 ****
     VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
  
  static cp_declarator *make_call_declarator
!   (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree, tree);
  static cp_declarator *make_array_declarator
    (cp_declarator *, tree);
  static cp_declarator *make_pointer_declarator
--- 853,859 ----
     VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
  
  static cp_declarator *make_call_declarator
!   (cp_declarator *, tree, cp_cv_quals, tree, tree);
  static cp_declarator *make_array_declarator
    (cp_declarator *, tree);
  static cp_declarator *make_pointer_declarator
*************** make_ptrmem_declarator (cp_cv_quals cv_q
*** 1013,1019 ****
  
  cp_declarator *
  make_call_declarator (cp_declarator *target,
! 		      cp_parameter_declarator *parms,
  		      cp_cv_quals cv_qualifiers,
  		      tree exception_specification,
  		      tree late_return_type)
--- 1013,1019 ----
  
  cp_declarator *
  make_call_declarator (cp_declarator *target,
! 		      tree parms,
  		      cp_cv_quals cv_qualifiers,
  		      tree exception_specification,
  		      tree late_return_type)
*************** static tree cp_parser_type_id
*** 1736,1744 ****
    (cp_parser *);
  static void cp_parser_type_specifier_seq
    (cp_parser *, bool, cp_decl_specifier_seq *);
! static cp_parameter_declarator *cp_parser_parameter_declaration_clause
    (cp_parser *);
! static cp_parameter_declarator *cp_parser_parameter_declaration_list
    (cp_parser *, bool *);
  static cp_parameter_declarator *cp_parser_parameter_declaration
    (cp_parser *, bool, bool *);
--- 1736,1744 ----
    (cp_parser *);
  static void cp_parser_type_specifier_seq
    (cp_parser *, bool, cp_decl_specifier_seq *);
! static tree cp_parser_parameter_declaration_clause
    (cp_parser *);
! static tree cp_parser_parameter_declaration_list
    (cp_parser *, bool *);
  static cp_parameter_declarator *cp_parser_parameter_declaration
    (cp_parser *, bool, bool *);
*************** cp_parser_direct_declarator (cp_parser* 
*** 12986,12993 ****
  
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
! 	      cp_parameter_declarator *params;
  	      unsigned saved_num_template_parameter_lists;
  
  	      /* In a member-declarator, the only valid interpretation
  		 of a parenthesis is the start of a
--- 12986,12995 ----
  
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
! 	      tree params;
  	      unsigned saved_num_template_parameter_lists;
+ 	      bool is_declarator = false;
+ 	      tree t;
  
  	      /* In a member-declarator, the only valid interpretation
  		 of a parenthesis is the start of a
*************** cp_parser_direct_declarator (cp_parser* 
*** 13014,13019 ****
--- 13016,13023 ----
  		= parser->num_template_parameter_lists;
  	      parser->num_template_parameter_lists = 0;
  
+ 	      begin_scope (sk_function_parms, NULL_TREE);
+ 
  	      /* Parse the parameter-declaration-clause.  */
  	      params = cp_parser_parameter_declaration_clause (parser);
  
*************** cp_parser_direct_declarator (cp_parser* 
*** 13028,13033 ****
--- 13032,13039 ----
  		  tree exception_specification;
  		  tree late_return;
  
+ 		  is_declarator = true;
+ 
  		  if (ctor_dtor_or_conv_p)
  		    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
  		  first = false;
*************** cp_parser_direct_declarator (cp_parser* 
*** 13053,13062 ****
  		     return type, so are not those of the declared
  		     function.  */
  		  parser->default_arg_ok_p = false;
- 
- 		  /* Repeat the main loop.  */
- 		  continue;
  		}
  	    }
  
  	  /* If this is the first, we can try a parenthesized
--- 13059,13074 ----
  		     return type, so are not those of the declared
  		     function.  */
  		  parser->default_arg_ok_p = false;
  		}
+ 
+ 	      /* Remove the function parms from scope.  */
+ 	      for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+ 		pop_binding (DECL_NAME (t), t);
+ 	      leave_scope();
+ 
+ 	      if (is_declarator)
+ 		/* Repeat the main loop.  */
+ 		continue;
  	    }
  
  	  /* If this is the first, we can try a parenthesized
*************** cp_parser_type_specifier_seq (cp_parser*
*** 13728,13737 ****
     value of NULL indicates a parameter-declaration-clause consisting
     only of an ellipsis.  */
  
! static cp_parameter_declarator *
  cp_parser_parameter_declaration_clause (cp_parser* parser)
  {
!   cp_parameter_declarator *parameters;
    cp_token *token;
    bool ellipsis_p;
    bool is_error;
--- 13740,13749 ----
     value of NULL indicates a parameter-declaration-clause consisting
     only of an ellipsis.  */
  
! static tree
  cp_parser_parameter_declaration_clause (cp_parser* parser)
  {
!   tree parameters;
    cp_token *token;
    bool ellipsis_p;
    bool is_error;
*************** cp_parser_parameter_declaration_clause (
*** 13743,13749 ****
      {
        /* Consume the `...' token.  */
        cp_lexer_consume_token (parser->lexer);
!       return NULL;
      }
    else if (token->type == CPP_CLOSE_PAREN)
      /* There are no parameters.  */
--- 13755,13761 ----
      {
        /* Consume the `...' token.  */
        cp_lexer_consume_token (parser->lexer);
!       return NULL_TREE;
      }
    else if (token->type == CPP_CLOSE_PAREN)
      /* There are no parameters.  */
*************** cp_parser_parameter_declaration_clause (
*** 13751,13760 ****
  #ifndef NO_IMPLICIT_EXTERN_C
        if (in_system_header && current_class_type == NULL
  	  && current_lang_name == lang_name_c)
! 	return NULL;
        else
  #endif
! 	return no_parameters;
      }
    /* Check for `(void)', too, which is a special case.  */
    else if (token->keyword == RID_VOID
--- 13763,13772 ----
  #ifndef NO_IMPLICIT_EXTERN_C
        if (in_system_header && current_class_type == NULL
  	  && current_lang_name == lang_name_c)
! 	return NULL_TREE;
        else
  #endif
! 	return void_list_node;
      }
    /* Check for `(void)', too, which is a special case.  */
    else if (token->keyword == RID_VOID
*************** cp_parser_parameter_declaration_clause (
*** 13764,13770 ****
        /* Consume the `void' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* There are no parameters.  */
!       return no_parameters;
      }
  
    /* Parse the parameter-declaration-list.  */
--- 13776,13782 ----
        /* Consume the `void' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* There are no parameters.  */
!       return void_list_node;
      }
  
    /* Parse the parameter-declaration-list.  */
*************** cp_parser_parameter_declaration_clause (
*** 13799,13806 ****
      ellipsis_p = false;
  
    /* Finish the parameter list.  */
!   if (parameters && ellipsis_p)
!     parameters->ellipsis_p = true;
  
    return parameters;
  }
--- 13811,13818 ----
      ellipsis_p = false;
  
    /* Finish the parameter list.  */
!   if (!ellipsis_p)
!     parameters = chainon (parameters, void_list_node);
  
    return parameters;
  }
*************** cp_parser_parameter_declaration_clause (
*** 13816,13826 ****
     `void_list_node' is never appended to the list.  Upon return,
     *IS_ERROR will be true iff an error occurred.  */
  
! static cp_parameter_declarator *
  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
  {
!   cp_parameter_declarator *parameters = NULL;
!   cp_parameter_declarator **tail = &parameters;
    bool saved_in_unbraced_linkage_specification_p;
  
    /* Assume all will go well.  */
--- 13828,13838 ----
     `void_list_node' is never appended to the list.  Upon return,
     *IS_ERROR will be true iff an error occurred.  */
  
! static tree
  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
  {
!   tree parameters = NULL_TREE;
!   tree *tail = &parameters; 
    bool saved_in_unbraced_linkage_specification_p;
  
    /* Assume all will go well.  */
*************** cp_parser_parameter_declaration_list (cp
*** 13836,13841 ****
--- 13848,13854 ----
    while (true)
      {
        cp_parameter_declarator *parameter;
+       tree decl = error_mark_node;
        bool parenthesized_p;
        /* Parse the parameter.  */
        parameter
*************** cp_parser_parameter_declaration_list (cp
*** 13843,13859 ****
  					   /*template_parm_p=*/false,
  					   &parenthesized_p);
  
        /* If a parse error occurred parsing the parameter declaration,
  	 then the entire parameter-declaration-list is erroneous.  */
!       if (!parameter)
  	{
  	  *is_error = true;
! 	  parameters = NULL;
  	  break;
  	}
        /* Add the new parameter to the list.  */
!       *tail = parameter;
!       tail = &parameter->next;
  
        /* Peek at the next token.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
--- 13856,13893 ----
  					   /*template_parm_p=*/false,
  					   &parenthesized_p);
  
+       /* We don't know yet if the enclosing context is deprecated, so wait
+ 	 and warn in grokparms if appropriate.  */
+       deprecated_state = DEPRECATED_SUPPRESS;
+ 
+       if (parameter)
+ 	decl = grokdeclarator (parameter->declarator,
+ 			       &parameter->decl_specifiers,
+ 			       PARM,
+ 			       parameter->default_argument != NULL_TREE,
+ 			       &parameter->decl_specifiers.attributes);
+ 
+       deprecated_state = DEPRECATED_NORMAL;
+ 
        /* If a parse error occurred parsing the parameter declaration,
  	 then the entire parameter-declaration-list is erroneous.  */
!       if (decl == error_mark_node)
  	{
  	  *is_error = true;
! 	  parameters = error_mark_node;
  	  break;
  	}
+ 
+       if (parameter->decl_specifiers.attributes)
+ 	cplus_decl_attributes (&decl,
+ 			       parameter->decl_specifiers.attributes,
+ 			       0);
+       if (DECL_NAME (decl))
+ 	decl = pushdecl (decl);
+ 
        /* Add the new parameter to the list.  */
!       *tail = build_tree_list (parameter->default_argument, decl);
!       tail = &TREE_CHAIN (*tail);
  
        /* Peek at the next token.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 140075)
--- cp/pt.c	(working copy)
*************** tsubst (tree t, tree args, tsubst_flags_
*** 9556,9566 ****
        {
  	tree type;
  
! 	type = 
!           finish_decltype_type (tsubst_expr 
!                                 (DECLTYPE_TYPE_EXPR (t), args,
!                                  complain, in_decl,
!                                  /*integral_constant_expression_p=*/false),
                                  DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
  	return cp_build_qualified_type_real (type,
  					     cp_type_quals (t)
--- 9556,9571 ----
        {
  	tree type;
  
! 	++skip_evaluation;
! 
! 	type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args,
! 			    complain, in_decl,
! 			    /*integral_constant_expression_p=*/false);
! 
! 	--skip_evaluation;
! 
! 	type =
!           finish_decltype_type (type,
                                  DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
  	return cp_build_qualified_type_real (type,
  					     cp_type_quals (t)
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 9796,9802 ****
      {
      case PARM_DECL:
        r = retrieve_local_specialization (t);
!       gcc_assert (r != NULL);
        if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
  	r = ARGUMENT_PACK_SELECT_ARG (r);
        mark_used (r);
--- 9801,9822 ----
      {
      case PARM_DECL:
        r = retrieve_local_specialization (t);
! 
!       if (r == NULL)
! 	{
! 	  /* This can happen for a parameter name used later in a function
! 	     declaration (such as in a late-specified return type).
! 	     Replace it with an arbitrary expression with the same type
! 	     (*(T*)0).  This should only occur in an unevaluated context
! 	     (i.e. decltype).  */
! 	  gcc_assert (skip_evaluation && DECL_CONTEXT (t) == NULL_TREE);
! 	  r = non_reference (TREE_TYPE (t));
! 	  r = tsubst (r, args, complain, in_decl);
! 	  r = build_pointer_type (r);
! 	  r = build_c_cast (r, null_node);
! 	  return cp_build_indirect_ref (r, NULL, tf_warning_or_error);
! 	}
!       
        if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
  	r = ARGUMENT_PACK_SELECT_ARG (r);
        mark_used (r);
Index: testsuite/g++.old-deja/g++.oliva/template1.C
===================================================================
*** testsuite/g++.old-deja/g++.oliva/template1.C	(revision 140075)
--- testsuite/g++.old-deja/g++.oliva/template1.C	(working copy)
*************** template<int P = 0> struct foo {
*** 11,15 ****
  };
  
  void bar() {
!   foo<>::bar(0); // { dg-error "" "" } instantiated from here
  }
--- 11,15 ----
  };
  
  void bar() {
!   foo<>::bar(0);
  }
Index: testsuite/g++.old-deja/g++.jason/rfg16.C
===================================================================
*** testsuite/g++.old-deja/g++.jason/rfg16.C	(revision 140075)
--- testsuite/g++.old-deja/g++.jason/rfg16.C	(working copy)
***************
*** 1,5 ****
  // { dg-do assemble  }
  // Bug: g++ doesn't push parameter decls as they are parsed.
  
! void (*ptr) (int foo, int array[sizeof(foo)]); // { dg-bogus "" "" { xfail *-*-* } }  
! void test2 (int bar, int array[sizeof(bar)]) { } // { dg-bogus "" "" { xfail *-*-* } }  
--- 1,5 ----
  // { dg-do assemble  }
  // Bug: g++ doesn't push parameter decls as they are parsed.
  
! void (*ptr) (int foo, int array[sizeof(foo)]);
! void test2 (int bar, int array[sizeof(bar)]) { }
Index: testsuite/g++.old-deja/g++.pt/memtemp29.C
===================================================================
*** testsuite/g++.old-deja/g++.pt/memtemp29.C	(revision 140075)
--- testsuite/g++.old-deja/g++.pt/memtemp29.C	(working copy)
*************** struct S
*** 9,15 ****
    void f(U u);
  
    template <class U>
!   void g(U U);
  
    int c[16];
  };
--- 9,15 ----
    void f(U u);
  
    template <class U>
!   void g(U u);
  
    int c[16];
  };
Index: testsuite/g++.dg/other/error15.C
===================================================================
*** testsuite/g++.dg/other/error15.C	(revision 140075)
--- testsuite/g++.dg/other/error15.C	(working copy)
***************
*** 3,60 ****
  extern void g0 (int a, int b);
  extern void g1 (int a, float b);
  
! extern void f0 (int a,
!                 int a);  // { dg-error "multiple parameters named 'a'" }
! extern void f1 (int a,
!                 float a);  // { dg-error "multiple parameters named 'a'" }
! extern void f3 (int a, int b, int c,
!                 int a);  // { dg-error "multiple parameters named 'a'" }
! extern void f4 (int a, int b, int c,
!                 int a,
!                 int a);  // { dg-error "multiple parameters named 'a'" }
! extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h,
!                 int a,
                  int i, int j, int k, int l, int m, int n, int o, int p,
                  int q, int r, int s, int t, int u, int v, int w, int x, int y,
!                 int z);  // { dg-error "multiple parameters named 'a'" }
  
! extern void f6 (int a, int, int, int, int, int, int, int, int, int, int,
!                 int a,
                  int, int, int, int, int, int, int, int, int, int, int,
                  float, float, float, float, float, float, float, float,
!                 int);  // { dg-error "multiple parameters named 'a'" }
  
! extern void f7 (void (*a)(int),
!                 void (*a)(int));  // { dg-error "multiple parameters named 'a'" }
! extern void f8 (float (*a)(int),
!                 int (*a)(float));  // { dg-error "multiple parameters named 'a'" }
! 
! extern void f9 (int a,
!                 int a,
!                 int a);
! // { dg-error "multiple parameters named 'a'" "" { target *-*-* } 34 }
! 
! extern void f10 (int a,
!                  int b,
!                  int c,
!                  int c,
!                  int b,
!                  int a);
! // { dg-error "multiple parameters named 'a'" "" { target *-*-* } 42 }
! // { dg-error "multiple parameters named 'b'" "" { target *-*-* } 42 }
! // { dg-error "multiple parameters named 'c'" "" { target *-*-* } 42 }
  
  class C1 {
   public:
    void C1_g0 (int a, int b);
!   void C1_f0 (int a,
!               int a);  // { dg-error "multiple parameters named 'a'" }
  };
  
  template <class T>
  class C2 {
   public:
    void C2_g0 (T a, T b);
!   void C2_f0 (T a,
!               T a);  // { dg-error "multiple parameters named 'a'" }
  };
--- 3,56 ----
  extern void g0 (int a, int b);
  extern void g1 (int a, float b);
  
! extern void f0 (int a,		// { dg-error "previous" }
!                 int a);		// { dg-error "redefinition" }
! extern void f1 (int a,		// { dg-error "previous" }
!                 float a);	// { dg-error "conflicting" }
! extern void f3 (int a, int b, int c, // { dg-error "previous" }
!                 int a);		// { dg-error "redefinition" }
! extern void f4 (int a, int b, int c, // { dg-error "previous" }
!                 int a,		     // { dg-error "redefinition" }
!                 int a);		     // { dg-error "redefinition" }
! extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h, // { dg-error "previous" }
!                 int a,							// { dg-error "redefinition" }
                  int i, int j, int k, int l, int m, int n, int o, int p,
                  int q, int r, int s, int t, int u, int v, int w, int x, int y,
!                 int z);
  
! extern void f6 (int a, int, int, int, int, int, int, int, int, int, int, // { dg-error "previous" }
!                 int a,		// { dg-error "redefinition" }
                  int, int, int, int, int, int, int, int, int, int, int,
                  float, float, float, float, float, float, float, float,
!                 int);
  
! extern void f7 (void (*a)(int),	  // { dg-error "previous" }
!                 void (*a)(int));  // { dg-error "redefinition" }
! extern void f8 (float (*a)(int),  // { dg-error "previous" }
!                 int (*a)(float));  // { dg-error "conflicting" }
! 
! extern void f9 (int a,		// { dg-error "previous" }
!                 int a,		// { dg-error "redefinition" }
!                 int a);		// { dg-error "redefinition" }
! 
! extern void f10 (int a,		// { dg-error "previous" }
!                  int b,		// { dg-error "previous" }
!                  int c,		// { dg-error "previous" }
!                  int c,		// { dg-error "redefinition" }
!                  int b,		// { dg-error "redefinition" }
!                  int a);	// { dg-error "redefinition" }
  
  class C1 {
   public:
    void C1_g0 (int a, int b);
!   void C1_f0 (int a,		// { dg-error "previous" }
!               int a);		// { dg-error "redefinition" }
  };
  
  template <class T>
  class C2 {
   public:
    void C2_g0 (T a, T b);
!   void C2_f0 (T a,		// { dg-error "previous" }
!               T a);		// { dg-error "redefinition" }
  };
Index: testsuite/g++.dg/other/pr28114.C
===================================================================
*** testsuite/g++.dg/other/pr28114.C	(revision 140075)
--- testsuite/g++.dg/other/pr28114.C	(working copy)
*************** template<int> void foo(struct {}*); // {
*** 5,9 ****
  
  void bar()
  {
!   foo<0>(0);
  }
--- 5,9 ----
  
  void bar()
  {
!   foo<0>(0);			// { dg-error "" }
  }
Index: testsuite/g++.dg/other/error6.C
===================================================================
*** testsuite/g++.dg/other/error6.C	(revision 140075)
--- testsuite/g++.dg/other/error6.C	(working copy)
***************
*** 1,6 ****
--- 1,7 ----
  // { dg-do compile }
  // Make sure we emit a decent error message when trying to mangle an
  //  expression not supported by the C++ ABI due to a defect.
+ // Update: Better to make it supported, I think...
  
  template <int N>
  struct A {};
*************** A<sizeof(T::foo())> func(void);
*** 15,19 ****
  
  int main()
  {
!   func<B>();  // { dg-error "sorry, unimplemented" }
  }
--- 16,20 ----
  
  int main()
  {
!   func<B>();
  }
Index: testsuite/g++.dg/parse/error3.C
===================================================================
*** testsuite/g++.dg/parse/error3.C	(revision 140075)
--- testsuite/g++.dg/parse/error3.C	(working copy)
*************** static void InstantiateConstraint(const 
*** 6,19 ****
                                                       char*, char*,
                                                       unsigned*));
  // { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
! 
! /// in the coming test, the column information is broken as it points to
! //  the end of the declaration instead of pointing to the begining of the
! //  'TYPE' identifier. This is due to the warning being generated by the
! //  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
! //  code, the exact token location information is lost as the declaration
! //  groking code manipulates TREEs only. The token location used is then
! //  the global one that is not accurate enough. Anyway, let's say it is
! //  good enough for now, until we find a way to propagate token location to
! //  code paths that manipulate TREEs only.
! // { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
--- 6,9 ----
                                                       char*, char*,
                                                       unsigned*));
  // { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
! // { dg-error "60: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 5 } }
Index: testsuite/g++.dg/cpp0x/auto2.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto2.C	(revision 140075)
--- testsuite/g++.dg/cpp0x/auto2.C	(working copy)
*************** int main()
*** 69,72 ****
--- 69,74 ----
      case 42:
        break;
      }
+ 
+   auto j = 42, k = 24;
  }
Index: testsuite/g++.dg/cpp0x/auto3.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto3.C	(revision 140075)
--- testsuite/g++.dg/cpp0x/auto3.C	(working copy)
***************
*** 5,10 ****
--- 5,14 ----
  
  auto x;				// { dg-error "auto" }
  
+ // If the type deduced for the template parameter U is not the same in each
+ // deduction, the program is ill-formed.
+ auto i = 42, j = 42.0;		// { dg-error "" "" { xfail *-*-* } }
+ 
  // New CWG issue
  auto a[2] = { 1, 2 };		// { dg-error "auto" }
  
Index: testsuite/g++.dg/cpp0x/auto6.C
===================================================================
*** testsuite/g++.dg/cpp0x/auto6.C	(revision 140075)
--- testsuite/g++.dg/cpp0x/auto6.C	(working copy)
*************** auto f() -> int
*** 6,9 ****
  }
  
  template<class T, class U>
! auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } }
--- 6,25 ----
  }
  
  template<class T, class U>
! auto add(T t, U u) -> decltype (t+u);
! 
! template<class T, class U>
! decltype(T()+U()) add2(T t, U u);
! 
! template <class T, class U>
! U g (T, U);
! 
! template<class T, class U>
! auto add3(T t, U u) -> decltype (g(t,u));
! 
! int main()
! {
!   auto i = add(1, 2.0);
!   auto i2 = add2(1, 2.0);
!   auto i3 = add3(1, 2.0);
! }

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