FreeBSD/contrib/gcc/cp/parser.c
/* Parse an unqualified-id.

   unqualified-id:
     identifier
     operator-function-id
     conversion-function-id
     ~ class-name
     template-id

   If TEMPLATE_KEYWORD_P is TRUE, we have just seen the `template'
   keyword, in a construct like `A::template ...'.

   Returns a representation of unqualified-id.  For the `identifier'
   production, an IDENTIFIER_NODE is returned.  For the `~ class-name'
   production a BIT_NOT_EXPR is returned; the operand of the
   BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name.  For the
   other productions, see the documentation accompanying the
   corresponding parsing functions.  If CHECK_DEPENDENCY_P is false,
   names are looked up in uninstantiated templates.  If DECLARATOR_P
   is true, the unqualified-id is appearing as part of a declarator,
   rather than as part of an expression.  */
Parse an unqualified-id.

If TEMPLATE_KEYWORD_P is TRUE, we have just seen the `template'
keyword, in a construct like `A::template ...'.

Returns a representation of unqualified-id.  For the `identifier'
production, an IDENTIFIER_NODE is returned.  For the `~ class-name'
production a BIT_NOT_EXPR is returned; the operand of the
BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name.  For the
other productions, see the documentation accompanying the
corresponding parsing functions.  If CHECK_DEPENDENCY_P is false,
names are looked up in uninstantiated templates.  If DECLARATOR_P
is true, the unqualified-id is appearing as part of a declarator,
rather than as part of an expression.
Parse an unqualified - id . If TEMPLATE_KEYWORD_P is TRUE we have just seen the ` template ' keyword in a construct like ` A :: template ... ' . Returns a representation of unqualified - id . For the ` identifier ' production an IDENTIFIER_NODE is returned . For the ` ~ class - name ' production a BIT_NOT_EXPR is returned ; the operand of the BIT_NOT_EXPR is an IDENTIFIER_NODE for the class - name . For the other productions see the documentation accompanying the corresponding parsing functions . If CHECK_DEPENDENCY_P is false names are looked up in uninstantiated templates . If DECLARATOR_P is true the unqualified - id is appearing as part of a declarator rather than as part of an expression .
static tree
cp_parser_unqualified_id (cp_parser* parser,
			  bool template_keyword_p,
			  bool check_dependency_p,
			  bool declarator_p,
			  bool optional_p)
{
  cp_token *token;
  token = cp_lexer_peek_token (parser->lexer);
  switch (token->type)
    {
    case CPP_NAME:
      {
	tree id;
	cp_parser_parse_tentatively (parser);
	id = cp_parser_template_id (parser, template_keyword_p,
				    check_dependency_p,
				    declarator_p);
	if (cp_parser_parse_definitely (parser))
	  return id;
	return cp_parser_identifier (parser);
      }
    case CPP_TEMPLATE_ID:
      return cp_parser_template_id (parser, template_keyword_p,
				    check_dependency_p,
				    declarator_p);
    case CPP_COMPL:
      {
	tree type_decl;
	tree qualifying_scope;
	tree object_scope;
	tree scope;
	bool done;
	cp_lexer_consume_token (parser->lexer);
	scope = parser->scope;
	object_scope = parser->object_scope;
	qualifying_scope = parser->qualifying_scope;
	if (scope == error_mark_node)
	  {
	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
	      cp_lexer_consume_token (parser->lexer);
	    return error_mark_node;
	  }
	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
	  {
	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
	      error ("scope %qT before %<~%> is not a class-name", scope);
	    cp_parser_simulate_error (parser);
	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
	      cp_lexer_consume_token (parser->lexer);
	    return error_mark_node;
	  }
	gcc_assert (!scope || TYPE_P (scope));
	token = cp_lexer_peek_token (parser->lexer);
	if (scope
	    && token->type == CPP_NAME
	    && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
		== CPP_OPEN_PAREN)
	    && constructor_name_p (token->u.value, scope))
	  {
	    cp_lexer_consume_token (parser->lexer);
	    return build_nt (BIT_NOT_EXPR, scope);
	  }
	done = false;
	type_decl = NULL_TREE;
	if (scope)
	  {
	    cp_parser_parse_tentatively (parser);
	    type_decl = cp_parser_class_name (parser,
					      false,
					      false,
					      none_type,
					      false,
					      false,
					      declarator_p);
	    if (cp_parser_parse_definitely (parser))
	      done = true;
	  }
	if (!done && scope && qualifying_scope)
	  {
	    cp_parser_parse_tentatively (parser);
	    parser->scope = qualifying_scope;
	    parser->object_scope = NULL_TREE;
	    parser->qualifying_scope = NULL_TREE;
	    type_decl
	      = cp_parser_class_name (parser,
				      false,
				      false,
				      none_type,
				      false,
				      false,
				      declarator_p);
	    if (cp_parser_parse_definitely (parser))
	      done = true;
	  }
	else if (!done && object_scope)
	  {
	    cp_parser_parse_tentatively (parser);
	    parser->scope = object_scope;
	    parser->object_scope = NULL_TREE;
	    parser->qualifying_scope = NULL_TREE;
	    type_decl
	      = cp_parser_class_name (parser,
				      false,
				      false,
				      none_type,
				      false,
				      false,
				      declarator_p);
	    if (cp_parser_parse_definitely (parser))
	      done = true;
	  }
	if (!done)
	  {
	    parser->scope = NULL_TREE;
	    parser->object_scope = NULL_TREE;
	    parser->qualifying_scope = NULL_TREE;
	    type_decl
	      = cp_parser_class_name (parser,
				      false,
				      false,
				      none_type,
				      false,
				      false,
				      declarator_p);
	  }
	if (type_decl == error_mark_node && scope)
	  return build_nt (BIT_NOT_EXPR, scope);
	else if (type_decl == error_mark_node)
	  return error_mark_node;
	if (declarator_p && scope && !check_dtor_name (scope, type_decl))
	  {
	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
	      error ("declaration of %<~%T%> as member of %qT",
		     type_decl, scope);
	    cp_parser_simulate_error (parser);
	    return error_mark_node;
	  }
	if (declarator_p
	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
	    && !DECL_SELF_REFERENCE_P (type_decl)
	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
	  error ("typedef-name %qD used as destructor declarator",
		 type_decl);
	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
      }
    case CPP_KEYWORD:
      if (token->keyword == RID_OPERATOR)
	{
	  tree id;
	  cp_parser_parse_tentatively (parser);
	  id = cp_parser_template_id (parser, template_keyword_p,
				      true,
				      declarator_p);
	  if (cp_parser_parse_definitely (parser))
	    return id;
	  cp_parser_parse_tentatively (parser);
	  id = cp_parser_operator_function_id (parser);
	  if (!cp_parser_parse_definitely (parser))
	    id = cp_parser_conversion_function_id (parser);
	  return id;
	}
    default:
      if (optional_p)
	return NULL_TREE;
      cp_parser_error (parser, "expected unqualified-id");
      return error_mark_node;
    }
}
static tree cp_parser_unqualified_id ( cp_parser * parser , bool template_keyword_p , bool check_dependency_p , bool declarator_p , bool optional_p ) { cp_token * token ; token = cp_lexer_peek_token ( parser -> lexer ) ; switch ( token -> type ) { case CPP_NAME : { tree id ; cp_parser_parse_tentatively ( parser ) ; id = cp_parser_template_id ( parser , template_keyword_p , check_dependency_p , declarator_p ) ; if ( cp_parser_parse_definitely ( parser ) ) return id ; return cp_parser_identifier ( parser ) ; } case CPP_TEMPLATE_ID : return cp_parser_template_id ( parser , template_keyword_p , check_dependency_p , declarator_p ) ; case CPP_COMPL : { tree type_decl ; tree qualifying_scope ; tree object_scope ; tree scope ; bool done ; cp_lexer_consume_token ( parser -> lexer ) ; scope = parser -> scope ; object_scope = parser -> object_scope ; qualifying_scope = parser -> qualifying_scope ; if ( scope == error_mark_node ) { if ( cp_lexer_next_token_is ( parser -> lexer , CPP_NAME ) ) cp_lexer_consume_token ( parser -> lexer ) ; return error_mark_node ; } if ( scope && TREE_CODE ( scope ) == NAMESPACE_DECL ) { if ( ! cp_parser_uncommitted_to_tentative_parse_p ( parser ) ) error ( " " , scope ) ; cp_parser_simulate_error ( parser ) ; if ( cp_lexer_next_token_is ( parser -> lexer , CPP_NAME ) ) cp_lexer_consume_token ( parser -> lexer ) ; return error_mark_node ; } gcc_assert ( ! scope || TYPE_P ( scope ) ) ; token = cp_lexer_peek_token ( parser -> lexer ) ; if ( scope && token -> type == CPP_NAME && ( cp_lexer_peek_nth_token ( parser -> lexer , 2 ) -> type == CPP_OPEN_PAREN ) && constructor_name_p ( token -> u . value , scope ) ) { cp_lexer_consume_token ( parser -> lexer ) ; return build_nt ( BIT_NOT_EXPR , scope ) ; } done = false ; type_decl = NULL_TREE ; if ( scope ) { cp_parser_parse_tentatively ( parser ) ; type_decl = cp_parser_class_name ( parser , false , false , none_type , false , false , declarator_p ) ; if ( cp_parser_parse_definitely ( parser ) ) done = true ; } if ( ! done && scope && qualifying_scope ) { cp_parser_parse_tentatively ( parser ) ; parser -> scope = qualifying_scope ; parser -> object_scope = NULL_TREE ; parser -> qualifying_scope = NULL_TREE ; type_decl = cp_parser_class_name ( parser , false , false , none_type , false , false , declarator_p ) ; if ( cp_parser_parse_definitely ( parser ) ) done = true ; } else if ( ! done && object_scope ) { cp_parser_parse_tentatively ( parser ) ; parser -> scope = object_scope ; parser -> object_scope = NULL_TREE ; parser -> qualifying_scope = NULL_TREE ; type_decl = cp_parser_class_name ( parser , false , false , none_type , false , false , declarator_p ) ; if ( cp_parser_parse_definitely ( parser ) ) done = true ; } if ( ! done ) { parser -> scope = NULL_TREE ; parser -> object_scope = NULL_TREE ; parser -> qualifying_scope = NULL_TREE ; type_decl = cp_parser_class_name ( parser , false , false , none_type , false , false , declarator_p ) ; } if ( type_decl == error_mark_node && scope ) return build_nt ( BIT_NOT_EXPR , scope ) ; else if ( type_decl == error_mark_node ) return error_mark_node ; if ( declarator_p && scope && ! check_dtor_name ( scope , type_decl ) ) { if ( ! cp_parser_uncommitted_to_tentative_parse_p ( parser ) ) error ( " " , type_decl , scope ) ; cp_parser_simulate_error ( parser ) ; return error_mark_node ; } if ( declarator_p && ! DECL_IMPLICIT_TYPEDEF_P ( type_decl ) && ! DECL_SELF_REFERENCE_P ( type_decl ) && ! cp_parser_uncommitted_to_tentative_parse_p ( parser ) ) error ( " " , type_decl ) ; return build_nt ( BIT_NOT_EXPR , TREE_TYPE ( type_decl ) ) ; } case CPP_KEYWORD : if ( token -> keyword == RID_OPERATOR ) { tree id ; cp_parser_parse_tentatively ( parser ) ; id = cp_parser_template_id ( parser , template_keyword_p , true , declarator_p ) ; if ( cp_parser_parse_definitely ( parser ) ) return id ; cp_parser_parse_tentatively ( parser ) ; id = cp_parser_operator_function_id ( parser ) ; if ( ! cp_parser_parse_definitely ( parser ) ) id = cp_parser_conversion_function_id ( parser ) ; return id ; } default : if ( optional_p ) return NULL_TREE ; cp_parser_error ( parser , " " ) ; return error_mark_node ; } }
Parse an unqualified-id.
Parse an unqualified - id .
/* Peek at the next token.  */ /* We don't know yet whether or not this will be a
	   template-id.  */ /* Try a template-id.  */ /* If it worked, we're done.  */ /* Otherwise, it's an ordinary identifier.  */ /* Consume the `~' token.  */ /* Parse the class-name.  The standard, as written, seems to
	   say that:

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

	   is invalid, since `~' must be followed by a class-name, but
	   `S<T>' is dependent, and so not known to be a class.
	   That's not right; we need to look in uninstantiated
	   templates.  A further complication arises from:

	     template <typename T> void f(T t) {
	       t.T::~T();
	     }

	   Here, it is not possible to look up `T' in the scope of `T'
	   itself.  We must look in both the current scope, and the
	   scope of the containing complete expression.

	   Yet another issue is:

	     struct S {
	       int S;
	       ~S();
	     };

	     S::~S() {}

	   The standard does not seem to say that the `S' in `~S'
	   should refer to the type `S' and not the data member
	   `S::S'.  */ /* DR 244 says that we look up the name after the "~" in the
	   same scope as we looked up the qualifying name.  That idea
	   isn't fully worked out; it's more complicated than that.  */ /* Check for invalid scopes.  */ /* If the name is of the form "X::~X" it's OK.  */ /* If there was an explicit qualification (S::~T), first look
	   in the scope given by the qualification (i.e., S).  */ /*typename_keyword_p=*/ /*template_keyword_p=*/ /*check_dependency=*/ /*class_head_p=*/ /* In "N::S::~S", look in "N" as well.  */ /*typename_keyword_p=*/ /*template_keyword_p=*/ /*check_dependency=*/ /*class_head_p=*/ /* In "p->S::~T", look in the scope given by "*p" as well.  */ /*typename_keyword_p=*/ /*template_keyword_p=*/ /*check_dependency=*/ /*class_head_p=*/ /* Look in the surrounding context.  */ /*typename_keyword_p=*/ /*template_keyword_p=*/ /*check_dependency=*/ /*class_head_p=*/ /* If an error occurred, assume that the name of the
	   destructor is the same as the name of the qualifying
	   class.  That allows us to keep parsing after running
	   into ill-formed destructor names.  */ /* Check that destructor name and scope match.  */ /* [class.dtor]

	   A typedef-name that names a class shall not be used as the
	   identifier in the declarator for a destructor declaration.  */ /* This could be a template-id, so we try that first.  */ /* Try a template-id.  */ /*check_dependency_p=*/ /* If that worked, we're done.  */ /* We still 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.  */ /* Fall through.  */