This is an archive of the discontinued LLVM Phabricator instance.

[flang] Allow function result as ALLOCATABLE arg
AbandonedPublic

Authored by luporl on Apr 5 2023, 7:01 AM.

Details

Summary

Allow the result of a function that has the ALLOCATABLE attribute
to be used as an actual argument in procedures that expect an
ALLOCATABLE dummy argument. This is allowed by gfortran and ifort,
but as it is not standards conforming, a portability warning is
emitted when this extension is used.

Fixes https://github.com/llvm/llvm-project/issues/60226

Diff Detail

Event Timeline

luporl created this revision.Apr 5 2023, 7:01 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptApr 5 2023, 7:01 AM
Herald added a subscriber: sunshaoce. · View Herald Transcript
luporl requested review of this revision.Apr 5 2023, 7:01 AM

I don't think that this patch implements correct Fortran behavior. While function result can indeed have the ALLOCATABLE attribute within the function, the attribute is not part of the function's characteristics, and in the calling context the result of the function is a value, not a variable (*), and it explicitly does not have the ALLOCATABLE attribute.

See Note 1 in 8.5.3: "Only variables and components can have the ALLOCATABLE attribute. The result of referencing a func- tion whose result variable has the ALLOCATABLE attribute is a value that does not itself have the ALLOCATABLE attribute."

(*) A function can return an object pointer, and in that case it is a variable in the calling context.

I don't think that this patch implements correct Fortran behavior. While function result can indeed have the ALLOCATABLE attribute within the function, the attribute is not part of the function's characteristics, and in the calling context the result of the function is a value, not a variable (*), and it explicitly does not have the ALLOCATABLE attribute.

See Note 1 in 8.5.3: "Only variables and components can have the ALLOCATABLE attribute. The result of referencing a func- tion whose result variable has the ALLOCATABLE attribute is a value that does not itself have the ALLOCATABLE attribute."

(*) A function can return an object pointer, and in that case it is a variable in the calling context.

I agree that F2018 standard doesn't allow the result of a function that has the ALLOCATABLE attribute to be used as an actual argument in procedures that expect an ALLOCATABLE dummy argument, given Note 1 in 8.5.3.

However, in F2003 and F2008 standards there is no such note in the description of the ALLOCATABLE attribute.
So, isn't it possible that this is allowed by them? If so, couldn't we support this when -std=f2003 or -std=f2008 is specified?
This would improve our compatibility with other compilers, such as gfortran and ifort.

On a quick search through F2003/F2008 docs, I didn't find anything that disallows this use of an ALLOCATABLE function result, but I don't have much knowledge of the standards to assert this.

luporl edited the summary of this revision. (Show Details)Apr 6 2023, 11:02 AM

We don't have a means to restrict the compiler to use only an earlier edition of the standard, and generally with Fortran that hasn't been desirable (with the famous exception of F'2003's introduction of (re)allocation of left-hand sides of assignments to allocatables, which can cause slowdowns that are easily fixed with a minor source change).

J3 seems to have gone out of its way here to make F'2008 conforming code non-conforming with F'2018. It may have been inadvertent. But if it was intentional, and for a good reason, then we might expect these two compilers to catch up and start emitting errors where they currently do not do so.

You could ask the J3 committee's mailing list for clarification on this point, and you might or might not get a useful response.

If it turns out that it's a defensible extension to retain the old behavior, you should also extend the analysis of procedure characteristics to represent an allocatable function result as a distinguishing characteristic for the purpose of procedure pointer and actual/dummy procedure compatibility checking.

luporl added a comment.Apr 6 2023, 1:18 PM

Ok, thanks for the detailed response.
I'll try to ask J3 committee's mailing list for clarification on this point, as you suggested.

luporl added a comment.Apr 6 2023, 2:56 PM

Before sending an email to J3 committee's mailing list, I did some research in its archives and found some interesting discussions:

  1. https://mailman.j3-fortran.org/pipermail/j3/2017-March/010158.html
  2. https://mailman.j3-fortran.org/pipermail/j3/2012-April/005029.html

