diff --git a/flang/runtime/allocatable.cpp b/flang/runtime/allocatable.cpp --- a/flang/runtime/allocatable.cpp +++ b/flang/runtime/allocatable.cpp @@ -21,6 +21,9 @@ void RTNAME(AllocatableInitIntrinsic)(Descriptor &descriptor, TypeCategory category, int kind, int rank, int corank) { + if (descriptor.IsAllocated()) { + return; // Bypass so AllocatableAllocate can raise the error. + } INTERNAL_CHECK(corank == 0); descriptor.Establish(TypeCode{category, kind}, Descriptor::BytesFor(category, kind), nullptr, rank, nullptr, @@ -29,6 +32,9 @@ void RTNAME(AllocatableInitCharacter)(Descriptor &descriptor, SubscriptValue length, int kind, int rank, int corank) { + if (descriptor.IsAllocated()) { + return; // Bypass so AllocatableAllocate can raise the error. + } INTERNAL_CHECK(corank == 0); descriptor.Establish( kind, length, nullptr, rank, nullptr, CFI_attribute_allocatable); @@ -36,6 +42,9 @@ void RTNAME(AllocatableInitDerived)(Descriptor &descriptor, const typeInfo::DerivedType &derivedType, int rank, int corank) { + if (descriptor.IsAllocated()) { + return; // Bypass so AllocatableAllocate can raise the error. + } INTERNAL_CHECK(corank == 0); descriptor.Establish( derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable); diff --git a/flang/unittests/Runtime/Allocatable.cpp b/flang/unittests/Runtime/Allocatable.cpp --- a/flang/unittests/Runtime/Allocatable.cpp +++ b/flang/unittests/Runtime/Allocatable.cpp @@ -94,3 +94,21 @@ EXPECT_EQ(*a->OffsetElement(), 3.4F); a->Destroy(); } + +TEST(AllocatableTest, DoubleAllocation) { + + // CLASS(*), ALLOCATABLE :: r + // ALLOCATE(REAL::r) + auto r{createAllocatable(TypeCategory::Real, 4, 0)}; + EXPECT_FALSE(r->IsAllocated()); + EXPECT_TRUE(r->IsAllocatable()); + RTNAME(AllocatableAllocate)(*r); + EXPECT_TRUE(r->IsAllocated()); + + // Make sure AllocatableInitIntrinsic doesn't reset the decsriptor if it is + // allocated. + // ALLOCATE(INTEGER::r) + RTNAME(AllocatableInitIntrinsic) + (*r, Fortran::common::TypeCategory::Integer, 4); + EXPECT_TRUE(r->IsAllocated()); +}