diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /flang/lib/Semantics/check-call.cpp | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'flang/lib/Semantics/check-call.cpp')
| -rw-r--r-- | flang/lib/Semantics/check-call.cpp | 217 |
1 files changed, 99 insertions, 118 deletions
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 83f59f0cac3d..f0078fda3600 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -67,7 +67,7 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg, "Null pointer argument requires an explicit interface"_err_en_US); } else if (auto named{evaluate::ExtractNamedEntity(*expr)}) { const Symbol &symbol{named->GetLastSymbol()}; - if (evaluate::IsAssumedRank(symbol)) { + if (IsAssumedRank(symbol)) { messages.Say( "Assumed rank argument requires an explicit interface"_err_en_US); } @@ -131,7 +131,7 @@ static void CheckCharacterActual(evaluate::Expr<evaluate::SomeType> &actual, dummy.type.type().kind() == actualType.type().kind() && !dummy.attrs.test( characteristics::DummyDataObject::Attr::DeducedFromActual)) { - bool actualIsAssumedRank{evaluate::IsAssumedRank(actual)}; + bool actualIsAssumedRank{IsAssumedRank(actual)}; if (actualIsAssumedRank && !dummy.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedRank)) { @@ -140,7 +140,8 @@ static void CheckCharacterActual(evaluate::Expr<evaluate::SomeType> &actual, messages.Say( "Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank"_err_en_US); } else { - context.Warn(common::LanguageFeature::AssumedRankPassedToNonAssumedRank, + context.Warn(messages, + common::LanguageFeature::AssumedRankPassedToNonAssumedRank, messages.at(), "Assumed-rank character array should not be associated with a dummy argument that is not assumed-rank"_port_en_US); } @@ -187,9 +188,9 @@ static void CheckCharacterActual(evaluate::Expr<evaluate::SomeType> &actual, "Actual argument has fewer characters remaining in storage sequence (%jd) than %s (%jd)"_err_en_US, static_cast<std::intmax_t>(actualChars), dummyName, static_cast<std::intmax_t>(dummyChars)); - } else if (context.ShouldWarn( - common::UsageWarning::ShortCharacterActual)) { - messages.Say(common::UsageWarning::ShortCharacterActual, + } else { + context.Warn(messages, + common::UsageWarning::ShortCharacterActual, "Actual argument has fewer characters remaining in storage sequence (%jd) than %s (%jd)"_warn_en_US, static_cast<std::intmax_t>(actualChars), dummyName, static_cast<std::intmax_t>(dummyChars)); @@ -207,9 +208,9 @@ static void CheckCharacterActual(evaluate::Expr<evaluate::SomeType> &actual, static_cast<std::intmax_t>(*actualSize * *actualLength), dummyName, static_cast<std::intmax_t>(*dummySize * *dummyLength)); - } else if (context.ShouldWarn( - common::UsageWarning::ShortCharacterActual)) { - messages.Say(common::UsageWarning::ShortCharacterActual, + } else { + context.Warn(messages, + common::UsageWarning::ShortCharacterActual, "Actual argument array has fewer characters (%jd) than %s array (%jd)"_warn_en_US, static_cast<std::intmax_t>(*actualSize * *actualLength), dummyName, @@ -229,17 +230,14 @@ static void CheckCharacterActual(evaluate::Expr<evaluate::SomeType> &actual, } else if (*actualLength < *dummyLength) { CHECK(dummy.type.Rank() == 0); bool isVariable{evaluate::IsVariable(actual)}; - if (context.ShouldWarn( - common::UsageWarning::ShortCharacterActual)) { - if (isVariable) { - messages.Say(common::UsageWarning::ShortCharacterActual, - "Actual argument variable length '%jd' is less than expected length '%jd'"_warn_en_US, - *actualLength, *dummyLength); - } else { - messages.Say(common::UsageWarning::ShortCharacterActual, - "Actual argument expression length '%jd' is less than expected length '%jd'"_warn_en_US, - *actualLength, *dummyLength); - } + if (isVariable) { + context.Warn(messages, common::UsageWarning::ShortCharacterActual, + "Actual argument variable length '%jd' is less than expected length '%jd'"_warn_en_US, + *actualLength, *dummyLength); + } else { + context.Warn(messages, common::UsageWarning::ShortCharacterActual, + "Actual argument expression length '%jd' is less than expected length '%jd'"_warn_en_US, + *actualLength, *dummyLength); } if (!isVariable) { auto converted{ @@ -279,9 +277,8 @@ static void ConvertIntegerActual(evaluate::Expr<evaluate::SomeType> &actual, messages.Say( "Actual argument scalar expression of type INTEGER(%d) cannot be implicitly converted to smaller dummy argument type INTEGER(%d)"_err_en_US, actualType.type().kind(), dummyType.type().kind()); - } else if (semanticsContext.ShouldWarn(common::LanguageFeature:: - ActualIntegerConvertedToSmallerKind)) { - messages.Say( + } else { + semanticsContext.Warn(messages, common::LanguageFeature::ActualIntegerConvertedToSmallerKind, "Actual argument scalar expression of type INTEGER(%d) was converted to smaller dummy argument type INTEGER(%d)"_port_en_US, actualType.type().kind(), dummyType.type().kind()); @@ -364,20 +361,16 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, if (const auto *constantChar{ evaluate::UnwrapConstantValue<evaluate::Ascii>(actual)}; constantChar && constantChar->wasHollerith() && - dummy.type.type().IsUnlimitedPolymorphic() && - context.ShouldWarn(common::LanguageFeature::HollerithPolymorphic)) { - messages.Say(common::LanguageFeature::HollerithPolymorphic, + dummy.type.type().IsUnlimitedPolymorphic()) { + foldingContext.Warn(common::LanguageFeature::HollerithPolymorphic, "passing Hollerith to unlimited polymorphic as if it were CHARACTER"_port_en_US); } } else if (dummyRank == 0 && allowActualArgumentConversions) { // Extension: pass Hollerith literal to scalar as if it had been BOZ if (auto converted{evaluate::HollerithToBOZ( foldingContext, actual, dummy.type.type())}) { - if (context.ShouldWarn( - common::LanguageFeature::HollerithOrCharacterAsBOZ)) { - messages.Say(common::LanguageFeature::HollerithOrCharacterAsBOZ, - "passing Hollerith or character literal as if it were BOZ"_port_en_US); - } + foldingContext.Warn(common::LanguageFeature::HollerithOrCharacterAsBOZ, + "passing Hollerith or character literal as if it were BOZ"_port_en_US); actual = *converted; actualType.type() = dummy.type.type(); typesCompatible = true; @@ -387,7 +380,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, characteristics::TypeAndShape::Attr::AssumedRank)}; bool actualIsAssumedSize{actualType.attrs().test( characteristics::TypeAndShape::Attr::AssumedSize)}; - bool actualIsAssumedRank{evaluate::IsAssumedRank(actual)}; + bool actualIsAssumedRank{IsAssumedRank(actual)}; bool actualIsPointer{evaluate::IsObjectPointer(actual)}; bool actualIsAllocatable{evaluate::IsAllocatableDesignator(actual)}; bool actualMayBeAssumedSize{actualIsAssumedSize || @@ -411,7 +404,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, "%s actual argument may not be associated with INTENT(OUT) assumed-rank dummy argument requiring finalization, destruction, or initialization"_err_en_US, actualDesc); } else { - context.Warn(common::UsageWarning::Portability, messages.at(), + foldingContext.Warn(common::UsageWarning::Portability, messages.at(), "%s actual argument should not be associated with INTENT(OUT) assumed-rank dummy argument"_port_en_US, actualDesc); } @@ -671,9 +664,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, "Actual argument has fewer elements remaining in storage sequence (%jd) than %s array (%jd)"_err_en_US, static_cast<std::intmax_t>(*actualElements), dummyName, static_cast<std::intmax_t>(*dummySize)); - } else if (context.ShouldWarn( - common::UsageWarning::ShortArrayActual)) { - messages.Say(common::UsageWarning::ShortArrayActual, + } else { + context.Warn(common::UsageWarning::ShortArrayActual, "Actual argument has fewer elements remaining in storage sequence (%jd) than %s array (%jd)"_warn_en_US, static_cast<std::intmax_t>(*actualElements), dummyName, static_cast<std::intmax_t>(*dummySize)); @@ -690,9 +682,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, "Actual argument array has fewer elements (%jd) than %s array (%jd)"_err_en_US, static_cast<std::intmax_t>(*actualSize), dummyName, static_cast<std::intmax_t>(*dummySize)); - } else if (context.ShouldWarn( - common::UsageWarning::ShortArrayActual)) { - messages.Say(common::UsageWarning::ShortArrayActual, + } else { + context.Warn(common::UsageWarning::ShortArrayActual, "Actual argument array has fewer elements (%jd) than %s array (%jd)"_warn_en_US, static_cast<std::intmax_t>(*actualSize), dummyName, static_cast<std::intmax_t>(*dummySize)); @@ -779,24 +770,36 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, // Cases when temporaries might be needed but must not be permitted. bool dummyIsAssumedShape{dummy.type.attrs().test( characteristics::TypeAndShape::Attr::AssumedShape)}; - if ((actualIsAsynchronous || actualIsVolatile) && - (dummyIsAsynchronous || dummyIsVolatile) && !dummyIsValue) { - if (actualCoarrayRef) { // C1538 - messages.Say( - "Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with %s with ASYNCHRONOUS or VOLATILE attributes unless VALUE"_err_en_US, - dummyName); - } - if ((actualRank > 0 || actualIsAssumedRank) && !actualIsContiguous) { - if (dummyIsContiguous || - !(dummyIsAssumedShape || dummyIsAssumedRank || - (actualIsPointer && dummyIsPointer))) { // C1539 & C1540 + if (!dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) { + if (actualIsAsynchronous || actualIsVolatile) { + if (actualCoarrayRef) { // F'2023 C1547 messages.Say( - "ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous ASYNCHRONOUS or VOLATILE %s"_err_en_US, + "Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with %s with ASYNCHRONOUS or VOLATILE attributes unless VALUE"_err_en_US, dummyName); } + if ((actualRank > 0 || actualIsAssumedRank) && !actualIsContiguous) { + if (dummyIsContiguous || + !(dummyIsAssumedShape || dummyIsAssumedRank || + (actualIsPointer && dummyIsPointer))) { // F'2023 C1548 & C1549 + messages.Say( + "ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous ASYNCHRONOUS or VOLATILE %s"_err_en_US, + dummyName); + } + } + // The vector subscript case is handled by the definability check above. + // The copy-in/copy-out cases are handled by the previous checks. + // Nag, GFortran, and NVFortran all error on this case, even though it is + // ok, prossibly as an over-restriction of C1548. + } else if (!(dummyIsAssumedShape || dummyIsAssumedRank || + (actualIsPointer && dummyIsPointer)) && + evaluate::IsArraySection(actual) && + !evaluate::HasVectorSubscript(actual)) { + context.Warn(common::UsageWarning::Portability, messages.at(), + "The array section '%s' should not be associated with %s with %s attribute, unless the dummy is assumed-shape or assumed-rank"_port_en_US, + actual.AsFortran(), dummyName, + dummyIsAsynchronous ? "ASYNCHRONOUS" : "VOLATILE"); } } - // 15.5.2.6 -- dummy is ALLOCATABLE bool dummyIsOptional{ dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)}; @@ -821,10 +824,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, messages.Say( "A null pointer should not be associated with allocatable %s without INTENT(IN)"_warn_en_US, dummyName); - } else if (dummy.intent == common::Intent::In && - context.ShouldWarn( - common::LanguageFeature::NullActualForAllocatable)) { - messages.Say(common::LanguageFeature::NullActualForAllocatable, + } else if (dummy.intent == common::Intent::In) { + foldingContext.Warn(common::LanguageFeature::NullActualForAllocatable, "Allocatable %s is associated with a null pointer"_port_en_US, dummyName); } @@ -878,11 +879,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, checkTypeCompatibility = false; if (dummyIsUnlimited && dummy.intent == common::Intent::In && context.IsEnabled(common::LanguageFeature::RelaxedIntentInChecking)) { - if (context.ShouldWarn( - common::LanguageFeature::RelaxedIntentInChecking)) { - messages.Say(common::LanguageFeature::RelaxedIntentInChecking, - "If a POINTER or ALLOCATABLE dummy or actual argument is unlimited polymorphic, both should be so"_port_en_US); - } + foldingContext.Warn(common::LanguageFeature::RelaxedIntentInChecking, + "If a POINTER or ALLOCATABLE dummy or actual argument is unlimited polymorphic, both should be so"_port_en_US); } else { messages.Say( "If a POINTER or ALLOCATABLE dummy or actual argument is unlimited polymorphic, both must be so"_err_en_US); @@ -890,21 +888,15 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, } else if (dummyIsPolymorphic != actualIsPolymorphic) { if (dummyIsPolymorphic && dummy.intent == common::Intent::In && context.IsEnabled(common::LanguageFeature::RelaxedIntentInChecking)) { - if (context.ShouldWarn( - common::LanguageFeature::RelaxedIntentInChecking)) { - messages.Say(common::LanguageFeature::RelaxedIntentInChecking, - "If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both should be so"_port_en_US); - } + foldingContext.Warn(common::LanguageFeature::RelaxedIntentInChecking, + "If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both should be so"_port_en_US); } else if (actualIsPolymorphic && context.IsEnabled(common::LanguageFeature:: PolymorphicActualAllocatableOrPointerToMonomorphicDummy)) { - if (context.ShouldWarn(common::LanguageFeature:: - PolymorphicActualAllocatableOrPointerToMonomorphicDummy)) { - messages.Say( - common::LanguageFeature:: - PolymorphicActualAllocatableOrPointerToMonomorphicDummy, - "If a POINTER or ALLOCATABLE actual argument is polymorphic, the corresponding dummy argument should also be so"_port_en_US); - } + foldingContext.Warn( + common::LanguageFeature:: + PolymorphicActualAllocatableOrPointerToMonomorphicDummy, + "If a POINTER or ALLOCATABLE actual argument is polymorphic, the corresponding dummy argument should also be so"_port_en_US); } else { checkTypeCompatibility = false; messages.Say( @@ -916,11 +908,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, if (dummy.intent == common::Intent::In && context.IsEnabled( common::LanguageFeature::RelaxedIntentInChecking)) { - if (context.ShouldWarn( - common::LanguageFeature::RelaxedIntentInChecking)) { - messages.Say(common::LanguageFeature::RelaxedIntentInChecking, - "POINTER or ALLOCATABLE dummy and actual arguments should have the same declared type and kind"_port_en_US); - } + foldingContext.Warn(common::LanguageFeature::RelaxedIntentInChecking, + "POINTER or ALLOCATABLE dummy and actual arguments should have the same declared type and kind"_port_en_US); } else { messages.Say( "POINTER or ALLOCATABLE dummy and actual arguments must have the same declared type and kind"_err_en_US); @@ -991,13 +980,13 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, bool actualIsTemp{ !actualIsVariable || HasVectorSubscript(actual) || actualCoarrayRef}; if (actualIsTemp) { - messages.Say(common::UsageWarning::NonTargetPassedToTarget, + foldingContext.Warn(common::UsageWarning::NonTargetPassedToTarget, "Any pointer associated with TARGET %s during this call will not be associated with the value of '%s' afterwards"_warn_en_US, dummyName, actual.AsFortran()); } else { auto actualSymbolVector{GetSymbolVector(actual)}; if (!evaluate::GetLastTarget(actualSymbolVector)) { - messages.Say(common::UsageWarning::NonTargetPassedToTarget, + foldingContext.Warn(common::UsageWarning::NonTargetPassedToTarget, "Any pointer associated with TARGET %s during this call must not be used afterwards, as '%s' is not a target"_warn_en_US, dummyName, actual.AsFortran()); } @@ -1126,9 +1115,8 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg, evaluate::SayWithDeclaration(messages, *argProcSymbol, "Procedure binding '%s' passed as an actual argument"_err_en_US, argProcSymbol->name()); - } else if (context.ShouldWarn( - common::LanguageFeature::BindingAsProcedure)) { - evaluate::SayWithDeclaration(messages, *argProcSymbol, + } else { + evaluate::WarnWithDeclaration(foldingContext, *argProcSymbol, common::LanguageFeature::BindingAsProcedure, "Procedure binding '%s' passed as an actual argument"_port_en_US, argProcSymbol->name()); @@ -1180,15 +1168,14 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg, messages.Say( "Actual procedure argument for %s of a PURE procedure must have an explicit interface"_err_en_US, dummyName); - } else if (context.ShouldWarn( - common::UsageWarning::ImplicitInterfaceActual)) { - messages.Say(common::UsageWarning::ImplicitInterfaceActual, + } else { + foldingContext.Warn( + common::UsageWarning::ImplicitInterfaceActual, "Actual procedure argument has an implicit interface which is not known to be compatible with %s which has an explicit interface"_warn_en_US, dummyName); } - } else if (warning && - context.ShouldWarn(common::UsageWarning::ProcDummyArgShapes)) { - messages.Say(common::UsageWarning::ProcDummyArgShapes, + } else if (warning) { + foldingContext.Warn(common::UsageWarning::ProcDummyArgShapes, "Actual procedure argument has possible interface incompatibility with %s: %s"_warn_en_US, dummyName, std::move(*warning)); } @@ -1363,16 +1350,14 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg, messages.Say( "NULL() actual argument '%s' may not be associated with allocatable dummy argument %s that is INTENT(OUT) or INTENT(IN OUT)"_err_en_US, expr->AsFortran(), dummyName); - } else if (object.intent == common::Intent::Default && - context.ShouldWarn(common::UsageWarning:: - NullActualForDefaultIntentAllocatable)) { - messages.Say(common::UsageWarning:: - NullActualForDefaultIntentAllocatable, + } else if (object.intent == common::Intent::Default) { + foldingContext.Warn( + common::UsageWarning:: + NullActualForDefaultIntentAllocatable, "NULL() actual argument '%s' should not be associated with allocatable dummy argument %s without INTENT(IN)"_warn_en_US, expr->AsFortran(), dummyName); - } else if (context.ShouldWarn(common::LanguageFeature:: - NullActualForAllocatable)) { - messages.Say( + } else { + foldingContext.Warn( common::LanguageFeature::NullActualForAllocatable, "Allocatable %s is associated with %s"_port_en_US, dummyName, expr->AsFortran()); @@ -1390,8 +1375,7 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg, assumed.name(), dummyName); } else if (object.type.attrs().test(characteristics:: TypeAndShape::Attr::AssumedRank) && - !IsAssumedShape(assumed) && - !evaluate::IsAssumedRank(assumed)) { + !IsAssumedShape(assumed) && !IsAssumedRank(assumed)) { messages.Say( // C711 "Assumed-type '%s' must be either assumed shape or assumed rank to be associated with assumed rank %s"_err_en_US, assumed.name(), dummyName); @@ -1562,7 +1546,7 @@ static void CheckAssociated(evaluate::ActualArguments &arguments, if (semanticsContext.ShouldWarn(common::UsageWarning::Portability)) { if (!evaluate::ExtractDataRef(*pointerExpr) && !evaluate::IsProcedurePointer(*pointerExpr)) { - messages.Say(common::UsageWarning::Portability, + foldingContext.Warn(common::UsageWarning::Portability, pointerArg->sourceLocation(), "POINTER= argument of ASSOCIATED() is required by some other compilers to be a pointer"_port_en_US); } else if (scope && !evaluate::UnwrapProcedureRef(*pointerExpr)) { @@ -1573,7 +1557,8 @@ static void CheckAssociated(evaluate::ActualArguments &arguments, DefinabilityFlag::DoNotNoteDefinition}, *pointerExpr)}) { if (whyNot->IsFatal()) { - if (auto *msg{messages.Say(common::UsageWarning::Portability, + if (auto *msg{foldingContext.Warn( + common::UsageWarning::Portability, pointerArg->sourceLocation(), "POINTER= argument of ASSOCIATED() is required by some other compilers to be a valid left-hand side of a pointer assignment statement"_port_en_US)}) { msg->Attach(std::move( @@ -2000,8 +1985,9 @@ static void CheckReduce( } } } - const auto *result{ - procChars ? procChars->functionResult->GetTypeAndShape() : nullptr}; + const auto *result{procChars && procChars->functionResult + ? procChars->functionResult->GetTypeAndShape() + : nullptr}; if (!procChars || !procChars->IsPure() || procChars->dummyArguments.size() != 2 || !procChars->functionResult) { messages.Say( @@ -2087,10 +2073,8 @@ static void CheckReduce( // TRANSFER (16.9.193) static void CheckTransferOperandType(SemanticsContext &context, const evaluate::DynamicType &type, const char *which) { - if (type.IsPolymorphic() && - context.ShouldWarn(common::UsageWarning::PolymorphicTransferArg)) { - context.foldingContext().messages().Say( - common::UsageWarning::PolymorphicTransferArg, + if (type.IsPolymorphic()) { + context.foldingContext().Warn(common::UsageWarning::PolymorphicTransferArg, "%s of TRANSFER is polymorphic"_warn_en_US, which); } else if (!type.IsUnlimitedPolymorphic() && type.category() == TypeCategory::Derived && @@ -2098,7 +2082,7 @@ static void CheckTransferOperandType(SemanticsContext &context, DirectComponentIterator directs{type.GetDerivedTypeSpec()}; if (auto bad{std::find_if(directs.begin(), directs.end(), IsDescriptor)}; bad != directs.end()) { - evaluate::SayWithDeclaration(context.foldingContext().messages(), *bad, + evaluate::WarnWithDeclaration(context.foldingContext(), *bad, common::UsageWarning::PointerComponentTransferArg, "%s of TRANSFER contains allocatable or pointer component %s"_warn_en_US, which, bad.BuildResultDesignatorName()); @@ -2128,8 +2112,8 @@ static void CheckTransfer(evaluate::ActualArguments &arguments, messages.Say( "Element size of MOLD= array may not be zero when SOURCE= is not empty"_err_en_US); } - } else if (context.ShouldWarn(common::UsageWarning::VoidMold)) { - messages.Say(common::UsageWarning::VoidMold, + } else { + foldingContext.Warn(common::UsageWarning::VoidMold, "Element size of MOLD= array may not be zero unless SOURCE= is empty"_warn_en_US); } } @@ -2145,7 +2129,7 @@ static void CheckTransfer(evaluate::ActualArguments &arguments, } else if (context.ShouldWarn( common::UsageWarning::TransferSizePresence) && IsAllocatableOrObjectPointer(whole)) { - messages.Say(common::UsageWarning::TransferSizePresence, + foldingContext.Warn(common::UsageWarning::TransferSizePresence, "SIZE= argument that is allocatable or pointer must be present at execution; parenthesize to silence this warning"_warn_en_US); } } @@ -2368,13 +2352,10 @@ bool CheckArguments(const characteristics::Procedure &proc, /*extentErrors=*/true, ignoreImplicitVsExplicit)}; if (!buffer.empty()) { if (treatingExternalAsImplicit) { - if (context.ShouldWarn( - common::UsageWarning::KnownBadImplicitInterface)) { - if (auto *msg{messages.Say( - common::UsageWarning::KnownBadImplicitInterface, - "If the procedure's interface were explicit, this reference would be in error"_warn_en_US)}) { - buffer.AttachTo(*msg, parser::Severity::Because); - } + if (auto *msg{foldingContext.Warn( + common::UsageWarning::KnownBadImplicitInterface, + "If the procedure's interface were explicit, this reference would be in error"_warn_en_US)}) { + buffer.AttachTo(*msg, parser::Severity::Because); } else { buffer.clear(); } |
