Skip to content

Commit 5942f02

Browse files
authored
[flang] Preserve compiler directives in -E output (#133959)
No longer require -fopenmp or -fopenacc with -E, unless specific version number options are also required for predefined macros. This means that most source can be preprocessed with -E and then later compiled with -fopenmp, -fopenacc, or neither. This means that OpenMP conditional compilation lines (!$) are also passed through to -E output. The tricky part of this patch was dealing with the fact that those conditional lines can also contain regular Fortran line continuation, and that now has to be deferred when !$ lines are interspersed.
1 parent 70a1445 commit 5942f02

10 files changed

+188
-124
lines changed

flang/lib/Parser/parsing.cpp

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,24 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
7979
.set_expandIncludeLines(!options.prescanAndReformat ||
8080
options.expandIncludeLinesInPreprocessedOutput)
8181
.AddCompilerDirectiveSentinel("dir$");
82-
if (options.features.IsEnabled(LanguageFeature::OpenACC)) {
82+
bool noneOfTheAbove{!options.features.IsEnabled(LanguageFeature::OpenACC) &&
83+
!options.features.IsEnabled(LanguageFeature::OpenMP) &&
84+
!options.features.IsEnabled(LanguageFeature::CUDA)};
85+
if (options.features.IsEnabled(LanguageFeature::OpenACC) ||
86+
(options.prescanAndReformat && noneOfTheAbove)) {
8387
prescanner.AddCompilerDirectiveSentinel("$acc");
8488
}
85-
if (options.features.IsEnabled(LanguageFeature::OpenMP)) {
89+
if (options.features.IsEnabled(LanguageFeature::OpenMP) ||
90+
(options.prescanAndReformat && noneOfTheAbove)) {
8691
prescanner.AddCompilerDirectiveSentinel("$omp");
8792
prescanner.AddCompilerDirectiveSentinel("$"); // OMP conditional line
8893
}
89-
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
94+
if (options.features.IsEnabled(LanguageFeature::CUDA) ||
95+
(options.prescanAndReformat && noneOfTheAbove)) {
9096
prescanner.AddCompilerDirectiveSentinel("$cuf");
9197
prescanner.AddCompilerDirectiveSentinel("@cuf");
98+
}
99+
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
92100
preprocessor_.Define("_CUDA", "1");
93101
}
94102
ProvenanceRange range{allSources.AddIncludedFile(
@@ -119,11 +127,13 @@ void Parsing::EmitPreprocessedSource(
119127
int sourceLine{0};
120128
int column{1};
121129
bool inDirective{false};
130+
bool ompConditionalLine{false};
122131
bool inContinuation{false};
123132
bool lineWasBlankBefore{true};
124133
const AllSources &allSources{allCooked().allSources()};
125-
// All directives that flang support are known to have a length of 3 chars
126-
constexpr int directiveNameLength{3};
134+
// All directives that flang supports are known to have a length of 4 chars,
135+
// except for OpenMP conditional compilation lines (!$).
136+
constexpr int directiveNameLength{4};
127137
// We need to know the current directive in order to provide correct
128138
// continuation for the directive
129139
std::string directive;
@@ -133,6 +143,7 @@ void Parsing::EmitPreprocessedSource(
133143
out << '\n'; // TODO: DOS CR-LF line ending if necessary
134144
column = 1;
135145
inDirective = false;
146+
ompConditionalLine = false;
136147
inContinuation = false;
137148
lineWasBlankBefore = true;
138149
++sourceLine;
@@ -153,16 +164,21 @@ void Parsing::EmitPreprocessedSource(
153164
return ch;
154165
}};
155166

167+
bool inDirectiveSentinel{false};
156168
if (ch == '!' && lineWasBlankBefore) {
157169
// Other comment markers (C, *, D) in original fixed form source
158170
// input card column 1 will have been deleted or normalized to !,
159171
// which signifies a comment (directive) in both source forms.
160172
inDirective = true;
161-
}
162-
bool inDirectiveSentinel{
163-
inDirective && directive.size() < directiveNameLength};
164-
if (inDirectiveSentinel && IsLetter(ch)) {
165-
directive += getOriginalChar(ch);
173+
inDirectiveSentinel = true;
174+
} else if (inDirective && !ompConditionalLine &&
175+
directive.size() < directiveNameLength) {
176+
if (IsLetter(ch) || ch == '$' || ch == '@') {
177+
directive += getOriginalChar(ch);
178+
inDirectiveSentinel = true;
179+
} else if (directive == "$"s) {
180+
ompConditionalLine = true;
181+
}
166182
}
167183

168184
std::optional<SourcePosition> position{provenance
@@ -199,9 +215,16 @@ void Parsing::EmitPreprocessedSource(
199215
// column limit override option.
200216
// OpenMP and OpenACC directives' continuations should have the
201217
// corresponding sentinel at the next line.
202-
const auto continuation{
203-
inDirective ? "&\n!$" + directive + "&" : "&\n &"s};
204-
out << continuation;
218+
out << "&\n";
219+
if (inDirective) {
220+
if (ompConditionalLine) {
221+
out << "!$ &";
222+
} else {
223+
out << '!' << directive << '&';
224+
}
225+
} else {
226+
out << " &";
227+
}
205228
column = 7; // start of fixed form source field
206229
++sourceLine;
207230
inContinuation = true;
@@ -212,11 +235,20 @@ void Parsing::EmitPreprocessedSource(
212235
out << ' ';
213236
}
214237
}
215-
if (!inContinuation && !inDirectiveSentinel && position &&
216-
position->column <= 72 && ch != ' ') {
217-
// Preserve original indentation
218-
for (; column < position->column; ++column) {
219-
out << ' ';
238+
if (ch != ' ') {
239+
if (ompConditionalLine) {
240+
// Only digits can stay in the label field
241+
if (!(ch >= '0' && ch <= '9')) {
242+
for (; column < 7; ++column) {
243+
out << ' ';
244+
}
245+
}
246+
} else if (!inContinuation && !inDirectiveSentinel && position &&
247+
position->column <= 72) {
248+
// Preserve original indentation
249+
for (; column < position->column; ++column) {
250+
out << ' ';
251+
}
220252
}
221253
}
222254
out << getOriginalChar(ch);

0 commit comments

Comments
 (0)