[flang-commits] [flang] [flang] Fix continued literals incorrect padding with -ffixed-line-length=none (PR #225051)
Mattéo Rizza Murgier via flang-commits
flang-commits at lists.llvm.org
Mon Sep 21 04:32:40 PDT 2026
https://github.com/matteo-rm updated https://github.com/llvm/llvm-project/pull/225051
>From 0e784ed92b81710cae4348435c87f58549cc81d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matt=C3=A9o=20Rizza=20Murgier?=
<matteo.rizza-murgier at sipearl.com>
Date: Fri, 18 Sep 2026 17:59:01 +0200
Subject: [PATCH 1/2] [flang] Fix continued literals incorrect padding with
-ffixed-line-length=none
---
.../include/flang/Frontend/FrontendOptions.h | 3 ++-
flang/include/flang/Parser/options.h | 2 +-
flang/lib/Frontend/CompilerInvocation.cpp | 2 +-
flang/lib/Parser/prescan.cpp | 19 +++++++++++--------
flang/lib/Parser/prescan.h | 7 +++++--
...fixed-line-length-none-char-continuation.f | 11 +++++++++++
6 files changed, 31 insertions(+), 13 deletions(-)
create mode 100644 flang/test/Parser/fixed-line-length-none-char-continuation.f
diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index b0e4918d6b4a0..abc008bfbe339 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstdint>
+#include <optional>
#include <string>
namespace Fortran::frontend {
@@ -290,7 +291,7 @@ struct FrontendOptions {
// The column after which characters are ignored in fixed form lines in the
// source file.
- int fixedFormColumns = 72;
+ std::optional<int> fixedFormColumns = 72;
/// The input kind, either specified via -x argument or deduced from the input
/// file name.
diff --git a/flang/include/flang/Parser/options.h b/flang/include/flang/Parser/options.h
index e65f253748d26..5f24b89c23035 100644
--- a/flang/include/flang/Parser/options.h
+++ b/flang/include/flang/Parser/options.h
@@ -24,7 +24,7 @@ struct Options {
using Predefinition = std::pair<std::string, std::optional<std::string>>;
bool isFixedForm{false};
- int fixedFormColumns{72};
+ std::optional<int> fixedFormColumns{72};
common::LanguageFeatureControl features;
std::vector<std::string> searchDirectories;
std::vector<std::string> intrinsicModuleDirectories;
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 85e5f477dcb8c..9ee4142de7710 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -872,7 +872,7 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
diags.Report(clang::diag::err_drv_negative_columns)
<< arg->getOption().getName() << arg->getValue();
} else if (columns == 0) {
- opts.fixedFormColumns = 1000000;
+ opts.fixedFormColumns = std::nullopt;
} else if (columns < 7) {
diags.Report(clang::diag::err_drv_small_columns)
<< arg->getOption().getName() << arg->getValue() << "7";
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index db4b50a492002..11d3527e07638 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -572,7 +572,8 @@ void Prescanner::SkipToEndOfLine() {
}
bool Prescanner::MustSkipToEndOfLine() const {
- if (inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_) {
+ if (inFixedForm_ && IsPastFixedFormColumnLimit(column_) &&
+ !tabInCurrentLine_) {
return true; // skip over ignored columns in right margin (73:80)
} else if (*at_ == '!' && !inCharLiteral_ &&
(!inFixedForm_ || tabInCurrentLine_ || column_ != 6)) {
@@ -880,12 +881,13 @@ bool Prescanner::NextToken(TokenSequence &tokens) {
!preprocessingOnly_ && IsSpaceOrTab(at_)) {
const char *probe{at_};
int col{column_};
- while (col <= fixedFormColumnLimit_ && IsSpaceOrTab(probe)) {
+ while (!IsPastFixedFormColumnLimit(col) && IsSpaceOrTab(probe)) {
probe += IsSpaceOrTab(probe);
++col;
}
- if (col > fixedFormColumnLimit_ || *probe == '\n' || *probe == '\r' ||
- (*probe == '!' && col <= fixedFormColumnLimit_)) {
+ if (IsPastFixedFormColumnLimit(col) || *probe == '\n' ||
+ *probe == '\r' ||
+ (*probe == '!' && !IsPastFixedFormColumnLimit(col))) {
SkipSpaces();
hadContinuation = SkipToNextSignificantCharacter();
}
@@ -1204,8 +1206,9 @@ void Prescanner::Hollerith(
// In fixed form, source card images must be processed as if they were at
// least 72 columns wide, at least in character literal contexts.
bool Prescanner::PadOutCharacterLiteral(TokenSequence &tokens) {
- while (inFixedForm_ && !tabInCurrentLine_ && at_[1] == '\n') {
- if (column_ < fixedFormColumnLimit_) {
+ while (inFixedForm_ && fixedFormColumnLimit_ && !tabInCurrentLine_ &&
+ at_[1] == '\n') {
+ if (column_ < *fixedFormColumnLimit_) {
tokens.PutNextTokenChar(' ', spaceProvenance_);
++column_;
return true;
@@ -1254,7 +1257,7 @@ bool Prescanner::IsFixedFormCommentLine(const char *start) const {
break;
}
}
- if (!anyTabs && p >= start + fixedFormColumnLimit_) {
+ if (!anyTabs && IsPastFixedFormColumnLimit(p - start + 1)) {
return true;
}
if (*p == '!' && !inCharLiteral_ && (anyTabs || p != start + 5)) {
@@ -1755,7 +1758,7 @@ Prescanner::IsFixedFormCompilerDirectiveLine(const char *start) const {
(features_.IsEnabled(LanguageFeature::OpenMP) &&
std::strcmp(sentinel, "$omp") == 0)};
if (isOpenMPSentinelScan) {
- for (; column <= fixedFormColumnLimit_; ++column, ++p) {
+ for (; !IsPastFixedFormColumnLimit(column); ++column, ++p) {
if (IsSpaceOrTab(p)) {
} else if (*p == '!') {
return std::nullopt; // sentinel + blanks + ! is a comment, not a
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index 656b3c98b6c73..1c57cfa2c6fe5 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -64,7 +64,7 @@ class Prescanner {
encoding_ = code;
return *this;
}
- Prescanner &set_fixedFormColumnLimit(int limit) {
+ Prescanner &set_fixedFormColumnLimit(std::optional<int> limit) {
fixedFormColumnLimit_ = limit;
return *this;
}
@@ -208,6 +208,9 @@ class Prescanner {
std::strcmp(directiveSentinel_, "$omx") == 0 ||
std::strcmp(directiveSentinel_, "$ompx") == 0);
}
+ bool IsPastFixedFormColumnLimit(int column) const {
+ return fixedFormColumnLimit_ && column > *fixedFormColumnLimit_;
+ }
bool InFixedFormSource() const {
return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
}
@@ -280,7 +283,7 @@ class Prescanner {
bool isNestedInIncludeDirective_{false};
bool backslashFreeFormContinuation_{false};
bool inFixedForm_{false};
- int fixedFormColumnLimit_{72};
+ std::optional<int> fixedFormColumnLimit_{72};
Encoding encoding_{Encoding::UTF_8};
int parenthesisNesting_{0};
int prescannerNesting_{0};
diff --git a/flang/test/Parser/fixed-line-length-none-char-continuation.f b/flang/test/Parser/fixed-line-length-none-char-continuation.f
new file mode 100644
index 0000000000000..17444cec18a8b
--- /dev/null
+++ b/flang/test/Parser/fixed-line-length-none-char-continuation.f
@@ -0,0 +1,11 @@
+! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s --check-prefix=DEFAULT
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=132 %s | FileCheck %s --check-prefix=LEN132
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=none %s | FileCheck %s --check-prefix=NONE
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=0 %s | FileCheck %s --check-prefix=NONE
+ character*4 s
+ s = 'ab
+ +cd'
+ end
+! DEFAULT: s="ab{{( {59})}}cd"
+! LEN132: s="ab{{( {119})}}cd"
+! NONE: s="abcd"
>From aed530b4808e27f5c522c3f171b40c3c084ec79b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matt=C3=A9o=20Rizza=20Murgier?=
<matteo.rizza-murgier at sipearl.com>
Date: Mon, 21 Sep 2026 13:32:15 +0200
Subject: [PATCH 2/2] Add strict whitespace flag to test
---
.../Parser/fixed-line-length-none-char-continuation.f | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/flang/test/Parser/fixed-line-length-none-char-continuation.f b/flang/test/Parser/fixed-line-length-none-char-continuation.f
index 17444cec18a8b..325b820a0f674 100644
--- a/flang/test/Parser/fixed-line-length-none-char-continuation.f
+++ b/flang/test/Parser/fixed-line-length-none-char-continuation.f
@@ -1,7 +1,7 @@
-! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s --check-prefix=DEFAULT
-! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=132 %s | FileCheck %s --check-prefix=LEN132
-! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=none %s | FileCheck %s --check-prefix=NONE
-! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=0 %s | FileCheck %s --check-prefix=NONE
+! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s --strict-whitespace --check-prefix=DEFAULT
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=132 %s | FileCheck %s --strict-whitespace --check-prefix=LEN132
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=none %s | FileCheck %s --strict-whitespace --check-prefix=NONE
+! RUN: %flang_fc1 -fdebug-unparse -ffixed-line-length=0 %s | FileCheck %s --strict-whitespace --check-prefix=NONE
character*4 s
s = 'ab
+cd'
More information about the flang-commits
mailing list