FreeBSD/contrib/gcc/cp/parser.c
/* Parse a template-name.

   template-name:
     identifier

   The standard should actually say:

   template-name:
     identifier
     operator-function-id

   A defect report has been filed about this issue.

   A conversion-function-id cannot be a template name because they cannot
   be part of a template-id. In fact, looking at this code:

   a.operator K<int>()

   the conversion-function-id is "operator K<int>", and K<int> is a type-id.
   It is impossible to call a templated conversion-function-id with an
   explicit argument list, since the only allowed template parameter is
   the type to which it is converting.

   If TEMPLATE_KEYWORD_P is true, then we have just seen the
   `template' keyword, in a construction like:

     T::template f<3>()

   In that case `f' is taken to be a template-name, even though there
   is no way of knowing for sure.

   Returns the TEMPLATE_DECL for the template, or an OVERLOAD if the
   name refers to a set of overloaded functions, at least one of which
   is a template, or an IDENTIFIER_NODE with the name of the template,
   if TEMPLATE_KEYWORD_P is true.  If CHECK_DEPENDENCY_P is FALSE,
   names are looked up inside uninstantiated templates.  */
Parse a template-name.
template-name:
identifier

The standard should actually say.

template-name:
identifier
operator-function-id

A defect report has been filed about this issue.

A conversion-function-id cannot be a template name because they cannot
be part of a template-id. In fact, looking at this code.



the conversion-function-id is "operator K", and K is a type-id.
It is impossible to call a templated conversion-function-id with an
explicit argument list, since the only allowed template parameter is
the type to which it is converting.

If TEMPLATE_KEYWORD_P is true, then we have just seen the
`template' keyword, in a construction like.



In that case `f' is taken to be a template-name, even though there
is no way of knowing for sure.

