[PATCH] libcpp: Correct typo 'r' -> '\r'
[official-gcc.git] / libgfortran / runtime / ISO_Fortran_binding.c
blobd22d0066ace442274546fcedd63e1a6f507c024f
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-2024 Free Software Foundation, Inc.
5 Contributed by Daniel Celis Garza <celisdanieljr@gmail.com>
6 and Paul Thomas <pault@gcc.gnu.org>
8 This file is part of the GNU Fortran runtime library (libgfortran).
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.
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.
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.
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/>. */
29 #include "libgfortran.h"
30 #include "ISO_Fortran_binding.h"
31 #include <string.h>
32 #include <inttypes.h> /* for PRIiPTR */
34 extern void cfi_desc_to_gfc_desc (gfc_array_void *, CFI_cdesc_t **);
35 export_proto(cfi_desc_to_gfc_desc);
37 /* NOTE: Since GCC 12, the FE generates code to do the conversion
38 directly without calling this function. */
39 void
40 cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
42 int n;
43 index_type kind;
44 CFI_cdesc_t *s = *s_ptr;
46 if (!s)
47 return;
49 GFC_DESCRIPTOR_DATA (d) = s->base_addr;
50 GFC_DESCRIPTOR_TYPE (d) = (signed char)(s->type & CFI_type_mask);
51 kind = (index_type)((s->type - (s->type & CFI_type_mask)) >> CFI_type_kind_shift);
53 /* Correct the unfortunate difference in order with types. */
54 if (GFC_DESCRIPTOR_TYPE (d) == BT_CHARACTER)
55 GFC_DESCRIPTOR_TYPE (d) = BT_DERIVED;
56 else if (GFC_DESCRIPTOR_TYPE (d) == BT_DERIVED)
57 GFC_DESCRIPTOR_TYPE (d) = BT_CHARACTER;
59 if (!s->rank || s->dim[0].sm == (CFI_index_t)s->elem_len)
60 GFC_DESCRIPTOR_SIZE (d) = s->elem_len;
61 else if (GFC_DESCRIPTOR_TYPE (d) != BT_DERIVED)
62 GFC_DESCRIPTOR_SIZE (d) = kind;
63 else
64 GFC_DESCRIPTOR_SIZE (d) = s->elem_len;
66 d->dtype.version = 0;
67 GFC_DESCRIPTOR_RANK (d) = (signed char)s->rank;
69 d->dtype.attribute = (signed short)s->attribute;
71 if (s->rank)
73 if ((size_t)s->dim[0].sm % s->elem_len)
74 d->span = (index_type)s->dim[0].sm;
75 else
76 d->span = (index_type)s->elem_len;
79 d->offset = 0;
80 if (GFC_DESCRIPTOR_DATA (d))
81 for (n = 0; n < GFC_DESCRIPTOR_RANK (d); n++)
83 CFI_index_t lb = 1;
85 if (s->attribute != CFI_attribute_other)
86 lb = s->dim[n].lower_bound;
88 GFC_DESCRIPTOR_LBOUND(d, n) = (index_type)lb;
89 GFC_DESCRIPTOR_UBOUND(d, n) = (index_type)(s->dim[n].extent + lb - 1);
90 GFC_DESCRIPTOR_STRIDE(d, n) = (index_type)(s->dim[n].sm / s->elem_len);
91 d->offset -= GFC_DESCRIPTOR_STRIDE(d, n) * GFC_DESCRIPTOR_LBOUND(d, n);
95 extern void gfc_desc_to_cfi_desc (CFI_cdesc_t **, const gfc_array_void *);
96 export_proto(gfc_desc_to_cfi_desc);
98 /* NOTE: Since GCC 12, the FE generates code to do the conversion
99 directly without calling this function. */
100 void
101 gfc_desc_to_cfi_desc (CFI_cdesc_t **d_ptr, const gfc_array_void *s)
103 int n;
104 CFI_cdesc_t *d;
106 /* Play it safe with allocation of the flexible array member 'dim'
107 by setting the length to CFI_MAX_RANK. This should not be necessary
108 but valgrind complains accesses after the allocated block. */
109 if (*d_ptr == NULL)
110 d = calloc (1, (sizeof (CFI_cdesc_t)
111 + (CFI_type_t)(CFI_MAX_RANK * sizeof (CFI_dim_t))));
112 else
113 d = *d_ptr;
115 d->base_addr = GFC_DESCRIPTOR_DATA (s);
116 d->elem_len = GFC_DESCRIPTOR_SIZE (s);
117 d->version = CFI_VERSION;
118 d->rank = (CFI_rank_t)GFC_DESCRIPTOR_RANK (s);
119 d->attribute = (CFI_attribute_t)s->dtype.attribute;
121 if (GFC_DESCRIPTOR_TYPE (s) == BT_CHARACTER)
122 d->type = CFI_type_Character;
123 else if (GFC_DESCRIPTOR_TYPE (s) == BT_DERIVED)
124 d->type = CFI_type_struct;
125 else
126 d->type = (CFI_type_t)GFC_DESCRIPTOR_TYPE (s);
128 if (GFC_DESCRIPTOR_TYPE (s) != BT_DERIVED)
129 d->type = (CFI_type_t)(d->type
130 + ((CFI_type_t)d->elem_len << CFI_type_kind_shift));
132 if (d->base_addr)
133 /* Full pointer or allocatable arrays retain their lower_bounds. */
134 for (n = 0; n < GFC_DESCRIPTOR_RANK (s); n++)
136 if (d->attribute != CFI_attribute_other)
137 d->dim[n].lower_bound = (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n);
138 else
139 d->dim[n].lower_bound = 0;
141 /* Assumed size arrays have gfc ubound == 0 and CFI extent = -1. */
142 if (n == GFC_DESCRIPTOR_RANK (s) - 1
143 && GFC_DESCRIPTOR_LBOUND(s, n) == 1
144 && GFC_DESCRIPTOR_UBOUND(s, n) == 0)
145 d->dim[n].extent = -1;
146 else
147 d->dim[n].extent = (CFI_index_t)GFC_DESCRIPTOR_UBOUND(s, n)
148 - (CFI_index_t)GFC_DESCRIPTOR_LBOUND(s, n) + 1;
149 d->dim[n].sm = (CFI_index_t)(GFC_DESCRIPTOR_STRIDE(s, n) * s->span);
152 if (*d_ptr == NULL)
153 *d_ptr = d;
156 void *CFI_address (const CFI_cdesc_t *dv, const CFI_index_t subscripts[])
158 int i;
159 char *base_addr = (char *)dv->base_addr;
161 if (unlikely (compile_options.bounds_check))
163 /* C descriptor must not be NULL. */
164 if (dv == NULL)
166 fprintf (stderr, "CFI_address: C descriptor is NULL.\n");
167 return NULL;
170 /* Base address of C descriptor must not be NULL. */
171 if (dv->base_addr == NULL)
173 fprintf (stderr, "CFI_address: base address of C descriptor "
174 "must not be NULL.\n");
175 return NULL;
179 /* Return base address if C descriptor is a scalar. */
180 if (dv->rank == 0)
181 return dv->base_addr;
183 /* Calculate the appropriate base address if dv is not a scalar. */
184 else
186 /* Base address is the C address of the element of the object
187 specified by subscripts. */
188 for (i = 0; i < dv->rank; i++)
190 CFI_index_t idx = subscripts[i] - dv->dim[i].lower_bound;
191 if (unlikely (compile_options.bounds_check)
192 && ((dv->dim[i].extent != -1 && idx >= dv->dim[i].extent)
193 || idx < 0))
195 fprintf (stderr, "CFI_address: subscripts[%d] is out of "
196 "bounds. For dimension = %d, subscripts = %d, "
197 "lower_bound = %" PRIiPTR ", upper bound = %" PRIiPTR
198 ", extent = %" PRIiPTR "\n",
199 i, i, (int)subscripts[i],
200 (ptrdiff_t)dv->dim[i].lower_bound,
201 (ptrdiff_t)(dv->dim[i].extent - dv->dim[i].lower_bound),
202 (ptrdiff_t)dv->dim[i].extent);
203 return NULL;
206 base_addr = base_addr + (CFI_index_t)(idx * dv->dim[i].sm);
210 return (void *)base_addr;
215 CFI_allocate (CFI_cdesc_t *dv, const CFI_index_t lower_bounds[],
216 const CFI_index_t upper_bounds[], size_t elem_len)
218 if (unlikely (compile_options.bounds_check))
220 /* C descriptor must not be NULL. */
221 if (dv == NULL)
223 fprintf (stderr, "CFI_allocate: C descriptor is NULL.\n");
224 return CFI_INVALID_DESCRIPTOR;
227 /* The C descriptor must be for an allocatable or pointer object. */
228 if (dv->attribute == CFI_attribute_other)
230 fprintf (stderr, "CFI_allocate: The object of the C descriptor "
231 "must be a pointer or allocatable variable.\n");
232 return CFI_INVALID_ATTRIBUTE;
235 /* Base address of C descriptor must be NULL. */
236 if (dv->base_addr != NULL)
238 fprintf (stderr, "CFI_allocate: Base address of C descriptor "
239 "must be NULL.\n");
240 return CFI_ERROR_BASE_ADDR_NOT_NULL;
244 /* If the type is a Fortran character type, the descriptor's element
245 length is replaced by the elem_len argument. */
246 if (dv->type == CFI_type_char || dv->type == CFI_type_ucs4_char)
247 dv->elem_len = elem_len;
249 /* Dimension information and calculating the array length. */
250 size_t arr_len = 1;
252 /* If rank is greater than 0, lower_bounds and upper_bounds are used. They're
253 ignored otherwise. */
254 if (dv->rank > 0)
256 if (unlikely (compile_options.bounds_check)
257 && (lower_bounds == NULL || upper_bounds == NULL))
259 fprintf (stderr, "CFI_allocate: The lower_bounds and "
260 "upper_bounds arguments must be non-NULL when "
261 "rank is greater than zero.\n");
262 return CFI_INVALID_EXTENT;
265 for (int i = 0; i < dv->rank; i++)
267 dv->dim[i].lower_bound = lower_bounds[i];
268 dv->dim[i].extent = upper_bounds[i] - dv->dim[i].lower_bound + 1;
269 dv->dim[i].sm = dv->elem_len * arr_len;
270 arr_len *= dv->dim[i].extent;
274 dv->base_addr = calloc (arr_len, dv->elem_len);
275 if (dv->base_addr == NULL)
277 fprintf (stderr, "CFI_allocate: Failure in memory allocation.\n");
278 return CFI_ERROR_MEM_ALLOCATION;
281 return CFI_SUCCESS;
286 CFI_deallocate (CFI_cdesc_t *dv)
288 if (unlikely (compile_options.bounds_check))
290 /* C descriptor must not be NULL */
291 if (dv == NULL)
293 fprintf (stderr, "CFI_deallocate: C descriptor is NULL.\n");
294 return CFI_INVALID_DESCRIPTOR;
297 /* Base address must not be NULL. */
298 if (dv->base_addr == NULL)
300 fprintf (stderr, "CFI_deallocate: Base address is already NULL.\n");
301 return CFI_ERROR_BASE_ADDR_NULL;
304 /* C descriptor must be for an allocatable or pointer variable. */
305 if (dv->attribute == CFI_attribute_other)
307 fprintf (stderr, "CFI_deallocate: C descriptor must describe a "
308 "pointer or allocatable object.\n");
309 return CFI_INVALID_ATTRIBUTE;
313 /* Free and nullify memory. */
314 free (dv->base_addr);
315 dv->base_addr = NULL;
317 return CFI_SUCCESS;
321 int CFI_establish (CFI_cdesc_t *dv, void *base_addr, CFI_attribute_t attribute,
322 CFI_type_t type, size_t elem_len, CFI_rank_t rank,
323 const CFI_index_t extents[])
325 if (unlikely (compile_options.bounds_check))
327 /* C descriptor must not be NULL. */
328 if (dv == NULL)
330 fprintf (stderr, "CFI_establish: C descriptor is NULL.\n");
331 return CFI_INVALID_DESCRIPTOR;
334 /* Rank must be between 0 and CFI_MAX_RANK. */
335 if (rank < 0 || rank > CFI_MAX_RANK)
337 fprintf (stderr, "CFI_establish: Rank must be between 0 and %d, "
338 "0 < rank (0 !< %d).\n", CFI_MAX_RANK, (int)rank);
339 return CFI_INVALID_RANK;
342 /* If base address is not NULL, the established C descriptor is for a
343 nonallocatable entity. */
344 if (attribute == CFI_attribute_allocatable && base_addr != NULL)
346 fprintf (stderr, "CFI_establish: If base address is not NULL, "
347 "the established C descriptor must be "
348 "for a nonallocatable entity.\n");
349 return CFI_INVALID_ATTRIBUTE;
353 dv->base_addr = base_addr;
355 if (type == CFI_type_char || type == CFI_type_ucs4_char
356 || type == CFI_type_struct || type == CFI_type_other)
358 /* Note that elem_len has type size_t, which is unsigned. */
359 if (unlikely (compile_options.bounds_check) && elem_len == 0)
361 fprintf (stderr, "CFI_establish: The supplied elem_len must "
362 "be greater than zero.\n");
363 return CFI_INVALID_ELEM_LEN;
365 dv->elem_len = elem_len;
367 else if (type == CFI_type_cptr)
368 dv->elem_len = sizeof (void *);
369 else if (type == CFI_type_cfunptr)
370 dv->elem_len = sizeof (void (*)(void));
371 else if (unlikely (compile_options.bounds_check) && type < 0)
373 fprintf (stderr, "CFI_establish: Invalid type (type = %d).\n",
374 (int)type);
375 return CFI_INVALID_TYPE;
377 else
379 /* base_type describes the intrinsic type with kind parameter. */
380 size_t base_type = type & CFI_type_mask;
381 /* base_type_size is the size in bytes of the variable as given by its
382 * kind parameter. */
383 size_t base_type_size = (type - base_type) >> CFI_type_kind_shift;
384 /* Kind type 10 maps onto the 80-bit long double encoding on x86.
385 Note that this has different storage size for -m32 than -m64. */
386 if (base_type_size == 10)
387 base_type_size = sizeof (long double);
388 /* Complex numbers are twice the size of their real counterparts. */
389 if (base_type == CFI_type_Complex)
390 base_type_size *= 2;
391 dv->elem_len = base_type_size;
394 dv->version = CFI_VERSION;
395 dv->rank = rank;
396 dv->attribute = attribute;
397 dv->type = type;
399 /* Extents must not be NULL if rank is greater than zero and base_addr is not
400 NULL */
401 if (rank > 0 && base_addr != NULL)
403 if (unlikely (compile_options.bounds_check) && extents == NULL)
405 fprintf (stderr, "CFI_establish: Extents must not be NULL "
406 "if rank is greater than zero and base address is "
407 "not NULL.\n");
408 return CFI_INVALID_EXTENT;
411 for (int i = 0; i < rank; i++)
413 /* The standard requires all dimensions to be nonnegative.
414 Apparently you can have an extent-zero dimension but can't
415 construct an assumed-size array with -1 as the extent
416 of the last dimension. */
417 if (unlikely (compile_options.bounds_check) && extents[i] < 0)
419 fprintf (stderr, "CFI_establish: Extents must be nonnegative "
420 "(extents[%d] = %" PRIiPTR ").\n",
421 i, (ptrdiff_t)extents[i]);
422 return CFI_INVALID_EXTENT;
424 dv->dim[i].lower_bound = 0;
425 dv->dim[i].extent = extents[i];
426 if (i == 0)
427 dv->dim[i].sm = dv->elem_len;
428 else
430 CFI_index_t extents_product = 1;
431 for (int j = 0; j < i; j++)
432 extents_product *= extents[j];
433 dv->dim[i].sm = (CFI_index_t)(dv->elem_len * extents_product);
438 return CFI_SUCCESS;
442 int CFI_is_contiguous (const CFI_cdesc_t *dv)
444 if (unlikely (compile_options.bounds_check))
446 /* C descriptor must not be NULL. */
447 if (dv == NULL)
449 fprintf (stderr, "CFI_is_contiguous: C descriptor is NULL.\n");
450 return 0;
453 /* Base address must not be NULL. */
454 if (dv->base_addr == NULL)
456 fprintf (stderr, "CFI_is_contiguous: Base address of C descriptor "
457 "is already NULL.\n");
458 return 0;
461 /* Must be an array. */
462 if (dv->rank <= 0)
464 fprintf (stderr, "CFI_is_contiguous: C descriptor must describe "
465 "an array.\n");
466 return 0;
470 /* Assumed size arrays are always contiguous. */
471 if (dv->rank > 0 && dv->dim[dv->rank - 1].extent == -1)
472 return 1;
474 /* If an array is not contiguous the memory stride is different to
475 the element length. */
476 for (int i = 0; i < dv->rank; i++)
478 if (i == 0 && dv->dim[i].sm == (CFI_index_t)dv->elem_len)
479 continue;
480 else if (i > 0
481 && dv->dim[i].sm == (CFI_index_t)(dv->dim[i - 1].sm
482 * dv->dim[i - 1].extent))
483 continue;
485 return 0;
488 /* Array sections are guaranteed to be contiguous by the previous test. */
489 return 1;
493 int CFI_section (CFI_cdesc_t *result, const CFI_cdesc_t *source,
494 const CFI_index_t lower_bounds[],
495 const CFI_index_t upper_bounds[], const CFI_index_t strides[])
497 /* Dimension information. */
498 CFI_index_t lower[CFI_MAX_RANK];
499 CFI_index_t upper[CFI_MAX_RANK];
500 CFI_index_t stride[CFI_MAX_RANK];
501 int zero_count = 0;
503 if (unlikely (compile_options.bounds_check))
505 /* C descriptors must not be NULL. */
506 if (source == NULL)
508 fprintf (stderr, "CFI_section: Source must not be NULL.\n");
509 return CFI_INVALID_DESCRIPTOR;
512 if (result == NULL)
514 fprintf (stderr, "CFI_section: Result must not be NULL.\n");
515 return CFI_INVALID_DESCRIPTOR;
518 /* Base address of source must not be NULL. */
519 if (source->base_addr == NULL)
521 fprintf (stderr, "CFI_section: Base address of source must "
522 "not be NULL.\n");
523 return CFI_ERROR_BASE_ADDR_NULL;
526 /* Result must not be an allocatable array. */
527 if (result->attribute == CFI_attribute_allocatable)
529 fprintf (stderr, "CFI_section: Result must not describe an "
530 "allocatable array.\n");
531 return CFI_INVALID_ATTRIBUTE;
534 /* Source must be some form of array (nonallocatable nonpointer array,
535 allocated allocatable array or an associated pointer array). */
536 if (source->rank <= 0)
538 fprintf (stderr, "CFI_section: Source must describe an array.\n");
539 return CFI_INVALID_RANK;
542 /* Element lengths of source and result must be equal. */
543 if (result->elem_len != source->elem_len)
545 fprintf (stderr, "CFI_section: The element lengths of "
546 "source (source->elem_len = %" PRIiPTR ") and result "
547 "(result->elem_len = %" PRIiPTR ") must be equal.\n",
548 (ptrdiff_t)source->elem_len, (ptrdiff_t)result->elem_len);
549 return CFI_INVALID_ELEM_LEN;
552 /* Types must be equal. */
553 if (result->type != source->type)
555 fprintf (stderr, "CFI_section: Types of source "
556 "(source->type = %d) and result (result->type = %d) "
557 "must be equal.\n", source->type, result->type);
558 return CFI_INVALID_TYPE;
562 /* Stride of zero in the i'th dimension means rank reduction in that
563 dimension. */
564 for (int i = 0; i < source->rank; i++)
566 if (strides[i] == 0)
567 zero_count++;
570 /* Rank of result must be equal the the rank of source minus the number of
571 * zeros in strides. */
572 if (unlikely (compile_options.bounds_check)
573 && result->rank != source->rank - zero_count)
575 fprintf (stderr, "CFI_section: Rank of result must be equal to the "
576 "rank of source minus the number of zeros in strides "
577 "(result->rank = source->rank - zero_count, %d != %d "
578 "- %d).\n", result->rank, source->rank, zero_count);
579 return CFI_INVALID_RANK;
582 /* Lower bounds. */
583 if (lower_bounds == NULL)
585 for (int i = 0; i < source->rank; i++)
586 lower[i] = source->dim[i].lower_bound;
588 else
590 for (int i = 0; i < source->rank; i++)
591 lower[i] = lower_bounds[i];
594 /* Upper bounds. */
595 if (upper_bounds == NULL)
597 if (unlikely (compile_options.bounds_check)
598 && source->dim[source->rank - 1].extent == -1)
600 fprintf (stderr, "CFI_section: Source must not be an assumed-size "
601 "array if upper_bounds is NULL.\n");
602 return CFI_INVALID_EXTENT;
605 for (int i = 0; i < source->rank; i++)
606 upper[i] = source->dim[i].lower_bound + source->dim[i].extent - 1;
608 else
610 for (int i = 0; i < source->rank; i++)
611 upper[i] = upper_bounds[i];
614 /* Stride */
615 if (strides == NULL)
617 for (int i = 0; i < source->rank; i++)
618 stride[i] = 1;
620 else
622 for (int i = 0; i < source->rank; i++)
624 stride[i] = strides[i];
625 /* If stride[i] == 0 then lower[i] and upper[i] must be equal. */
626 if (unlikely (compile_options.bounds_check)
627 && stride[i] == 0 && lower[i] != upper[i])
629 fprintf (stderr, "CFI_section: If strides[%d] = 0, then "
630 "lower_bounds[%d] = %" PRIiPTR " and "
631 "upper_bounds[%d] = %" PRIiPTR " must be equal.\n",
632 i, i, (ptrdiff_t)lower_bounds[i], i,
633 (ptrdiff_t)upper_bounds[i]);
634 return CFI_ERROR_OUT_OF_BOUNDS;
639 /* Check that section upper and lower bounds are within the array bounds. */
640 if (unlikely (compile_options.bounds_check))
641 for (int i = 0; i < source->rank; i++)
643 bool assumed_size
644 = (i == source->rank - 1 && source->dim[i].extent == -1);
645 CFI_index_t ub
646 = source->dim[i].lower_bound + source->dim[i].extent - 1;
647 if (lower_bounds != NULL
648 && (lower[i] < source->dim[i].lower_bound
649 || (!assumed_size && lower[i] > ub)))
651 fprintf (stderr, "CFI_section: Lower bounds must be within "
652 "the bounds of the Fortran array "
653 "(source->dim[%d].lower_bound "
654 "<= lower_bounds[%d] <= source->dim[%d].lower_bound "
655 "+ source->dim[%d].extent - 1, "
656 "%" PRIiPTR " <= %" PRIiPTR " <= %" PRIiPTR ").\n",
657 i, i, i, i,
658 (ptrdiff_t)source->dim[i].lower_bound,
659 (ptrdiff_t)lower[i],
660 (ptrdiff_t)ub);
661 return CFI_ERROR_OUT_OF_BOUNDS;
664 if (upper_bounds != NULL
665 && (upper[i] < source->dim[i].lower_bound
666 || (!assumed_size && upper[i] > ub)))
668 fprintf (stderr, "CFI_section: Upper bounds must be within "
669 "the bounds of the Fortran array "
670 "(source->dim[%d].lower_bound "
671 "<= upper_bounds[%d] <= source->dim[%d].lower_bound "
672 "+ source->dim[%d].extent - 1, "
673 "%" PRIiPTR " !<= %" PRIiPTR " !<= %" PRIiPTR ").\n",
674 i, i, i, i,
675 (ptrdiff_t)source->dim[i].lower_bound,
676 (ptrdiff_t)upper[i],
677 (ptrdiff_t)ub);
678 return CFI_ERROR_OUT_OF_BOUNDS;
681 if (upper[i] < lower[i] && stride[i] >= 0)
683 fprintf (stderr, "CFI_section: If the upper bound is smaller than "
684 "the lower bound for a given dimension (upper[%d] < "
685 "lower[%d], %" PRIiPTR " < %" PRIiPTR "), then the "
686 "stride for said dimension must be negative "
687 "(stride[%d] < 0, %" PRIiPTR " < 0).\n",
688 i, i, (ptrdiff_t)upper[i], (ptrdiff_t)lower[i],
689 i, (ptrdiff_t)stride[i]);
690 return CFI_INVALID_STRIDE;
694 /* Set the base address. We have to compute this first in the case
695 where source == result, before we overwrite the dimension data. */
696 result->base_addr = CFI_address (source, lower);
698 /* Set the appropriate dimension information that gives us access to the
699 * data. */
700 for (int i = 0, o = 0; i < source->rank; i++)
702 if (stride[i] == 0)
703 continue;
704 result->dim[o].lower_bound = 0;
705 result->dim[o].extent = 1 + (upper[i] - lower[i])/stride[i];
706 result->dim[o].sm = stride[i] * source->dim[i].sm;
707 o++;
710 return CFI_SUCCESS;
714 int CFI_select_part (CFI_cdesc_t *result, const CFI_cdesc_t *source,
715 size_t displacement, size_t elem_len)
717 if (unlikely (compile_options.bounds_check))
719 /* C descriptors must not be NULL. */
720 if (source == NULL)
722 fprintf (stderr, "CFI_select_part: Source must not be NULL.\n");
723 return CFI_INVALID_DESCRIPTOR;
726 if (result == NULL)
728 fprintf (stderr, "CFI_select_part: Result must not be NULL.\n");
729 return CFI_INVALID_DESCRIPTOR;
732 /* Attribute of result will be CFI_attribute_other or
733 CFI_attribute_pointer. */
734 if (result->attribute == CFI_attribute_allocatable)
736 fprintf (stderr, "CFI_select_part: Result must not describe an "
737 "allocatable object (result->attribute != %d).\n",
738 CFI_attribute_allocatable);
739 return CFI_INVALID_ATTRIBUTE;
742 /* Base address of source must not be NULL. */
743 if (source->base_addr == NULL)
745 fprintf (stderr, "CFI_select_part: Base address of source must "
746 "not be NULL.\n");
747 return CFI_ERROR_BASE_ADDR_NULL;
750 /* Source and result must have the same rank. */
751 if (source->rank != result->rank)
753 fprintf (stderr, "CFI_select_part: Source and result must have "
754 "the same rank (source->rank = %d, result->rank = %d).\n",
755 (int)source->rank, (int)result->rank);
756 return CFI_INVALID_RANK;
759 /* Nonallocatable nonpointer must not be an assumed size array. */
760 if (source->rank > 0 && source->dim[source->rank - 1].extent == -1)
762 fprintf (stderr, "CFI_select_part: Source must not describe an "
763 "assumed size array (source->dim[%d].extent != -1).\n",
764 source->rank - 1);
765 return CFI_INVALID_DESCRIPTOR;
769 /* Element length is ignored unless result->type specifies a Fortran
770 character type. */
771 if (result->type == CFI_type_char || result->type == CFI_type_ucs4_char)
772 result->elem_len = elem_len;
774 if (unlikely (compile_options.bounds_check))
776 /* Ensure displacement is within the bounds of the element length
777 of source.*/
778 if (displacement > source->elem_len - 1)
780 fprintf (stderr, "CFI_select_part: Displacement must be within the "
781 "bounds of source (0 <= displacement <= source->elem_len "
782 "- 1, 0 <= %" PRIiPTR " <= %" PRIiPTR ").\n",
783 (ptrdiff_t)displacement,
784 (ptrdiff_t)(source->elem_len - 1));
785 return CFI_ERROR_OUT_OF_BOUNDS;
788 /* Ensure displacement and element length of result are less than or
789 equal to the element length of source. */
790 if (displacement + result->elem_len > source->elem_len)
792 fprintf (stderr, "CFI_select_part: Displacement plus the element "
793 "length of result must be less than or equal to the "
794 "element length of source (displacement + result->elem_len "
795 "<= source->elem_len, "
796 "%" PRIiPTR " + %" PRIiPTR " = %" PRIiPTR " <= %" PRIiPTR
797 ").\n",
798 (ptrdiff_t)displacement, (ptrdiff_t)result->elem_len,
799 (ptrdiff_t)(displacement + result->elem_len),
800 (ptrdiff_t)source->elem_len);
801 return CFI_ERROR_OUT_OF_BOUNDS;
805 if (result->rank > 0)
807 for (int i = 0; i < result->rank; i++)
809 result->dim[i].lower_bound = source->dim[i].lower_bound;
810 result->dim[i].extent = source->dim[i].extent;
811 result->dim[i].sm = source->dim[i].sm;
815 result->base_addr = (char *) source->base_addr + displacement;
816 return CFI_SUCCESS;
820 int CFI_setpointer (CFI_cdesc_t *result, CFI_cdesc_t *source,
821 const CFI_index_t lower_bounds[])
823 /* Result must not be NULL and must be a Fortran pointer. */
824 if (unlikely (compile_options.bounds_check))
826 if (result == NULL)
828 fprintf (stderr, "CFI_setpointer: Result is NULL.\n");
829 return CFI_INVALID_DESCRIPTOR;
832 if (result->attribute != CFI_attribute_pointer)
834 fprintf (stderr, "CFI_setpointer: Result shall be the address of a "
835 "C descriptor for a Fortran pointer.\n");
836 return CFI_INVALID_ATTRIBUTE;
840 /* If source is NULL, the result is a C descriptor that describes a
841 * disassociated pointer. */
842 if (source == NULL)
844 result->base_addr = NULL;
845 result->version = CFI_VERSION;
847 else
849 /* Check that the source is valid and that element lengths, ranks
850 and types of source and result are the same. */
851 if (unlikely (compile_options.bounds_check))
853 if (source->base_addr == NULL
854 && source->attribute == CFI_attribute_allocatable)
856 fprintf (stderr, "CFI_setpointer: The source is an "
857 "allocatable object but is not allocated.\n");
858 return CFI_ERROR_BASE_ADDR_NULL;
860 if (source->rank > 0
861 && source->dim[source->rank - 1].extent == -1)
863 fprintf (stderr, "CFI_setpointer: The source is an "
864 "assumed-size array.\n");
865 return CFI_INVALID_EXTENT;
867 if (result->elem_len != source->elem_len)
869 fprintf (stderr, "CFI_setpointer: Element lengths of result "
870 "(result->elem_len = %" PRIiPTR ") and source "
871 "(source->elem_len = %" PRIiPTR ") "
872 " must be the same.\n",
873 (ptrdiff_t)result->elem_len,
874 (ptrdiff_t)source->elem_len);
875 return CFI_INVALID_ELEM_LEN;
878 if (result->rank != source->rank)
880 fprintf (stderr, "CFI_setpointer: Ranks of result "
881 "(result->rank = %d) and source (source->rank = %d) "
882 "must be the same.\n", result->rank, source->rank);
883 return CFI_INVALID_RANK;
886 if (result->type != source->type)
888 fprintf (stderr, "CFI_setpointer: Types of result "
889 "(result->type = %d) and source (source->type = %d) "
890 "must be the same.\n", result->type, source->type);
891 return CFI_INVALID_TYPE;
895 /* If the source is a disassociated pointer, the result must also
896 describe a disassociated pointer. */
897 if (source->base_addr == NULL
898 && source->attribute == CFI_attribute_pointer)
899 result->base_addr = NULL;
900 else
901 result->base_addr = source->base_addr;
903 /* Assign components to result. */
904 result->version = source->version;
906 /* Dimension information. */
907 for (int i = 0; i < source->rank; i++)
909 if (lower_bounds != NULL)
910 result->dim[i].lower_bound = lower_bounds[i];
911 else
912 result->dim[i].lower_bound = source->dim[i].lower_bound;
914 result->dim[i].extent = source->dim[i].extent;
915 result->dim[i].sm = source->dim[i].sm;
919 return CFI_SUCCESS;