Bug 45424

Summary: [F08] Add IS_CONTIGUOUS intrinsic
Product: gcc Reporter: Tobias Burnus <burnus>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: gcc-bugs, janus, quantheory
Priority: P3    
Version: 4.6.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2013-12-20 00:00:00
Bug Depends on: 36825, 53298    
Bug Blocks: 39627, 53320    
Attachments: Draft patch: is_contiguous.diff

Description Tobias Burnus 2010-08-27 07:48:09 UTC
For compile-time checking that can simply use the the gfc_is_simply_contiguous check. For run time, it should use the flag in the descriptor (if existing) or some library check, cf. pack checks.

Because of the potential descriptor element, mark dependent on PR 36825.

From Fortran 2008:


Description.  Test contiguity of an array (5.3.7).
Class.  Inquiry function.
Argument.  ARRAY may be of any type. It shall be an array. If it is a pointer it shall be associated.
Result Characteristics.  Default logical scalar.
Result Value.  The result has the value true if ARRAY is contiguous, and false otherwise.
Example.  After the pointer assignment AP => TARGET (1:10:2), IS_CONTIGUOUS (AP) has the value false.
Comment 1 Tobias Burnus 2012-05-09 15:36:40 UTC
Created attachment 27359 [details]
Draft patch: is_contiguous.diff

Attached is a mostly ready patch for IS_CONTIGUOUS.

The main TODO is to understand when IS_CONTIGUOUS should print .TRUE. and when .FALSE. The standard is not very clear about it, cf. 5.3.7 of F2008.

a) Array element with nonzero strides (which is still a single array element): "a(1:1:1)" vs. "a(1:1:5)". With the attached patch but also with ifort and crayftn, the result is .true. and .false. The attached patch only checks the "stride", ignoring the number of elements.

b) The same - but instead of a single element, using zero-sized arrays: a(2:1:1) vs. a(2:1:2).

c) The following example is mishandled as we have a stride and not a stride multiplied (sm):

type t
  integer :: i, j
end type t
type(t) :: x(5)
print *, is_contiguous(x(:)) ! Shall be (and is) true
print *, is_contiguous(x(:)%i) ! Shall be false - but prints "true".

The fortran-devel solution would be to use: sm == TYPE_SIZE(a%i). The trunk solution is to compare the array spec's object "a" with the the type-size of "a%i" - and if it differs to abort.

d) The gfc_is_simply_contiguous function needs to be refined and extended - and a "gfc_is_simply_noncontiguous" has to be added.

e) More tests are needed - including polymorphic arrays and compile-time checks for the code in simplify.c. [Which is related to (d).]

f) For TS29113, one needs to handle assumed-rank arrays, including rank-1 ones. Again the question is whether the dummy argument associated with a scalar is then contiguous or not.
Comment 2 Tobias Burnus 2012-05-09 16:02:18 UTC
(In reply to comment #1)
> a) Array element with nonzero strides

I meant: A an array containing a single element and having a nonunity stride.

> type t
>   integer :: i, j
> end type t
> print *, is_contiguous(x(:)%i) ! Shall be false - but prints "true".

Those kind of arguments can get really tricky! Assume as component a:
    integer :: i(1) ! or "i(2)
    class(t), allocatable :: a
    integer, allocatable :: a(:)
which is accessed as "is_contiguous(x(:)%a(1))".

Intel and Cray handle it simply: by always returning "F" - even for "type t; integer :: i; end type", which should have no padding and be contiguous in memory. We could do the same - or we rule out BT_CLASS, arrays and coarrays and do then a size check: whole derived type == expr->ts.type size.

Another issue are substrings. For those one needs to check that the substring range matches the string length.
Comment 3 Sean Santos 2013-04-19 21:12:06 UTC
A naive interpretation of the standard suggests that in the case "a)", is_contiguous should return .true., because the standard doesn't say anything about strides here, only about the ordering of the elements. (Of course strides matter for "simply contiguous" things, but that's different.)

Case "b)" seems to be the same.

In case "f)", since scalars can be associated with assumed-rank entities that have the contiguous attribute, it wouldn't make much sense to return ".false." in this case.
Comment 4 janus 2013-04-20 17:41:22 UTC
(In reply to comment #1)
> d) The gfc_is_simply_contiguous function needs to be refined and extended - and
> a "gfc_is_simply_noncontiguous" has to be added.

Another application for 'gfc_is_simply_noncontiguous' would be to reject invalid code like

  integer, dimension(1:5,1:5), target :: zzz
  type(c_ptr) :: ptr
  ptr = c_loc (zzz(4:,4:))

cf. http://gcc.gnu.org/ml/fortran/2013-04/msg00181.html and follow-ups.