From b949a6f5e3219290ce090895e284d12fc76f9d61 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:08:26 -0700 Subject: [PATCH] [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. --- flang/include/flang/Common/Fortran-features.h | 3 ++- flang/lib/Semantics/check-io.cpp | 19 +++++++++++++++++++ flang/lib/Semantics/check-io.h | 1 + flang/lib/Semantics/semantics.cpp | 5 ++++- flang/test/Semantics/io05.f90 | 1 + flang/test/Semantics/undef-result01.f90 | 1 + 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h index 518304191d63f7..6ef5f44c89db07 100644 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -70,7 +70,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable, IgnoredIntrinsicFunctionType, PreviousScalarUse, RedeclaredInaccessibleComponent, ImplicitShared, IndexVarRedefinition, IncompatibleImplicitInterfaces, BadTypeForTarget, - VectorSubscriptFinalization, UndefinedFunctionResult) + VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg) using LanguageFeatures = EnumSet; using UsageWarnings = EnumSet; @@ -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; diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp index 8bde737c4cb948..54e8e09cbf7e48 100644 --- a/flang/lib/Semantics/check-io.cpp +++ b/flang/lib/Semantics/check-io.cpp @@ -675,6 +675,7 @@ void IoChecker::Leave(const parser::BackspaceStmt &) { CheckForPureSubprogram(); CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1240 + CheckForUselessIomsg(); Done(); } @@ -682,6 +683,7 @@ void IoChecker::Leave(const parser::CloseStmt &) { CheckForPureSubprogram(); CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1208 + CheckForUselessIomsg(); Done(); } @@ -689,6 +691,7 @@ void IoChecker::Leave(const parser::EndfileStmt &) { CheckForPureSubprogram(); CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1240 + CheckForUselessIomsg(); Done(); } @@ -696,6 +699,7 @@ void IoChecker::Leave(const parser::FlushStmt &) { CheckForPureSubprogram(); CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1243 + CheckForUselessIomsg(); Done(); } @@ -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(); } @@ -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(); } @@ -817,6 +824,7 @@ void IoChecker::Leave(const parser::RewindStmt &) { CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1240 CheckForPureSubprogram(); + CheckForUselessIomsg(); Done(); } @@ -824,6 +832,7 @@ void IoChecker::Leave(const parser::WaitStmt &) { CheckForRequiredSpecifier( flags_.test(Flag::NumberUnit), "UNIT number"); // C1237 CheckForPureSubprogram(); + CheckForUselessIomsg(); Done(); } @@ -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) { @@ -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. diff --git a/flang/lib/Semantics/check-io.h b/flang/lib/Semantics/check-io.h index 0ef166f7f100ed..2fb03c63afe353 100644 --- a/flang/lib/Semantics/check-io.h +++ b/flang/lib/Semantics/check-io.h @@ -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; diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp index 3cb24f6c6af437..f7a277d1b414f6 100644 --- a/flang/lib/Semantics/semantics.cpp +++ b/flang/lib/Semantics/semantics.cpp @@ -221,10 +221,13 @@ static bool PerformStatementSemantics( if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) { SemanticsVisitor{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(); diff --git a/flang/test/Semantics/io05.f90 b/flang/test/Semantics/io05.f90 index 8480ea4b784c29..bef0d6db89524a 100644 --- a/flang/test/Semantics/io05.f90 +++ b/flang/test/Semantics/io05.f90 @@ -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 diff --git a/flang/test/Semantics/undef-result01.f90 b/flang/test/Semantics/undef-result01.f90 index a372fcd544feea..dd73f9c76df0a5 100644 --- a/flang/test/Semantics/undef-result01.f90 +++ b/flang/test/Semantics/undef-result01.f90 @@ -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