From 7794b9bf0df5ff88c250527b3eb9cc9e76fa0032 Mon Sep 17 00:00:00 2001 From: Peter Klausler 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 1d2f1e9766879..e4e52345e40dc 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 0000000000000..d60d7f6c409f0 --- /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