llvm-gcc-4.2-2.9/gcc/cp/parser.c
/* Parse a parameter declaration.

   parameter-declaration:
     decl-specifier-seq declarator
     decl-specifier-seq declarator = assignment-expression
     decl-specifier-seq abstract-declarator [opt]
     decl-specifier-seq abstract-declarator [opt] = assignment-expression

   If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
   declares a template parameter.  (In that case, a non-nested `>'
   token encountered during the parsing of the assignment-expression
   is not interpreted as a greater-than operator.)

   Returns a representation of the parameter, or NULL if an error
   occurs.  If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to
   true iff the declarator is of the form "(p)".  */
Parse a parameter declaration.

If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
declares a template parameter.  (In that case, a non-nested `>'
token encountered during the parsing of the assignment-expression
is not interpreted as a greater-than operator.)

Returns a representation of the parameter, or NULL if an error
occurs.  If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to
true iff the declarator is of the form "(p)".
Parse a parameter declaration . If TEMPLATE_PARM_P is TRUE then this parameter - declaration declares a template parameter . ( In that case a non - nested ` > ' token encountered during the parsing of the assignment - expression is not interpreted as a greater - than operator . ) Returns a representation of the parameter or NULL if an error occurs . If PARENTHESIZED_P is non - NULL * PARENTHESIZED_P is set to true iff the declarator is of the form " ( p ) " .
static cp_parameter_declarator *
cp_parser_parameter_declaration (cp_parser *parser,
				 bool template_parm_p,
				 bool *parenthesized_p)
{
  int declares_class_or_enum;
  bool greater_than_is_operator_p;
  cp_decl_specifier_seq decl_specifiers;
  cp_declarator *declarator;
  tree default_argument;
  cp_token *token;
  const char *saved_message;
  greater_than_is_operator_p = !template_parm_p;
  saved_message = parser->type_definition_forbidden_message;
  parser->type_definition_forbidden_message
    = "types may not be defined in parameter types";
  cp_parser_decl_specifier_seq (parser,
				CP_PARSER_FLAGS_NONE,
				&decl_specifiers,
				&declares_class_or_enum);
  if (cp_parser_error_occurred (parser))
    {
      parser->type_definition_forbidden_message = saved_message;
      return NULL;
    }
  token = cp_lexer_peek_token (parser->lexer);
  if (token->type == CPP_CLOSE_PAREN
      || token->type == CPP_COMMA
      || token->type == CPP_EQ
      || token->type == CPP_ELLIPSIS
      || token->type == CPP_GREATER)
    {
      declarator = NULL;
      if (parenthesized_p)
	*parenthesized_p = false;
    }
  else
    {
      bool saved_default_arg_ok_p = parser->default_arg_ok_p;
      parser->default_arg_ok_p = false;
      if (!parser->in_template_argument_list_p
	  && !parser->in_type_id_in_expr_p
	  && cp_parser_uncommitted_to_tentative_parse_p (parser)
	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
	cp_parser_commit_to_tentative_parse (parser);
      declarator = cp_parser_declarator (parser,
					 CP_PARSER_DECLARATOR_EITHER,
					 NULL,
					 parenthesized_p,
					 false);
      parser->default_arg_ok_p = saved_default_arg_ok_p;
      decl_specifiers.attributes
	= chainon (decl_specifiers.attributes,
		   cp_parser_attributes_opt (parser));
    }
  parser->type_definition_forbidden_message = saved_message;
  if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
    {
      bool saved_greater_than_is_operator_p;
      cp_lexer_consume_token (parser->lexer);
      if (!template_parm_p && at_class_scope_p ()
	  && TYPE_BEING_DEFINED (current_class_type))
	{
	  unsigned depth = 0;
	  cp_token *first_token;
	  cp_token *token;
	  first_token = cp_lexer_peek_token (parser->lexer);
	  while (true)
	    {
	      bool done = false;
	      token = cp_lexer_peek_token (parser->lexer);
	      switch (token->type)
		{
		case CPP_COMMA:
		case CPP_CLOSE_PAREN:
		case CPP_ELLIPSIS:
		case CPP_SEMICOLON:
		case CPP_CLOSE_BRACE:
		case CPP_CLOSE_SQUARE:
		  if (depth == 0)
		    done = true;
		  else if (token->type == CPP_CLOSE_PAREN
			   || token->type == CPP_CLOSE_BRACE
			   || token->type == CPP_CLOSE_SQUARE)
		    --depth;
		  break;
		case CPP_OPEN_PAREN:
		case CPP_OPEN_SQUARE:
		case CPP_OPEN_BRACE:
		  ++depth;
		  break;
		case CPP_GREATER:
		  if (!depth && !greater_than_is_operator_p)
		    done = true;
		  break;
		case CPP_EOF:
		case CPP_PRAGMA_EOL:
		  error ("file ends in default argument");
		  done = true;
		  break;
		case CPP_NAME:
		case CPP_SCOPE:
		  break;
		default:
		  break;
		}
	      if (done)
		break;
	      token = cp_lexer_consume_token (parser->lexer);
	    }
	  default_argument = make_node (DEFAULT_ARG);
	  DEFARG_TOKENS (default_argument)
	    = cp_token_cache_new (first_token, token);
	  DEFARG_INSTANTIATIONS (default_argument) = NULL;
	}
      else
	{
	  bool saved_local_variables_forbidden_p;
	  saved_greater_than_is_operator_p
	    = parser->greater_than_is_operator_p;
	  parser->greater_than_is_operator_p = greater_than_is_operator_p;
	  saved_local_variables_forbidden_p
	    = parser->local_variables_forbidden_p;
	  parser->local_variables_forbidden_p = true;
	  ++function_depth;
	  if (template_parm_p)
	    push_deferring_access_checks (dk_no_deferred);
	  default_argument
	    = cp_parser_assignment_expression (parser, false);
	  if (template_parm_p)
	    pop_deferring_access_checks ();
	  --function_depth;
	  parser->greater_than_is_operator_p
	    = saved_greater_than_is_operator_p;
	  parser->local_variables_forbidden_p
	    = saved_local_variables_forbidden_p;
	}
      if (!parser->default_arg_ok_p)
	{
	  if (!flag_pedantic_errors)
	    warning (0, "deprecated use of default argument for parameter of non-function");
	  else
	    {
	      error ("default arguments are only permitted for function parameters");
	      default_argument = NULL_TREE;
	    }
	}
    }
  else
    default_argument = NULL_TREE;
  return make_parameter_declarator (&decl_specifiers,
				    declarator,
				    default_argument);
}
static cp_parameter_declarator * cp_parser_parameter_declaration ( cp_parser * parser , bool template_parm_p , bool * parenthesized_p ) { int declares_class_or_enum ; bool greater_than_is_operator_p ; cp_decl_specifier_seq decl_specifiers ; cp_declarator * declarator ; tree default_argument ; cp_token * token ; const char * saved_message ; greater_than_is_operator_p = ! template_parm_p ; saved_message = parser -> type_definition_forbidden_message ; parser -> type_definition_forbidden_message = " " ; cp_parser_decl_specifier_seq ( parser , CP_PARSER_FLAGS_NONE , & decl_specifiers , & declares_class_or_enum ) ; if ( cp_parser_error_occurred ( parser ) ) { parser -> type_definition_forbidden_message = saved_message ; return NULL ; } token = cp_lexer_peek_token ( parser -> lexer ) ; if ( token -> type == CPP_CLOSE_PAREN || token -> type == CPP_COMMA || token -> type == CPP_EQ || token -> type == CPP_ELLIPSIS || token -> type == CPP_GREATER ) { declarator = NULL ; if ( parenthesized_p ) * parenthesized_p = false ; } else { bool saved_default_arg_ok_p = parser -> default_arg_ok_p ; parser -> default_arg_ok_p = false ; if ( ! parser -> in_template_argument_list_p && ! parser -> in_type_id_in_expr_p && cp_parser_uncommitted_to_tentative_parse_p ( parser ) && cp_lexer_next_token_is_not ( parser -> lexer , CPP_OPEN_PAREN ) ) cp_parser_commit_to_tentative_parse ( parser ) ; declarator = cp_parser_declarator ( parser , CP_PARSER_DECLARATOR_EITHER , NULL , parenthesized_p , false ) ; parser -> default_arg_ok_p = saved_default_arg_ok_p ; decl_specifiers . attributes = chainon ( decl_specifiers . attributes , cp_parser_attributes_opt ( parser ) ) ; } parser -> type_definition_forbidden_message = saved_message ; if ( cp_lexer_next_token_is ( parser -> lexer , CPP_EQ ) ) { bool saved_greater_than_is_operator_p ; cp_lexer_consume_token ( parser -> lexer ) ; if ( ! template_parm_p && at_class_scope_p ( ) && TYPE_BEING_DEFINED ( current_class_type ) ) { unsigned depth = 0 ; cp_token * first_token ; cp_token * token ; first_token = cp_lexer_peek_token ( parser -> lexer ) ; while ( true ) { bool done = false ; token = cp_lexer_peek_token ( parser -> lexer ) ; switch ( token -> type ) { case CPP_COMMA : case CPP_CLOSE_PAREN : case CPP_ELLIPSIS : case CPP_SEMICOLON : case CPP_CLOSE_BRACE : case CPP_CLOSE_SQUARE : if ( depth == 0 ) done = true ; else if ( token -> type == CPP_CLOSE_PAREN || token -> type == CPP_CLOSE_BRACE || token -> type == CPP_CLOSE_SQUARE ) -- depth ; break ; case CPP_OPEN_PAREN : case CPP_OPEN_SQUARE : case CPP_OPEN_BRACE : ++ depth ; break ; case CPP_GREATER : if ( ! depth && ! greater_than_is_operator_p ) done = true ; break ; case CPP_EOF : case CPP_PRAGMA_EOL : error ( " " ) ; done = true ; break ; case CPP_NAME : case CPP_SCOPE : break ; default : break ; } if ( done ) break ; token = cp_lexer_consume_token ( parser -> lexer ) ; } default_argument = make_node ( DEFAULT_ARG ) ; DEFARG_TOKENS ( default_argument ) = cp_token_cache_new ( first_token , token ) ; DEFARG_INSTANTIATIONS ( default_argument ) = NULL ; } else { bool saved_local_variables_forbidden_p ; saved_greater_than_is_operator_p = parser -> greater_than_is_operator_p ; parser -> greater_than_is_operator_p = greater_than_is_operator_p ; saved_local_variables_forbidden_p = parser -> local_variables_forbidden_p ; parser -> local_variables_forbidden_p = true ; ++ function_depth ; if ( template_parm_p ) push_deferring_access_checks ( dk_no_deferred ) ; default_argument = cp_parser_assignment_expression ( parser , false ) ; if ( template_parm_p ) pop_deferring_access_checks ( ) ; -- function_depth ; parser -> greater_than_is_operator_p = saved_greater_than_is_operator_p ; parser -> local_variables_forbidden_p = saved_local_variables_forbidden_p ; } if ( ! parser -> default_arg_ok_p ) { if ( ! flag_pedantic_errors ) warning ( 0 , " " ) ; else { error ( " " ) ; default_argument = NULL_TREE ; } } } else default_argument = NULL_TREE ; return make_parameter_declarator ( & decl_specifiers , declarator , default_argument ) ; }
Parse a parameter declaration.
Parse a parameter declaration .
/* In a template parameter, `>' is not an operator.

     [temp.param]

     When parsing a default template-argument for a non-type
     template-parameter, the first non-nested `>' is taken as the end
     of the template parameter-list rather than a greater-than
     operator.  */ /* Type definitions may not appear in parameter types.  */ /* Parse the declaration-specifiers.  */ /* If an error occurred, there's no reason to attempt to parse the
     rest of the declaration.  */ /* Peek at the next token.  */ /* If the next token is a `)', `,', `=', `>', or `...', then there
     is no declarator.  */ /* Otherwise, there should be a declarator.  */ /* After seeing a decl-specifier-seq, if the next token is not a
	 "(", there is no possibility that the code is a valid
	 expression.  Therefore, if parsing tentatively, we commit at
	 this point.  */ /* In an expression context, having seen:

	       (int((char ...

	     we cannot be sure whether we are looking at a
	     function-type (taking a "char" as a parameter) or a cast
	     of some object of type "char" to "int".  */ /* Parse the declarator.  */ /*ctor_dtor_or_conv_p=*/ /*member_p=*/ /* After the declarator, allow more attributes.  */ /* The restriction on defining new types applies only to the type
     of the parameter, not to the default argument.  */ /* If the next token is `=', then process a default argument.  */ /* Consume the `='.  */ /* If we are defining a class, then the tokens that make up the
	 default argument must be saved and processed later.  */ /* Add tokens until we have processed the entire default
	     argument.  We add the range [first_token, token).  */ /* Peek at the next token.  */ /* What we do depends on what token we have.  */ /* In valid code, a default argument must be
		     immediately followed by a `,' `)', or `...'.  */ /* If we run into a non-nested `;', `}', or `]',
		     then the code is invalid -- but the default
		     argument is certainly over.  */ /* Update DEPTH, if necessary.  */ /* If we see a non-nested `>', and `>' is not an
		     operator, then it marks the end of the default
		     argument.  */ /* If we run out of tokens, issue an error message.  */ /* In these cases, we should look for template-ids.
		     For example, if the default argument is
		     `X<int, double>()', we need to do name lookup to
		     figure out whether or not `X' is a template; if
		     so, the `,' does not end the default argument.

		     That is not yet done.  */ /* If we've reached the end, stop.  */ /* Add the token to the token block.  */ /* Create a DEFAULT_ARG to represented the unparsed default
	     argument.  */ /* Outside of a class definition, we can just parse the
	 assignment-expression.  */ /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
	     set correctly.  */ /* Local variable names (and the `this' keyword) may not
	     appear in a default argument.  */ /* The default argument expression may cause implicitly
	     defined member functions to be synthesized, which will
	     result in garbage collection.  We must treat this
	     situation as if we were within the body of function so as
	     to avoid collecting live data on the stack.  */ /* Parse the assignment-expression.  */ /*cast_p=*/ /* Restore saved state.  */