Skip to content

Commit d0f44ed

Browse files
authored
[flang] Don't create impossible conversions in intrinsic extension (#79042)
We support specific intrinsic calls like `AMAX0(1.0,2)` that have heterogeneous argument types as an optional extension in cases where the specific intrinsic has a related generic intrinsic function capable of handling the argument types. This feature can't be allowed to apply to calls where the result of the related generic intrinsic function is not convertible to the type of the specific intrinsic, as in `AMAX0('a', 'b')`. Fixes #78932.
1 parent b1938b7 commit d0f44ed

File tree

3 files changed

+33
-18
lines changed

3 files changed

+33
-18
lines changed

flang/lib/Evaluate/fold-implementation.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,14 +1124,17 @@ Expr<T> RewriteSpecificMINorMAX(
11241124
intrinsic.characteristics.value().functionResult.value().SetType(*resultType);
11251125
auto insertConversion{[&](const auto &x) -> Expr<T> {
11261126
using TR = ResultType<decltype(x)>;
1127-
FunctionRef<TR> maxRef{std::move(funcRef.proc()), std::move(args)};
1127+
FunctionRef<TR> maxRef{
1128+
ProcedureDesignator{funcRef.proc()}, ActualArguments{args}};
11281129
return Fold(context, ConvertToType<T>(AsCategoryExpr(std::move(maxRef))));
11291130
}};
11301131
if (auto *sx{UnwrapExpr<Expr<SomeReal>>(*resultTypeArg)}) {
11311132
return common::visit(insertConversion, sx->u);
1133+
} else if (auto *sx{UnwrapExpr<Expr<SomeInteger>>(*resultTypeArg)}) {
1134+
return common::visit(insertConversion, sx->u);
1135+
} else {
1136+
return Expr<T>{std::move(funcRef)}; // error recovery
11321137
}
1133-
auto &sx{DEREF(UnwrapExpr<Expr<SomeInteger>>(*resultTypeArg))};
1134-
return common::visit(insertConversion, sx.u);
11351138
}
11361139

11371140
// FoldIntrinsicFunction()

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,23 +3105,31 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
31053105
if (auto specificCall{
31063106
matchOrBufferMessages(*genIter->second, specificBuffer)}) {
31073107
// Force the call result type to the specific intrinsic result
3108-
// type
3108+
// type, if possible.
3109+
DynamicType genericType{
3110+
DEREF(specificCall->specificIntrinsic.characteristics.value()
3111+
.functionResult.value()
3112+
.GetTypeAndShape())
3113+
.type()};
31093114
DynamicType newType{GetReturnType(*specIter->second, defaults_)};
3110-
if (context.languageFeatures().ShouldWarn(
3111-
common::LanguageFeature::
3112-
UseGenericIntrinsicWhenSpecificDoesntMatch)) {
3113-
context.messages().Say(
3114-
"Argument types do not match specific intrinsic '%s' "
3115-
"requirements; using '%s' generic instead and converting "
3116-
"the "
3117-
"result to %s if needed"_port_en_US,
3118-
call.name, genericName, newType.AsFortran());
3115+
if (genericType.category() == newType.category() ||
3116+
((genericType.category() == TypeCategory::Integer ||
3117+
genericType.category() == TypeCategory::Real) &&
3118+
(newType.category() == TypeCategory::Integer ||
3119+
newType.category() == TypeCategory::Real))) {
3120+
if (context.languageFeatures().ShouldWarn(
3121+
common::LanguageFeature::
3122+
UseGenericIntrinsicWhenSpecificDoesntMatch)) {
3123+
context.messages().Say(
3124+
"Argument types do not match specific intrinsic '%s' requirements; using '%s' generic instead and converting the result to %s if needed"_port_en_US,
3125+
call.name, genericName, newType.AsFortran());
3126+
}
3127+
specificCall->specificIntrinsic.name = call.name;
3128+
specificCall->specificIntrinsic.characteristics.value()
3129+
.functionResult.value()
3130+
.SetType(newType);
3131+
return specificCall;
31193132
}
3120-
specificCall->specificIntrinsic.name = call.name;
3121-
specificCall->specificIntrinsic.characteristics.value()
3122-
.functionResult.value()
3123-
.SetType(newType);
3124-
return specificCall;
31253133
}
31263134
}
31273135
}

flang/test/Evaluate/bug78932.f90

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
!RUN: not %flang_fc1 %s 2>&1 | FileCheck %s
2+
!CHECK: error: Actual argument for 'a1=' has bad type 'CHARACTER(KIND=1,LEN=1_8)'
3+
real, parameter :: bad_amax0 = amax0('a', 'b')
4+
end

0 commit comments

Comments
 (0)