Item 1 makes it clear that the intention is to prohibit code such as move_alloc ( F(X), V ).
In item 2, F2008 5.3.3 "ALLOCATABLE attribute" is quoted to argue that a similiar construct (DO, WHILE(ALLOCATED(F())) is not conforming:

An entity with the ALLOCATABLE attribute is a VARIABLE

Lastly, I tried to compile a program that uses a function result as an ALLOCATABLE argument, with NAG compiler, and it reports an error (even with -f2003 or -f2008):
Expected an ALLOCATABLE variable for argument P

Therefore, now I am convinced that this was not intended to be supported in F2003/F2008. The purpose of the note in F2018 then seems to be that of clarifying this point.

luporl abandoned this revision.Apr 6 2023, 2:58 PM

Before sending an email to J3 committee's mailing list, I did some research in its archives and found some interesting discussions:

  1. https://mailman.j3-fortran.org/pipermail/j3/2017-March/010158.html
  2. https://mailman.j3-fortran.org/pipermail/j3/2012-April/005029.html

Item 1 makes it clear that the intention is to prohibit code such as move_alloc ( F(X), V ).
In item 2, F2008 5.3.3 "ALLOCATABLE attribute" is quoted to argue that a similiar construct (DO, WHILE(ALLOCATED(F())) is not conforming:

An entity with the ALLOCATABLE attribute is a VARIABLE

Lastly, I tried to compile a program that uses a function result as an ALLOCATABLE argument, with NAG compiler, and it reports an error (even with -f2003 or -f2008):
Expected an ALLOCATABLE variable for argument P

Therefore, now I am convinced that this was not intended to be supported in F2003/F2008. The purpose of the note in F2018 then seems to be that of clarifying this point.

However, since they do seem to work with at least two other compilers, perhaps they should be supported in f18 too for maximum portability.

If it turns out that it's a defensible extension to retain the old behavior, you should also extend the analysis of procedure characteristics to represent an allocatable function result as a distinguishing characteristic for the purpose of procedure pointer and actual/dummy procedure compatibility checking.

It looks like the standard already states that whether a function result is allocatable or not is defined as a characteristic of a procedure, and that I included that attribute as part of the definition of function result characteristics. So the necessary compatibility checks should already work.

Suggestion: if this extension already works in f18, add a portability warning when it's used, and document it in Extensions.md. We should try to make it as easy as possible to port code to this new compiler, especially when it comes to language extensions supported by multiple other existing Fortran compilers that are unambiguous, well defined, and actually used in existing code.

luporl reclaimed this revision.Apr 6 2023, 4:03 PM

OK, I think I rushed a little bit with regards to this topic.
Increasing the compatibility with other compilers would be great.

Can you add a small lowering test to check lowering is OK with this extension (given lowering deals with pointer and allocatable in a very similar way, it probably is, but it is best to ensure this remains so).

In previous discussion with @klausler, I think we had quickly discussed that this extension would raise the question: what if the callee deallocate/reallocates the allocatable? Lowering inserts clean-up code when it faces a function that returns an allocatable. Can you make sure that this cleanup code is conditional on the allocation status after the call, and that it is not assuming that the base address to be cleaned-up is the same as the one at the point where the allocatable was returned (in case the call reallocated it)?

luporl updated this revision to Diff 514223.EditedApr 17 2023, 7:21 AM
  • Added a portability warning and documented the use of function results as allocatable arguments in Extensions.md.
  • Changed IsAllocatableOrPointerObject() to handle allocatable function results (without this, lowering of intrinsic arguments triggers an assert).
  • Changed allocated() checks to emit an error when trying to use a function result as argument (because gfortran doesn't support this).
  • Added a lowering test, to confirm that the generated FIR handles deallocation/reallocation of allocatable function results properly.

While inspecting the FIR for the lowering test, I noticed that the x variable is not deallocated automatically, even if the function call is removed and x is allocated with allocate().
It seems to be a known issue: https://github.com/orgs/llvm/projects/12/views/1?pane=issue&itemId=23809512

luporl edited the summary of this revision. (Show Details)Apr 17 2023, 7:30 AM
luporl edited the summary of this revision. (Show Details)

While inspecting the FIR for the lowering test, I noticed that the x variable is not deallocated automatically, even if the function call is removed and x is allocated with allocate().
It seems to be a known issue: https://github.com/orgs/llvm/projects/12/views/1?pane=issue&itemId=23809512

Yes, that is a know issue, since it does not cause "correctness issues" it had been sitting for a while even though it is not a hard TODO.

Thanks for the update and answers. The lowering aspects looks good to me.

klausler accepted this revision.Apr 25 2023, 7:42 AM
This revision is now accepted and ready to land.Apr 25 2023, 7:42 AM

gfortran just turned returning a function result as an ALLOCATABLE arg into an error: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109500

In the report, it's said that this was likely only supported by accident and that the new Intel Fortran compiler, ifx, also doesn't support this.
So flang would be one of the only supporting this extension, that IMHO doesn't seem worth anymore, even though this patch is almost ready to land (the lowering test need to be updated to work with recent changes).

Any comments on this?

The purpose of this patch was to remove a code porting barrier, but if the other compilers that support(ed) this feature no longer do so, then the motivation of the patch seems to have evaporated.

jeanPerier accepted this revision.May 9 2023, 2:19 AM

Any comments on this?

Thanks for this update. I agree with Peter here. Thanks a lot for the work and the update on this patch though, it is appreciated, even if this does not make it in!

luporl abandoned this revision.May 9 2023, 3:27 AM

Thanks for all comments and feedback. Closing this now.