diff options
author | Peter Klausler <35819229+klausler@users.noreply.github.com> | 2023-11-13 16:13:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-13 16:13:50 -0800 |
commit | 1c91d9bdea3b6c38e8fbce46ec8181a9c0aa26f8 (patch) | |
tree | cf9c2d958a333e7dbbe60c600a5ad025ce41b049 /flang/lib/Evaluate/intrinsics.cpp | |
parent | a5eb6bdd8e126ad94de0a12002cac2c3f01e05f5 (diff) | |
download | llvm-1c91d9bdea3b6c38e8fbce46ec8181a9c0aa26f8.zip llvm-1c91d9bdea3b6c38e8fbce46ec8181a9c0aa26f8.tar.gz llvm-1c91d9bdea3b6c38e8fbce46ec8181a9c0aa26f8.tar.bz2 |
[flang] Ensure that portability warnings are conditional (#71857)
Before emitting a warning message, code should check that the usage in
question should be diagnosed by calling ShouldWarn(). A fair number of
sites in the code do not, and can emit portability warnings
unconditionally, which can confuse a user that hasn't asked for them
(-pedantic) and isn't terribly concerned about portability *to* other
compilers.
Add calls to ShouldWarn() or IsEnabled() around messages that need them,
and add -pedantic to tests that now require it to test their portability
messages, and add more expected message lines to those tests when
-pedantic causes other diagnostics to fire.
Diffstat (limited to 'flang/lib/Evaluate/intrinsics.cpp')
-rw-r--r-- | flang/lib/Evaluate/intrinsics.cpp | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 9eb01df..c5faf31 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -2225,12 +2225,15 @@ std::optional<SpecificCall> IntrinsicInterface::Match( if (const Symbol *whole{ UnwrapWholeSymbolOrComponentDataRef(actualForDummy[*dimArg])}) { if (IsOptional(*whole) || IsAllocatableOrObjectPointer(whole)) { - if (rank == Rank::scalarIfDim || arrayRank.value_or(-1) == 1) { - messages.Say( - "The actual argument for DIM= is optional, pointer, or allocatable, and it is assumed to be present and equal to 1 at execution time"_port_en_US); - } else { - messages.Say( - "The actual argument for DIM= is optional, pointer, or allocatable, and may not be absent during execution; parenthesize to silence this warning"_warn_en_US); + if (context.languageFeatures().ShouldWarn( + common::UsageWarning::DimMustBePresent)) { + if (rank == Rank::scalarIfDim || arrayRank.value_or(-1) == 1) { + messages.Say( + "The actual argument for DIM= is optional, pointer, or allocatable, and it is assumed to be present and equal to 1 at execution time"_warn_en_US); + } else { + messages.Say( + "The actual argument for DIM= is optional, pointer, or allocatable, and may not be absent during execution; parenthesize to silence this warning"_warn_en_US); + } } } } @@ -3181,28 +3184,37 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe( // If there was no exact match with a specific, try to match the related // generic and convert the result to the specific required type. - for (auto specIter{specificRange.first}; specIter != specificRange.second; - ++specIter) { - // We only need to check the cases with distinct generic names. - if (const char *genericName{specIter->second->generic}) { - if (specIter->second->useGenericAndForceResultType) { - auto genericRange{genericFuncs_.equal_range(genericName)}; - for (auto genIter{genericRange.first}; genIter != genericRange.second; - ++genIter) { - if (auto specificCall{ - matchOrBufferMessages(*genIter->second, specificBuffer)}) { - // Force the call result type to the specific intrinsic result type - DynamicType newType{GetReturnType(*specIter->second, defaults_)}; - context.messages().Say( - "argument types do not match specific intrinsic '%s' " - "requirements; using '%s' generic instead and converting the " - "result to %s if needed"_port_en_US, - call.name, genericName, newType.AsFortran()); - specificCall->specificIntrinsic.name = call.name; - specificCall->specificIntrinsic.characteristics.value() - .functionResult.value() - .SetType(newType); - return specificCall; + if (context.languageFeatures().IsEnabled(common::LanguageFeature:: + UseGenericIntrinsicWhenSpecificDoesntMatch)) { + for (auto specIter{specificRange.first}; specIter != specificRange.second; + ++specIter) { + // We only need to check the cases with distinct generic names. + if (const char *genericName{specIter->second->generic}) { + if (specIter->second->useGenericAndForceResultType) { + auto genericRange{genericFuncs_.equal_range(genericName)}; + for (auto genIter{genericRange.first}; genIter != genericRange.second; + ++genIter) { + if (auto specificCall{ + matchOrBufferMessages(*genIter->second, specificBuffer)}) { + // Force the call result type to the specific intrinsic result + // type + DynamicType newType{GetReturnType(*specIter->second, defaults_)}; + if (context.languageFeatures().ShouldWarn( + common::LanguageFeature:: + UseGenericIntrinsicWhenSpecificDoesntMatch)) { + context.messages().Say( + "Argument types do not match specific intrinsic '%s' " + "requirements; using '%s' generic instead and converting " + "the " + "result to %s if needed"_port_en_US, + call.name, genericName, newType.AsFortran()); + } + specificCall->specificIntrinsic.name = call.name; + specificCall->specificIntrinsic.characteristics.value() + .functionResult.value() + .SetType(newType); + return specificCall; + } } } } |