https://gcc.gnu.org/g:065a6ab3747fe9116643ac6754582bc195847bfc

commit r16-7437-g065a6ab3747fe9116643ac6754582bc195847bfc
Author: Marek Polacek <[email protected]>
Date:   Mon Feb 9 13:54:39 2026 -0500

    c++: fix for saved_token_sentinel
    
    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 we could just save input_location in
    saved_token_sentinel instead of trying to recover it.  And then
    cp_parser_splice_spec_is_nns_p can be simplified.
    
    gcc/cp/ChangeLog:
    
            * parser.cc (struct saved_token_sentinel): Save input_location.
            (saved_token_sentinel::rollback): Restore input_location.
            (cp_parser_splice_spec_is_nns_p): Use saved_token_sentinel.  
Refactor.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/parser.cc | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 986605e0cdc1..8c46b260fffd 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -1635,10 +1635,11 @@ struct saved_token_sentinel
 {
   cp_lexer *lexer;
   unsigned len;
+  location_t loc;
   saved_token_sentinel_mode mode;
   saved_token_sentinel (cp_lexer *_lexer,
                        saved_token_sentinel_mode _mode = STS_COMMIT)
-    : lexer (_lexer), mode (_mode)
+    : lexer (_lexer), loc (input_location), mode (_mode)
   {
     len = lexer->saved_tokens.length ();
     cp_lexer_save_tokens (lexer);
@@ -1646,8 +1647,7 @@ struct saved_token_sentinel
   void rollback ()
   {
     cp_lexer_rollback_tokens (lexer);
-    cp_lexer_set_source_position_from_token
-      (cp_lexer_previous_token (lexer));
+    input_location = loc;
     mode = STS_DONOTHING;
   }
   ~saved_token_sentinel ()
@@ -6523,18 +6523,9 @@ cp_parser_skip_entire_splice_expr (cp_parser *parser)
 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);
-
-  const bool ok = (cp_parser_skip_entire_splice_expr (parser)
-                  && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE));
-
-  /* Roll back the tokens we skipped.  */
-  cp_lexer_rollback_tokens (parser->lexer);
-
-  return ok;
+  saved_token_sentinel toks (parser->lexer, STS_ROLLBACK);
+  return (cp_parser_skip_entire_splice_expr (parser)
+         && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE));
 }
 
 /* Return true if the N-th token is '[:' and its closing ':]' is NOT

Reply via email to