Skip to content

Commit d78701e

Browse files
committed
[flang] Fix minor nits with INCLUDE line recognition
Fix some problems with INCLUDE line recognition pointed out by some recently-added tests to the LLVM test suite. Differential Revision: https://reviews.llvm.org/D155497
1 parent 1b29a84 commit d78701e

File tree

4 files changed

+97
-4
lines changed

4 files changed

+97
-4
lines changed

flang/docs/Extensions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ end
285285
it's an error only if the resolution is ambiguous.
286286
* An entity may appear in a `DATA` statement before its explicit
287287
type declaration under `IMPLICIT NONE(TYPE)`.
288+
* INCLUDE lines can start in any column, can be preceded in
289+
fixed form source by a '0' in column 6, can contain spaces
290+
between the letters of the word INCLUDE, and can have a
291+
numeric character literal kind prefix on the file name.
288292

289293
### Extensions supported when enabled by options
290294

@@ -412,6 +416,9 @@ end
412416
This is especially desirable when two generics of the same
413417
name are combined due to USE association and the mixture may
414418
be inadvertent.
419+
* Since Fortran 90, INCLUDE lines have been allowed to have
420+
a numeric kind parameter prefix on the file name. No other
421+
Fortran compiler supports them that I can find.
415422

416423
## Behavior in cases where the standard is ambiguous or indefinite
417424

flang/lib/Parser/prescan.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,25 @@ const char *Prescanner::IsFreeFormComment(const char *p) const {
847847

848848
std::optional<std::size_t> Prescanner::IsIncludeLine(const char *start) const {
849849
const char *p{SkipWhiteSpace(start)};
850-
for (char ch : "include"s) {
851-
if (ToLowerCaseLetter(*p++) != ch) {
850+
if (*p == '0' && inFixedForm_ && p == start + 5) {
851+
// Accept " 0INCLUDE" in fixed form.
852+
p = SkipWhiteSpace(p + 1);
853+
}
854+
for (const char *q{"include"}; *q; ++q) {
855+
if (ToLowerCaseLetter(*p) != *q) {
852856
return std::nullopt;
853857
}
858+
p = SkipWhiteSpace(p + 1);
859+
}
860+
if (IsDecimalDigit(*p)) { // accept & ignore a numeric kind prefix
861+
for (p = SkipWhiteSpace(p + 1); IsDecimalDigit(*p);
862+
p = SkipWhiteSpace(p + 1)) {
863+
}
864+
if (*p != '_') {
865+
return std::nullopt;
866+
}
867+
p = SkipWhiteSpace(p + 1);
854868
}
855-
p = SkipWhiteSpace(p);
856869
if (*p == '"' || *p == '\'') {
857870
return {p - start};
858871
}
@@ -1022,7 +1035,11 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
10221035
nextLine_[3] == ' ' && nextLine_[4] == ' ') {
10231036
char col6{nextLine_[5]};
10241037
if (col6 != '\n' && col6 != '\t' && col6 != ' ' && col6 != '0') {
1025-
return nextLine_ + 6;
1038+
if ((col6 == 'i' || col6 == 'I') && IsIncludeLine(nextLine_)) {
1039+
// It's An INCLUDE line, not a continuation
1040+
} else {
1041+
return nextLine_ + 6;
1042+
}
10261043
}
10271044
}
10281045
if (IsImplicitContinuation()) {

flang/test/Parser/Inputs/include-file

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x = 1

flang/test/Parser/include.f

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
! RUN: %flang_fc1 -E -I %S/Inputs %s 2>&1 | FileCheck %s
2+
include 'include-file'
3+
include "include-file"
4+
include 1_'include-file'
5+
include 1_"include-file"
6+
i n c l u d e 'include-file'
7+
INCLUDE 'include-file'
8+
I N C L U D E 'include-file'
9+
include 'include-file'
10+
include "include-file"
11+
include 1_'include-file'
12+
include 1_"include-file"
13+
i n c l u d e 'include-file'
14+
INCLUDE 'include-file'
15+
I N C L U D E 'include-file'
16+
0include 'include-file'
17+
x = 2
18+
include 'include-file'
19+
print *, "
20+
1include 'not-an-include'
21+
2"
22+
cinclude 'not-an-include'
23+
*include 'not-an-include'
24+
!include 'not-an-include'
25+
c include 'not-an-include'
26+
* include 'not-an-include'
27+
! include 'not-an-include'
28+
end
29+
30+
!CHECK:#line "{{.*[/\\]}}include-file" 1
31+
!CHECK: x = 1
32+
!CHECK:#line "{{.*[/\\]}}include-file" 1
33+
!CHECK: x = 1
34+
!CHECK:#line "{{.*[/\\]}}include-file" 1
35+
!CHECK: x = 1
36+
!CHECK:#line "{{.*[/\\]}}include-file" 1
37+
!CHECK: x = 1
38+
!CHECK:#line "{{.*[/\\]}}include-file" 1
39+
!CHECK: x = 1
40+
!CHECK:#line "{{.*[/\\]}}include-file" 1
41+
!CHECK: x = 1
42+
!CHECK:#line "{{.*[/\\]}}include-file" 1
43+
!CHECK: x = 1
44+
!CHECK:#line "{{.*[/\\]}}include-file" 1
45+
!CHECK: x = 1
46+
!CHECK:#line "{{.*[/\\]}}include-file" 1
47+
!CHECK: x = 1
48+
!CHECK:#line "{{.*[/\\]}}include-file" 1
49+
!CHECK: x = 1
50+
!CHECK:#line "{{.*[/\\]}}include-file" 1
51+
!CHECK: x = 1
52+
!CHECK:#line "{{.*[/\\]}}include-file" 1
53+
!CHECK: x = 1
54+
!CHECK:#line "{{.*[/\\]}}include-file" 1
55+
!CHECK: x = 1
56+
!CHECK:#line "{{.*[/\\]}}include-file" 1
57+
!CHECK: x = 1
58+
!CHECK:#line "{{.*[/\\]}}include-file" 1
59+
!CHECK: x = 1
60+
!CHECK:#line "{{.*[/\\]}}include.f" 17
61+
!CHECK: x = 2
62+
!CHECK:#line "{{.*[/\\]}}include-file" 1
63+
!CHECK: x = 1
64+
!CHECK:#line "{{.*[/\\]}}include.f" 19
65+
!CHECK: print *, " &
66+
!CHECK: &include 'not-an-include' &
67+
!CHECK: &"
68+
!CHECK: end

0 commit comments

Comments
 (0)