Returns the TEMPLATE_DECL for the template, or an OVERLOAD if the
name refers to a set of overloaded functions, at least one of which
is a template, or an IDENTIFIER_NODE with the name of the template,
if TEMPLATE_KEYWORD_P is true.  If CHECK_DEPENDENCY_P is FALSE,
names are looked up inside uninstantiated templates.
Parse a template - name . template - name : identifier The standard should actually say . template - name : identifier operator - function - id A defect report has been filed about this issue . A conversion - function - id cannot be a template name because they cannot be part of a template - id . In fact looking at this code . the conversion - function - id is " operator K " and K is a type - id . It is impossible to call a templated conversion - function - id with an explicit argument list since the only allowed template parameter is the type to which it is converting . If TEMPLATE_KEYWORD_P is true then we have just seen the ` template ' keyword in a construction like . In that case ` f ' is taken to be a template - name even though there is no way of knowing for sure . Returns the TEMPLATE_DECL for the template or an OVERLOAD if the name refers to a set of overloaded functions at least one of which is a template or an IDENTIFIER_NODE with the name of the template if TEMPLATE_KEYWORD_P is true . If CHECK_DEPENDENCY_P is FALSE names are looked up inside uninstantiated templates .
static tree
cp_parser_template_name (cp_parser* parser,
			 bool template_keyword_p,
			 bool check_dependency_p,
			 bool is_declaration,
			 bool *is_identifier)
{
  tree identifier;
  tree decl;
  tree fns;
  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_OPERATOR))
    {
      cp_parser_parse_tentatively (parser);
      identifier = cp_parser_operator_function_id (parser);
      if (!cp_parser_parse_definitely (parser))
	{
	  cp_parser_error (parser, "expected template-name");
	  return error_mark_node;
	}
    }
  else
    identifier = cp_parser_identifier (parser);
  if (identifier == error_mark_node)
    return error_mark_node;
  if (processing_template_decl
      && cp_parser_nth_token_starts_template_argument_list_p (parser, 1))
    {
      if (is_declaration
	  && !template_keyword_p
	  && parser->scope && TYPE_P (parser->scope)
	  && check_dependency_p
	  && dependent_type_p (parser->scope)
	  && !constructor_name_p (identifier, parser->scope))
	{
	  cp_token_position start = 0;
	  error ("non-template %qD used as template", identifier);
	  inform ("use %<%T::template %D%> to indicate that it is a template",
		  parser->scope, identifier);
	  if (cp_parser_simulate_error (parser))
	    start = cp_lexer_token_position (parser->lexer, true);
	  cp_lexer_consume_token (parser->lexer);
	  cp_parser_enclosed_template_argument_list (parser);
	  cp_parser_skip_to_closing_parenthesis (parser,
						 true,
						 true,
						 false);
	  if (start)
	    cp_lexer_purge_tokens_after (parser->lexer, start);
	  if (is_identifier)
	    *is_identifier = true;
	  return identifier;
	}
      if (template_keyword_p
	  && (!parser->scope
	      || (TYPE_P (parser->scope)
		  && dependent_type_p (parser->scope))))
	return identifier;
    }
  decl = cp_parser_lookup_name (parser, identifier,
				none_type,
				false,
				false,
				check_dependency_p,
				NULL);
  decl = maybe_get_template_decl_from_type_decl (decl);
  if (TREE_CODE (decl) == TEMPLATE_DECL)
    ;
  else
    {
      tree fn = NULL_TREE;
      fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl;
      if (TREE_CODE (fns) == OVERLOAD)
	for (fn = fns; fn; fn = OVL_NEXT (fn))
	  if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
	    break;
      if (!fn)
	{
	  cp_parser_error (parser, "expected template-name");
	  return error_mark_node;
	}
    }
  if (DECL_FUNCTION_TEMPLATE_P (decl) || !DECL_P (decl))
    {
      tree scope = CP_DECL_CONTEXT (get_first_fn (decl));
      if (TYPE_P (scope) && dependent_type_p (scope))
	return identifier;
    }
  return decl;
}
static tree cp_parser_template_name ( cp_parser * parser , bool template_keyword_p , bool check_dependency_p , bool is_declaration , bool * is_identifier ) { tree identifier ; tree decl ; tree fns ; if ( cp_lexer_next_token_is_keyword ( parser -> lexer , RID_OPERATOR ) ) { cp_parser_parse_tentatively ( parser ) ; identifier = cp_parser_operator_function_id ( parser ) ; if ( ! cp_parser_parse_definitely ( parser ) ) { cp_parser_error ( parser , " " ) ; return error_mark_node ; } } else identifier = cp_parser_identifier ( parser ) ; if ( identifier == error_mark_node ) return error_mark_node ; if ( processing_template_decl && cp_parser_nth_token_starts_template_argument_list_p ( parser , 1 ) ) { if ( is_declaration && ! template_keyword_p && parser -> scope && TYPE_P ( parser -> scope ) && check_dependency_p && dependent_type_p ( parser -> scope ) && ! constructor_name_p ( identifier , parser -> scope ) ) { cp_token_position start = 0 ; error ( " " , identifier ) ; inform ( " " , parser -> scope , identifier ) ; if ( cp_parser_simulate_error ( parser ) ) start = cp_lexer_token_position ( parser -> lexer , true ) ; cp_lexer_consume_token ( parser -> lexer ) ; cp_parser_enclosed_template_argument_list ( parser ) ; cp_parser_skip_to_closing_parenthesis ( parser , true , true , false ) ; if ( start ) cp_lexer_purge_tokens_after ( parser -> lexer , start ) ; if ( is_identifier ) * is_identifier = true ; return identifier ; } if ( template_keyword_p && ( ! parser -> scope || ( TYPE_P ( parser -> scope ) && dependent_type_p ( parser -> scope ) ) ) ) return identifier ; } decl = cp_parser_lookup_name ( parser , identifier , none_type , false , false , check_dependency_p , NULL ) ; decl = maybe_get_template_decl_from_type_decl ( decl ) ; if ( TREE_CODE ( decl ) == TEMPLATE_DECL ) ; else { tree fn = NULL_TREE ; fns = BASELINK_P ( decl ) ? BASELINK_FUNCTIONS ( decl ) : decl ; if ( TREE_CODE ( fns ) == OVERLOAD ) for ( fn = fns ; fn ; fn = OVL_NEXT ( fn ) ) if ( TREE_CODE ( OVL_CURRENT ( fn ) ) == TEMPLATE_DECL ) break ; if ( ! fn ) { cp_parser_error ( parser , " " ) ; return error_mark_node ; } } if ( DECL_FUNCTION_TEMPLATE_P ( decl ) || ! DECL_P ( decl ) ) { tree scope = CP_DECL_CONTEXT ( get_first_fn ( decl ) ) ; if ( TYPE_P ( scope ) && dependent_type_p ( scope ) ) return identifier ; } return decl ; }
Parse a template-name.
Parse a template - name .
/* If the next token is `operator', then we have either an
     operator-function-id or a conversion-function-id.  */ /* We don't know whether we're looking at an
	 operator-function-id or a conversion-function-id.  */ /* Try an operator-function-id.  */ /* If that didn't work, try a conversion-function-id.  */ /* Look for the identifier.  */ /* If we didn't find an identifier, we don't have a template-id.  */ /* If the name immediately followed the `template' keyword, then it
     is a template-name.  However, if the next token is not `<', then
     we do not treat it as a template-name, since it is not being used
     as part of a template-id.  This enables us to handle constructs
     like:

       template <typename T> struct S { S(); };
       template <typename T> S<T>::S();

     correctly.  We would treat `S' as a template -- if it were `S<T>'
     -- but we do not if there is no `<'.  */ /* In a declaration, in a dependent context, we pretend that the
	 "template" keyword was present in order to improve error
	 recovery.  For example, given:

	   template <typename T> void f(T::X<int>);

	 we want to treat "X<int>" as a template-id.  */ /* Do not do this for dtors (or ctors), since they never
	     need the template keyword before their name.  */ /* Explain what went wrong.  */ /* If parsing tentatively, find the location of the "<" token.  */ /* Parse the template arguments so that we can issue error
	     messages about them.  */ /* Skip tokens until we find a good place from which to
	     continue parsing.  */ /*recovering=*/ /*or_comma=*/ /*consume_paren=*/ /* If parsing tentatively, permanently remove the
	     template argument list.  That will prevent duplicate
	     error messages from being issued about the missing
	     "template" keyword.  */ /* If the "template" keyword is present, then there is generally
	 no point in doing name-lookup, so we just return IDENTIFIER.
	 But, if the qualifying scope is non-dependent then we can
	 (and must) do name-lookup normally.  */ /* Look up the name.  */ /*is_template=*/ /*is_namespace=*/ /*ambiguous_decls=*/ /* If DECL is a template, then the name was a template-name.  */ /* The standard does not explicitly indicate whether a name that
	 names a set of overloaded declarations, some of which are
	 templates, is a template-name.  However, such a name should
	 be a template-name; otherwise, there is no way to form a
	 template-id for the overloaded templates.  */ /* The name does not name a template.  */ /* If DECL is dependent, and refers to a function, then just return
     its name; we will look it up again during template instantiation.  */