aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Evaluate/intrinsics.cpp
diff options
context:
space:
mode:
authorPeter Klausler <35819229+klausler@users.noreply.github.com>2023-11-13 16:13:50 -0800
committerGitHub <noreply@github.com>2023-11-13 16:13:50 -0800
commit1c91d9bdea3b6c38e8fbce46ec8181a9c0aa26f8 (patch)
treecf9c2d958a333e7dbbe60c600a5ad025ce41b049 /flang/lib/Evaluate/intrinsics.cpp
parenta5eb6bdd8e126ad94de0a12002cac2c3f01e05f5 (diff)
downloadllvm-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.cpp68
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;
+ }
}
}
}