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

   class-name:
     identifier
     template-id

   TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used
   to indicate that names looked up in dependent types should be
   assumed to be types.  TEMPLATE_KEYWORD_P is true iff the `template'
   keyword has been used to indicate that the name that appears next
   is a template.  TAG_TYPE indicates the explicit tag given before
   the type name, if any.  If CHECK_DEPENDENCY_P is FALSE, names are
   looked up in dependent scopes.  If CLASS_HEAD_P is TRUE, this class
   is the class being defined in a class-head.

   Returns the TYPE_DECL representing the class.  */
Parse a class-name.
class-name:
identifier
template-id

TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used
to indicate that names looked up in dependent types should be
assumed to be types.  TEMPLATE_KEYWORD_P is true iff the `template'
keyword has been used to indicate that the name that appears next
is a template.  TAG_TYPE indicates the explicit tag given before
the type name, if any.  If CHECK_DEPENDENCY_P is FALSE, names are
looked up in dependent scopes.  If CLASS_HEAD_P is TRUE, this class
is the class being defined in a class-head.

Returns the TYPE_DECL representing the class.
Parse a class - name . class - name : identifier template - id TYPENAME_KEYWORD_P is true iff the ` typename ' keyword has been used to indicate that names looked up in dependent types should be assumed to be types . TEMPLATE_KEYWORD_P is true iff the ` template ' keyword has been used to indicate that the name that appears next is a template . TAG_TYPE indicates the explicit tag given before the type name if any . If CHECK_DEPENDENCY_P is FALSE names are looked up in dependent scopes . If CLASS_HEAD_P is TRUE this class is the class being defined in a class - head . Returns the TYPE_DECL representing the class .
static tree
cp_parser_class_name (cp_parser *parser,
		      bool typename_keyword_p,
		      bool template_keyword_p,
		      enum tag_types tag_type,
		      bool check_dependency_p,
		      bool class_head_p,
		      bool is_declaration)
{
  tree decl;
  tree scope;
  bool typename_p;
  cp_token *token;
  token = cp_lexer_peek_token (parser->lexer);
  if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
    {
      cp_parser_error (parser, "expected class-name");
      return error_mark_node;
    }
  scope = parser->scope;
  if (scope == error_mark_node)
    return error_mark_node;
  typename_p = (typename_keyword_p && scope && TYPE_P (scope)
		&& dependent_type_p (scope));
  if (token->type == CPP_NAME
      && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
    {
      cp_token *identifier_token;
      tree identifier;
      bool ambiguous_p;
      identifier_token = cp_lexer_peek_token (parser->lexer);
      ambiguous_p = identifier_token->ambiguous_p;
      identifier = cp_parser_identifier (parser);
      if (identifier == error_mark_node)
	decl = error_mark_node;
      else if (typename_p)
	decl = identifier;
      else
	{
	  tree ambiguous_decls;
	  if (ambiguous_p)
	    {
	      cp_parser_simulate_error (parser);
	      return error_mark_node;
	    }
	  if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
	    tag_type = typename_type;
	  decl = cp_parser_lookup_name (parser, identifier,
					tag_type,
					false,
					false,
					check_dependency_p,
					&ambiguous_decls);
	  if (ambiguous_decls)
	    {
	      error ("reference to %qD is ambiguous", identifier);
	      print_candidates (ambiguous_decls);
	      if (cp_parser_parsing_tentatively (parser))
		{
		  identifier_token->ambiguous_p = true;
		  cp_parser_simulate_error (parser);
		}
	      return error_mark_node;
	    }
	}
    }
  else
    {
      decl = cp_parser_template_id (parser, template_keyword_p,
				    check_dependency_p,
				    is_declaration);
      if (decl == error_mark_node)
	return error_mark_node;
    }
  decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
  if (typename_p && decl != error_mark_node)
    {
      decl = make_typename_type (scope, decl, typename_type,
				 tf_error);
      if (decl != error_mark_node)
	decl = TYPE_NAME (decl);
    }
  if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
      && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
      && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
    {
      decl = make_typename_type (scope, decl, tag_type, tf_error);
      if (decl != error_mark_node)
	decl = TYPE_NAME (decl);
    }
  else if (TREE_CODE (decl) != TYPE_DECL
	   || TREE_TYPE (decl) == error_mark_node
	   || !IS_AGGR_TYPE (TREE_TYPE (decl)))
    decl = error_mark_node;
  if (decl == error_mark_node)
    cp_parser_error (parser, "expected class-name");
  return decl;
}
static tree cp_parser_class_name ( cp_parser * parser , bool typename_keyword_p , bool template_keyword_p , enum tag_types tag_type , bool check_dependency_p , bool class_head_p , bool is_declaration ) { tree decl ; tree scope ; bool typename_p ; cp_token * token ; token = cp_lexer_peek_token ( parser -> lexer ) ; if ( token -> type != CPP_NAME && token -> type != CPP_TEMPLATE_ID ) { cp_parser_error ( parser , " " ) ; return error_mark_node ; } scope = parser -> scope ; if ( scope == error_mark_node ) return error_mark_node ; typename_p = ( typename_keyword_p && scope && TYPE_P ( scope ) && dependent_type_p ( scope ) ) ; if ( token -> type == CPP_NAME && ! cp_parser_nth_token_starts_template_argument_list_p ( parser , 2 ) ) { cp_token * identifier_token ; tree identifier ; bool ambiguous_p ; identifier_token = cp_lexer_peek_token ( parser -> lexer ) ; ambiguous_p = identifier_token -> ambiguous_p ; identifier = cp_parser_identifier ( parser ) ; if ( identifier == error_mark_node ) decl = error_mark_node ; else if ( typename_p ) decl = identifier ; else { tree ambiguous_decls ; if ( ambiguous_p ) { cp_parser_simulate_error ( parser ) ; return error_mark_node ; } if ( cp_lexer_next_token_is ( parser -> lexer , CPP_SCOPE ) ) tag_type = typename_type ; decl = cp_parser_lookup_name ( parser , identifier , tag_type , false , false , check_dependency_p , & ambiguous_decls ) ; if ( ambiguous_decls ) { error ( " " , identifier ) ; print_candidates ( ambiguous_decls ) ; if ( cp_parser_parsing_tentatively ( parser ) ) { identifier_token -> ambiguous_p = true ; cp_parser_simulate_error ( parser ) ; } return error_mark_node ; } } } else { decl = cp_parser_template_id ( parser , template_keyword_p , check_dependency_p , is_declaration ) ; if ( decl == error_mark_node ) return error_mark_node ; } decl = cp_parser_maybe_treat_template_as_class ( decl , class_head_p ) ; if ( typename_p && decl != error_mark_node ) { decl = make_typename_type ( scope , decl , typename_type , tf_error ) ; if ( decl != error_mark_node ) decl = TYPE_NAME ( decl ) ; } if ( TREE_CODE ( decl ) == TEMPLATE_ID_EXPR && TREE_CODE ( TREE_OPERAND ( decl , 0 ) ) == IDENTIFIER_NODE && cp_lexer_next_token_is ( parser -> lexer , CPP_SCOPE ) ) { decl = make_typename_type ( scope , decl , tag_type , tf_error ) ; if ( decl != error_mark_node ) decl = TYPE_NAME ( decl ) ; } else if ( TREE_CODE ( decl ) != TYPE_DECL || TREE_TYPE ( decl ) == error_mark_node || ! IS_AGGR_TYPE ( TREE_TYPE ( decl ) ) ) decl = error_mark_node ; if ( decl == error_mark_node ) cp_parser_error ( parser , " " ) ; return decl ; }
Parse a class-name.
Parse a class - name .
/* All class-names start with an identifier.  */ /* PARSER->SCOPE can be cleared when parsing the template-arguments
     to a template-id, so we save it here.  */ /* Any name names a type if we're following the `typename' keyword
     in a qualified name where the enclosing scope is type-dependent.  */ /* Handle the common case (an identifier, but not a template-id)
     efficiently.  */ /* Look for the identifier.  */ /* If the next token isn't an identifier, we are certainly not
	 looking at a class-name.  */ /* If we know this is a type-name, there's no need to look it
	 up.  */ /* If we already know that this lookup is ambiguous, then
	     we've already issued an error message; there's no reason
	     to check again.  */ /* If the next token is a `::', then the name must be a type
	     name.

	     [basic.lookup.qual]

	     During the lookup for a name preceding the :: scope
	     resolution operator, object, function, and enumerator
	     names are ignored.  */ /* Look up the name.  */ /*is_template=*/ /*is_namespace=*/ /* Try a template-id.  */ /* If this is a typename, create a TYPENAME_TYPE.  */ /*complain=*/ /* Check to see that it is really the name of a class.  */ /* Situations like this:

	 template <typename T> struct A {
	   typename T::template X<int>::I i;
	 };

       are problematic.  Is `T::template X<int>' a class-name?  The
       standard does not seem to be definitive, but there is no other
       valid interpretation of the following `::'.  Therefore, those
       names are considered class-names.  */