Skip to content

Commit b949a6f

Browse files
authored
[flang] Warn on useless IOMSG= (#102250)
An I/O statement with IOMSG= but neither ERR= nor IOSTAT= deserves a warning to the effect that it's not useful.
1 parent 245eb0a commit b949a6f

File tree

6 files changed

+28
-2
lines changed

6 files changed

+28
-2
lines changed

flang/include/flang/Common/Fortran-features.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
7070
IgnoredIntrinsicFunctionType, PreviousScalarUse,
7171
RedeclaredInaccessibleComponent, ImplicitShared, IndexVarRedefinition,
7272
IncompatibleImplicitInterfaces, BadTypeForTarget,
73-
VectorSubscriptFinalization, UndefinedFunctionResult)
73+
VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg)
7474

7575
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
7676
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
@@ -145,6 +145,7 @@ class LanguageFeatureControl {
145145
warnUsage_.set(UsageWarning::BadTypeForTarget);
146146
warnUsage_.set(UsageWarning::VectorSubscriptFinalization);
147147
warnUsage_.set(UsageWarning::UndefinedFunctionResult);
148+
warnUsage_.set(UsageWarning::UselessIomsg);
148149
}
149150
LanguageFeatureControl(const LanguageFeatureControl &) = default;
150151

flang/lib/Semantics/check-io.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,27 +675,31 @@ void IoChecker::Leave(const parser::BackspaceStmt &) {
675675
CheckForPureSubprogram();
676676
CheckForRequiredSpecifier(
677677
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
678+
CheckForUselessIomsg();
678679
Done();
679680
}
680681

681682
void IoChecker::Leave(const parser::CloseStmt &) {
682683
CheckForPureSubprogram();
683684
CheckForRequiredSpecifier(
684685
flags_.test(Flag::NumberUnit), "UNIT number"); // C1208
686+
CheckForUselessIomsg();
685687
Done();
686688
}
687689

688690
void IoChecker::Leave(const parser::EndfileStmt &) {
689691
CheckForPureSubprogram();
690692
CheckForRequiredSpecifier(
691693
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
694+
CheckForUselessIomsg();
692695
Done();
693696
}
694697

695698
void IoChecker::Leave(const parser::FlushStmt &) {
696699
CheckForPureSubprogram();
697700
CheckForRequiredSpecifier(
698701
flags_.test(Flag::NumberUnit), "UNIT number"); // C1243
702+
CheckForUselessIomsg();
699703
Done();
700704
}
701705

@@ -708,6 +712,7 @@ void IoChecker::Leave(const parser::InquireStmt &stmt) {
708712
"UNIT number or FILE"); // C1246
709713
CheckForProhibitedSpecifier(IoSpecKind::File, IoSpecKind::Unit); // C1246
710714
CheckForRequiredSpecifier(IoSpecKind::Id, IoSpecKind::Pending); // C1248
715+
CheckForUselessIomsg();
711716
}
712717
Done();
713718
}
@@ -742,11 +747,13 @@ void IoChecker::Leave(const parser::OpenStmt &) {
742747
CheckForProhibitedSpecifier(flags_.test(Flag::AccessStream),
743748
"STATUS='STREAM'", IoSpecKind::Recl); // 12.5.6.15
744749
}
750+
CheckForUselessIomsg();
745751
Done();
746752
}
747753

748754
void IoChecker::Leave(const parser::PrintStmt &) {
749755
CheckForPureSubprogram();
756+
CheckForUselessIomsg();
750757
Done();
751758
}
752759

@@ -817,13 +824,15 @@ void IoChecker::Leave(const parser::RewindStmt &) {
817824
CheckForRequiredSpecifier(
818825
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
819826
CheckForPureSubprogram();
827+
CheckForUselessIomsg();
820828
Done();
821829
}
822830

823831
void IoChecker::Leave(const parser::WaitStmt &) {
824832
CheckForRequiredSpecifier(
825833
flags_.test(Flag::NumberUnit), "UNIT number"); // C1237
826834
CheckForPureSubprogram();
835+
CheckForUselessIomsg();
827836
Done();
828837
}
829838

@@ -883,6 +892,7 @@ void IoChecker::LeaveReadWrite() const {
883892
"FMT or NML"); // C1227
884893
CheckForRequiredSpecifier(IoSpecKind::Round, flags_.test(Flag::FmtOrNml),
885894
"FMT or NML"); // C1227
895+
CheckForUselessIomsg();
886896
}
887897

888898
void IoChecker::SetSpecifier(IoSpecKind specKind) {
@@ -1057,6 +1067,15 @@ void IoChecker::CheckForPureSubprogram() const { // C1597
10571067
}
10581068
}
10591069

1070+
void IoChecker::CheckForUselessIomsg() const {
1071+
if (specifierSet_.test(IoSpecKind::Iomsg) &&
1072+
!specifierSet_.test(IoSpecKind::Err) &&
1073+
!specifierSet_.test(IoSpecKind::Iostat) &&
1074+
context_.ShouldWarn(common::UsageWarning::UselessIomsg)) {
1075+
context_.Say("IOMSG= is useless without either ERR= or IOSTAT="_warn_en_US);
1076+
}
1077+
}
1078+
10601079
// Seeks out an allocatable or pointer ultimate component that is not
10611080
// nested in a nonallocatable/nonpointer component with a specific
10621081
// defined I/O procedure.

flang/lib/Semantics/check-io.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class IoChecker : public virtual BaseChecker {
125125
void CheckForDefinableVariable(const A &var, const std::string &s) const;
126126

127127
void CheckForPureSubprogram() const;
128+
void CheckForUselessIomsg() const;
128129

129130
parser::Message *CheckForBadIoType(const evaluate::DynamicType &,
130131
common::DefinedIo, parser::CharBlock) const;

flang/lib/Semantics/semantics.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,13 @@ static bool PerformStatementSemantics(
221221
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
222222
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
223223
}
224-
if (!context.AnyFatalError()) {
224+
if (!context.messages().AnyFatalError()) {
225+
// Do this if all messages are only warnings
225226
if (context.ShouldWarn(common::UsageWarning::UndefinedFunctionResult)) {
226227
WarnUndefinedFunctionResult(context, context.globalScope());
227228
}
229+
}
230+
if (!context.AnyFatalError()) {
228231
pass2.CompileDataInitializationsIntoInitializers();
229232
}
230233
return !context.AnyFatalError();

flang/test/Semantics/io05.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
inquire(1, read=c(1), write=c(2), sign=c(3), sign=c(4), read=c(5), write=c(1))
5656

5757
!ERROR: Duplicate IOMSG specifier
58+
!WARNING: IOMSG= is useless without either ERR= or IOSTAT=
5859
inquire(10, iomsg=msg, pos=ipos, iomsg=msg)
5960

6061
!ERROR: If ID appears, PENDING must also appear

flang/test/Semantics/undef-result01.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ integer function defdBySize()
121121
end
122122

123123
character(40) function defdByIomsg()
124+
!WARNING: IOMSG= is useless without either ERR= or IOSTAT=
124125
write(123,*,iomsg=defdByIomsg)
125126
end
126127

0 commit comments

Comments
 (0)