[flang-commits] [flang] cddbcd1 - [flang][preprocessor] Expand some keyword macros in quoted character … (#96987)

via flang-commits flang-commits at lists.llvm.org
Fri Jun 28 12:14:27 PDT 2024


Author: Peter Klausler
Date: 2024-06-28T12:14:23-07:00
New Revision: cddbcd15a0e6ef59e1cae0a68d000b0c5942ff43

URL: https://github.com/llvm/llvm-project/commit/cddbcd15a0e6ef59e1cae0a68d000b0c5942ff43
DIFF: https://github.com/llvm/llvm-project/commit/cddbcd15a0e6ef59e1cae0a68d000b0c5942ff43.diff

LOG: [flang][preprocessor] Expand some keyword macros in quoted character … (#96987)

…literals

To help port codes from compilers using pre-ANSI C preprocessors, which
didn't care much about context when replacing macros, support the
replacement of keyword macros in quoted character literals when (and
only when) the name of the keyword macro constitutes the entire
significant portion of a free form continuation line. See the new test
case for a motivating example.

Fixes https://github.com/llvm/llvm-project/issues/96781.

Added: 
    flang/test/Preprocessing/kw-in-char.F90

Modified: 
    flang/lib/Parser/prescan.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 42aa829e0ed5b..668429a882291 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -820,6 +820,41 @@ void Prescanner::QuotedCharacterLiteral(
       }
       break;
     }
+    // Here's a weird edge case.  When there's a two or more following
+    // continuation lines at this point, and the entire significant part of
+    // the next continuation line is the name of a keyword macro, replace
+    // it in the character literal with its definition.  Example:
+    //   #define FOO foo
+    //   subroutine subr() bind(c, name="my_&
+    //     &FOO&
+    //     &_bar") ...
+    // produces a binding name of "my_foo_bar".
+    while (at_[1] == '&' && nextLine_ < limit_ && !InFixedFormSource()) {
+      const char *idStart{nextLine_};
+      if (const char *amper{SkipWhiteSpace(nextLine_)}; *amper == '&') {
+        idStart = amper + 1;
+      }
+      if (IsLegalIdentifierStart(*idStart)) {
+        std::size_t idLen{1};
+        for (; IsLegalInIdentifier(idStart[idLen]); ++idLen) {
+        }
+        if (idStart[idLen] == '&') {
+          CharBlock id{idStart, idLen};
+          if (preprocessor_.IsNameDefined(id)) {
+            TokenSequence ppTokens;
+            ppTokens.Put(id, GetProvenance(idStart));
+            if (auto replaced{
+                    preprocessor_.MacroReplacement(ppTokens, *this)}) {
+              tokens.Put(*replaced);
+              at_ = &idStart[idLen - 1];
+              NextLine();
+              continue; // try again on the next line
+            }
+          }
+        }
+      }
+      break;
+    }
     end = at_ + 1;
     NextChar();
     if (*at_ == quote && !isEscaped) {

diff  --git a/flang/test/Preprocessing/kw-in-char.F90 b/flang/test/Preprocessing/kw-in-char.F90
new file mode 100644
index 0000000000000..e8f3a33b8a749
--- /dev/null
+++ b/flang/test/Preprocessing/kw-in-char.F90
@@ -0,0 +1,14 @@
+! RUN: %flang -E %s 2>&1 | FileCheck %s
+! CHECK: subroutine test_b_wrapper_c() bind(C, name="test_b_c_f")
+#define TEMP_LETTER b
+#define VAL c
+subroutine test_&
+TEMP_LETTER&
+_wrapper_&
+VAL&
+ () bind(C, name="test_&
+    &TEMP_LETTER&
+    &_&
+    &VAL&
+    &_f")
+end


        


More information about the flang-commits mailing list