@@ -105,3 +105,47 @@ TEST(Pointer, AllocateSourceZeroSize) {
105105 EXPECT_EQ (p->GetDimension (0 ).UpperBound (), 0 );
106106 p->Destroy ();
107107}
108+
109+ TEST (Pointer, PointerAssociateRemapping) {
110+ using Fortran::common::TypeCategory;
111+ // REAL(4), POINTER :: p(:)
112+ StaticDescriptor<Fortran::common::maxRank, true > staticDesc;
113+ auto p{staticDesc.descriptor ()};
114+ SubscriptValue extent[1 ]{1 };
115+ p.Establish (TypeCode{Fortran::common::TypeCategory::Real, 4 }, 4 , nullptr , 1 ,
116+ extent, CFI_attribute_pointer);
117+ std::size_t descSize{p.SizeInBytes ()};
118+ EXPECT_LE (descSize, staticDesc.byteSize );
119+ // REAL(4), CONTIGUOUS, POINTER :: t(:,:,:)
120+ auto t{Descriptor::Create (TypeCode{Fortran::common::TypeCategory::Real, 4 }, 4 ,
121+ nullptr , 3 , nullptr , CFI_attribute_pointer)};
122+ RTNAME (PointerSetBounds)(*t, 0 , 1 , 1 );
123+ RTNAME (PointerSetBounds)(*t, 1 , 1 , 1 );
124+ RTNAME (PointerSetBounds)(*t, 2 , 1 , 1 );
125+ RTNAME (PointerAllocate)(
126+ *t, /* hasStat=*/ false , /* errMsg=*/ nullptr , __FILE__, __LINE__);
127+ EXPECT_TRUE (RTNAME (PointerIsAssociated)(*t));
128+ // INTEGER(4) :: b(2,1) = [[1,1]]
129+ auto b{MakeArray<TypeCategory::Integer, 4 >(
130+ std::vector<int >{2 , 1 }, std::vector<std::int32_t >{1 , 1 })};
131+ // p(1:1) => t
132+ RTNAME (PointerAssociateRemapping)(p, *t, *b, __FILE__, __LINE__);
133+ EXPECT_TRUE (RTNAME (PointerIsAssociated)(p));
134+ EXPECT_EQ (p.rank (), 1 );
135+ EXPECT_EQ (p.Elements (), 1u );
136+
137+ // Verify that the memory past the p's descriptor is not affected.
138+ const char *addr = reinterpret_cast <const char *>(&staticDesc);
139+ const char *ptr = addr + descSize;
140+ const char *end = addr + staticDesc.byteSize ;
141+ while (ptr != end) {
142+ if (*ptr != ' \0 ' ) {
143+ std::fprintf (stderr, " byte %zd after pointer descriptor was written\n " ,
144+ ptr - addr);
145+ EXPECT_EQ (*ptr, ' \0 ' );
146+ break ;
147+ }
148+ ++ptr;
149+ }
150+ p.Destroy ();
151+ }
0 commit comments