Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][runtime] zero size allocation in source allocation #66124

Merged
merged 2 commits into from
Sep 18, 2023

Conversation

jeanPerier
Copy link
Contributor

Source allocation with a zero sized array is legal, and the resulting allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable or pointer to look unallocated/disassociated.

Source allocation with a zero sized array is legal, and the resulting
allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable
or pointer to look unallocated/disassociated.
@jeanPerier jeanPerier requested a review from a team as a code owner September 12, 2023 18:36
@llvmbot llvmbot added the flang Flang issues not falling into any other category label Sep 12, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 12, 2023

@llvm/pr-subscribers-flang-runtime

Changes

Source allocation with a zero sized array is legal, and the resulting allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable or pointer to look unallocated/disassociated.

Full diff: https://github.com/llvm/llvm-project/pull/66124.diff

4 Files Affected:

  • (modified) flang/runtime/allocatable.cpp (-3)
  • (modified) flang/runtime/pointer.cpp (-3)
  • (modified) flang/unittests/Runtime/Allocatable.cpp (+21)
  • (modified) flang/unittests/Runtime/Pointer.cpp (+22)
diff --git a/flang/runtime/allocatable.cpp b/flang/runtime/allocatable.cpp
index b53440c2c3fad64..4b9e438e8a10995 100644
--- a/flang/runtime/allocatable.cpp
+++ b/flang/runtime/allocatable.cpp
@@ -168,9 +168,6 @@ int RTNAME(AllocatableAllocate)(Descriptor &descriptor, bool hasStat,
 int RTNAME(AllocatableAllocateSource)(Descriptor &alloc,
     const Descriptor &source, bool hasStat, const Descriptor *errMsg,
     const char *sourceFile, int sourceLine) {
-  if (alloc.Elements() == 0) {
-    return StatOk;
-  }
   int stat{RTNAME(AllocatableAllocate)(
       alloc, hasStat, errMsg, sourceFile, sourceLine)};
   if (stat == StatOk) {
diff --git a/flang/runtime/pointer.cpp b/flang/runtime/pointer.cpp
index 4024b78c88e33e1..0320468ffdc7904 100644
--- a/flang/runtime/pointer.cpp
+++ b/flang/runtime/pointer.cpp
@@ -154,9 +154,6 @@ int RTNAME(PointerAllocate)(Descriptor &pointer, bool hasStat,
 int RTNAME(PointerAllocateSource)(Descriptor &pointer, const Descriptor &source,
     bool hasStat, const Descriptor *errMsg, const char *sourceFile,
     int sourceLine) {
-  if (pointer.Elements() == 0) {
-    return StatOk;
-  }
   int stat{RTNAME(PointerAllocate)(
       pointer, hasStat, errMsg, sourceFile, sourceLine)};
   if (stat == StatOk) {
diff --git a/flang/unittests/Runtime/Allocatable.cpp b/flang/unittests/Runtime/Allocatable.cpp
index ed8e9193204911c..f15f26bfd9c5751 100644
--- a/flang/unittests/Runtime/Allocatable.cpp
+++ b/flang/unittests/Runtime/Allocatable.cpp
@@ -95,6 +95,27 @@ TEST(AllocatableTest, AllocateFromScalarSource) {
   a->Destroy();
 }
 
+TEST(AllocatableTest, AllocateSourceZeroSize) {
+  using Fortran::common::TypeCategory;
+  // REAL(4), ALLOCATABLE :: a(:)
+  auto a{createAllocatable(TypeCategory::Real, 4)};
+  // REAL(4) :: s(-1:-2) = 0.
+  float sourecStorage{0.F};
+  const SubscriptValue extents[1]{0};
+  auto s{Descriptor::Create(TypeCategory::Real, 4,
+      reinterpret_cast(&sourecStorage), 1, extents,
+      CFI_attribute_other)};
+  // ALLOCATE(a, SOURCE=s)
+  RTNAME(AllocatableSetBounds)(*a, 0, -1, -2);
+  RTNAME(AllocatableAllocateSource)
+  (*a, *s, /*hasStat=*/false, /*errMsg=*/nullptr, __FILE__, __LINE__);
+  EXPECT_TRUE(a->IsAllocated());
+  EXPECT_EQ(a->Elements(), 0u);
+  EXPECT_EQ(a->GetDimension(0).LowerBound(), 1);
+  EXPECT_EQ(a->GetDimension(0).UpperBound(), 0);
+  a->Destroy();
+}
+
 TEST(AllocatableTest, DoubleAllocation) {
   // CLASS(*), ALLOCATABLE :: r
   // ALLOCATE(REAL::r)
diff --git a/flang/unittests/Runtime/Pointer.cpp b/flang/unittests/Runtime/Pointer.cpp
index 09ae3c4b4d966c5..4ce13ebc50a565c 100644
--- a/flang/unittests/Runtime/Pointer.cpp
+++ b/flang/unittests/Runtime/Pointer.cpp
@@ -83,3 +83,25 @@ TEST(Pointer, AllocateFromScalarSource) {
   EXPECT_EQ(*p->OffsetElement(), 3.4F);
   p->Destroy();
 }
+
+TEST(Pointer, AllocateSourceZeroSize) {
+  using Fortran::common::TypeCategory;
+  // REAL(4), POINTER :: p(:)
+  auto p{Descriptor::Create(TypeCode{Fortran::common::TypeCategory::Real, 4}, 4,
+      nullptr, 1, nullptr, CFI_attribute_pointer)};
+  // REAL(4) :: s(-1:-2) = 0.
+  float sourecStorage{0.F};
+  const SubscriptValue extents[1]{0};
+  auto s{Descriptor::Create(TypeCategory::Real, 4,
+      reinterpret_cast(&sourecStorage), 1, extents,
+      CFI_attribute_other)};
+  // ALLOCATE(p, SOURCE=s)
+  RTNAME(PointerSetBounds)(*p, 0, -1, -2);
+  RTNAME(PointerAllocateSource)
+  (*p, *s, /*hasStat=*/false, /*errMsg=*/nullptr, __FILE__, __LINE__);
+  EXPECT_TRUE(RTNAME(PointerIsAssociated)(*p));
+  EXPECT_EQ(p->Elements(), 0u);
+  EXPECT_EQ(p->GetDimension(0).LowerBound(), 1);
+  EXPECT_EQ(p->GetDimension(0).UpperBound(), 0);
+  p->Destroy();
+}

@klausler
Copy link
Contributor

Be advised, the C/C++ standards leave the behavior of malloc implementation-defined in the case of a zero-sized allocation, and they are allowed to return a null pointer or to return a non-null pointer that is not distinct from other zero-sized allocations. Consider allocating at least a single byte.

@jeanPerier
Copy link
Contributor Author

Be advised, the C/C++ standards leave the behavior of malloc implementation-defined in the case of a zero-sized allocation, and they are allowed to return a null pointer or to return a non-null pointer that is not distinct from other zero-sized allocations. Consider allocating at least a single byte.

Thanks, I updated Descriptor::Allocate runtime to do that since it is the core place called by all sorts of allocations that may be zero sized in Fortran.

@jeanPerier jeanPerier merged commit 79508db into llvm:main Sep 18, 2023
@jeanPerier jeanPerier deleted the jpr-zero-size-source-alloc branch September 18, 2023 06:51
ZijunZhaoCCK pushed a commit to ZijunZhaoCCK/llvm-project that referenced this pull request Sep 19, 2023
Source allocation with a zero sized array is legal, and the resulting
allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable
or pointer to look unallocated/disassociated.
zahiraam pushed a commit to tahonermann/llvm-project that referenced this pull request Oct 24, 2023
Source allocation with a zero sized array is legal, and the resulting
allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable
or pointer to look unallocated/disassociated.
zahiraam pushed a commit to tahonermann/llvm-project that referenced this pull request Oct 24, 2023
Source allocation with a zero sized array is legal, and the resulting
allocatable/pointer should be allocated/associated.

The current code skipped the actual allocation, leading the allocatable
or pointer to look unallocated/disassociated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants