Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
In cp_parser_splice_spec_is_nns_p I didn't use saved_token_sentinel:
its rollback uses cp_lexer_previous_token so if we are the first token
in the file, there are no previous tokens so we crash.
It would be simple to just use the _safe variant of cp_lexer_previous_token
and be done with this. But that's not how this worked out: I saw a new
-fcompare-debug FAIL with pr104025.C. The problem is that at the end of
cp_parser_id_expression we have a saved_token_sentinel guarded by
warn_missing_template_keyword and in that spot lexer->buffer is NULL (so
cp_lexer_set_source_position_from_token would be skipped). pr104025.C
is compiled twice, the second time with "-w -fcompare-debug-second". So
the first time we don't _set_source_position back to where we were after the
_skip_entire_template_parameter_list (lexer->buffer is NULL) and the second
time we don't get to the saved_token_sentinel at all. That left us with
different columns in the location:
"pr104025.C":16:16 vs "pr104025.C":16:12
thus the -fcompare-debug FAIL. I assume we don't want -fcompare-debug
to ignore the column location. So this patch adds STS_ROLLBACK_SAFE to
use the _safe variant of cp_lexer_previous_token. And then
cp_parser_splice_spec_is_nns_p can be simplified.
gcc/cp/ChangeLog:
* parser.cc (enum saved_token_sentinel_mode): Add STS_ROLLBACK_SAFE.
(saved_token_sentinel::rollback): Add a new "safe" parameter. Use
cp_lexer_safe_previous_token rather than cp_lexer_previous_token if
"safe" is true.
(saved_token_sentinel::~saved_token_sentinel): Also check
STS_ROLLBACK_SAFE.
(cp_parser_splice_spec_is_nns_p): Use saved_token_sentinel. Refactor.
---
gcc/cp/parser.cc | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 393c8b2ec44..5319e9d7fb6 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -1604,6 +1604,7 @@ cp_lexer_rollback_tokens (cp_lexer* lexer)
enum saved_token_sentinel_mode {
STS_COMMIT,
STS_ROLLBACK,
+ STS_ROLLBACK_SAFE,
STS_DONOTHING
};
@@ -1613,9 +1614,11 @@ enum saved_token_sentinel_mode {
Creating a variable saves tokens. MODE determines what happens when the
object is destroyed. STS_COMMIT commits tokens (default),
- STS_ROLLBACK rolls-back and STS_DONOTHING does nothing. Calling
+ STS_ROLLBACK{,_SAFE} rolls-back and STS_DONOTHING does nothing. Calling
rollback() will immediately roll-back tokens and set MODE to
- STS_DONOTHING. */
+ STS_DONOTHING. STS_ROLLBACK_SAFE is like STS_ROLLBACK, but uses the
+ _safe version of _previous_token. Use the _SAFE version when we may be at
+ the first token in the file in which case there are no previous tokens. */
struct saved_token_sentinel
{
@@ -1629,19 +1632,25 @@ struct saved_token_sentinel
len = lexer->saved_tokens.length ();
cp_lexer_save_tokens (lexer);
}
- void rollback ()
+ void rollback (bool safe = false)
{
cp_lexer_rollback_tokens (lexer);
- cp_lexer_set_source_position_from_token
- (cp_lexer_previous_token (lexer));
+ if (safe)
+ {
+ if (cp_token *prev_token = cp_lexer_safe_previous_token (lexer))
+ cp_lexer_set_source_position_from_token (prev_token);
+ }
+ else
+ cp_lexer_set_source_position_from_token
+ (cp_lexer_previous_token (lexer));
mode = STS_DONOTHING;
}
~saved_token_sentinel ()
{
if (mode == STS_COMMIT)
cp_lexer_commit_tokens (lexer);
- else if (mode == STS_ROLLBACK)
- rollback ();
+ else if (mode == STS_ROLLBACK || mode == STS_ROLLBACK_SAFE)
+ rollback (mode == STS_ROLLBACK_SAFE);
gcc_assert (lexer->saved_tokens.length () == len);
}
@@ -6458,20 +6467,15 @@ cp_parser_splice_scope_specifier (cp_parser *parser,
bool typename_p,
static bool
cp_parser_splice_spec_is_nns_p (cp_parser *parser)
{
- /* ??? It'd be nice to use saved_token_sentinel, but its rollback
- uses cp_lexer_previous_token, but we may be the first token in the
- file so there are no previous tokens. Sigh. */
- cp_lexer_save_tokens (parser->lexer);
+ saved_token_sentinel toks (parser->lexer, STS_ROLLBACK_SAFE);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)
|| cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
cp_lexer_consume_token (parser->lexer);
- bool ok = false;
size_t n = cp_parser_skip_balanced_tokens (parser, 1);
if (n != 1)
{
- ok = true;
/* Consume tokens up to the ':]' (including). */
for (n = n - 1; n; --n)
cp_lexer_consume_token (parser->lexer);
@@ -6479,15 +6483,12 @@ cp_parser_splice_spec_is_nns_p (cp_parser *parser)
/* Consume the whole '<....>', if present. */
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)
&& !cp_parser_skip_entire_template_parameter_list (parser))
- ok = false;
+ return false;
- ok = ok && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE);
+ return cp_lexer_next_token_is (parser->lexer, CPP_SCOPE);
}
- /* Roll back the tokens we skipped. */
- cp_lexer_rollback_tokens (parser->lexer);
-
- return ok;
+ return false;
}
/* Return true if the N-th token is '[:' and its closing ':]' is NOT
base-commit: 2a20b792133c8f3b3c5fcf2d9f647b1634362637
--
2.52.0