Skip to content

[flang][preprocessor] Support \ as line continuation #89970

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

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flang/docs/Preprocessing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Parser/preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 13 additions & 5 deletions flang/lib/Parser/prescan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_} {}
Expand Down Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Parser/prescan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
8 changes: 8 additions & 0 deletions flang/test/Preprocessing/backslash-contin1.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
! RUN: %flang -E %s | FileCheck %s
print *, \
"hello, \
world"
end
!CHECK: print *, "hello, world"
!CHECK: end