[flang-commits] [flang] [flang][preprocessor] Support \ as line continuation (PR #89970)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Wed Apr 24 14:16:48 PDT 2024
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/89970
>From c3fa4bb1d6b96dc5d4787337c292e9c2daa62ea7 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 24 Apr 2024 11:25:24 -0700
Subject: [PATCH] [flang][preprocessor] Support \ as line continuation
When prescanning a Fortran source file with preprocessing enabled
in free source form, interpret a line-ending backslash as a source
line continuation marker as a C preprocessor would. This usage
isn't completely portable, but it is supported by GNU Fortran and
appears in the source for FPM package manager.
---
flang/docs/Preprocessing.md | 3 +++
flang/include/flang/Parser/preprocessor.h | 1 +
flang/lib/Parser/prescan.cpp | 18 +++++++++++++-----
flang/lib/Parser/prescan.h | 1 +
flang/test/Preprocessing/backslash-contin1.F90 | 8 ++++++++
5 files changed, 26 insertions(+), 5 deletions(-)
create mode 100644 flang/test/Preprocessing/backslash-contin1.F90
diff --git a/flang/docs/Preprocessing.md b/flang/docs/Preprocessing.md
index 3c523472f39bd0..0b70d857833cef 100644
--- a/flang/docs/Preprocessing.md
+++ b/flang/docs/Preprocessing.md
@@ -93,6 +93,9 @@ local:
* If a `#define` or `#undef` directive appears among continuation
lines, it may or may not affect text in the continued statement that
appeared before the directive.
+* A backslash at the end of a free form source line is a continuation
+ marker, with no space skipping or special handling of a leading `&`
+ on the next line.
## Behavior that few compilers properly support (or none), but should:
diff --git a/flang/include/flang/Parser/preprocessor.h b/flang/include/flang/Parser/preprocessor.h
index 630d5273d427c6..c3076435be5f0b 100644
--- a/flang/include/flang/Parser/preprocessor.h
+++ b/flang/include/flang/Parser/preprocessor.h
@@ -81,6 +81,7 @@ class Preprocessor {
void Undefine(std::string macro);
bool IsNameDefined(const CharBlock &);
bool IsFunctionLikeDefinition(const CharBlock &);
+ bool AnyDefinitions() const { return !definitions_.empty(); }
// When called with partialFunctionLikeMacro not null, MacroReplacement()
// and ReplaceMacros() handle an unclosed function-like macro reference
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 96db3955299f33..2d46eae531b186 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -29,15 +29,18 @@ Prescanner::Prescanner(Messages &messages, CookedSource &cooked,
Preprocessor &preprocessor, common::LanguageFeatureControl lfc)
: messages_{messages}, cooked_{cooked}, preprocessor_{preprocessor},
allSources_{preprocessor_.allSources()}, features_{lfc},
+ backslashFreeFormContinuation_{preprocessor.AnyDefinitions()},
encoding_{allSources_.encoding()} {}
Prescanner::Prescanner(const Prescanner &that)
: messages_{that.messages_}, cooked_{that.cooked_},
preprocessor_{that.preprocessor_}, allSources_{that.allSources_},
- features_{that.features_}, inFixedForm_{that.inFixedForm_},
+ features_{that.features_},
+ backslashFreeFormContinuation_{that.backslashFreeFormContinuation_},
+ inFixedForm_{that.inFixedForm_},
fixedFormColumnLimit_{that.fixedFormColumnLimit_},
- encoding_{that.encoding_}, prescannerNesting_{that.prescannerNesting_ +
- 1},
+ encoding_{that.encoding_},
+ prescannerNesting_{that.prescannerNesting_ + 1},
skipLeadingAmpersand_{that.skipLeadingAmpersand_},
compilerDirectiveBloomFilter_{that.compilerDirectiveBloomFilter_},
compilerDirectiveSentinels_{that.compilerDirectiveSentinels_} {}
@@ -1226,9 +1229,14 @@ bool Prescanner::Continuation(bool mightNeedFixedFormSpace) {
} else {
return FreeFormContinuation();
}
- } else {
- return false;
+ } else if (*at_ == '\\' && at_ + 2 == nextLine_ &&
+ backslashFreeFormContinuation_ && !inFixedForm_ && nextLine_ < limit_) {
+ // cpp-like handling of \ at end of a free form source line
+ BeginSourceLine(nextLine_);
+ NextLine();
+ return true;
}
+ return false;
}
std::optional<Prescanner::LineClassification>
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 581980001bcc23..3ee4c5a2c69eaa 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -197,6 +197,7 @@ class Prescanner {
Preprocessor &preprocessor_;
AllSources &allSources_;
common::LanguageFeatureControl features_;
+ bool backslashFreeFormContinuation_{false};
bool inFixedForm_{false};
int fixedFormColumnLimit_{72};
Encoding encoding_{Encoding::UTF_8};
diff --git a/flang/test/Preprocessing/backslash-contin1.F90 b/flang/test/Preprocessing/backslash-contin1.F90
new file mode 100644
index 00000000000000..cf2ed36370dab3
--- /dev/null
+++ b/flang/test/Preprocessing/backslash-contin1.F90
@@ -0,0 +1,8 @@
+! RUN: %flang -E %s | FileCheck %s
+print *, \
+ "hello, \
+world"
+end
+!CHECK: print *, "hello, world"
+!CHECK: end
+
More information about the flang-commits
mailing list