diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp index 8c993e7ced0e8..10661dda32bc3 100644 --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -642,27 +642,33 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { "#include: missing name of file to include"_err_en_US); return; } - std::string include; std::optional prependPath; - if (dir.TokenAt(j).ToString() == "<") { // #include - std::size_t k{j + 1}; - if (k >= tokens) { - prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j), + TokenSequence path{dir, j, tokens - j}; + std::string include{path.TokenAt(0).ToString()}; + if (include != "<" && include.substr(0, 1) != "\"" && + include.substr(0, 1) != "'") { + path = ReplaceMacros(path, prescanner); + include = path.empty() ? ""s : path.TokenAt(0).ToString(); + } + auto pathTokens{path.SizeInTokens()}; + std::size_t k{0}; + if (include == "<") { // #include + k = 1; + if (k >= pathTokens) { + prescanner.Say(dir.GetIntervalProvenanceRange(j, pathTokens), "#include: file name missing"_err_en_US); return; } - while (k < tokens && dir.TokenAt(k) != ">") { + while (k < pathTokens && path.TokenAt(k) != ">") { ++k; } - if (k >= tokens) { + if (k >= pathTokens) { prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j), "#include: expected '>' at end of included file"_port_en_US); } - TokenSequence braced{dir, j + 1, k - j - 1}; + TokenSequence braced{path, 1, k - 1}; include = braced.ToString(); - j = k; - } else if (((include = dir.TokenAt(j).ToString()).substr(0, 1) == "\"" || - include.substr(0, 1) == "'") && + } else if ((include.substr(0, 1) == "\"" || include.substr(0, 1) == "'") && include.substr(include.size() - 1, 1) == include.substr(0, 1)) { // #include "foo" and #include 'foo' include = include.substr(1, include.size() - 2); @@ -673,16 +679,17 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { } } else { prescanner.Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1), - "#include: expected name of file to include"_err_en_US); + "#include %s: expected name of file to include"_err_en_US, + path.ToString()); return; } if (include.empty()) { prescanner.Say(dir.GetTokenProvenanceRange(dirOffset), - "#include: empty include file name"_err_en_US); + "#include %s: empty include file name"_err_en_US, path.ToString()); return; } - j = dir.SkipBlanks(j + 1); - if (j < tokens && dir.TokenAt(j).ToString() != "!") { + k = path.SkipBlanks(k + 1); + if (k < pathTokens && path.TokenAt(k).ToString() != "!") { prescanner.Say(dir.GetIntervalProvenanceRange(j, tokens - j), "#include: extra stuff ignored after file name"_port_en_US); } @@ -691,8 +698,8 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { const SourceFile *included{ allSources_.Open(include, error, std::move(prependPath))}; if (!included) { - prescanner.Say(dir.GetTokenProvenanceRange(dirOffset), - "#include: %s"_err_en_US, error.str()); + prescanner.Say(dir.GetTokenProvenanceRange(j), "#include: %s"_err_en_US, + error.str()); } else if (included->bytes() > 0) { ProvenanceRange fileRange{ allSources_.AddIncludedFile(*included, dir.GetProvenanceRange())}; diff --git a/flang/test/Driver/prescanner-diag.f90 b/flang/test/Driver/prescanner-diag.f90 index e133628f71d77..7c2f8d4d7ef4f 100644 --- a/flang/test/Driver/prescanner-diag.f90 +++ b/flang/test/Driver/prescanner-diag.f90 @@ -12,8 +12,8 @@ ! RUN: %flang -fsyntax-only -I %S/Inputs/ %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -fsyntax-only -I %S/Inputs/ %s 2>&1 | FileCheck %s -! CHECK: prescanner-diag.f90:[[#@LINE+3]]:20: portability: #include: extra stuff ignored after file name -! CHECK: prescanner-diag.f90:[[#@LINE+3]]:20: portability: #include: extra stuff ignored after file name +! CHECK: prescanner-diag.f90:[[#@LINE+3]]:10: portability: #include: extra stuff ignored after file name +! CHECK: prescanner-diag.f90:[[#@LINE+3]]:10: portability: #include: extra stuff ignored after file name #include comment #include "empty.h" comment diff --git a/flang/test/Preprocessing/include-comment.F90 b/flang/test/Preprocessing/include-comment.F90 index 5997a52292a5f..c55d07ec66d30 100644 --- a/flang/test/Preprocessing/include-comment.F90 +++ b/flang/test/Preprocessing/include-comment.F90 @@ -5,7 +5,7 @@ #include /* comment */ ! CHECK-NOT: :7: #include !comment -! CHECK: :9:20: portability: #include: extra stuff ignored after file name +! CHECK: :9:10: portability: #include: extra stuff ignored after file name #include comment ! CHECK-NOT: :11: #include "empty.h" ! comment @@ -13,6 +13,6 @@ #include "empty.h" /* comment */ ! CHECK-NOT: :15: #include "empty.h" !comment -! CHECK: :17:20: portability: #include: extra stuff ignored after file name +! CHECK: :17:10: portability: #include: extra stuff ignored after file name #include "empty.h" comment end diff --git a/flang/test/Preprocessing/macro-in-include.F90 b/flang/test/Preprocessing/macro-in-include.F90 new file mode 100644 index 0000000000000..047398859d651 --- /dev/null +++ b/flang/test/Preprocessing/macro-in-include.F90 @@ -0,0 +1,20 @@ +! RUN: %flang -I%S '-DFILE="defines.F90"' -DFOO=1 -DBAR=2 -E %s 2>&1 | FileCheck %s +#include FILE +! CHECK: integer :: a = 1 +! CHECK: integer :: b = 2 +#define SAME(x) x +#undef FOO +#undef BAR +#define FOO 3 +#define BAR 4 +#include SAME(FILE) +! CHECK: integer :: a = 3 +! CHECK: integer :: b = 4 +#define TOSTR(x) #x +#undef FOO +#undef BAR +#define FOO 5 +#define BAR 6 +#include TOSTR(defines.F90) +! CHECK: integer :: a = 5 +! CHECK: integer :: b = 6