[flang-commits] [flang] [flang] Don't tokenize an exponent that isn't one (PR #117061)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed Nov 20 13:37:48 PST 2024


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/117061

The character 'e' or 'd' (either case) shouldn't be tokenized as part of a real literal during preprocessing if it is not followed by an optionally-signed digit string.  Doing so prevents it from being recognized as a macro name, or as the start of one.

Fixes https://github.com/llvm/llvm-project/issues/115676.

>From 7794b9bf0df5ff88c250527b3eb9cc9e76fa0032 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 20 Nov 2024 13:32:26 -0800
Subject: [PATCH] [flang] Don't tokenize an exponent that isn't one

The character 'e' or 'd' (either case) shouldn't be tokenized
as part of a real literal during preprocessing if it is not
followed by an optionally-signed digit string.  Doing so
prevents it from being recognized as a macro name, or as the
start of one.

Fixes https://github.com/llvm/llvm-project/issues/115676.
---
 flang/lib/Parser/prescan.cpp                 | 31 +++++++++++++++-----
 flang/test/Preprocessing/not-an-exponent.F90 | 24 +++++++++++++++
 2 files changed, 47 insertions(+), 8 deletions(-)
 create mode 100644 flang/test/Preprocessing/not-an-exponent.F90

diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 1d2f1e97668792..e4e52345e40dc6 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -815,18 +815,33 @@ bool Prescanner::ExponentAndKind(TokenSequence &tokens) {
   if (ed != 'e' && ed != 'd') {
     return false;
   }
-  EmitCharAndAdvance(tokens, ed);
-  if (*at_ == '+' || *at_ == '-') {
-    EmitCharAndAdvance(tokens, *at_);
+  // Do some look-ahead to ensure that this 'e'/'d' is an exponent,
+  // not the start of an identifier that could be a macro.
+  const char *p{at_};
+  if (int n{IsSpace(++p)}) {
+    p += n;
   }
-  while (IsDecimalDigit(*at_)) {
-    EmitCharAndAdvance(tokens, *at_);
+  if (*p == '+' || *p == '-') {
+    if (int n{IsSpace(++p)}) {
+      p += n;
+    }
   }
-  if (*at_ == '_') {
-    while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
+  if (IsDecimalDigit(*p)) { // it's an exponent
+    EmitCharAndAdvance(tokens, ed);
+    if (*at_ == '+' || *at_ == '-') {
+      EmitCharAndAdvance(tokens, *at_);
+    }
+    while (IsDecimalDigit(*at_)) {
+      EmitCharAndAdvance(tokens, *at_);
     }
+    if (*at_ == '_') {
+      while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
+      }
+    }
+    return true;
+  } else {
+    return false;
   }
-  return true;
 }
 
 void Prescanner::QuotedCharacterLiteral(
diff --git a/flang/test/Preprocessing/not-an-exponent.F90 b/flang/test/Preprocessing/not-an-exponent.F90
new file mode 100644
index 00000000000000..d60d7f6c409f0e
--- /dev/null
+++ b/flang/test/Preprocessing/not-an-exponent.F90
@@ -0,0 +1,24 @@
+!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
+#define e eeeee
+module m
+  interface operator(.e.)
+     module procedure ir,rr
+  end interface operator(.e.)
+contains
+  function ir(k1,k2)
+    intent(in)::k1,k2
+    ir=k1+k2
+  end function ir
+  function rr(k1,k2)
+    real,intent(in)::k1,k2
+    rr=k1+k2
+  end function rr
+end module m
+program main
+  use m
+!CHECK: IF (real((ir(1_4,5_4)),kind=4)/=6._4) ERROR STOP 1_4
+!CHECK: IF ((rr(1._4,5.e-1_4))/=1.5_4) ERROR STOP 2_4
+  if((1.e.5)/=6.e0) error stop 1
+  if((1..e..5)/=1.5) error stop 2
+  print *,'pass'
+end program main



More information about the flang-commits mailing list