parser.c (cp_token_position): New typedef.

* parser.c (cp_token_position): New typedef. Define VEC thereof.
	(struct cp_lexer): Allow buffer and buffer_end to be NULL. Make
	next_token and last_token cp_token_position. Make saved_tokens a
	VEC(cp_token_position).
	(eof_token): New static variable.
	(CP_SAVED_TOKENS_SIZE): Rename to ...
	(CP_SAVED_TOKEN_STACK): ... here.
	(cp_lexer_new_main): Adjust main lexer creation and buffer
	filling.
	(cp_lexer_new_from_tokens): Do not copy the tokens, merely point
	to the parent buffer.  Do not append eof token.
	(cp_lexer_destroy): Only free buffer if non-NULL. Free token
	stack.
	(cp_lexer_next_token, cp_lexer_prev_token): Remove.
	(cp_lexer_token_position, cp_lexer_token_at): New.
	(cp_lexer_saving_tokens): Adjust. Make inline.
	(cp_lexer_advance_token, cp_lexer_token_difference): Remove.
	(cp_lexer_peek_token_emit_debug_info): Fold into ...
	(cp_lexer_peek_token): ... here.
	(cp_lexer_peek_nth_token): Don't peek past EOF.
	(cp_lexer_consume_token): Set next_token to eof_token, if reaching
	EOF.
	(cp_lexer_purge_token): Adjust eof setting.
	(cp_lexer_purge_tokens_after): Likewise.
	(cp_lexer_save_tokens): Push next_token directly.
	(cp_lexer_commit_tokens): Adjust.
	(cp_lexer_rollback_tokens): Pop next_token directly.
	(cp_parser_check_for_invalid_template_id): Adjust token purging.
	(cp_parser_translation_unit): Do not consume the EOF.
	(cp_parser_nested_name_specifier_opt): Adjust token purging.
	(cp_parser_template_id, cp_parser_template_name): Likewise.

From-SVN: r89320
This commit is contained in:
Nathan Sidwell 2004-10-20 07:25:35 +00:00 committed by Nathan Sidwell
parent 242b11bd65
commit 0c5e486680
2 changed files with 149 additions and 194 deletions

View File

@ -1,3 +1,37 @@
2004-10-20 Nathan Sidwell <nathan@codesourcery.com>
* parser.c (cp_token_position): New typedef. Define VEC thereof.
(struct cp_lexer): Allow buffer and buffer_end to be NULL. Make
next_token and last_token cp_token_position. Make saved_tokens a
VEC(cp_token_position).
(eof_token): New static variable.
(CP_SAVED_TOKENS_SIZE): Rename to ...
(CP_SAVED_TOKEN_STACK): ... here.
(cp_lexer_new_main): Adjust main lexer creation and buffer
filling.
(cp_lexer_new_from_tokens): Do not copy the tokens, merely point
to the parent buffer. Do not append eof token.
(cp_lexer_destroy): Only free buffer if non-NULL. Free token
stack.
(cp_lexer_next_token, cp_lexer_prev_token): Remove.
(cp_lexer_token_position, cp_lexer_token_at): New.
(cp_lexer_saving_tokens): Adjust. Make inline.
(cp_lexer_advance_token, cp_lexer_token_difference): Remove.
(cp_lexer_peek_token_emit_debug_info): Fold into ...
(cp_lexer_peek_token): ... here.
(cp_lexer_peek_nth_token): Don't peek past EOF.
(cp_lexer_consume_token): Set next_token to eof_token, if reaching
EOF.
(cp_lexer_purge_token): Adjust eof setting.
(cp_lexer_purge_tokens_after): Likewise.
(cp_lexer_save_tokens): Push next_token directly.
(cp_lexer_commit_tokens): Adjust.
(cp_lexer_rollback_tokens): Pop next_token directly.
(cp_parser_check_for_invalid_template_id): Adjust token purging.
(cp_parser_translation_unit): Do not consume the EOF.
(cp_parser_nested_name_specifier_opt): Adjust token purging.
(cp_parser_template_id, cp_parser_template_name): Likewise.
2004-10-19 Mark Mitchell <mark@codesourcery.com>
PR c++/14035

