Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Do the associate contruct associations have a defined order of evalulation

Andrew_Smith
New Contributor III
1,078 Views

If we define multiple associations in a single construct is it legal for chained references or does it work by accident?

Neither the Intel documentation or the Fortran 2003 standard are any help here.

integer a
associate(b => a, c => b)
    c = 1
end associate

 

17 Replies
Arjen_Markus
Honored Contributor I
1,073 Views

Well, gfortran does not accept it:

assoc.f90:8:24:

 associate(b => a, c => b)
                        1
Error: Symbol ‘b’ at (1) has no IMPLICIT type
assoc.f90:8:24:

 associate(b => a, c => b)
                        1
Error: Symbol ‘c’ at (1) has no IMPLICIT type

and chaining would mean that you have to prevent circularity

associate(b => a, c => b, a => c)

(Note: I added "implicit none" to the test program - Intel Fortran did not complain then either)

IanH
Honored Contributor II
1,073 Views

The F2003 standard (and later) specifies that the association is active "during execution of that block" (F2003 8.1.4.2, and elsewhere).  "The block" is a reference to a component of the syntax of the construct - it is the non-inclusive bit in between the associate and end associate statements - i.e. the association is not (supposed to be) active within the associate statement itself.  The current compiler documentation has similar words.

Andrew_Smith
New Contributor III
1,073 Views

Thanks IanH, that seams to cover it.

0 Kudos
FortranFan
Honored Contributor II
1,073 Views

Arjen Markus wrote:

Well, gfortran does not accept it: .. 

(Note: I added "implicit none" to the test program - Intel Fortran did not complain then either)

Hopefully Intel Fortran team will make a note of this thread and follow up with an incident submission to implement a suitable error/warning mechanism for such code in a future version of the Intel Fortran compiler.

0 Kudos
Kevin_D_Intel
Employee
1,073 Views

With gfotran 6.3, when A is given an initial value before the ASSOCIATE and there is no IMPLICIT NONE, the cited code is accepted; however, the value of A after the construct is incorrect. With ifort, the value of A after the construct is correct both with and with IMPLICIT NONE.

In the ifort 17.0 User Gudie, under ASSOCIATE is says: “The associating entity assumes the declared type and type parameters of the selector.”  so I am uncertain whether the IMPLICIT NONE case should issue an error. I reported it to Development for them to analyze.

(Internal tracking id: DPD200417965)

0 Kudos
Steve_Lionel
Honored Contributor III
1,073 Views

I am not seeing anything wrong with ifort's behavior.

The key here is that the c=>b does not refer to the associate name b but whatever b is outside the construct. As Kevin notes, b is not given a type so it is default real but is uninitialized. Given that the selector is uninitialized, so its value is undefined.

If IMPLICIT NONE is used, then a compiler would be correct in complaining about c=>b since b has no declared type.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,073 Views

Kevin,

The IVF documentation relating to ASSOCIATE if the associate-name, when multiple assoc-entity's are used, can or must not be aliases of each other. Can you provide the rule on this, and include a note in future documentation.

A second point to address is to point out the difference between ASSOCIATE and a statement function where/when variables are use in subscripts within the selector.

Jim Dempsey

0 Kudos
Kevin_D_Intel
Employee
1,073 Views

Jim, I may not be understanding your comment. I don’t see such a rule in the Standard. As Steve noted, there’s no aliasing between a and c via b because the <selector> “b” in c => b is not the same entity as the <associate-name> from b => a so there’s no aliasing.

Can you expand or give an example related to the comment about the difference related to a statement function?

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,073 Views

associate( cell => array(X,Y))

Is (correct me if I am wrong)

real, target :: array(12,34)
real, pointer :: Pcell
...
Pcell => array(X,Y)

Where in both cases (cell and Pcell) resolve to the same address.

Note, in the associate case, array need not have TARGET

Now then consider two cenarios:

1) associate(cell1 => array(X,Y), cell2 => array(X,Y) ! same cell
    call sub(cell1, cell2)

2) associate(cell => array(X,Y))
    some_loop_iterating_through_array_and using_cell

In the first case, it is the programmers responsibility .NOT. to pass in aliased actual arguments (unless the callee permits this)

In the second case, you are permitted to do this, however, array does not have target attribute, and therefor compiler optimizations may not take this into consideration (unless the associate infers TARGET on array for the duration of the association).

It would be nice (informative) if the IFV documentation discussed this.

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,074 Views

Jim, you're describing a different issue, and are misrepresenting some of it. This has nothing to do with selectors that are themselves associate names in the same ASSOCIATE, as is earlier in this thread.

Both cases you show are acceptable because cell does indeed inherit TARGET from array. If array did not have TARGET, then the first call would still be ok on its own, but sub would be restricted in what it could do.

The second case is not a problem for the compiler - it can see everything it needs to know. Indeed, a lot of code works this way.

The documentation pretty much mirrors what the standard says. What additional text do you think would be worthwhile? Do keep in mind that the Intel Language Reference is not intended to teach the language.

