[flang-commits] [flang] [flang][preprocessing] Mix preprocessing directives with free form li… (PR #96244)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 20 15:32:52 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-parser
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
…ne continuation
Allow preprocessing directives to appear between a source line and its continuation, including conditional compilation directives (#if, #ifdef, &c.).
Fixes https://github.com/llvm/llvm-project/issues/95476.
---
Full diff: https://github.com/llvm/llvm-project/pull/96244.diff
4 Files Affected:
- (modified) flang/include/flang/Parser/preprocessor.h (+1)
- (modified) flang/lib/Parser/prescan.cpp (+23-17)
- (modified) flang/lib/Parser/prescan.h (+1-1)
- (added) flang/test/Preprocessing/cond-contin.F90 (+21)
``````````diff
diff --git a/flang/include/flang/Parser/preprocessor.h b/flang/include/flang/Parser/preprocessor.h
index c3076435be5f0..57690dd226f62 100644
--- a/flang/include/flang/Parser/preprocessor.h
+++ b/flang/include/flang/Parser/preprocessor.h
@@ -82,6 +82,7 @@ class Preprocessor {
bool IsNameDefined(const CharBlock &);
bool IsFunctionLikeDefinition(const CharBlock &);
bool AnyDefinitions() const { return !definitions_.empty(); }
+ bool InConditional() const { return !ifStack_.empty(); }
// When called with partialFunctionLikeMacro not null, MacroReplacement()
// and ReplaceMacros() handle an unclosed function-like macro reference
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index 2a6ecfbb0830e..452752cc89962 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -105,13 +105,14 @@ void Prescanner::Statement() {
NextLine();
return;
case LineClassification::Kind::ConditionalCompilationDirective:
- case LineClassification::Kind::DefinitionDirective:
- case LineClassification::Kind::PreprocessorDirective:
+ case LineClassification::Kind::IncludeDirective:
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
+ afterPreprocessingDirective_ = true;
return;
- case LineClassification::Kind::IncludeDirective:
+ case LineClassification::Kind::PreprocessorDirective:
+ case LineClassification::Kind::DefinitionDirective:
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
- afterIncludeDirective_ = true;
+ // Don't set afterPreprocessingDirective_
return;
case LineClassification::Kind::CompilerDirective: {
directiveSentinel_ = line.sentinel;
@@ -289,13 +290,14 @@ void Prescanner::CheckAndEmitLine(
tokens.CheckBadFortranCharacters(
messages_, *this, disableSourceContinuation_);
// Parenthesis nesting check does not apply while any #include is
- // active, nor on the lines before and after a top-level #include.
+ // active, nor on the lines before and after a top-level #include,
+ // nor before or after conditional source.
// Applications play shenanigans with line continuation before and
- // after #include'd subprogram argument lists.
+ // after #include'd subprogram argument lists and conditional source.
if (!isNestedInIncludeDirective_ && !omitNewline_ &&
- !afterIncludeDirective_ && tokens.BadlyNestedParentheses()) {
- if (inFixedForm_ && nextLine_ < limit_ &&
- IsPreprocessorDirectiveLine(nextLine_)) {
+ !afterPreprocessingDirective_ && tokens.BadlyNestedParentheses() &&
+ !preprocessor_.InConditional()) {
+ if (nextLine_ < limit_ && IsPreprocessorDirectiveLine(nextLine_)) {
// don't complain
} else {
tokens.CheckBadParentheses(messages_);
@@ -306,7 +308,7 @@ void Prescanner::CheckAndEmitLine(
omitNewline_ = false;
} else {
cooked_.Put('\n', newlineProvenance);
- afterIncludeDirective_ = false;
+ afterPreprocessingDirective_ = false;
}
}
@@ -1069,6 +1071,17 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
return true;
} else if (inPreprocessorDirective_) {
return false;
+ } else if (afterAmpersand &&
+ (lineClass.kind ==
+ LineClassification::Kind::ConditionalCompilationDirective ||
+ lineClass.kind == LineClassification::Kind::DefinitionDirective ||
+ lineClass.kind == LineClassification::Kind::PreprocessorDirective ||
+ lineClass.kind == LineClassification::Kind::IncludeDirective ||
+ lineClass.kind == LineClassification::Kind::IncludeLine)) {
+ SkipToEndOfLine();
+ omitNewline_ = true;
+ skipLeadingAmpersand_ = true;
+ return false;
} else if (lineClass.kind ==
LineClassification::Kind::ConditionalCompilationDirective ||
lineClass.kind == LineClassification::Kind::PreprocessorDirective) {
@@ -1080,13 +1093,6 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
// continued line).
preprocessor_.Directive(TokenizePreprocessorDirective(), *this);
return true;
- } else if (afterAmpersand &&
- (lineClass.kind == LineClassification::Kind::IncludeDirective ||
- lineClass.kind == LineClassification::Kind::IncludeLine)) {
- SkipToEndOfLine();
- omitNewline_ = true;
- skipLeadingAmpersand_ = true;
- return false;
} else {
return false;
}
diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h
index b6f6d2ca439ee..421ba97d324c9 100644
--- a/flang/lib/Parser/prescan.h
+++ b/flang/lib/Parser/prescan.h
@@ -214,7 +214,7 @@ class Prescanner {
int prescannerNesting_{0};
int continuationLines_{0};
bool isPossibleMacroCall_{false};
- bool afterIncludeDirective_{false};
+ bool afterPreprocessingDirective_{false};
bool disableSourceContinuation_{false};
Provenance startProvenance_;
diff --git a/flang/test/Preprocessing/cond-contin.F90 b/flang/test/Preprocessing/cond-contin.F90
new file mode 100644
index 0000000000000..919ea5b127d60
--- /dev/null
+++ b/flang/test/Preprocessing/cond-contin.F90
@@ -0,0 +1,21 @@
+! RUN: %flang -fc1 -E %s 2>&1 | FileCheck %s
+! CHECK: subroutine test(ARG1,FA, FB,ARG2)
+! CHECK: end
+
+subroutine test( &
+ARG1, &
+! test
+#ifndef SWAP
+#define ARG1 FA
+#define ARG2 FB
+#else
+#define ARG1 FB
+#define ARG2 FA
+#endif
+ARG1, ARG2, &
+! test
+#undef ARG1
+#undef ARG2
+&ARG2)
+! comment
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/96244
More information about the flang-commits
mailing list