Skip to content
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

Merged
merged 1 commit into from
Jan 31, 2024

Conversation

klausler
Copy link
Contributor

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 .

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>.
@llvmbot llvmbot added flang:driver flang Flang issues not falling into any other category flang:parser labels Jan 30, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 30, 2024

@llvm/pr-subscribers-flang-driver

@llvm/pr-subscribers-flang-parser

Author: Peter Klausler (klausler)

Changes

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>.


Full diff: https://github.com/llvm/llvm-project/pull/80039.diff

4 Files Affected:

  • (modified) flang/lib/Parser/preprocessor.cpp (+24-17)
  • (modified) flang/test/Driver/prescanner-diag.f90 (+2-2)
  • (modified) flang/test/Preprocessing/include-comment.F90 (+2-2)
  • (added) flang/test/Preprocessing/macro-in-include.F90 (+20)
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

Copy link
Contributor

@jeanPerier jeanPerier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@klausler klausler merged commit 6086007 into llvm:main Jan 31, 2024
6 of 7 checks passed
@klausler klausler deleted the bug1516 branch January 31, 2024 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:driver flang:parser flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants