-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][preprocessor] Replace macros in some #include directives #80039
Conversation
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>.
@llvm/pr-subscribers-flang-driver @llvm/pr-subscribers-flang-parser Author: Peter Klausler (klausler) ChangesEnsure 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>. Full diff: https://github.com/llvm/llvm-project/pull/80039.diff 4 Files Affected:
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<std::string> prependPath;
- if (dir.TokenAt(j).ToString() == "<") { // #include <foo>
- 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 <foo>
+ 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 <empty.h> 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 <empty.h> /* comment */
! CHECK-NOT: :7:
#include <empty.h> !comment
-! CHECK: :9:20: portability: #include: extra stuff ignored after file name
+! CHECK: :9:10: portability: #include: extra stuff ignored after file name
#include <empty.h> 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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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 .