Skip to content

Commit 0511614

Browse files
committed
[flang][preprocessing] Mix preprocessing directives with free form line continuation
Allow preprocessing directives to appear between a source line and its continuation, including conditional compilation directives (#if, #ifdef, &c.). Fixes #95476.
1 parent 34a2889 commit 0511614

File tree

4 files changed

+46
-18
lines changed

4 files changed

+46
-18
lines changed

flang/include/flang/Parser/preprocessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class Preprocessor {
8282
bool IsNameDefined(const CharBlock &);
8383
bool IsFunctionLikeDefinition(const CharBlock &);
8484
bool AnyDefinitions() const { return !definitions_.empty(); }
85+
bool InConditional() const { return !ifStack_.empty(); }
8586

8687
// When called with partialFunctionLikeMacro not null, MacroReplacement()
8788
// and ReplaceMacros() handle an unclosed function-like macro reference

flang/lib/Parser/prescan.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ void Prescanner::Statement() {
105105
NextLine();
106106
return;
107107
case LineClassification::Kind::ConditionalCompilationDirective:
108-
case LineClassification::Kind::DefinitionDirective:
109-
case LineClassification::Kind::PreprocessorDirective:
108+
case LineClassification::Kind::IncludeDirective:
110109
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
110+
afterPreprocessingDirective_ = true;
111111
return;
112-
case LineClassification::Kind::IncludeDirective:
112+
case LineClassification::Kind::PreprocessorDirective:
113+
case LineClassification::Kind::DefinitionDirective:
113114
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
114-
afterIncludeDirective_ = true;
115+
// Don't set afterPreprocessingDirective_
115116
return;
116117
case LineClassification::Kind::CompilerDirective: {
117118
directiveSentinel_ = line.sentinel;
@@ -289,13 +290,14 @@ void Prescanner::CheckAndEmitLine(
289290
tokens.CheckBadFortranCharacters(
290291
messages_, *this, disableSourceContinuation_);
291292
// Parenthesis nesting check does not apply while any #include is
292-
// active, nor on the lines before and after a top-level #include.
293+
// active, nor on the lines before and after a top-level #include,
294+
// nor before or after conditional source.
293295
// Applications play shenanigans with line continuation before and
294-
// after #include'd subprogram argument lists.
296+
// after #include'd subprogram argument lists and conditional source.
295297
if (!isNestedInIncludeDirective_ && !omitNewline_ &&
296-
!afterIncludeDirective_ && tokens.BadlyNestedParentheses()) {
297-
if (inFixedForm_ && nextLine_ < limit_ &&
298-
IsPreprocessorDirectiveLine(nextLine_)) {
298+
!afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() &&
299+
!preprocessor_.InConditional()) {
300+
if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) {
299301
// don't complain
300302
} else {
301303
tokens.CheckBadParentheses(messages_);
@@ -306,7 +308,7 @@ void Prescanner::CheckAndEmitLine(
306308
omitNewline_ = false;
307309
} else {
308310
cooked_.Put('\n', newlineProvenance);
309-
afterIncludeDirective_ = false;
311+
afterPreprocessingDirective_ = false;
310312
}
311313
}
312314

@@ -1069,6 +1071,17 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
10691071
return true;
10701072
} else if (inPreprocessorDirective_) {
10711073
return false;
1074+
} else if (afterAmpersand &&
1075+
(lineClass.kind ==
1076+
LineClassification::Kind::ConditionalCompilationDirective ||
1077+
lineClass.kind == LineClassification::Kind::DefinitionDirective ||
1078+
lineClass.kind == LineClassification::Kind::PreprocessorDirective ||
1079+
lineClass.kind == LineClassification::Kind::IncludeDirective ||
1080+
lineClass.kind == LineClassification::Kind::IncludeLine)) {
1081+
SkipToEndOfLine();
1082+
omitNewline_ = true;
1083+
skipLeadingAmpersand_ = true;
1084+
return false;
10721085
} else if (lineClass.kind ==
10731086
LineClassification::Kind::ConditionalCompilationDirective ||
10741087
lineClass.kind == LineClassification::Kind::PreprocessorDirective) {
@@ -1080,13 +1093,6 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
10801093
// continued line).
10811094
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
10821095
return true;
1083-
} else if (afterAmpersand &&
1084-
(lineClass.kind == LineClassification::Kind::IncludeDirective ||
1085-
lineClass.kind == LineClassification::Kind::IncludeLine)) {
1086-
SkipToEndOfLine();
1087-
omitNewline_ = true;
1088-
skipLeadingAmpersand_ = true;
1089-
return false;
10901096
} else {
10911097
return false;
10921098
}

flang/lib/Parser/prescan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class Prescanner {
214214
int prescannerNesting_{0};
215215
int continuationLines_{0};
216216
bool isPossibleMacroCall_{false};
217-
bool afterIncludeDirective_{false};
217+
bool afterPreprocessingDirective_{false};
218218
bool disableSourceContinuation_{false};
219219

220220
Provenance startProvenance_;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
! RUN: %flang -fc1 -E %s 2>&1 | FileCheck %s
2+
! CHECK: subroutine test(ARG1,FA, FB,ARG2)
3+
! CHECK: end
4+
5+
subroutine test( &
6+
ARG1, &
7+
! test
8+
#ifndef SWAP
9+
#define ARG1 FA
10+
#define ARG2 FB
11+
#else
12+
#define ARG1 FB
13+
#define ARG2 FA
14+
#endif
15+
ARG1, ARG2, &
16+
! test
17+
#undef ARG1
18+
#undef ARG2
19+
&ARG2)
20+
! comment
21+
end

0 commit comments

Comments
 (0)