Skip to content

Commit

Permalink
[flang] Warn on useless IOMSG= (llvm#102250)
Browse files Browse the repository at this point in the history
An I/O statement with IOMSG= but neither ERR= nor IOSTAT= deserves a
warning to the effect that it's not useful.
  • Loading branch information
klausler committed Aug 8, 2024
1 parent 245eb0a commit b949a6f
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 2 deletions.
3 changes: 2 additions & 1 deletion flang/include/flang/Common/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
IgnoredIntrinsicFunctionType, PreviousScalarUse,
RedeclaredInaccessibleComponent, ImplicitShared, IndexVarRedefinition,
IncompatibleImplicitInterfaces, BadTypeForTarget,
VectorSubscriptFinalization, UndefinedFunctionResult)
VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg)

using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
Expand Down Expand Up @@ -145,6 +145,7 @@ class LanguageFeatureControl {
warnUsage_.set(UsageWarning::BadTypeForTarget);
warnUsage_.set(UsageWarning::VectorSubscriptFinalization);
warnUsage_.set(UsageWarning::UndefinedFunctionResult);
warnUsage_.set(UsageWarning::UselessIomsg);
}
LanguageFeatureControl(const LanguageFeatureControl &) = default;

Expand Down
19 changes: 19 additions & 0 deletions flang/lib/Semantics/check-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,27 +675,31 @@ void IoChecker::Leave(const parser::BackspaceStmt &) {
CheckForPureSubprogram();
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
CheckForUselessIomsg();
Done();
}

void IoChecker::Leave(const parser::CloseStmt &) {
CheckForPureSubprogram();
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1208
CheckForUselessIomsg();
Done();
}

void IoChecker::Leave(const parser::EndfileStmt &) {
CheckForPureSubprogram();
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
CheckForUselessIomsg();
Done();
}

void IoChecker::Leave(const parser::FlushStmt &) {
CheckForPureSubprogram();
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1243
CheckForUselessIomsg();
Done();
}

Expand All @@ -708,6 +712,7 @@ void IoChecker::Leave(const parser::InquireStmt &stmt) {
"UNIT number or FILE"); // C1246
CheckForProhibitedSpecifier(IoSpecKind::File, IoSpecKind::Unit); // C1246
CheckForRequiredSpecifier(IoSpecKind::Id, IoSpecKind::Pending); // C1248
CheckForUselessIomsg();
}
Done();
}
Expand Down Expand Up @@ -742,11 +747,13 @@ void IoChecker::Leave(const parser::OpenStmt &) {
CheckForProhibitedSpecifier(flags_.test(Flag::AccessStream),
"STATUS='STREAM'", IoSpecKind::Recl); // 12.5.6.15
}
CheckForUselessIomsg();
Done();
}

void IoChecker::Leave(const parser::PrintStmt &) {
CheckForPureSubprogram();
CheckForUselessIomsg();
Done();
}

Expand Down Expand Up @@ -817,13 +824,15 @@ void IoChecker::Leave(const parser::RewindStmt &) {
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1240
CheckForPureSubprogram();
CheckForUselessIomsg();
Done();
}

void IoChecker::Leave(const parser::WaitStmt &) {
CheckForRequiredSpecifier(
flags_.test(Flag::NumberUnit), "UNIT number"); // C1237
CheckForPureSubprogram();
CheckForUselessIomsg();
Done();
}

Expand Down Expand Up @@ -883,6 +892,7 @@ void IoChecker::LeaveReadWrite() const {
"FMT or NML"); // C1227
CheckForRequiredSpecifier(IoSpecKind::Round, flags_.test(Flag::FmtOrNml),
"FMT or NML"); // C1227
CheckForUselessIomsg();
}

void IoChecker::SetSpecifier(IoSpecKind specKind) {
Expand Down Expand Up @@ -1057,6 +1067,15 @@ void IoChecker::CheckForPureSubprogram() const { // C1597
}
}

void IoChecker::CheckForUselessIomsg() const {
if (specifierSet_.test(IoSpecKind::Iomsg) &&
!specifierSet_.test(IoSpecKind::Err) &&
!specifierSet_.test(IoSpecKind::Iostat) &&
context_.ShouldWarn(common::UsageWarning::UselessIomsg)) {
context_.Say("IOMSG= is useless without either ERR= or IOSTAT="_warn_en_US);
}
}

// Seeks out an allocatable or pointer ultimate component that is not
// nested in a nonallocatable/nonpointer component with a specific
// defined I/O procedure.
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Semantics/check-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class IoChecker : public virtual BaseChecker {
void CheckForDefinableVariable(const A &var, const std::string &s) const;

void CheckForPureSubprogram() const;
void CheckForUselessIomsg() const;

parser::Message *CheckForBadIoType(const evaluate::DynamicType &,
common::DefinedIo, parser::CharBlock) const;
Expand Down
5 changes: 4 additions & 1 deletion flang/lib/Semantics/semantics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,13 @@ static bool PerformStatementSemantics(
if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
SemanticsVisitor<CUDAChecker>{context}.Walk(program);
}
if (!context.AnyFatalError()) {
if (!context.messages().AnyFatalError()) {
// Do this if all messages are only warnings
if (context.ShouldWarn(common::UsageWarning::UndefinedFunctionResult)) {
WarnUndefinedFunctionResult(context, context.globalScope());
}
}
if (!context.AnyFatalError()) {
pass2.CompileDataInitializationsIntoInitializers();
}
return !context.AnyFatalError();
Expand Down
1 change: 1 addition & 0 deletions flang/test/Semantics/io05.f90
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
inquire(1, read=c(1), write=c(2), sign=c(3), sign=c(4), read=c(5), write=c(1))

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

!ERROR: If ID appears, PENDING must also appear
Expand Down
1 change: 1 addition & 0 deletions flang/test/Semantics/undef-result01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ integer function defdBySize()
end

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

Expand Down

0 comments on commit b949a6f

Please sign in to comment.