Skip to content

Commit bb23ac6

Browse files
authored
[flang] Don't tokenize an exponent that isn't one (#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 #115676.
1 parent bde2f39 commit bb23ac6

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
@@ -820,18 +820,33 @@ bool Prescanner::ExponentAndKind(TokenSequence &tokens) {
820820
if (ed != 'e' && ed != 'd') {
821821
return false;
822822
}
823-
EmitCharAndAdvance(tokens, ed);
824-
if (*at_ == '+' || *at_ == '-') {
825-
EmitCharAndAdvance(tokens, *at_);
823+
// Do some look-ahead to ensure that this 'e'/'d' is an exponent,
824+
// not the start of an identifier that could be a macro.
825+
const char *p{at_};
826+
if (int n{IsSpace(++p)}) {
827+
p += n;
826828
}
827-
while (IsDecimalDigit(*at_)) {
828-
EmitCharAndAdvance(tokens, *at_);
829+
if (*p == '+' || *p == '-') {
830+
if (int n{IsSpace(++p)}) {
831+
p += n;
832+
}
829833
}
830-
if (*at_ == '_') {
831-
while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
834+
if (IsDecimalDigit(*p)) { // it's an exponent
835+
EmitCharAndAdvance(tokens, ed);
836+
if (*at_ == '+' || *at_ == '-') {
837+
EmitCharAndAdvance(tokens, *at_);
838+
}
839+
while (IsDecimalDigit(*at_)) {
840+
EmitCharAndAdvance(tokens, *at_);
832841
}
842+
if (*at_ == '_') {
843+
while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
844+
}
845+
}
846+
return true;
847+
} else {
848+
return false;
833849
}
834-
return true;
835850
}
836851

837852
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)