@@ -180,6 +180,24 @@ void Prescanner::Statement() {
180
180
}
181
181
} else {
182
182
SkipSpaces ();
183
+ // Check for a leading identifier that might be a keyword macro
184
+ // that will expand to anything indicating a non-source line, like
185
+ // a comment marker or directive sentinel. If so, disable line
186
+ // continuation, so that NextToken() won't consume anything from
187
+ // following lines.
188
+ if (IsLegalIdentifierStart (*at_)) {
189
+ CHECK (NextToken (tokens));
190
+ CHECK (tokens.SizeInTokens () == 1 );
191
+ CharBlock id{tokens.TokenAt (0 )};
192
+ if (preprocessor_.IsNameDefined (id) &&
193
+ !preprocessor_.IsFunctionLikeDefinition (id)) {
194
+ if (auto replaced{preprocessor_.MacroReplacement (tokens, *this )}) {
195
+ disableSourceContinuation_ =
196
+ ClassifyLine (*replaced, GetCurrentProvenance ()).kind !=
197
+ LineClassification::Kind::Source;
198
+ }
199
+ }
200
+ }
183
201
}
184
202
break ;
185
203
}
@@ -197,17 +215,13 @@ void Prescanner::Statement() {
197
215
Provenance newlineProvenance{GetCurrentProvenance ()};
198
216
if (std::optional<TokenSequence> preprocessed{
199
217
preprocessor_.MacroReplacement (tokens, *this )}) {
200
- // Reprocess the preprocessed line. Append a newline temporarily.
201
- preprocessed->PutNextTokenChar (' \n ' , newlineProvenance);
202
- preprocessed->CloseToken ();
203
- const char *ppd{preprocessed->ToCharBlock ().begin ()};
204
- LineClassification ppl{ClassifyLine (ppd)};
205
- preprocessed->pop_back (); // remove the newline
218
+ // Reprocess the preprocessed line.
219
+ LineClassification ppl{ClassifyLine (*preprocessed, newlineProvenance)};
206
220
switch (ppl.kind ) {
207
221
case LineClassification::Kind::Comment:
208
222
break ;
209
223
case LineClassification::Kind::IncludeLine:
210
- FortranInclude (ppd + ppl.payloadOffset );
224
+ FortranInclude (preprocessed-> TokenAt ( 0 ). begin () + ppl.payloadOffset );
211
225
break ;
212
226
case LineClassification::Kind::ConditionalCompilationDirective:
213
227
case LineClassification::Kind::IncludeDirective:
@@ -270,7 +284,8 @@ void Prescanner::Statement() {
270
284
271
285
void Prescanner::CheckAndEmitLine (
272
286
TokenSequence &tokens, Provenance newlineProvenance) {
273
- tokens.CheckBadFortranCharacters (messages_, *this );
287
+ tokens.CheckBadFortranCharacters (
288
+ messages_, *this , disableSourceContinuation_);
274
289
// Parenthesis nesting check does not apply while any #include is
275
290
// active, nor on the lines before and after a top-level #include.
276
291
// Applications play shenanigans with line continuation before and
@@ -1243,7 +1258,9 @@ bool Prescanner::IsImplicitContinuation() const {
1243
1258
}
1244
1259
1245
1260
bool Prescanner::Continuation (bool mightNeedFixedFormSpace) {
1246
- if (*at_ == ' \n ' || *at_ == ' &' ) {
1261
+ if (disableSourceContinuation_) {
1262
+ return false ;
1263
+ } else if (*at_ == ' \n ' || *at_ == ' &' ) {
1247
1264
if (inFixedForm_) {
1248
1265
return FixedFormContinuation (mightNeedFixedFormSpace);
1249
1266
} else {
@@ -1255,8 +1272,9 @@ bool Prescanner::Continuation(bool mightNeedFixedFormSpace) {
1255
1272
BeginSourceLine (nextLine_);
1256
1273
NextLine ();
1257
1274
return true ;
1275
+ } else {
1276
+ return false ;
1258
1277
}
1259
- return false ;
1260
1278
}
1261
1279
1262
1280
std::optional<Prescanner::LineClassification>
@@ -1418,6 +1436,17 @@ Prescanner::LineClassification Prescanner::ClassifyLine(
1418
1436
return {LineClassification::Kind::Source};
1419
1437
}
1420
1438
1439
+ Prescanner::LineClassification Prescanner::ClassifyLine (
1440
+ TokenSequence &tokens, Provenance newlineProvenance) const {
1441
+ // Append a newline temporarily.
1442
+ tokens.PutNextTokenChar (' \n ' , newlineProvenance);
1443
+ tokens.CloseToken ();
1444
+ const char *ppd{tokens.ToCharBlock ().begin ()};
1445
+ LineClassification classification{ClassifyLine (ppd)};
1446
+ tokens.pop_back (); // remove the newline
1447
+ return classification;
1448
+ }
1449
+
1421
1450
void Prescanner::SourceFormChange (std::string &&dir) {
1422
1451
if (dir == " !dir$ free" ) {
1423
1452
inFixedForm_ = false ;
0 commit comments