View File

@ -63,6 +63,12 @@ typedef struct cp_token GTY (())
location_t location;
} cp_token;
/* We use a stack of token pointer for saving token sets. */
typedef struct cp_token *cp_token_position;
DEF_VEC_MALLOC_P (cp_token_position);
static cp_token eof_token = {CPP_EOF, 0, 0, 0, 0, NULL_TREE, {0, 0}};
/* The cp_lexer structure represents the C++ lexer. It is responsible
for managing the token stream from the preprocessor and supplying
it to the parser. Tokens are never added to the cp_lexer after
@ -70,24 +76,26 @@ typedef struct cp_token GTY (())
typedef struct cp_lexer GTY (())
{
/* The memory allocated for the buffer. Never NULL. */
/* The memory allocated for the buffer. NULL if this lexer does not
own the token buffer. */
cp_token * GTY ((length ("(%h.buffer_end - %h.buffer)"))) buffer;
/* A pointer just past the end of the memory allocated for the buffer. */
/* If non-null, a pointer just past the end of the memory allocated
for the buffer. */
cp_token * GTY ((skip)) buffer_end;
/* A pointer just past the last available token. The tokens
in this lexer are [buffer, last_token). */
cp_token * GTY ((skip)) last_token;
cp_token_position GTY ((skip)) last_token;
/* The next available token. If NEXT_TOKEN is NULL, then there are
/* The next available token. If NEXT_TOKEN is &eof_token, then there are
no more available tokens. */
cp_token * GTY ((skip)) next_token;
cp_token_position GTY ((skip)) next_token;
/* A stack indicating positions at which cp_lexer_save_tokens was
called. The top entry is the most recent position at which we
began saving tokens. The entries are differences in token
position between BUFFER and the first saved token.
If the stack is non-empty, we are saving tokens. */
varray_type saved_tokens;
began saving tokens. If the stack is non-empty, we are saving
tokens. */
VEC (cp_token_position) *GTY ((skip)) saved_tokens;
/* True if we should output debugging information. */
bool debugging_p;
@ -121,12 +129,10 @@ static void cp_lexer_destroy
(cp_lexer *);
static int cp_lexer_saving_tokens
(const cp_lexer *);
static cp_token *cp_lexer_next_token
(cp_lexer *, cp_token *);
static cp_token *cp_lexer_prev_token
(cp_lexer *, cp_token *);
static ptrdiff_t cp_lexer_token_difference
(cp_lexer *, cp_token *, cp_token *);
static cp_token_position cp_lexer_token_position
(cp_lexer *, bool);
static cp_token *cp_lexer_token_at
(cp_lexer *, cp_token_position);
static void cp_lexer_grow_buffer
(cp_lexer *);
static void cp_lexer_get_preprocessor_token
@ -146,7 +152,7 @@ static cp_token *cp_lexer_consume_token
static void cp_lexer_purge_token
(cp_lexer *);
static void cp_lexer_purge_tokens_after
(cp_lexer *, cp_token *);
(cp_lexer *, cp_token_position);
static void cp_lexer_handle_pragma
(cp_lexer *);
static void cp_lexer_save_tokens
@ -164,8 +170,6 @@ static void cp_lexer_start_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_stop_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_peek_token_emit_debug_info
(cp_lexer *, cp_token *);
#else
/* If we define cp_lexer_debug_stream to NULL it will provoke warnings
about passing NULL to functions that require non-NULL arguments
@ -174,16 +178,14 @@ static void cp_lexer_peek_token_emit_debug_info
#define cp_lexer_debug_stream stdout
#define cp_lexer_print_token(str, tok) (void) 0
#define cp_lexer_debugging_p(lexer) 0
#define cp_lexer_peek_token_emit_debug_info(lexer, tok) (void) 0
#endif /* ENABLE_CHECKING */
static cp_token_cache *cp_token_cache_new
(cp_token *, cp_token *);
/* Manifest constants. */
#define CP_LEXER_BUFFER_SIZE 10000
#define CP_SAVED_TOKENS_SIZE 5
#define CP_SAVED_TOKEN_STACK 5
/* A token type for keywords, as opposed to ordinary identifiers. */
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
@ -245,12 +247,11 @@ cp_lexer_new_main (void)
lexer->buffer_end = lexer->buffer + CP_LEXER_BUFFER_SIZE;
/* There is one token in the buffer. */
lexer->last_token = lexer->buffer + 1;
lexer->last_token = lexer->buffer;
lexer->next_token = lexer->buffer;
*lexer->next_token = first_token;
/* Create the SAVED_TOKENS stack. */
VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
@ -258,11 +259,12 @@ cp_lexer_new_main (void)
#endif /* ENABLE_CHECKING */
/* Get the rest of the tokens from the preprocessor. */
while (lexer->last_token[-1].type != CPP_EOF)
while (lexer->last_token->type != CPP_EOF)
{
lexer->last_token++;
if (lexer->last_token == lexer->buffer_end)
cp_lexer_grow_buffer (lexer);
cp_lexer_get_preprocessor_token (lexer, lexer->last_token++);
cp_lexer_get_preprocessor_token (lexer, lexer->last_token);
}
/* Pragma processing (via cpp_handle_deferred_pragma) may result in
@ -283,26 +285,13 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
cp_token *first = cache->first;
cp_token *last = cache->last;
cp_lexer *lexer = GGC_CNEW (cp_lexer);
cp_token *eof;
/* Allocate a new buffer. The reason we do this is to make sure
there's a CPP_EOF token at the end. An alternative would be to
modify cp_lexer_peek_token so that it checks for end-of-buffer
and returns a CPP_EOF when appropriate. */
lexer->buffer = GGC_NEWVEC (cp_token, (last - first) + 1);
memcpy (lexer->buffer, first, sizeof (cp_token) * (last - first));
lexer->next_token = lexer->buffer;
lexer->buffer_end = lexer->last_token = lexer->buffer + (last - first);
eof = lexer->buffer + (last - first);
eof->type = CPP_EOF;
eof->location = UNKNOWN_LOCATION;
eof->value = NULL_TREE;
eof->keyword = RID_MAX;
/* Create the SAVED_TOKENS stack. */
VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
/* We do not own the buffer. */
lexer->buffer = lexer->buffer_end = NULL;
lexer->next_token = first == last ? &eof_token : first;
lexer->last_token = last;
lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
@ -318,7 +307,9 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
static void
cp_lexer_destroy (cp_lexer *lexer)
{
ggc_free (lexer->buffer);
if (lexer->buffer)
ggc_free (lexer->buffer);
VEC_free (cp_token_position, lexer->saved_tokens);
ggc_free (lexer);
}
@ -334,51 +325,26 @@ cp_lexer_debugging_p (cp_lexer *lexer)
#endif /* ENABLE_CHECKING */
/* TOKEN points into the circular token buffer. Return a pointer to
the next token in the buffer. */
static inline cp_token *
cp_lexer_next_token (cp_lexer* lexer ATTRIBUTE_UNUSED, cp_token* token)
static inline cp_token_position
cp_lexer_token_position (cp_lexer *lexer, bool previous_p)
{
token++;
return token;
gcc_assert (!previous_p || lexer->next_token != &eof_token);
return lexer->next_token - previous_p;
}
/* TOKEN points into the circular token buffer. Return a pointer to
the previous token in the buffer. */
static inline cp_token *
cp_lexer_prev_token (cp_lexer* lexer ATTRIBUTE_UNUSED, cp_token* token)
cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos)
{
return token - 1;
return pos;
}
/* nonzero if we are presently saving tokens. */
static int
static inline int
cp_lexer_saving_tokens (const cp_lexer* lexer)
{
return VARRAY_ACTIVE_SIZE (lexer->saved_tokens) != 0;
}
/* Return a pointer to the token that is N tokens beyond TOKEN in the
buffer. */
static inline cp_token *
cp_lexer_advance_token (cp_lexer *lexer ATTRIBUTE_UNUSED,
cp_token *token, ptrdiff_t n)
{
return token + n;
}
/* Returns the number of times that START would have to be incremented
to reach FINISH. If START and FINISH are the same, returns zero. */
static inline ptrdiff_t
cp_lexer_token_difference (cp_lexer* lexer ATTRIBUTE_UNUSED,
cp_token* start, cp_token* finish)
{
return finish - start;
return VEC_length (cp_token_position, lexer->saved_tokens) != 0;
}
/* If the buffer is full, make it bigger. */
@ -491,25 +457,14 @@ static inline cp_token *
cp_lexer_peek_token (cp_lexer *lexer)
{
if (cp_lexer_debugging_p (lexer))
cp_lexer_peek_token_emit_debug_info (lexer, lexer->next_token);
{
fputs ("cp_lexer: peeking at token: ", cp_lexer_debug_stream);
cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token);
putc ('\n', cp_lexer_debug_stream);
}
return lexer->next_token;
}
#ifdef ENABLE_CHECKING
/* Emit debug output for cp_lexer_peek_token. Split out into a
separate function so that cp_lexer_peek_token can be small and
inlinable. */
static void
cp_lexer_peek_token_emit_debug_info (cp_lexer *lexer ATTRIBUTE_UNUSED,
cp_token *token ATTRIBUTE_UNUSED)
{
fputs ("cp_lexer: peeking at token: ", cp_lexer_debug_stream);
cp_lexer_print_token (cp_lexer_debug_stream, token);
putc ('\n', cp_lexer_debug_stream);
}
#endif
/* Return true if the next token has the indicated TYPE. */
static inline bool
@ -551,7 +506,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
cp_token *token;
/* N is 1-based, not zero-based. */
gcc_assert (n > 0);
gcc_assert (n > 0 && lexer->next_token != &eof_token);
if (cp_lexer_debugging_p (lexer))
fprintf (cp_lexer_debug_stream,
@ -562,6 +517,12 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
while (n != 0)
{
++token;
if (token == lexer->last_token)
{
token = &eof_token;
break;
}
if (token->type != CPP_PURGED)
--n;
}
@ -583,12 +544,22 @@ cp_lexer_consume_token (cp_lexer* lexer)
{
cp_token *token = lexer->next_token;
gcc_assert (token != &eof_token);
do
++lexer->next_token;
{
lexer->next_token++;
if (lexer->next_token == lexer->last_token)
{
lexer->next_token = &eof_token;
break;
}
}
while (lexer->next_token->type == CPP_PURGED);
cp_lexer_set_source_position_from_token (token);
/* Provide debugging output. */
if (cp_lexer_debugging_p (lexer))
{
@ -596,7 +567,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
cp_lexer_print_token (cp_lexer_debug_stream, token);
putc ('\n', cp_lexer_debug_stream);
}
return token;
}
@ -608,14 +579,24 @@ static void
cp_lexer_purge_token (cp_lexer *lexer)
{
cp_token *tok = lexer->next_token;
gcc_assert (tok != &eof_token);
tok->type = CPP_PURGED;
tok->location = UNKNOWN_LOCATION;
tok->value = NULL_TREE;
tok->keyword = RID_MAX;
do
++lexer->next_token;
while (lexer->next_token->type == CPP_PURGED);
{
tok++;
if (tok == lexer->last_token)
{
tok = &eof_token;
break;
}
}
while (tok->type == CPP_PURGED);
lexer->next_token = tok;
}
/* Permanently remove all tokens after TOK, up to, but not
@ -625,9 +606,11 @@ cp_lexer_purge_token (cp_lexer *lexer)
static void
cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
{
cp_token *peek;
cp_token *peek = lexer->next_token;
peek = cp_lexer_peek_token (lexer);
if (peek == &eof_token)
peek = lexer->last_token;
gcc_assert (tok < peek);
for ( tok += 1; tok != peek; tok += 1)
@ -668,10 +651,7 @@ cp_lexer_save_tokens (cp_lexer* lexer)
if (cp_lexer_debugging_p (lexer))
fprintf (cp_lexer_debug_stream, "cp_lexer: saving tokens\n");
VARRAY_PUSH_INT (lexer->saved_tokens,
cp_lexer_token_difference (lexer,
lexer->buffer,
lexer->next_token));
VEC_safe_push (cp_token_position, lexer->saved_tokens, lexer->next_token);
}
/* Commit to the portion of the token stream most recently saved. */
@ -683,7 +663,7 @@ cp_lexer_commit_tokens (cp_lexer* lexer)
if (cp_lexer_debugging_p (lexer))
fprintf (cp_lexer_debug_stream, "cp_lexer: committing tokens\n");
VARRAY_POP (lexer->saved_tokens);
VEC_pop (cp_token_position, lexer->saved_tokens);
}
/* Return all tokens saved since the last call to cp_lexer_save_tokens
@ -692,20 +672,11 @@ cp_lexer_commit_tokens (cp_lexer* lexer)
static void
cp_lexer_rollback_tokens (cp_lexer* lexer)
{
size_t delta;
/* Provide debugging output. */
if (cp_lexer_debugging_p (lexer))
fprintf (cp_lexer_debug_stream, "cp_lexer: restoring tokens\n");
/* Find the token that was the NEXT_TOKEN when we started saving
tokens. */
delta = VARRAY_TOP_INT(lexer->saved_tokens);
/* Make it the next token again now. */
lexer->next_token = cp_lexer_advance_token (lexer, lexer->buffer, delta);
/* Stop saving tokens. */
VARRAY_POP (lexer->saved_tokens);
lexer->next_token = VEC_pop (cp_token_position, lexer->saved_tokens);
}
/* Print a representation of the TOKEN on the STREAM. */
@ -1956,8 +1927,7 @@ static void
cp_parser_check_for_invalid_template_id (cp_parser* parser,
tree type)
{
ptrdiff_t start;
cp_token *token;
cp_token_position start = 0;
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
{
@ -1970,28 +1940,15 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
/* Remember the location of the invalid "<". */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
token = cp_lexer_peek_token (parser->lexer);
token = cp_lexer_prev_token (parser->lexer, token);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->buffer,
token);
}
else
start = -1;
start = cp_lexer_token_position (parser->lexer, true);
/* Consume the "<". */
cp_lexer_consume_token (parser->lexer);
/* Parse the template arguments. */
cp_parser_enclosed_template_argument_list (parser);
/* Permanently remove the invalid template arguments so that
this error message is not issued again. */
if (start >= 0)
{
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->buffer,
start);
cp_lexer_purge_tokens_after (parser->lexer, token);
}
if (start)
cp_lexer_purge_tokens_after (parser->lexer, start);
}
}
@ -2634,9 +2591,6 @@ cp_parser_translation_unit (cp_parser* parser)
/* If there are no tokens left then all went well. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
{
/* Consume the EOF token. */
cp_parser_require (parser, CPP_EOF, "end-of-file");
/* Get rid of the token array; we don't need it any more. */
cp_lexer_destroy (parser->lexer);
parser->lexer = NULL;
@ -3382,8 +3336,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
{
bool success = false;
tree access_check = NULL_TREE;
ptrdiff_t start;
cp_token* token;
cp_token_position start = 0;
cp_token *token;
/* If the next token corresponds to a nested name specifier, there
is no need to reparse it. However, if CHECK_DEPENDENCY_P is
@ -3402,14 +3356,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
/* Remember where the nested-name-specifier starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
token = cp_lexer_peek_token (parser->lexer);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->buffer,
token);
}
else
start = -1;
start = cp_lexer_token_position (parser->lexer, false);
push_deferring_access_checks (dk_deferred);
@ -3570,21 +3517,18 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token. That way, should we re-parse the token stream, we will
not have to repeat the effort required to do the parse, nor will
we issue duplicate error messages. */
if (success && start >= 0)
if (success && start)
{
/* Find the token that corresponds to the start of the
template-id. */
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->buffer,
start);
cp_token *token = cp_lexer_token_at (parser->lexer, start);
/* Reset the contents of the START token. */
token->type = CPP_NESTED_NAME_SPECIFIER;
token->value = build_tree_list (access_check, parser->scope);
TREE_TYPE (token->value) = parser->qualifying_scope;
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
cp_lexer_purge_tokens_after (parser->lexer, token);
cp_lexer_purge_tokens_after (parser->lexer, start);
}
pop_deferring_access_checks ();
@ -8358,7 +8302,7 @@ cp_parser_template_id (cp_parser *parser,
tree template;
tree arguments;
tree template_id;
ptrdiff_t start_of_id;
cp_token_position start_of_id = 0;
tree access_check = NULL_TREE;
cp_token *next_token, *next_token_2;
bool is_identifier;
@ -8395,14 +8339,7 @@ cp_parser_template_id (cp_parser *parser,
/* Remember where the template-id starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
next_token = cp_lexer_peek_token (parser->lexer);
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->buffer,
next_token);
}
else
start_of_id = -1;
start_of_id = cp_lexer_token_position (parser->lexer, false);
push_deferring_access_checks (dk_deferred);
@ -8503,22 +8440,17 @@ cp_parser_template_id (cp_parser *parser,
the effort required to do the parse, nor will we issue duplicate
error messages about problems during instantiation of the
template. */
if (start_of_id >= 0)
if (start_of_id)
{
cp_token *token;
/* Find the token that corresponds to the start of the
template-id. */
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->buffer,
start_of_id);
cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
/* Reset the contents of the START_OF_ID token. */
token->type = CPP_TEMPLATE_ID;
token->value = build_tree_list (access_check, template_id);
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
cp_lexer_purge_tokens_after (parser->lexer, token);
cp_lexer_purge_tokens_after (parser->lexer, start_of_id);
}
pop_deferring_access_checks ();
@ -8628,8 +8560,8 @@ cp_parser_template_name (cp_parser* parser,
need the template keyword before their name. */
&& !constructor_name_p (identifier, parser->scope))
{
ptrdiff_t start;
cp_token* token;
cp_token_position start = 0;
/* Explain what went wrong. */
error ("non-template %qD used as template", identifier);
inform ("use %<%T::template %D%> to indicate that it is a template",
@ -8640,14 +8572,8 @@ cp_parser_template_name (cp_parser* parser,
&& !cp_parser_committed_to_tentative_parse (parser))
{
cp_parser_simulate_error (parser);
token = cp_lexer_peek_token (parser->lexer);
token = cp_lexer_prev_token (parser->lexer, token);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->buffer,
token);
start = cp_lexer_token_position (parser->lexer, true);
}
else
start = -1;
/* Parse the template arguments so that we can issue error
messages about them. */
cp_lexer_consume_token (parser->lexer);
@ -8662,13 +8588,8 @@ cp_parser_template_name (cp_parser* parser,
template argument list. That will prevent duplicate
error messages from being issued about the missing
"template" keyword. */
if (start >= 0)
{
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->buffer,
start);
cp_lexer_purge_tokens_after (parser->lexer, token);
}
if (start)
cp_lexer_purge_tokens_after (parser->lexer, start);
if (is_identifier)
*is_identifier = true;
return identifier;