[flang] Auto conversion of integer scalar actual argument exprs

Add documentation

Original-commit: flang-compiler/f18@c1b200d238
Reviewed-on: https://github.com/flang-compiler/f18/pull/884
This commit is contained in:
peter klausler 2019-12-19 19:13:16 -08:00
parent d98d029b02
commit 3a725ca8d0
3 changed files with 38 additions and 1 deletions

View file

@ -23,6 +23,13 @@ Intentional violations of the standard
`SIZE`, `LBOUND`, `UBOUND`, `SHAPE`, and the location reductions
`FINDLOC`, `MAXLOC`, and `MINLOC`. We return `INTEGER(KIND=8)` by
default in these cases.
* Scalar `INTEGER` actual argument expressions (not variables!)
are converted to the kinds of scalar `INTEGER` dummy arguments
when the interface is explicit and the kinds differ.
This conversion allows the results of the intrinsics like
`SIZE` that (as mentioned above) no longer return default
`INTEGER` results by default to be passed. A warning is
emitted when truncation is possible.
Extensions, deletions, and legacy features supported by default
===============================================================

View file

@ -1646,7 +1646,9 @@ public:
}
void Unparse(const CallStmt &x) { // R1521
if (asFortran_ && x.typedCall.get()) {
Put(' ');
asFortran_->call(out_, *x.typedCall);
Put('\n');
} else {
const auto &pd{std::get<ProcedureDesignator>(x.v.t)};
const auto &args{std::get<std::list<ActualArgSpec>>(x.v.t)};

View file

@ -101,6 +101,33 @@ static void PadShortCharacterActual(evaluate::Expr<evaluate::SomeType> &actual,
}
}
// Automatic conversion of different-kind INTEGER scalar actual
// argument expressions (not variables) to INTEGER scalar dummies.
// We return nonstandard INTEGER(8) results from intrinsic functions
// like SIZE() by default in order to facilitate the use of large
// arrays. Emit a warning when downconverting.
static void ConvertIntegerActual(evaluate::Expr<evaluate::SomeType> &actual,
const characteristics::TypeAndShape &dummyType,
characteristics::TypeAndShape &actualType,
parser::ContextualMessages &messages) {
if (dummyType.type().category() == TypeCategory::Integer &&
actualType.type().category() == TypeCategory::Integer &&
dummyType.type().kind() != actualType.type().kind() &&
GetRank(dummyType.shape()) == 0 && GetRank(actualType.shape()) == 0 &&
!evaluate::IsVariable(actual)) {
auto converted{
evaluate::ConvertToType(dummyType.type(), std::move(actual))};
CHECK(converted);
actual = std::move(*converted);
if (dummyType.type().kind() < actualType.type().kind()) {
messages.Say(
"Actual argument scalar expression of type INTEGER(%d) was converted to smaller dummy argument type INTEGER(%d)"_en_US,
actualType.type().kind(), dummyType.type().kind());
}
actualType = dummyType;
}
}
static bool DefersSameTypeParameters(
const DerivedTypeSpec &actual, const DerivedTypeSpec &dummy) {
for (const auto &pair : actual.parameters()) {
@ -115,12 +142,13 @@ static bool DefersSameTypeParameters(
static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
const std::string &dummyName, evaluate::Expr<evaluate::SomeType> &actual,
const characteristics::TypeAndShape &actualType, bool isElemental,
characteristics::TypeAndShape &actualType, bool isElemental,
evaluate::FoldingContext &context, const Scope *scope) {
// Basic type & rank checking
parser::ContextualMessages &messages{context.messages()};
PadShortCharacterActual(actual, dummy.type, actualType, messages);
ConvertIntegerActual(actual, dummy.type, actualType, messages);
bool typesCompatible{dummy.type.IsCompatibleWith(
messages, actualType, "dummy argument", "actual argument", isElemental)};
bool actualIsPolymorphic{actualType.type().IsPolymorphic()};