Skip to content

Commit 732b9cb

Browse files
committed
[flang] Preserve compiler directives in -E output
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 3bc8aa7 commit 732b9cb

10 files changed

+185
-124
lines changed

flang/lib/Parser/parsing.cpp

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,21 @@ 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+
if (options.features.IsEnabled(LanguageFeature::OpenACC) ||
83+
options.prescanAndReformat) {
8384
prescanner.AddCompilerDirectiveSentinel("$acc");
8485
}
85-
if (options.features.IsEnabled(LanguageFeature::OpenMP)) {
86+
if (options.features.IsEnabled(LanguageFeature::OpenMP) ||
87+
options.prescanAndReformat) {
8688
prescanner.AddCompilerDirectiveSentinel("$omp");
8789
prescanner.AddCompilerDirectiveSentinel("$"); // OMP conditional line
8890
}
89-
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
91+
if (options.features.IsEnabled(LanguageFeature::CUDA) ||
92+
options.prescanAndReformat) {
9093
prescanner.AddCompilerDirectiveSentinel("$cuf");
9194
prescanner.AddCompilerDirectiveSentinel("@cuf");
95+
}
96+
if (options.features.IsEnabled(LanguageFeature::CUDA)) {
9297
preprocessor_.Define("_CUDA", "1");
9398
}
9499
ProvenanceRange range{allSources.AddIncludedFile(
@@ -119,11 +124,13 @@ void Parsing::EmitPreprocessedSource(
119124
int sourceLine{0};
120125
int column{1};
121126
bool inDirective{false};
127+
bool ompConditionalLine{false};
122128
bool inContinuation{false};
123129
bool lineWasBlankBefore{true};
124130
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};
131+
// All directives that flang supports are known to have a length of 4 chars,
132+
// except for OpenMP conditional compilation lines (!$).
133+
constexpr int directiveNameLength{4};
127134
// We need to know the current directive in order to provide correct
128135
// continuation for the directive
129136
std::string directive;
@@ -133,6 +140,7 @@ void Parsing::EmitPreprocessedSource(
133140
out << '\n'; // TODO: DOS CR-LF line ending if necessary
134141
column = 1;
135142
inDirective = false;
143+
ompConditionalLine = false;
136144
inContinuation = false;
137145
lineWasBlankBefore = true;
138146
++sourceLine;
@@ -153,16 +161,21 @@ void Parsing::EmitPreprocessedSource(
153161
return ch;
154162
}};
155163

164+
bool inDirectiveSentinel{false};
156165
if (ch == '!' && lineWasBlankBefore) {
157166
// Other comment markers (C, *, D) in original fixed form source
158167
// input card column 1 will have been deleted or normalized to !,
159168
// which signifies a comment (directive) in both source forms.
160169
inDirective = true;
161-
}
162-
bool inDirectiveSentinel{
163-
inDirective && directive.size() < directiveNameLength};
164-
if (inDirectiveSentinel && IsLetter(ch)) {
165-
directive += getOriginalChar(ch);
170+
inDirectiveSentinel = true;
171+
} else if (inDirective && !ompConditionalLine &&
172+
directive.size() < directiveNameLength) {
173+
if (IsLetter(ch) || ch == '$' || ch == '@') {
174+
directive += getOriginalChar(ch);
175+
inDirectiveSentinel = true;
176+
} else if (directive == "$"s) {
177+
ompConditionalLine = true;
178+
}
166179
}
167180

168181
std::optional<SourcePosition> position{provenance
@@ -199,9 +212,16 @@ void Parsing::EmitPreprocessedSource(
199212
// column limit override option.
200213
// OpenMP and OpenACC directives' continuations should have the
201214
// corresponding sentinel at the next line.
202-
const auto continuation{
203-
inDirective ? "&\n!$" + directive + "&" : "&\n &"s};
204-
out << continuation;
215+
out << "&\n";
216+
if (inDirective) {
217+
if (ompConditionalLine) {
218+
out << "!$ &";
219+
} else {
220+
out << '!' << directive << '&';
221+
}
222+
} else {
223+
out << " &";
224+
}
205225
column = 7; // start of fixed form source field
206226
++sourceLine;
207227
inContinuation = true;
@@ -212,11 +232,20 @@ void Parsing::EmitPreprocessedSource(
212232
out << ' ';
213233
}
214234
}
215-
if (!inContinuation && !inDirectiveSentinel && position &&
216-
position->column <= 72 && ch != ' ') {
217-
// Preserve original indentation
218-
for (; column < position->column; ++column) {
219-
out << ' ';
235+
if (ch != ' ') {
236+
if (ompConditionalLine) {
237+
// Only digits can stay in the label field
238+
if (!(ch >= '0' && ch <= '9')) {
239+
for (; column < 7; ++column) {
240+
out << ' ';
241+
}
242+
}
243+
} else if (!inContinuation && !inDirectiveSentinel && position &&
244+
position->column <= 72) {
245+
// Preserve original indentation
246+
for (; column < position->column; ++column) {
247+
out << ' ';
248+
}
220249
}
221250
}
222251
out << getOriginalChar(ch);

0 commit comments

Comments
 (0)