@@ -346,17 +346,11 @@ class ParseTreeAnalyzer {
346
346
const auto &firstStmt{std::get<parser::Statement<FIRST>>(a.t )};
347
347
if (const parser::CharBlock * firstName{GetStmtName (firstStmt)}) {
348
348
if (*firstName != *name) {
349
- context_
350
- .Say (*name,
351
- parser::MessageFormattedText{
352
- " %s name mismatch" _err_en_US, constructTag})
349
+ context_.Say (*name, " %s name mismatch" _err_en_US, constructTag)
353
350
.Attach (*firstName, " should be" _en_US);
354
351
}
355
352
} else {
356
- context_
357
- .Say (*name,
358
- parser::MessageFormattedText{
359
- " %s name not allowed" _err_en_US, constructTag})
353
+ context_.Say (*name, " %s name not allowed" _err_en_US, constructTag)
360
354
.Attach (firstStmt.source , " in unnamed %s" _en_US, constructTag);
361
355
}
362
356
}
@@ -383,32 +377,51 @@ class ParseTreeAnalyzer {
383
377
384
378
// C1502
385
379
void Post (const parser::InterfaceBlock &interfaceBlock) {
386
- auto &interfaceStmt{
387
- std::get<parser::Statement<parser::InterfaceStmt>>(interfaceBlock.t )};
388
- if (const auto *optionalGenericSpecPointer{
389
- std::get_if<std::optional<parser::GenericSpec>>(
390
- &interfaceStmt.statement .u )}) {
391
- if (*optionalGenericSpecPointer) {
392
- if (const auto *namePointer{
393
- std::get_if<parser::Name>(&(*optionalGenericSpecPointer)->u )}) {
394
- auto &optionalGenericSpec{
395
- std::get<parser::Statement<parser::EndInterfaceStmt>>(
396
- interfaceBlock.t )
397
- .statement .v };
398
- if (optionalGenericSpec) {
399
- if (const auto *otherPointer{
400
- std::get_if<parser::Name>(&optionalGenericSpec->u )}) {
401
- if (namePointer->source != otherPointer->source ) {
402
- context_
403
- .Say (currentPosition_,
404
- parser::MessageFormattedText{
405
- " INTERFACE generic-name (%s) mismatch" _err_en_US,
406
- namePointer->source })
407
- .Attach (interfaceStmt.source , " mismatched INTERFACE" _en_US);
408
- }
409
- }
380
+ if (const auto &endGenericSpec{
381
+ std::get<parser::Statement<parser::EndInterfaceStmt>>(
382
+ interfaceBlock.t )
383
+ .statement .v }) {
384
+ const auto &interfaceStmt{
385
+ std::get<parser::Statement<parser::InterfaceStmt>>(interfaceBlock.t )};
386
+ if (std::holds_alternative<parser::Abstract>(interfaceStmt.statement .u )) {
387
+ context_
388
+ .Say (endGenericSpec->source ,
389
+ " END INTERFACE generic name (%s) may not appear for ABSTRACT INTERFACE" _err_en_US,
390
+ endGenericSpec->source )
391
+ .Attach (
392
+ interfaceStmt.source , " corresponding ABSTRACT INTERFACE" _en_US);
393
+ } else if (const auto &genericSpec{
394
+ std::get<std::optional<parser::GenericSpec>>(
395
+ interfaceStmt.statement .u )}) {
396
+ bool ok{genericSpec->source == endGenericSpec->source };
397
+ if (!ok) {
398
+ // Accept variant spellings of .LT. &c.
399
+ const auto *endOp{
400
+ std::get_if<parser::DefinedOperator>(&endGenericSpec->u )};
401
+ const auto *op{std::get_if<parser::DefinedOperator>(&genericSpec->u )};
402
+ if (endOp && op) {
403
+ const auto *endIntrin{
404
+ std::get_if<parser::DefinedOperator::IntrinsicOperator>(
405
+ &endOp->u )};
406
+ const auto *intrin{
407
+ std::get_if<parser::DefinedOperator::IntrinsicOperator>(
408
+ &op->u )};
409
+ ok = endIntrin && intrin && *endIntrin == *intrin;
410
410
}
411
411
}
412
+ if (!ok) {
413
+ context_
414
+ .Say (endGenericSpec->source ,
415
+ " END INTERFACE generic name (%s) does not match generic INTERFACE (%s)" _err_en_US,
416
+ endGenericSpec->source , genericSpec->source )
417
+ .Attach (genericSpec->source , " corresponding INTERFACE" _en_US);
418
+ }
419
+ } else {
420
+ context_
421
+ .Say (endGenericSpec->source ,
422
+ " END INTERFACE generic name (%s) may not appear for non-generic INTERFACE" _err_en_US,
423
+ endGenericSpec->source )
424
+ .Attach (interfaceStmt.source , " corresponding INTERFACE" _en_US);
412
425
}
413
426
}
414
427
}
@@ -441,8 +454,7 @@ class ParseTreeAnalyzer {
441
454
}
442
455
} else {
443
456
context_.Say (*endName,
444
- parser::MessageFormattedText{
445
- " END PROGRAM has name without PROGRAM statement" _err_en_US});
457
+ " END PROGRAM has name without PROGRAM statement" _err_en_US);
446
458
}
447
459
}
448
460
}
@@ -640,24 +652,20 @@ class ParseTreeAnalyzer {
640
652
if (endName) {
641
653
if (*constructName != *endName) {
642
654
context_
643
- .Say (*endName,
644
- parser::MessageFormattedText{
645
- " %s construct name mismatch" _err_en_US, constructTag})
655
+ .Say (*endName, " %s construct name mismatch" _err_en_US,
656
+ constructTag)
646
657
.Attach (*constructName, " should be" _en_US);
647
658
}
648
659
} else {
649
660
context_
650
661
.Say (endStmt.source ,
651
- parser::MessageFormattedText{
652
- " %s construct name required but missing" _err_en_US,
653
- constructTag})
662
+ " %s construct name required but missing" _err_en_US,
663
+ constructTag)
654
664
.Attach (*constructName, " should be" _en_US);
655
665
}
656
666
} else if (endName) {
657
667
context_
658
- .Say (*endName,
659
- parser::MessageFormattedText{
660
- " %s construct name unexpected" _err_en_US, constructTag})
668
+ .Say (*endName, " %s construct name unexpected" _err_en_US, constructTag)
661
669
.Attach (
662
670
constructStmt.source , " unnamed %s statement" _en_US, constructTag);
663
671
}
@@ -737,18 +745,16 @@ class ParseTreeAnalyzer {
737
745
const auto iter{std::find (constructNames_.crbegin (),
738
746
constructNames_.crend (), constructName.ToString ())};
739
747
if (iter == constructNames_.crend ()) {
740
- context_.Say (constructName,
741
- parser::MessageFormattedText{
742
- " %s construct-name is not in scope" _err_en_US, stmtString});
748
+ context_.Say (constructName, " %s construct-name is not in scope" _err_en_US,
749
+ stmtString);
743
750
}
744
751
}
745
752
746
753
// 6.2.5, paragraph 2
747
754
void CheckLabelInRange (parser::Label label) {
748
755
if (label < 1 || label > 99999 ) {
749
- context_.Say (currentPosition_,
750
- parser::MessageFormattedText{
751
- " Label '%u' is out of range" _err_en_US, SayLabel (label)});
756
+ context_.Say (currentPosition_, " Label '%u' is out of range" _err_en_US,
757
+ SayLabel (label));
752
758
}
753
759
}
754
760
@@ -761,9 +767,8 @@ class ParseTreeAnalyzer {
761
767
LabeledStatementInfoTuplePOD{scope, currentPosition_,
762
768
labeledStmtClassificationSet, isExecutableConstructEndStmt})};
763
769
if (!pair.second ) {
764
- context_.Say (currentPosition_,
765
- parser::MessageFormattedText{
766
- " Label '%u' is not distinct" _err_en_US, SayLabel (label)});
770
+ context_.Say (currentPosition_, " Label '%u' is not distinct" _err_en_US,
771
+ SayLabel (label));
767
772
}
768
773
}
769
774
@@ -799,7 +804,7 @@ class ParseTreeAnalyzer {
799
804
800
805
std::vector<UnitAnalysis> programUnits_;
801
806
SemanticsContext &context_;
802
- parser::CharBlock currentPosition_{ nullptr } ;
807
+ parser::CharBlock currentPosition_;
803
808
ProxyForScope currentScope_;
804
809
std::vector<std::string> constructNames_;
805
810
};
@@ -904,15 +909,13 @@ void CheckLabelDoConstraints(const SourceStmtList &dos,
904
909
auto doTarget{GetLabel (labels, label)};
905
910
if (!HasScope (doTarget.proxyForScope )) {
906
911
// C1133
907
- context.Say (position,
908
- parser::MessageFormattedText{
909
- " Label '%u' cannot be found" _err_en_US, SayLabel (label)});
912
+ context.Say (
913
+ position, " Label '%u' cannot be found" _err_en_US, SayLabel (label));
910
914
} else if (doTarget.parserCharBlock .begin () < position.begin ()) {
911
915
// R1119
912
916
context.Say (position,
913
- parser::MessageFormattedText{
914
- " Label '%u' doesn't lexically follow DO stmt" _err_en_US,
915
- SayLabel (label)});
917
+ " Label '%u' doesn't lexically follow DO stmt" _err_en_US,
918
+ SayLabel (label));
916
919
917
920
} else if ((InInclusiveScope (scopes, scope, doTarget.proxyForScope ) &&
918
921
doTarget.labeledStmtClassificationSet .test (
@@ -924,20 +927,17 @@ void CheckLabelDoConstraints(const SourceStmtList &dos,
924
927
common::LanguageFeature::OldLabelDoEndStatements)) {
925
928
context
926
929
.Say (position,
927
- parser::MessageFormattedText{
928
- " A DO loop should terminate with an END DO or CONTINUE" _en_US})
930
+ " A DO loop should terminate with an END DO or CONTINUE" _en_US)
929
931
.Attach (doTarget.parserCharBlock ,
930
932
" DO loop currently ends at statement:" _en_US);
931
933
}
932
934
} else if (!InInclusiveScope (scopes, scope, doTarget.proxyForScope )) {
933
- context.Say (position,
934
- parser::MessageFormattedText{
935
- " Label '%u' is not in DO loop scope" _err_en_US, SayLabel (label)});
935
+ context.Say (position, " Label '%u' is not in DO loop scope" _err_en_US,
936
+ SayLabel (label));
936
937
} else if (!doTarget.labeledStmtClassificationSet .test (
937
938
TargetStatementEnum::Do)) {
938
939
context.Say (doTarget.parserCharBlock ,
939
- parser::MessageFormattedText{
940
- " A DO loop should terminate with an END DO or CONTINUE" _err_en_US});
940
+ " A DO loop should terminate with an END DO or CONTINUE" _err_en_US);
941
941
} else {
942
942
loopBodies.emplace_back (SkipLabel (position), doTarget.parserCharBlock );
943
943
}
@@ -957,19 +957,17 @@ void CheckScopeConstraints(const SourceStmtList &stmts,
957
957
const auto &position{stmt.parserCharBlock };
958
958
auto target{GetLabel (labels, label)};
959
959
if (!HasScope (target.proxyForScope )) {
960
- context.Say (position,
961
- parser::MessageFormattedText{
962
- " Label '%u' was not found" _err_en_US, SayLabel (label)});
960
+ context.Say (
961
+ position, " Label '%u' was not found" _err_en_US, SayLabel (label));
963
962
} else if (!InInclusiveScope (scopes, scope, target.proxyForScope )) {
964
963
// Clause 11.1.2.1 prohibits transfer of control to the interior of a
965
964
// block from outside the block, but this does not apply to formats.
966
965
if (target.labeledStmtClassificationSet .test (
967
966
TargetStatementEnum::Format)) {
968
967
continue ;
969
968
}
970
- context.Say (position,
971
- parser::MessageFormattedText{
972
- " Label '%u' is not in scope" _en_US, SayLabel (label)});
969
+ context.Say (
970
+ position, " Label '%u' is not in scope" _en_US, SayLabel (label));
973
971
}
974
972
}
975
973
}
@@ -986,21 +984,16 @@ void CheckBranchTargetConstraints(const SourceStmtList &stmts,
986
984
TargetStatementEnum::CompatibleBranch)) { // error
987
985
context
988
986
.Say (branchTarget.parserCharBlock ,
989
- parser::MessageFormattedText{
990
- " Label '%u' is not a branch target" _err_en_US,
991
- SayLabel (label)})
992
- .Attach (stmt.parserCharBlock ,
993
- parser::MessageFormattedText{
994
- " Control flow use of '%u'" _en_US, SayLabel (label)});
987
+ " Label '%u' is not a branch target" _err_en_US, SayLabel (label))
988
+ .Attach (stmt.parserCharBlock , " Control flow use of '%u'" _en_US,
989
+ SayLabel (label));
995
990
} else if (!branchTarget.labeledStmtClassificationSet .test (
996
991
TargetStatementEnum::Branch)) { // warning
997
992
context
998
993
.Say (branchTarget.parserCharBlock ,
999
- parser::MessageFormattedText{
1000
- " Label '%u' is not a branch target" _en_US, SayLabel (label)})
1001
- .Attach (stmt.parserCharBlock ,
1002
- parser::MessageFormattedText{
1003
- " Control flow use of '%u'" _en_US, SayLabel (label)});
994
+ " Label '%u' is not a branch target" _en_US, SayLabel (label))
995
+ .Attach (stmt.parserCharBlock , " Control flow use of '%u'" _en_US,
996
+ SayLabel (label));
1004
997
}
1005
998
}
1006
999
}
@@ -1022,12 +1015,10 @@ void CheckDataXferTargetConstraints(const SourceStmtList &stmts,
1022
1015
if (!ioTarget.labeledStmtClassificationSet .test (
1023
1016
TargetStatementEnum::Format)) {
1024
1017
context
1025
- .Say (ioTarget.parserCharBlock ,
1026
- parser::MessageFormattedText{
1027
- " '%u' not a FORMAT" _err_en_US, SayLabel (label)})
1028
- .Attach (stmt.parserCharBlock ,
1029
- parser::MessageFormattedText{
1030
- " data transfer use of '%u'" _en_US, SayLabel (label)});
1018
+ .Say (ioTarget.parserCharBlock , " '%u' not a FORMAT" _err_en_US,
1019
+ SayLabel (label))
1020
+ .Attach (stmt.parserCharBlock , " data transfer use of '%u'" _en_US,
1021
+ SayLabel (label));
1031
1022
}
1032
1023
}
1033
1024
}
0 commit comments