@@ -32,10 +32,11 @@ Prescanner::Prescanner(Messages &messages, CookedSource &cooked,
3232 backslashFreeFormContinuation_{preprocessor.AnyDefinitions ()},
3333 encoding_{allSources_.encoding ()} {}
3434
35- Prescanner::Prescanner (const Prescanner &that)
35+ Prescanner::Prescanner (const Prescanner &that, bool isNestedInIncludeDirective )
3636 : messages_{that.messages_ }, cooked_{that.cooked_ },
3737 preprocessor_{that.preprocessor_ }, allSources_{that.allSources_ },
3838 features_{that.features_ },
39+ isNestedInIncludeDirective_{isNestedInIncludeDirective},
3940 backslashFreeFormContinuation_{that.backslashFreeFormContinuation_ },
4041 inFixedForm_{that.inFixedForm_ },
4142 fixedFormColumnLimit_{that.fixedFormColumnLimit_ },
@@ -104,11 +105,14 @@ void Prescanner::Statement() {
104105 NextLine ();
105106 return ;
106107 case LineClassification::Kind::ConditionalCompilationDirective:
107- case LineClassification::Kind::IncludeDirective:
108108 case LineClassification::Kind::DefinitionDirective:
109109 case LineClassification::Kind::PreprocessorDirective:
110110 preprocessor_.Directive (TokenizePreprocessorDirective (), *this );
111111 return ;
112+ case LineClassification::Kind::IncludeDirective:
113+ preprocessor_.Directive (TokenizePreprocessorDirective (), *this );
114+ afterIncludeDirective_ = true ;
115+ return ;
112116 case LineClassification::Kind::CompilerDirective: {
113117 directiveSentinel_ = line.sentinel ;
114118 CHECK (InCompilerDirective ());
@@ -213,10 +217,7 @@ void Prescanner::Statement() {
213217 Say (preprocessed->GetProvenanceRange (),
214218 " Preprocessed line resembles a preprocessor directive" _warn_en_US);
215219 }
216- preprocessed->ToLowerCase ()
217- .CheckBadFortranCharacters (messages_, *this )
218- .CheckBadParentheses (messages_)
219- .Emit (cooked_);
220+ CheckAndEmitLine (preprocessed->ToLowerCase (), newlineProvenance);
220221 break ;
221222 case LineClassification::Kind::CompilerDirective:
222223 if (preprocessed->HasRedundantBlanks ()) {
@@ -228,10 +229,9 @@ void Prescanner::Statement() {
228229 NormalizeCompilerDirectiveCommentMarker (*preprocessed);
229230 preprocessed->ToLowerCase ();
230231 SourceFormChange (preprocessed->ToString ());
231- preprocessed->ClipComment (*this , true /* skip first ! */ )
232- .CheckBadFortranCharacters (messages_, *this )
233- .CheckBadParentheses (messages_)
234- .Emit (cooked_);
232+ CheckAndEmitLine (preprocessed->ToLowerCase ().ClipComment (
233+ *this , true /* skip first ! */ ),
234+ newlineProvenance);
235235 break ;
236236 case LineClassification::Kind::Source:
237237 if (inFixedForm_) {
@@ -246,14 +246,11 @@ void Prescanner::Statement() {
246246 preprocessed->RemoveRedundantBlanks ();
247247 }
248248 }
249- preprocessed->ToLowerCase ()
250- .ClipComment (*this )
251- .CheckBadFortranCharacters (messages_, *this )
252- .CheckBadParentheses (messages_)
253- .Emit (cooked_);
249+ CheckAndEmitLine (
250+ preprocessed->ToLowerCase ().ClipComment (*this ), newlineProvenance);
254251 break ;
255252 }
256- } else {
253+ } else { // no macro replacement
257254 if (line.kind == LineClassification::Kind::CompilerDirective) {
258255 while (CompilerDirectiveContinuation (tokens, line.sentinel )) {
259256 newlineProvenance = GetCurrentProvenance ();
@@ -266,16 +263,29 @@ void Prescanner::Statement() {
266263 EnforceStupidEndStatementRules (tokens);
267264 }
268265 }
269- tokens.CheckBadFortranCharacters (messages_, *this )
270- .CheckBadParentheses (messages_)
271- .Emit (cooked_);
266+ CheckAndEmitLine (tokens, newlineProvenance);
272267 }
268+ directiveSentinel_ = nullptr ;
269+ }
270+
271+ void Prescanner::CheckAndEmitLine (
272+ TokenSequence &tokens, Provenance newlineProvenance) {
273+ tokens.CheckBadFortranCharacters (messages_, *this );
274+ // Parenthesis nesting check does not apply while any #include is
275+ // active, nor on the lines before and after a top-level #include.
276+ // Applications play shenanigans with line continuation before and
277+ // after #include'd subprogram argument lists.
278+ if (!isNestedInIncludeDirective_ && !omitNewline_ &&
279+ !afterIncludeDirective_) {
280+ tokens.CheckBadParentheses (messages_);
281+ }
282+ tokens.Emit (cooked_);
273283 if (omitNewline_) {
274284 omitNewline_ = false ;
275285 } else {
276286 cooked_.Put (' \n ' , newlineProvenance);
287+ afterIncludeDirective_ = false ;
277288 }
278- directiveSentinel_ = nullptr ;
279289}
280290
281291TokenSequence Prescanner::TokenizePreprocessorDirective () {
@@ -985,7 +995,9 @@ void Prescanner::FortranInclude(const char *firstQuote) {
985995 provenance, static_cast <std::size_t >(p - nextLine_)};
986996 ProvenanceRange fileRange{
987997 allSources_.AddIncludedFile (*included, includeLineRange)};
988- Prescanner{*this }.set_encoding (included->encoding ()).Prescan (fileRange);
998+ Prescanner{*this , /* isNestedInIncludeDirective=*/ false }
999+ .set_encoding (included->encoding ())
1000+ .Prescan (fileRange);
9891001 }
9901002}
9911003
0 commit comments