0 Kudos
Andrew_Smith
New Contributor III
1,074 Views

My original example was too simplied. I should have given a working example nearer to my real application. Here is one. It prints 9 but according to Steve it should not compile because association a is not made yet at the point b is associated to it.

program Test
   implicit none
   type D
      integer x
   end type
   type(D) array(1)
   
   array%x = 0
   associate(a => array(1), b => a%x)
      b = 9
   end associate
   print *, array(1)%x
   pause
end 

 

Steve_Lionel
Honored Contributor III
1,074 Views

This is very interesting. My reading of the standard suggests that it is a compiler bug to allow Andrew's case in #12. Here is my reasoning (quotes are from the latest F2015 draft 17-007):

11.1.3.2 Execution of the ASSOCIATE construct

Execution of an ASSOCIATE construct causes evaluation of every expression within every selector that is a variable designator and evaluation of every other selector, followed by execution of its block. During execution of that block each associate name identifies an entity which is associated (19.5.1.6) with the corresponding selector.

Note the sequence of events here. First, all of the selectors are evaluated, and only once the block begins executing does the construct association occur. If my interpretation is correct, it is wrong to treat an associate name listed earlier in the same ASSOCIATE as a variable that can be used in a selector.

I can easily understand how this mistake could be made in a compiler. It's sort of like the way a declaration statement works, where the type and characteristics of a variable declared earlier in the same statement are allowed to be used in a later specification expression. But that's different from how ASSOCIATE works.

I'm going to run this by the standards committee to make sure my understanding is correct - will update here with the results.

FortranFan
Honored Contributor II
1,074 Views

Steve Lionel (Ret.) wrote:

This is very interesting. .. 

I can easily understand how this mistake could be made in a compiler. .. 

I'm going to run this by the standards committee ..

Kevin,

it appears Intel Fortran treats

   implicit none
   integer :: a
   associate ( b => a, c => b )
      c = 42
   end associate

the same as

   implicit none
   integer :: a
   asc1: associate ( b => a )
      asc2: associate ( c => b )
         c = 42
      end associate asc2
   end associate asc1

but gfortran does not; gfortran throws an error with the first construct.  Whereas with the second construct, the behavior is the same (as expected) using both the compilers.

It will be useful if you can confirm what the development team intended per their implementation of this Fortran 2003 feature in Intel Fortran so it can be reviewed vis-a-vis what Steve finds with the standards committee.

 

FortranFan
Honored Contributor II
1,074 Views

Steve Lionel (Ret.) wrote:

..

I'm going to run this by the standards committee to make sure my understanding is correct - will update here with the results.

Steve,

It will be useful if we can use the case shown below as a corollary item to review feedback from the standards committee:

program p

   implicit none

   integer :: a
   real :: b

   a = 0
   b = 0.0

   associate ( b => a, c => b )
      b = 42
      c = 99.0
   end associate

   print "(*(g0))", "Should a be 42 or 99?", new_line(""), "a = ", a
   print "(*(g0))", "Should b be 0.0 or 99.0?", new_line(""), "b = ", b

   stop

end program p

Using Intel Fortran, the output is:

Should a be 42 or 99?
a = 99
Should b be 0.0 or 99.0?
b = .000000

 

whereas using gfortran, one gets

Should a be 42 or 99?
a = 42
Should b be 0.0 or 99.0?
b = 99.0000000

 

I suspect gfortran is correct as suggested by comments in this thread but it will be good to get this cleared up.

0 Kudos
Steve_Lionel
Honored Contributor III
1,074 Views

I'm reasonably confident that Intel Fortran is not correct here. I have one response from a committee member so far but want to see at least another.

0 Kudos
Steve_Lionel
Honored Contributor III
1,074 Views
“The associate names of an ASSOCIATE construct have the scope of the block.”
This means that the association is only available after the ASSOCIATE statement.
It is confirmed that the ifort behavior is incorrect.
Kevin_D_Intel
Employee
1,078 Views

It appears we three (or at least two) defects here:

  1. ifort accepts a non-conformant program, post #12.
  2. ifort produces incorrect code/results for a conformant program, post #15.
  3. ifort accepts the OP’s test case with IMPLICIT NONE as noted in post #2.

I submitted all these separately to Development although there may be some overlap. All the internal tracking ids are summarized below.

Related to post #15, it was provided to me that the committee says the small program below should print 2.0 and 1.0, not 1.0 and 1.0. ifort produces the latter results; gfortran the former.

real :: a = 1, b = 2
associate(b=>a,a=>b)
print *,a,b
end associate
end

(Internal tracking id: DPD200417965 – ifort does not issue error for IMPLICIT NONE case)
(Internal tracking id: DPD200418193 – ifort accepts non-conformant ASSOCIATE usage – associate name used as selector)
(Internal tracking id: DPD200418195 – ifort produces incorrect results for ASSOCIATE)

Reply