Skip to content

Commit 6086007

Browse files
authored
[flang][preprocessor] Replace macros in some #include directives (#80039)
Ensure that #include FOO undergoes macro replacement. But, as is the case with C/C++, continue to not perform macro replacement in a #include directive with <angled brackets>.
1 parent dbf547f commit 6086007

File tree

4 files changed

+48
-21
lines changed

4 files changed

+48
-21
lines changed

flang/lib/Parser/preprocessor.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -642,27 +642,33 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
642642
"#include: missing name of file to include"_err_en_US);
643643
return;
644644
}
645-
std::string include;
646645
std::optional<std::string> prependPath;
647-
if (dir.TokenAt(j).ToString() == "<") { // #include <foo>
648-
std::size_t k{j + 1};
649-
if (k >= tokens) {
650-
prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j),
646+
TokenSequence path{dir, j, tokens - j};
647+
std::string include{path.TokenAt(0).ToString()};
648+
if (include != "<" && include.substr(0, 1) != "\"" &&
649+
include.substr(0, 1) != "'") {
650+
path = ReplaceMacros(path, prescanner);
651+
include = path.empty() ? ""s : path.TokenAt(0).ToString();
652+
}
653+
auto pathTokens{path.SizeInTokens()};
654+
std::size_t k{0};
655+
if (include == "<") { // #include <foo>
656+
k = 1;
657+
if (k >= pathTokens) {
658+
prescanner.Say(dir.GetIntervalProvenanceRange(j, pathTokens),
651659
"#include: file name missing"_err_en_US);
652660
return;
653661
}
654-
while (k < tokens && dir.TokenAt(k) != ">") {
662+
while (k < pathTokens && path.TokenAt(k) != ">") {
655663
++k;
656664
}
657-
if (k >= tokens) {
665+
if (k >= pathTokens) {
658666
prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j),
659667
"#include: expected '>' at end of included file"_port_en_US);
660668
}
661-
TokenSequence braced{dir, j + 1, k - j - 1};
669+
TokenSequence braced{path, 1, k - 1};
662670
include = braced.ToString();
663-
j = k;
664-
} else if (((include = dir.TokenAt(j).ToString()).substr(0, 1) == "\"" ||
665-
include.substr(0, 1) == "'") &&
671+
} else if ((include.substr(0, 1) == "\"" || include.substr(0, 1) == "'") &&
666672
include.substr(include.size() - 1, 1) == include.substr(0, 1)) {
667673
// #include "foo" and #include 'foo'
668674
include = include.substr(1, include.size() - 2);
@@ -673,16 +679,17 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
673679
}
674680
} else {
675681
prescanner.Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1),
676-
"#include: expected name of file to include"_err_en_US);
682+
"#include %s: expected name of file to include"_err_en_US,
683+
path.ToString());
677684
return;
678685
}
679686
if (include.empty()) {
680687
prescanner.Say(dir.GetTokenProvenanceRange(dirOffset),
681-
"#include: empty include file name"_err_en_US);
688+
"#include %s: empty include file name"_err_en_US, path.ToString());
682689
return;
683690
}
684-
j = dir.SkipBlanks(j + 1);
685-
if (j < tokens && dir.TokenAt(j).ToString() != "!") {
691+
k = path.SkipBlanks(k + 1);
692+
if (k < pathTokens && path.TokenAt(k).ToString() != "!") {
686693
prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j),
687694
"#include: extra stuff ignored after file name"_port_en_US);
688695
}
@@ -691,8 +698,8 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) {
691698
const SourceFile *included{
692699
allSources_.Open(include, error, std::move(prependPath))};
693700
if (!included) {
694-
prescanner.Say(dir.GetTokenProvenanceRange(dirOffset),
695-
"#include: %s"_err_en_US, error.str());
701+
prescanner.Say(dir.GetTokenProvenanceRange(j), "#include: %s"_err_en_US,
702+
error.str());
696703
} else if (included->bytes() > 0) {
697704
ProvenanceRange fileRange{
698705
allSources_.AddIncludedFile(*included, dir.GetProvenanceRange())};

flang/test/Driver/prescanner-diag.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
! RUN: %flang -fsyntax-only -I %S/Inputs/ %s 2>&1 | FileCheck %s
1313
! RUN: %flang_fc1 -fsyntax-only -I %S/Inputs/ %s 2>&1 | FileCheck %s
1414

15-
! CHECK: prescanner-diag.f90:[[#@LINE+3]]:20: portability: #include: extra stuff ignored after file name
16-
! CHECK: prescanner-diag.f90:[[#@LINE+3]]:20: portability: #include: extra stuff ignored after file name
15+
! CHECK: prescanner-diag.f90:[[#@LINE+3]]:10: portability: #include: extra stuff ignored after file name
16+
! CHECK: prescanner-diag.f90:[[#@LINE+3]]:10: portability: #include: extra stuff ignored after file name
1717

1818
#include <empty.h> comment
1919
#include "empty.h" comment

flang/test/Preprocessing/include-comment.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
#include <empty.h> /* comment */
66
! CHECK-NOT: :7:
77
#include <empty.h> !comment
8-
! CHECK: :9:20: portability: #include: extra stuff ignored after file name
8+
! CHECK: :9:10: portability: #include: extra stuff ignored after file name
99
#include <empty.h> comment
1010
! CHECK-NOT: :11:
1111
#include "empty.h" ! comment
1212
! CHECK-NOT: :13:
1313
#include "empty.h" /* comment */
1414
! CHECK-NOT: :15:
1515
#include "empty.h" !comment
16-
! CHECK: :17:20: portability: #include: extra stuff ignored after file name
16+
! CHECK: :17:10: portability: #include: extra stuff ignored after file name
1717
#include "empty.h" comment
1818
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
! RUN: %flang -I%S '-DFILE="defines.F90"' -DFOO=1 -DBAR=2 -E %s 2>&1 | FileCheck %s
2+
#include FILE
3+
! CHECK: integer :: a = 1
4+
! CHECK: integer :: b = 2
5+
#define SAME(x) x
6+
#undef FOO
7+
#undef BAR
8+
#define FOO 3
9+
#define BAR 4
10+
#include SAME(FILE)
11+
! CHECK: integer :: a = 3
12+
! CHECK: integer :: b = 4
13+
#define TOSTR(x) #x
14+
#undef FOO
15+
#undef BAR
16+
#define FOO 5
17+
#define BAR 6
18+
#include TOSTR(defines.F90)
19+
! CHECK: integer :: a = 5
20+
! CHECK: integer :: b = 6

0 commit comments

Comments
 (0)