Skip to content

Commit 0f79a29

Browse files
committed
[flang] Return arrays in Transfer runtime with SIZE argument
In TRANSFER runtime the result was an array only if the MOLD was an array. This is not in line with TRANSFER definition in 16.9.193 that rules that it must also be an array if MOLD is scalar and SIZE if provided. Differential Revision: https://reviews.llvm.org/D114943
1 parent 968a394 commit 0f79a29

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

flang/runtime/misc-intrinsic.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,19 @@
1111
#include "flang/Runtime/descriptor.h"
1212
#include <algorithm>
1313
#include <cstring>
14+
#include <optional>
1415

1516
namespace Fortran::runtime {
16-
extern "C" {
1717

18-
void RTNAME(Transfer)(Descriptor &result, const Descriptor &source,
19-
const Descriptor &mold, const char *sourceFile, int line) {
20-
if (mold.rank() > 0) {
21-
std::size_t moldElementBytes{mold.ElementBytes()};
22-
std::size_t elements{
23-
(source.Elements() * source.ElementBytes() + moldElementBytes - 1) /
24-
moldElementBytes};
25-
return RTNAME(TransferSize)(result, source, mold, sourceFile, line,
26-
static_cast<std::int64_t>(elements));
27-
} else {
28-
return RTNAME(TransferSize)(result, source, mold, sourceFile, line, 1);
29-
}
30-
}
31-
32-
void RTNAME(TransferSize)(Descriptor &result, const Descriptor &source,
18+
static void TransferImpl(Descriptor &result, const Descriptor &source,
3319
const Descriptor &mold, const char *sourceFile, int line,
34-
std::int64_t size) {
35-
int rank{mold.rank() > 0 ? 1 : 0};
20+
std::optional<std::int64_t> resultExtent) {
21+
int rank{resultExtent.has_value() ? 1 : 0};
3622
std::size_t elementBytes{mold.ElementBytes()};
3723
result.Establish(mold.type(), elementBytes, nullptr, rank, nullptr,
3824
CFI_attribute_allocatable, mold.Addendum() != nullptr);
39-
if (rank > 0) {
40-
result.GetDimension(0).SetBounds(1, size);
25+
if (resultExtent) {
26+
result.GetDimension(0).SetBounds(1, *resultExtent);
4127
}
4228
if (const DescriptorAddendum * addendum{mold.Addendum()}) {
4329
*result.Addendum() = *addendum;
@@ -47,7 +33,7 @@ void RTNAME(TransferSize)(Descriptor &result, const Descriptor &source,
4733
"TRANSFER: could not allocate memory for result; STAT=%d", stat);
4834
}
4935
char *to{result.OffsetElement<char>()};
50-
std::size_t resultBytes{size * elementBytes};
36+
std::size_t resultBytes{result.Elements() * result.ElementBytes()};
5137
const std::size_t sourceElementBytes{source.ElementBytes()};
5238
std::size_t sourceElements{source.Elements()};
5339
SubscriptValue sourceAt[maxRank];
@@ -65,5 +51,27 @@ void RTNAME(TransferSize)(Descriptor &result, const Descriptor &source,
6551
}
6652
}
6753

54+
extern "C" {
55+
56+
void RTNAME(Transfer)(Descriptor &result, const Descriptor &source,
57+
const Descriptor &mold, const char *sourceFile, int line) {
58+
if (mold.rank() > 0) {
59+
std::size_t moldElementBytes{mold.ElementBytes()};
60+
std::size_t elements{
61+
(source.Elements() * source.ElementBytes() + moldElementBytes - 1) /
62+
moldElementBytes};
63+
return TransferImpl(result, source, mold, sourceFile, line,
64+
static_cast<std::int64_t>(elements));
65+
} else {
66+
return TransferImpl(result, source, mold, sourceFile, line, {});
67+
}
68+
}
69+
70+
void RTNAME(TransferSize)(Descriptor &result, const Descriptor &source,
71+
const Descriptor &mold, const char *sourceFile, int line,
72+
std::int64_t size) {
73+
return TransferImpl(result, source, mold, sourceFile, line, size);
74+
}
75+
6876
} // extern "C"
6977
} // namespace Fortran::runtime

flang/unittests/Runtime/MiscIntrinsic.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,21 @@ TEST(MiscIntrinsic, TransferSize) {
6868
EXPECT_EQ(result.OffsetElement<float>()[1], 2.2F);
6969
result.Destroy();
7070
}
71+
TEST(MiscIntrinsic, TransferSizeScalarMold) {
72+
StaticDescriptor<2, true, 2> staticDesc[2];
73+
auto &result{staticDesc[0].descriptor()};
74+
std::complex<float> sourecStorage{1.1F, -2.2F};
75+
auto source{Descriptor::Create(TypeCategory::Complex, 4,
76+
reinterpret_cast<void *>(&sourecStorage), 0, nullptr,
77+
CFI_attribute_pointer)};
78+
auto &mold{staticDesc[1].descriptor()};
79+
mold.Establish(TypeCategory::Real, 4, nullptr, 0, nullptr);
80+
RTNAME(TransferSize)(result, *source, mold, __FILE__, __LINE__, 2);
81+
EXPECT_EQ(result.rank(), 1);
82+
EXPECT_EQ(result.GetDimension(0).LowerBound(), 1);
83+
EXPECT_EQ(result.GetDimension(0).Extent(), 2);
84+
EXPECT_EQ(result.type().raw(), (TypeCode{TypeCategory::Real, 4}.raw()));
85+
EXPECT_EQ(result.OffsetElement<float>()[0], 1.1F);
86+
EXPECT_EQ(result.OffsetElement<float>()[1], -2.2F);
87+
result.Destroy();
88+
}

0 commit comments

Comments
 (0)