[flang-commits] [flang] [Flang][Preprocessor] Avoid creating an empty token when a kind suffix is torn by a pasting operator (PR #139795)

Roger Ferrer Ibáñez via flang-commits flang-commits at lists.llvm.org
Tue May 13 14:03:57 PDT 2025


https://github.com/rofirrim created https://github.com/llvm/llvm-project/pull/139795

This input "tears" the expected tokens of an integer-literal due to a pasting operator `##`. When lexing `1_##` we generate the sequence of tokens `['1_', '']`, the second being an empty token of length zero. The second token is created at the end of `Prescanner::NextToken`.

Creating an empty token by accident (due to two consecutive `CloseToken` without consuming anything) can cause `TokenSequence::pop_back` to assert.

If zero-length tokens are acceptable, then instead of this patch we may have to fix the logic in `TokenPasting` found in `preprocessor.cpp`.

>From 4e1f840899384d9977105791785806b2c43c1a37 Mon Sep 17 00:00:00 2001
From: Roger Ferrer Ibanez <roger.ferrer at bsc.es>
Date: Tue, 13 May 2025 20:54:14 +0000
Subject: [PATCH] Avoid creating an empty token when a kind suffix is torn by a
 pasting operator

This confuses the logic that implements the pasting itself.
---
 flang/lib/Parser/prescan.cpp                      | 8 ++++++++
 flang/test/Preprocessing/torn-token-pasting-1.F90 | 9 +++++++++
 2 files changed, 17 insertions(+)
 create mode 100644 flang/test/Preprocessing/torn-token-pasting-1.F90

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 3bc2ea0b37508..004e4f013f90a 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -937,6 +937,7 @@ bool Prescanner::HandleKindSuffix(TokenSequence &tokens) {
   if (*at_ != '_') {
     return false;
   }
+  auto underscore = *at_;
   TokenSequence withUnderscore, separate;
   EmitChar(withUnderscore, '_');
   EmitCharAndAdvance(separate, '_');
@@ -951,6 +952,13 @@ bool Prescanner::HandleKindSuffix(TokenSequence &tokens) {
   }
   withUnderscore.CloseToken();
   separate.CloseToken();
+  // If we only saw "_" and nothing else, we have handled enough but we do not
+  // want to close the token here, or we will generate an extra token of length
+  // zero.
+  if (separate.SizeInTokens() == 1) {
+    EmitChar(tokens, underscore);
+    return true;
+  }
   tokens.CloseToken();
   if (separate.SizeInTokens() == 2 &&
       preprocessor_.IsNameDefined(separate.TokenAt(1)) &&
diff --git a/flang/test/Preprocessing/torn-token-pasting-1.F90 b/flang/test/Preprocessing/torn-token-pasting-1.F90
new file mode 100644
index 0000000000000..5e080129a94d1
--- /dev/null
+++ b/flang/test/Preprocessing/torn-token-pasting-1.F90
@@ -0,0 +1,9 @@
+! RUN: %flang -E %s 2>&1 | FileCheck %s
+! CHECK: IF(10>HUGE(1_4).OR.10<-HUGE(1_4)) CALL foo()
+#define CHECKSAFEINT(x,k)  IF(x>HUGE(1_  ##  k).OR.x<-HUGE(1_##k)) CALL foo()
+
+program main
+  implicit none
+
+  CHECKSAFEINT(10, 4)
+end program main



More information about the flang-commits mailing list