1 /* Functions to convert descriptors between CFI and gfortran
2    and the CFI function declarations whose prototypes appear
3    in ISO_Fortran_binding.h.
4    Copyright (C) 2018-2021 Free Software Foundation, Inc.
5    Contributed by Daniel Celis Garza  <celisdanieljr@gmail.com>
6 	       and Paul Thomas  <pault@gcc.gnu.org>
7 
8 This file is part of the GNU Fortran runtime library (libgfortran).
9 
10 Libgfortran is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
14 
15 Libgfortran is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
23 
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
27 <http://www.gnu.org/licenses/>.  */
28 
29 #include "libgfortran.h"
30 #include "ISO_Fortran_binding.h"
31 #include <string.h>
32 #include <inttypes.h>   /* for PRIiPTR */
33 
34 extern void cfi_desc_to_gfc_desc (gfc_array_void *, CFI_cdesc_t **);
35 export_proto(cfi_desc_to_gfc_desc);
36 
37 /* NOTE: Since GCC 12, the FE generates code to do the conversion
38    directly without calling this function.  */
39 void
cfi_desc_to_gfc_desc(gfc_array_void * d,CFI_cdesc_t ** s_ptr)40 cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
41 {
42   signed char type;
43   size_t size;
44   int n;
45   CFI_cdesc_t *s = *s_ptr;
46 
47   if (!s)
48     return;
49 
50   /* Verify descriptor.  */
51   switch (s->attribute)
52     {
53     case CFI_attribute_pointer:
54     case CFI_attribute_allocatable:
55       break;
56     case CFI_attribute_other:
57       if (s->base_addr)
58 	break;
59       runtime_error ("Nonallocatable, nonpointer actual argument to BIND(C) "
60 		     "dummy argument where the effective argument is either "
61 		     "not allocated or not associated");
62       break;
63     default:
64       runtime_error ("Invalid attribute type %d in CFI_cdesc_t descriptor",
65 		     (int) s->attribute);
66       break;
67     }
68   GFC_DESCRIPTOR_DATA (d) = s->base_addr;
69 
70   /* Correct the unfortunate difference in order with types.  */
71   type = (signed char)(s->type & CFI_type_mask);
72   switch (type)
73     {
74     case CFI_type_Character:
75       type = BT_CHARACTER;
76       break;
77     case CFI_type_struct:
78       type = BT_DERIVED;
79       break;
80     case CFI_type_cptr:
81       /* FIXME: PR 100915.  GFC descriptors do not distinguish between
82 	 CFI_type_cptr and CFI_type_cfunptr.  */
83       type = BT_VOID;
84       break;
85     default:
86       break;
87     }
88 
89   GFC_DESCRIPTOR_TYPE (d) = type;
90   GFC_DESCRIPTOR_SIZE (d) = s->elem_len;
91 
92   d->dtype.version = 0;
93 
94   if (s->rank < 0 || s->rank > CFI_MAX_RANK)
95     internal_error (NULL, "Invalid rank in descriptor");
96   GFC_DESCRIPTOR_RANK (d) = (signed char)s->rank;
97 
98   d->dtype.attribute = (signed short)s->attribute;
99 
100   if (s->rank)
101     {
102       if ((size_t)s->dim[0].sm % s->elem_len)
103 	d->span = (index_type)s->dim[0].sm;
104       else
105 	d->span = (index_type)s->elem_len;
106     }
107 
108   d->offset = 0;
109   if (GFC_DESCRIPTOR_DATA (d))
110     for (n = 0; n < GFC_DESCRIPTOR_RANK (d); n++)
111       {
112 	CFI_index_t lb = 1;
113 
114 	if (s->attribute != CFI_attribute_other)
115 	  lb = s->dim[n].lower_bound;
116 
117 	GFC_DESCRIPTOR_LBOUND(d, n) = (index_type)lb;
118 	GFC_DESCRIPTOR_UBOUND(d, n) = (index_type)(s->dim[n].extent + lb - 1);
119 	GFC_DESCRIPTOR_STRIDE(d, n) = (index_type)(s->dim[n].sm / s->elem_len);
120 	d->offset -= GFC_DESCRIPTOR_STRIDE(d, n) * GFC_DESCRIPTOR_LBOUND(d, n);
121       }
122 }
123 
124 extern void gfc_desc_to_cfi_desc (CFI_cdesc_t **, const gfc_array_void *);
125 export_proto(gfc_desc_to_cfi_desc);
126 
127 /* NOTE: Since GCC 12, the FE generates code to do the conversion
128    directly without calling this function.  */
129 void
gfc_desc_to_cfi_desc(CFI_cdesc_t ** d_ptr,const gfc_array_void * s)130 gfc_desc_to_cfi_desc (CFI_cdesc_t **d_ptr, const gfc_array_void *s)
131 {
132   int n;
133   CFI_cdesc_t *d;
134   signed char type, kind;
135 
136   /* Play it safe with allocation of the flexible array member 'dim'
137      by setting the length to CFI_MAX_RANK. This should not be necessary
138      but valgrind complains accesses after the allocated block.  */
139   if (*d_ptr == NULL)
140     d = calloc (1, (sizeof (CFI_cdesc_t)
141 		    + (CFI_type_t)(CFI_MAX_RANK * sizeof (CFI_dim_t))));
142   else
143     d = *d_ptr;
144 
145   /* Verify descriptor.  */
146   switch (s->dtype.attribute)
147     {
148     case CFI_attribute_pointer:
149     case CFI_attribute_allocatable:
150       break;
151     case CFI_attribute_other:
152       if (s->base_addr)
153 	break;
154       runtime_error ("Nonallocatable, nonpointer actual argument to BIND(C) "
155 		     "dummy argument where the effective argument is either "
156 		     "not allocated or not associated");
157       break;
158     default:
159       internal_error (NULL, "Invalid attribute in gfc_array descriptor");
160       break;
161     }
162   d->base_addr = GFC_DESCRIPTOR_DATA (s);
163   d->elem_len = GFC_DESCRIPTOR_SIZE (s);
164   if (d->elem_len <= 0)
165     internal_error (NULL, "Invalid size in descriptor");
166 
167   d->version = CFI_VERSION;
168 
169   d->rank = (CFI_rank_t)GFC_DESCRIPTOR_RANK (s);
170   if (d->rank < 0 || d->rank > CFI_MAX_RANK)
171     internal_error (NULL, "Invalid rank in descriptor");
172 
173   d->attribute = (CFI_attribute_t)s->dtype.attribute;
174 
175   type = GFC_DESCRIPTOR_TYPE (s);
176   switch (type)
177     {
178     case BT_CHARACTER:
179       d->type = CFI_type_Character;
180       break;
181     case BT_DERIVED:
182       d->type = CFI_type_struct;
183       break;
184     case BT_VOID:
185       /* FIXME: PR 100915.  GFC descriptors do not distinguish between
186 	 CFI_type_cptr and CFI_type_cfunptr.  */
187       d->type = CFI_type_cptr;
188       break;
189     default:
190       d->type = (CFI_type_t)type;
191       break;
192     }
193 
194   switch (d->type)
195     {
196     case CFI_type_Integer:
197     case CFI_type_Logical:
198     case CFI_type_Real:
199       kind = (signed char)d->elem_len;
200       break;
201     case CFI_type_Complex:
202       kind = (signed char)(d->elem_len >> 1);
203       break;
204     case CFI_type_Character:
205       /* FIXME: we can't distinguish between kind/len because
206 	 the GFC descriptor only encodes the elem_len..
207 	 Until PR92482 is fixed, assume elem_len refers to the
208 	 character size and not the string length.  */
209       kind = (signed char)d->elem_len;
210       break;
211     case CFI_type_struct:
212     case CFI_type_cptr:
213     case CFI_type_other:
214       /* FIXME: PR 100915.  GFC descriptors do not distinguish between
215 	 CFI_type_cptr and CFI_type_cfunptr.  */
216       kind = 0;
217       break;
218     default:
219       internal_error (NULL, "Invalid type in descriptor");
220     }
221 
222   if (kind < 0)
223     internal_error (NULL, "Invalid kind in descriptor");
224 
225   /* FIXME: This is PR100917.  Because the GFC descriptor encodes only the
226      elem_len and not the kind, we get into trouble with long double kinds
227      that do not correspond directly to the elem_len, specifically the
228      kind 10 80-bit long double on x86 targets.  On x86_64, this has size
229      16 and cannot be differentiated from true _Float128.  Prefer the
230      standard long double type over the GNU extension in that case.  */
231   if (d->type == CFI_type_Real && kind == sizeof (long double))
232     d->type = CFI_type_long_double;
233   else if (d->type == CFI_type_Complex && kind == sizeof (long double))
234     d->type = CFI_type_long_double_Complex;
235   else
236     d->type = (CFI_type_t)(d->type
237 			   + ((CFI_type_t)kind << CFI_type_kind_shift));
238 
239   if (d->base_addr)
240     /* Full pointer or allocatable arrays retain their lower_bounds.  */
241     for (n = 0; n < GFC_DESCRIPTOR_RANK (s); n++)
242       {
243 	if (d->attribute != CFI_attribute_other)
244 	  d->dim[n].lower_bound = (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n);
245 	else
246 	  d->dim[n].lower_bound = 0;
247 
248 	/* Assumed size arrays have gfc ubound == 0 and CFI extent = -1.  */
249 	if (n == GFC_DESCRIPTOR_RANK (s) - 1
250 	    && GFC_DESCRIPTOR_LBOUND(s, n) == 1
251 	    && GFC_DESCRIPTOR_UBOUND(s, n) == 0)
252 	  d->dim[n].extent = -1;
253 	else
254 	  d->dim[n].extent = (CFI_index_t)GFC_DESCRIPTOR_UBOUND(s, n)
255 			     - (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n) + 1;
256 	d->dim[n].sm = (CFI_index_t)(GFC_DESCRIPTOR_STRIDE(s, n) * s->span);
257       }
258 
259   if (*d_ptr == NULL)
260     *d_ptr = d;
261 }
262 
CFI_address(const CFI_cdesc_t * dv,const CFI_index_t subscripts[])263 void *CFI_address (const CFI_cdesc_t *dv, const CFI_index_t subscripts[])
264 {
265   int i;
266   char *base_addr = (char *)dv->base_addr;
267 
268   if (unlikely (compile_options.bounds_check))
269     {
270       /* C descriptor must not be NULL. */
271       if (dv == NULL)
272 	{
273 	  fprintf (stderr, "CFI_address: C descriptor is NULL.\n");
274 	  return NULL;
275 	}
276 
277       /* Base address of C descriptor must not be NULL. */
278       if (dv->base_addr == NULL)
279 	{
280 	  fprintf (stderr, "CFI_address: base address of C descriptor "
281 		   "must not be NULL.\n");
282 	  return NULL;
283 	}
284     }
285 
286   /* Return base address if C descriptor is a scalar. */
287   if (dv->rank == 0)
288     return dv->base_addr;
289 
290   /* Calculate the appropriate base address if dv is not a scalar. */
291   else
292     {
293       /* Base address is the C address of the element of the object
294 	 specified by subscripts. */
295       for (i = 0; i < dv->rank; i++)
296 	{
297 	  CFI_index_t idx = subscripts[i] - dv->dim[i].lower_bound;
298 	  if (unlikely (compile_options.bounds_check)
299 	      && ((dv->dim[i].extent != -1 && idx >= dv->dim[i].extent)
300 		  || idx < 0))
301 	    {
302 	      fprintf (stderr, "CFI_address: subscripts[%d] is out of "
303 		       "bounds. For dimension = %d, subscripts = %d, "
304 		       "lower_bound = %" PRIiPTR ", upper bound = %" PRIiPTR
305 		       ", extent = %" PRIiPTR "\n",
306 		       i, i, (int)subscripts[i],
307 		       (ptrdiff_t)dv->dim[i].lower_bound,
308 		       (ptrdiff_t)(dv->dim[i].extent - dv->dim[i].lower_bound),
309 		       (ptrdiff_t)dv->dim[i].extent);
310               return NULL;
311             }
312 
313 	  base_addr = base_addr + (CFI_index_t)(idx * dv->dim[i].sm);
314 	}
315     }
316 
317   return (void *)base_addr;
318 }
319 
320 
321 int
CFI_allocate(CFI_cdesc_t * dv,const CFI_index_t lower_bounds[],const CFI_index_t upper_bounds[],size_t elem_len)322 CFI_allocate (CFI_cdesc_t *dv, const CFI_index_t lower_bounds[],
323 	      const CFI_index_t upper_bounds[], size_t elem_len)
324 {
325   if (unlikely (compile_options.bounds_check))
326     {
327       /* C descriptor must not be NULL. */
328       if (dv == NULL)
329 	{
330 	  fprintf (stderr, "CFI_allocate: C descriptor is NULL.\n");
331 	  return CFI_INVALID_DESCRIPTOR;
332 	}
333 
334       /* The C descriptor must be for an allocatable or pointer object. */
335       if (dv->attribute == CFI_attribute_other)
336 	{
337 	  fprintf (stderr, "CFI_allocate: The object of the C descriptor "
338 		   "must be a pointer or allocatable variable.\n");
339 	  return CFI_INVALID_ATTRIBUTE;
340 	}
341 
342       /* Base address of C descriptor must be NULL. */
343       if (dv->base_addr != NULL)
344 	{
345 	  fprintf (stderr, "CFI_allocate: Base address of C descriptor "
346 		   "must be NULL.\n");
347 	  return CFI_ERROR_BASE_ADDR_NOT_NULL;
348 	}
349     }
350 
351   /* If the type is a Fortran character type, the descriptor's element
352      length is replaced by the elem_len argument. */
353   if (dv->type == CFI_type_char || dv->type == CFI_type_ucs4_char)
354     dv->elem_len = elem_len;
355 
356   /* Dimension information and calculating the array length. */
357   size_t arr_len = 1;
358 
359   /* If rank is greater than 0, lower_bounds and upper_bounds are used. They're
360      ignored otherwise. */
361   if (dv->rank > 0)
362     {
363       if (unlikely (compile_options.bounds_check)
364 	  && (lower_bounds == NULL || upper_bounds == NULL))
365 	{
366 	  fprintf (stderr, "CFI_allocate: The lower_bounds and "
367 		   "upper_bounds arguments must be non-NULL when "
368 		   "rank is greater than zero.\n");
369 	  return CFI_INVALID_EXTENT;
370 	}
371 
372       for (int i = 0; i < dv->rank; i++)
373 	{
374 	  dv->dim[i].lower_bound = lower_bounds[i];
375 	  dv->dim[i].extent = upper_bounds[i] - dv->dim[i].lower_bound + 1;
376 	  dv->dim[i].sm = dv->elem_len * arr_len;
377 	  arr_len *= dv->dim[i].extent;
378         }
379     }
380 
381   dv->base_addr = calloc (arr_len, dv->elem_len);
382   if (dv->base_addr == NULL)
383     {
384       fprintf (stderr, "CFI_allocate: Failure in memory allocation.\n");
385       return CFI_ERROR_MEM_ALLOCATION;
386     }
387 
388   return CFI_SUCCESS;
389 }
390 
391 
392 int
CFI_deallocate(CFI_cdesc_t * dv)393 CFI_deallocate (CFI_cdesc_t *dv)
394 {
395   if (unlikely (compile_options.bounds_check))
396     {
397       /* C descriptor must not be NULL */
398       if (dv == NULL)
399 	{
400 	  fprintf (stderr, "CFI_deallocate: C descriptor is NULL.\n");
401 	  return CFI_INVALID_DESCRIPTOR;
402 	}
403 
404       /* Base address must not be NULL. */
405       if (dv->base_addr == NULL)
406 	{
407 	  fprintf (stderr, "CFI_deallocate: Base address is already NULL.\n");
408 	  return CFI_ERROR_BASE_ADDR_NULL;
409 	}
410 
411       /* C descriptor must be for an allocatable or pointer variable. */
412       if (dv->attribute == CFI_attribute_other)
413 	{
414 	  fprintf (stderr, "CFI_deallocate: C descriptor must describe a "
415 		  "pointer or allocatable object.\n");
416 	  return CFI_INVALID_ATTRIBUTE;
417 	}
418     }
419 
420   /* Free and nullify memory. */
421   free (dv->base_addr);
422   dv->base_addr = NULL;
423 
424   return CFI_SUCCESS;
425 }
426 
427 
CFI_establish(CFI_cdesc_t * dv,void * base_addr,CFI_attribute_t attribute,CFI_type_t type,size_t elem_len,CFI_rank_t rank,const CFI_index_t extents[])428 int CFI_establish (CFI_cdesc_t *dv, void *base_addr, CFI_attribute_t attribute,
429 		   CFI_type_t type, size_t elem_len, CFI_rank_t rank,
430 		   const CFI_index_t extents[])
431 {
432   if (unlikely (compile_options.bounds_check))
433     {
434       /* C descriptor must not be NULL. */
435       if (dv == NULL)
436 	{
437 	  fprintf (stderr, "CFI_establish: C descriptor is NULL.\n");
438 	  return CFI_INVALID_DESCRIPTOR;
439 	}
440 
441       /* Rank must be between 0 and CFI_MAX_RANK. */
442       if (rank < 0 || rank > CFI_MAX_RANK)
443 	{
444 	  fprintf (stderr, "CFI_establish: Rank must be between 0 and %d, "
445 		   "0 < rank (0 !< %d).\n", CFI_MAX_RANK, (int)rank);
446 	  return CFI_INVALID_RANK;
447 	}
448 
449       /* If base address is not NULL, the established C descriptor is for a
450 	  nonallocatable entity. */
451       if (attribute == CFI_attribute_allocatable && base_addr != NULL)
452 	{
453 	  fprintf (stderr, "CFI_establish: If base address is not NULL, "
454 		   "the established C descriptor must be "
455 		   "for a nonallocatable entity.\n");
456 	  return CFI_INVALID_ATTRIBUTE;
457 	}
458     }
459 
460   dv->base_addr = base_addr;
461 
462   if (type == CFI_type_char || type == CFI_type_ucs4_char
463       || type == CFI_type_struct || type == CFI_type_other)
464     {
465       /* Note that elem_len has type size_t, which is unsigned.  */
466       if (unlikely (compile_options.bounds_check) && elem_len == 0)
467 	{
468 	  fprintf (stderr, "CFI_establish: The supplied elem_len must "
469 		   "be greater than zero.\n");
470 	  return CFI_INVALID_ELEM_LEN;
471 	}
472       dv->elem_len = elem_len;
473     }
474   else if (type == CFI_type_cptr)
475     dv->elem_len = sizeof (void *);
476   else if (type == CFI_type_cfunptr)
477     dv->elem_len = sizeof (void (*)(void));
478   else if (unlikely (compile_options.bounds_check) && type < 0)
479     {
480       fprintf (stderr, "CFI_establish: Invalid type (type = %d).\n",
481 	       (int)type);
482       return CFI_INVALID_TYPE;
483     }
484   else
485     {
486       /* base_type describes the intrinsic type with kind parameter. */
487       size_t base_type = type & CFI_type_mask;
488       /* base_type_size is the size in bytes of the variable as given by its
489        * kind parameter. */
490       size_t base_type_size = (type - base_type) >> CFI_type_kind_shift;
491       /* Kind type 10 maps onto the 80-bit long double encoding on x86.
492 	 Note that this has different storage size for -m32 than -m64.  */
493       if (base_type_size == 10)
494 	base_type_size = sizeof (long double);
495       /* Complex numbers are twice the size of their real counterparts. */
496       if (base_type == CFI_type_Complex)
497 	base_type_size *= 2;
498       dv->elem_len = base_type_size;
499     }
500 
501   dv->version = CFI_VERSION;
502   dv->rank = rank;
503   dv->attribute = attribute;
504   dv->type = type;
505 
506   /* Extents must not be NULL if rank is greater than zero and base_addr is not
507      NULL */
508   if (rank > 0 && base_addr != NULL)
509     {
510       if (unlikely (compile_options.bounds_check) && extents == NULL)
511         {
512 	  fprintf (stderr, "CFI_establish: Extents must not be NULL "
513 		   "if rank is greater than zero and base address is "
514 		   "not NULL.\n");
515 	  return CFI_INVALID_EXTENT;
516 	}
517 
518       for (int i = 0; i < rank; i++)
519 	{
520 	  /* The standard requires all dimensions to be nonnegative.
521 	     Apparently you can have an extent-zero dimension but can't
522 	     construct an assumed-size array with -1 as the extent
523 	     of the last dimension.  */
524 	  if (unlikely (compile_options.bounds_check) && extents[i] < 0)
525 	    {
526 	      fprintf (stderr, "CFI_establish: Extents must be nonnegative "
527 		       "(extents[%d] = %" PRIiPTR ").\n",
528 		       i, (ptrdiff_t)extents[i]);
529 	      return CFI_INVALID_EXTENT;
530 	    }
531 	  dv->dim[i].lower_bound = 0;
532 	  dv->dim[i].extent = extents[i];
533 	  if (i == 0)
534 	    dv->dim[i].sm = dv->elem_len;
535 	  else
536 	    {
537 	      CFI_index_t extents_product = 1;
538 	      for (int j = 0; j < i; j++)
539 		extents_product *= extents[j];
540 	      dv->dim[i].sm = (CFI_index_t)(dv->elem_len * extents_product);
541 	    }
542 	}
543     }
544 
545   return CFI_SUCCESS;
546 }
547 
548 
CFI_is_contiguous(const CFI_cdesc_t * dv)549 int CFI_is_contiguous (const CFI_cdesc_t *dv)
550 {
551   if (unlikely (compile_options.bounds_check))
552     {
553       /* C descriptor must not be NULL. */
554       if (dv == NULL)
555 	{
556 	  fprintf (stderr, "CFI_is_contiguous: C descriptor is NULL.\n");
557 	  return 0;
558 	}
559 
560       /* Base address must not be NULL. */
561       if (dv->base_addr == NULL)
562 	{
563 	  fprintf (stderr, "CFI_is_contiguous: Base address of C descriptor "
564 		   "is already NULL.\n");
565 	  return 0;
566 	}
567 
568       /* Must be an array. */
569       if (dv->rank <= 0)
570 	{
571 	  fprintf (stderr, "CFI_is_contiguous: C descriptor must describe "
572 		   "an array.\n");
573 	  return 0;
574 	}
575     }
576 
577   /* Assumed size arrays are always contiguous.  */
578   if (dv->rank > 0 && dv->dim[dv->rank - 1].extent == -1)
579     return 1;
580 
581   /* If an array is not contiguous the memory stride is different to
582      the element length. */
583   for (int i = 0; i < dv->rank; i++)
584     {
585       if (i == 0 && dv->dim[i].sm == (CFI_index_t)dv->elem_len)
586 	continue;
587       else if (i > 0
588 	       && dv->dim[i].sm == (CFI_index_t)(dv->dim[i - 1].sm
589 				   * dv->dim[i - 1].extent))
590 	continue;
591 
592       return 0;
593     }
594 
595   /* Array sections are guaranteed to be contiguous by the previous test.  */
596   return 1;
597 }
598 
599 
CFI_section(CFI_cdesc_t * result,const CFI_cdesc_t * source,const CFI_index_t lower_bounds[],const CFI_index_t upper_bounds[],const CFI_index_t strides[])600 int CFI_section (CFI_cdesc_t *result, const CFI_cdesc_t *source,
601 		 const CFI_index_t lower_bounds[],
602 		 const CFI_index_t upper_bounds[], const CFI_index_t strides[])
603 {
604   /* Dimension information. */
605   CFI_index_t lower[CFI_MAX_RANK];
606   CFI_index_t upper[CFI_MAX_RANK];
607   CFI_index_t stride[CFI_MAX_RANK];
608   int zero_count = 0;
609 
610   if (unlikely (compile_options.bounds_check))
611     {
612       /* C descriptors must not be NULL. */
613       if (source == NULL)
614 	{
615 	  fprintf (stderr, "CFI_section: Source must not be NULL.\n");
616 	  return CFI_INVALID_DESCRIPTOR;
617 	}
618 
619       if (result == NULL)
620 	{
621 	  fprintf (stderr, "CFI_section: Result must not be NULL.\n");
622 	  return CFI_INVALID_DESCRIPTOR;
623 	}
624 
625       /* Base address of source must not be NULL. */
626       if (source->base_addr == NULL)
627 	{
628 	  fprintf (stderr, "CFI_section: Base address of source must "
629 		   "not be NULL.\n");
630 	  return CFI_ERROR_BASE_ADDR_NULL;
631 	}
632 
633       /* Result must not be an allocatable array. */
634       if (result->attribute == CFI_attribute_allocatable)
635 	{
636 	  fprintf (stderr, "CFI_section: Result must not describe an "
637 		   "allocatable array.\n");
638 	  return CFI_INVALID_ATTRIBUTE;
639 	}
640 
641       /* Source must be some form of array (nonallocatable nonpointer array,
642 	 allocated allocatable array or an associated pointer array). */
643       if (source->rank <= 0)
644 	{
645 	  fprintf (stderr, "CFI_section: Source must describe an array.\n");
646 	  return CFI_INVALID_RANK;
647 	}
648 
649       /* Element lengths of source and result must be equal. */
650       if (result->elem_len != source->elem_len)
651 	{
652 	  fprintf (stderr, "CFI_section: The element lengths of "
653 		   "source (source->elem_len = %" PRIiPTR ") and result "
654 		   "(result->elem_len = %" PRIiPTR ") must be equal.\n",
655 		   (ptrdiff_t)source->elem_len, (ptrdiff_t)result->elem_len);
656 	  return CFI_INVALID_ELEM_LEN;
657 	}
658 
659       /* Types must be equal. */
660       if (result->type != source->type)
661 	{
662 	  fprintf (stderr, "CFI_section: Types of source "
663 		   "(source->type = %d) and result (result->type = %d) "
664 		   "must be equal.\n", source->type, result->type);
665 	  return CFI_INVALID_TYPE;
666 	}
667     }
668 
669   /* Stride of zero in the i'th dimension means rank reduction in that
670      dimension. */
671   for (int i = 0; i < source->rank; i++)
672     {
673       if (strides[i] == 0)
674 	zero_count++;
675     }
676 
677   /* Rank of result must be equal the the rank of source minus the number of
678    * zeros in strides. */
679   if (unlikely (compile_options.bounds_check)
680       && result->rank != source->rank - zero_count)
681     {
682       fprintf (stderr, "CFI_section: Rank of result must be equal to the "
683 		       "rank of source minus the number of zeros in strides "
684 		       "(result->rank = source->rank - zero_count, %d != %d "
685 		       "- %d).\n", result->rank, source->rank, zero_count);
686       return CFI_INVALID_RANK;
687     }
688 
689   /* Lower bounds. */
690   if (lower_bounds == NULL)
691     {
692       for (int i = 0; i < source->rank; i++)
693 	lower[i] = source->dim[i].lower_bound;
694     }
695   else
696     {
697       for (int i = 0; i < source->rank; i++)
698 	lower[i] = lower_bounds[i];
699     }
700 
701   /* Upper bounds. */
702   if (upper_bounds == NULL)
703     {
704       if (unlikely (compile_options.bounds_check)
705 	  && source->dim[source->rank - 1].extent == -1)
706         {
707 	  fprintf (stderr, "CFI_section: Source must not be an assumed-size "
708 		   "array if upper_bounds is NULL.\n");
709 	  return CFI_INVALID_EXTENT;
710 	}
711 
712       for (int i = 0; i < source->rank; i++)
713 	upper[i] = source->dim[i].lower_bound + source->dim[i].extent - 1;
714     }
715   else
716     {
717       for (int i = 0; i < source->rank; i++)
718 	upper[i] = upper_bounds[i];
719     }
720 
721   /* Stride */
722   if (strides == NULL)
723     {
724       for (int i = 0; i < source->rank; i++)
725 	stride[i] = 1;
726     }
727   else
728     {
729       for (int i = 0; i < source->rank; i++)
730 	{
731 	  stride[i] = strides[i];
732 	  /* If stride[i] == 0 then lower[i] and upper[i] must be equal. */
733 	  if (unlikely (compile_options.bounds_check)
734 	      && stride[i] == 0 && lower[i] != upper[i])
735 	    {
736 	      fprintf (stderr, "CFI_section: If strides[%d] = 0, then "
737 		       "lower_bounds[%d] = %" PRIiPTR " and "
738 		       "upper_bounds[%d] = %" PRIiPTR " must be equal.\n",
739 		       i, i, (ptrdiff_t)lower_bounds[i], i,
740 		       (ptrdiff_t)upper_bounds[i]);
741 	      return CFI_ERROR_OUT_OF_BOUNDS;
742 	    }
743 	}
744     }
745 
746   /* Check that section upper and lower bounds are within the array bounds. */
747   if (unlikely (compile_options.bounds_check))
748     for (int i = 0; i < source->rank; i++)
749       {
750 	bool assumed_size
751 	  = (i == source->rank - 1 && source->dim[i].extent == -1);
752 	CFI_index_t ub
753 	  = source->dim[i].lower_bound + source->dim[i].extent - 1;
754 	if (lower_bounds != NULL
755 	    && (lower[i] < source->dim[i].lower_bound
756 		|| (!assumed_size && lower[i] > ub)))
757 	  {
758 	    fprintf (stderr, "CFI_section: Lower bounds must be within "
759 		     "the bounds of the Fortran array "
760 		     "(source->dim[%d].lower_bound "
761 		     "<= lower_bounds[%d] <= source->dim[%d].lower_bound "
762 		     "+ source->dim[%d].extent - 1, "
763 		     "%" PRIiPTR " <= %" PRIiPTR " <= %" PRIiPTR ").\n",
764 		     i, i, i, i,
765 		     (ptrdiff_t)source->dim[i].lower_bound,
766 		     (ptrdiff_t)lower[i],
767 		     (ptrdiff_t)ub);
768 	    return CFI_ERROR_OUT_OF_BOUNDS;
769 	  }
770 
771 	if (upper_bounds != NULL
772 	    && (upper[i] < source->dim[i].lower_bound
773 		|| (!assumed_size && upper[i] > ub)))
774 	  {
775 	    fprintf (stderr, "CFI_section: Upper bounds must be within "
776 		     "the bounds of the Fortran array "
777 		     "(source->dim[%d].lower_bound "
778 		     "<= upper_bounds[%d] <= source->dim[%d].lower_bound "
779 		     "+ source->dim[%d].extent - 1, "
780 		     "%" PRIiPTR " !<= %" PRIiPTR " !<= %" PRIiPTR ").\n",
781 		     i, i, i, i,
782 		     (ptrdiff_t)source->dim[i].lower_bound,
783 		     (ptrdiff_t)upper[i],
784 		     (ptrdiff_t)ub);
785 	    return CFI_ERROR_OUT_OF_BOUNDS;
786 	  }
787 
788 	if (upper[i] < lower[i] && stride[i] >= 0)
789 	  {
790 	    fprintf (stderr, "CFI_section: If the upper bound is smaller than "
791 		     "the lower bound for a given dimension (upper[%d] < "
792 		     "lower[%d], %" PRIiPTR " < %" PRIiPTR "), then the "
793 		     "stride for said dimension must be negative "
794 		     "(stride[%d] < 0, %" PRIiPTR " < 0).\n",
795 		     i, i, (ptrdiff_t)upper[i], (ptrdiff_t)lower[i],
796 		     i, (ptrdiff_t)stride[i]);
797 	    return CFI_INVALID_STRIDE;
798 	  }
799       }
800 
801   /* Set the base address.  We have to compute this first in the case
802      where source == result, before we overwrite the dimension data.  */
803   result->base_addr = CFI_address (source, lower);
804 
805   /* Set the appropriate dimension information that gives us access to the
806    * data. */
807   for (int i = 0, o = 0; i < source->rank; i++)
808     {
809       if (stride[i] == 0)
810 	continue;
811       result->dim[o].lower_bound = 0;
812       result->dim[o].extent = 1 + (upper[i] - lower[i])/stride[i];
813       result->dim[o].sm = stride[i] * source->dim[i].sm;
814       o++;
815     }
816 
817   return CFI_SUCCESS;
818 }
819 
820 
CFI_select_part(CFI_cdesc_t * result,const CFI_cdesc_t * source,size_t displacement,size_t elem_len)821 int CFI_select_part (CFI_cdesc_t *result, const CFI_cdesc_t *source,
822 		     size_t displacement, size_t elem_len)
823 {
824   if (unlikely (compile_options.bounds_check))
825     {
826       /* C descriptors must not be NULL. */
827       if (source == NULL)
828 	{
829 	  fprintf (stderr, "CFI_select_part: Source must not be NULL.\n");
830 	  return CFI_INVALID_DESCRIPTOR;
831 	}
832 
833       if (result == NULL)
834 	{
835 	  fprintf (stderr, "CFI_select_part: Result must not be NULL.\n");
836 	  return CFI_INVALID_DESCRIPTOR;
837 	}
838 
839       /* Attribute of result will be CFI_attribute_other or
840 	 CFI_attribute_pointer. */
841       if (result->attribute == CFI_attribute_allocatable)
842 	{
843 	  fprintf (stderr, "CFI_select_part: Result must not describe an "
844 		   "allocatable object (result->attribute != %d).\n",
845 		   CFI_attribute_allocatable);
846 	  return CFI_INVALID_ATTRIBUTE;
847 	}
848 
849       /* Base address of source must not be NULL. */
850       if (source->base_addr == NULL)
851 	{
852 	  fprintf (stderr, "CFI_select_part: Base address of source must "
853 		   "not be NULL.\n");
854 	  return CFI_ERROR_BASE_ADDR_NULL;
855 	}
856 
857       /* Source and result must have the same rank. */
858       if (source->rank != result->rank)
859 	{
860 	  fprintf (stderr, "CFI_select_part: Source and result must have "
861 		   "the same rank (source->rank = %d, result->rank = %d).\n",
862 		   (int)source->rank, (int)result->rank);
863 	  return CFI_INVALID_RANK;
864 	}
865 
866       /* Nonallocatable nonpointer must not be an assumed size array. */
867       if (source->rank > 0 && source->dim[source->rank - 1].extent == -1)
868 	{
869 	  fprintf (stderr, "CFI_select_part: Source must not describe an "
870 		   "assumed size array  (source->dim[%d].extent != -1).\n",
871 		   source->rank - 1);
872 	  return CFI_INVALID_DESCRIPTOR;
873 	}
874     }
875 
876   /* Element length is ignored unless result->type specifies a Fortran
877      character type.  */
878   if (result->type == CFI_type_char || result->type == CFI_type_ucs4_char)
879     result->elem_len = elem_len;
880 
881   if (unlikely (compile_options.bounds_check))
882     {
883       /* Ensure displacement is within the bounds of the element length
884 	 of source.*/
885       if (displacement > source->elem_len - 1)
886 	{
887 	  fprintf (stderr, "CFI_select_part: Displacement must be within the "
888 		   "bounds of source (0 <= displacement <= source->elem_len "
889 		   "- 1, 0 <= %" PRIiPTR " <= %" PRIiPTR ").\n",
890 		   (ptrdiff_t)displacement,
891 		   (ptrdiff_t)(source->elem_len - 1));
892 	  return CFI_ERROR_OUT_OF_BOUNDS;
893 	}
894 
895       /* Ensure displacement and element length of result are less than or
896 	 equal to the element length of source. */
897       if (displacement + result->elem_len > source->elem_len)
898 	{
899 	  fprintf (stderr, "CFI_select_part: Displacement plus the element "
900 		   "length of result must be less than or equal to the "
901 		   "element length of source (displacement + result->elem_len "
902 		   "<= source->elem_len, "
903 		   "%" PRIiPTR " + %" PRIiPTR " = %" PRIiPTR " <= %" PRIiPTR
904 		   ").\n",
905 		   (ptrdiff_t)displacement, (ptrdiff_t)result->elem_len,
906 		   (ptrdiff_t)(displacement + result->elem_len),
907 		   (ptrdiff_t)source->elem_len);
908 	  return CFI_ERROR_OUT_OF_BOUNDS;
909 	}
910     }
911 
912   if (result->rank > 0)
913     {
914       for (int i = 0; i < result->rank; i++)
915 	{
916 	  result->dim[i].lower_bound = source->dim[i].lower_bound;
917 	  result->dim[i].extent = source->dim[i].extent;
918 	  result->dim[i].sm = source->dim[i].sm;
919         }
920     }
921 
922   result->base_addr = (char *) source->base_addr + displacement;
923   return CFI_SUCCESS;
924 }
925 
926 
CFI_setpointer(CFI_cdesc_t * result,CFI_cdesc_t * source,const CFI_index_t lower_bounds[])927 int CFI_setpointer (CFI_cdesc_t *result, CFI_cdesc_t *source,
928 		    const CFI_index_t lower_bounds[])
929 {
930   /* Result must not be NULL and must be a Fortran pointer. */
931   if (unlikely (compile_options.bounds_check))
932     {
933       if (result == NULL)
934 	{
935 	  fprintf (stderr, "CFI_setpointer: Result is NULL.\n");
936 	  return CFI_INVALID_DESCRIPTOR;
937 	}
938 
939       if (result->attribute != CFI_attribute_pointer)
940 	{
941  	  fprintf (stderr, "CFI_setpointer: Result shall be the address of a "
942 		   "C descriptor for a Fortran pointer.\n");
943  	  return CFI_INVALID_ATTRIBUTE;
944  	}
945     }
946 
947   /* If source is NULL, the result is a C descriptor that describes a
948    * disassociated pointer. */
949   if (source == NULL)
950     {
951       result->base_addr = NULL;
952       result->version  = CFI_VERSION;
953     }
954   else
955     {
956       /* Check that the source is valid and that element lengths, ranks
957 	 and types of source and result are the same. */
958       if (unlikely (compile_options.bounds_check))
959 	{
960 	  if (source->base_addr == NULL
961 	      && source->attribute == CFI_attribute_allocatable)
962 	    {
963 	      fprintf (stderr, "CFI_setpointer: The source is an "
964 		       "allocatable object but is not allocated.\n");
965 	      return CFI_ERROR_BASE_ADDR_NULL;
966 	    }
967 	  if (source->rank > 0
968 	      && source->dim[source->rank - 1].extent == -1)
969 	    {
970 	      fprintf (stderr, "CFI_setpointer: The source is an "
971 		       "assumed-size array.\n");
972 	      return CFI_INVALID_EXTENT;
973 	    }
974 	  if (result->elem_len != source->elem_len)
975 	    {
976 	      fprintf (stderr, "CFI_setpointer: Element lengths of result "
977 		       "(result->elem_len = %" PRIiPTR ") and source "
978 		       "(source->elem_len = %" PRIiPTR ") "
979 		       " must be the same.\n",
980 		       (ptrdiff_t)result->elem_len,
981 		       (ptrdiff_t)source->elem_len);
982 	      return CFI_INVALID_ELEM_LEN;
983 	    }
984 
985 	  if (result->rank != source->rank)
986 	    {
987 	      fprintf (stderr, "CFI_setpointer: Ranks of result "
988 		       "(result->rank = %d) and source (source->rank = %d) "
989 		       "must be the same.\n", result->rank, source->rank);
990 	      return CFI_INVALID_RANK;
991 	    }
992 
993 	  if (result->type != source->type)
994 	    {
995 	      fprintf (stderr, "CFI_setpointer: Types of result "
996 		       "(result->type = %d) and source (source->type = %d) "
997 		       "must be the same.\n", result->type, source->type);
998 	      return CFI_INVALID_TYPE;
999 	    }
1000 	}
1001 
1002       /* If the source is a disassociated pointer, the result must also
1003 	 describe a disassociated pointer. */
1004       if (source->base_addr == NULL
1005 	  && source->attribute == CFI_attribute_pointer)
1006 	result->base_addr = NULL;
1007       else
1008 	result->base_addr = source->base_addr;
1009 
1010       /* Assign components to result. */
1011       result->version = source->version;
1012 
1013       /* Dimension information. */
1014       for (int i = 0; i < source->rank; i++)
1015 	{
1016 	  if (lower_bounds != NULL)
1017 	    result->dim[i].lower_bound = lower_bounds[i];
1018 	  else
1019 	    result->dim[i].lower_bound = source->dim[i].lower_bound;
1020 
1021 	  result->dim[i].extent = source->dim[i].extent;
1022 	  result->dim[i].sm = source->dim[i].sm;
1023 	}
1024     }
1025 
1026   return CFI_SUCCESS;
1027 }
1028