Skip to content

Commit 7794b9b

Browse files
committed
[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 #115676.
1 parent 6e48214 commit 7794b9b

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -815,18 +815,33 @@ bool Prescanner::ExponentAndKind(TokenSequence &tokens) {
815815
if (ed != 'e' && ed != 'd') {
816816
return false;
817817
}
818-
EmitCharAndAdvance(tokens, ed);
819-
if (*at_ == '+' || *at_ == '-') {
820-
EmitCharAndAdvance(tokens, *at_);
818+
// Do some look-ahead to ensure that this 'e'/'d' is an exponent,
819+
// not the start of an identifier that could be a macro.
820+
const char *p{at_};
821+
if (int n{IsSpace(++p)}) {
822+
p += n;
821823
}
822-
while (IsDecimalDigit(*at_)) {
823-
EmitCharAndAdvance(tokens, *at_);
824+
if (*p == '+' || *p == '-') {
825+
if (int n{IsSpace(++p)}) {
826+
p += n;
827+
}
824828
}
825-
if (*at_ == '_') {
826-
while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
829+
if (IsDecimalDigit(*p)) { // it's an exponent
830+
EmitCharAndAdvance(tokens, ed);
831+
if (*at_ == '+' || *at_ == '-') {
832+
EmitCharAndAdvance(tokens, *at_);
833+
}
834+
while (IsDecimalDigit(*at_)) {
835+
EmitCharAndAdvance(tokens, *at_);
827836
}
837+
if (*at_ == '_') {
838+
while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
839+
}
840+
}
841+
return true;
842+
} else {
843+
return false;
828844
}
829-
return true;
830845
}
831846

832847
void Prescanner::QuotedCharacterLiteral(
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
2+
#define e eeeee
3+
module m
4+
interface operator(.e.)
5+
module procedure ir,rr
6+
end interface operator(.e.)
7+
contains
8+
function ir(k1,k2)
9+
intent(in)::k1,k2
10+
ir=k1+k2
11+
end function ir
12+
function rr(k1,k2)
13+
real,intent(in)::k1,k2
14+
rr=k1+k2
15+
end function rr
16+
end module m
17+
program main
18+
use m
19+
!CHECK: IF (real((ir(1_4,5_4)),kind=4)/=6._4) ERROR STOP 1_4
20+
!CHECK: IF ((rr(1._4,5.e-1_4))/=1.5_4) ERROR STOP 2_4
21+
if((1.e.5)/=6.e0) error stop 1
22+
if((1..e..5)/=1.5) error stop 2
23+
print *,'pass'
24+
end program main

0 commit comments

Comments
 (0)