Problem with CHARACTER(*) :: PICKLIST(:)

Problem with CHARACTER(*) :: PICKLIST(:)

I have a program that I am working on in two different places on my computer. The programs are nearly identical. Here is excerpt:

PROGRAM TEST_EDCELL

INTEGER, PARAMETER :: LENGTH = 5

CHARACTER(20) :: PICKLIST(LENGTH)

... define PICKLIST(1) through PICKLIST(5)...

CALL EDCELL (IROW, ICOL, ...PICKLIST...RETURNCODE)

END PROGRAM

 

SUBROUTINE PICKLIST (IROW, ICOL, ...PICKLIST...RETURNCODE)

CHARACTER(*) :: PICKLIST(:)

...

PRINT *, PICKLIST

END SUBROUTINE

In the first location this program runs fine. In the second location it compiles and links without error, but gives a runtime error "Program execption-stack overflow" on the PRINT *, PICKLIST line. In the debugger watchlist, PICKLIST is identified as "Undefined pointer/array".

I cannot see any differences in the codes or the directory structure that could cause these differences. In both cases I am running 2011.10.325. I believe that all of the compiler and link switches are standard. Can you suggest where or how to look for the cause? 

32 Beiträge / 0 neu
Letzter Beitrag
Nähere Informationen zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.

(I think you used the wrong name for the name of the subroutine.)

CHARACTER(*) :: PICKLIST(:)

That's a declaration for an assumed shape (the "(:)") dummy argument. In order for a procedure with an assumed shape argument to be invoked, an explicit interface (perhaps from the procedure being a module procedure or an internal procedure, or perhaps from an INTERFACE block for the procedure provided by the programmer) needs to be accessible in the invoking scope. Is this the case in your program?

Check whether the presence of PICKLIST as an argument of the subroutine makes it necessary for you to provide an explicit interface to the subroutine in the calling routine.

You gave only fragments of code, and I don't wish to speculate about this question.

"Check whether the presence of PICKLIST as an argument of the subroutine makes it necessary for you to provide an explicit interface"

How do I do this? I find the documentation confusing and hard to interpret on this matter, so I was hoping you could explain it. I normally get a compiler error when I omit an explicit interface if one is necessary. I don't get any errors or even warnings here. And why would it work in one environment and not the other?

Also, I should have mentioned that if i change the subroutine declaration to CHARACTER(*)::PICKLIST(*), then it works. I thought this was a deprecated (or at least not recommended) form of the more modern (:) usage.

Section 5.3.8 of the Fortran 2008 Standard, for instance, presents definitions of assumed-shape and assumed-size subprogram arguments. Section 12.4.2.2 lists cases where an explicit interface is to be available to the caller; case (2)(b) pertains to the example below.

Here is a version of your code with the subroutine name corrected (see IanH's comments above).


PROGRAM TEST_EDCELL

INTEGER, PARAMETER :: LENGTH = 5

CHARACTER(20) :: PICKLIST(LENGTH)

CALL EDCELL (PICKLIST)

END PROGRAM
SUBROUTINE EDCELL (PICKLIST)

CHARACTER(*) :: PICKLIST(:)

PRINT *, PICKLIST

END SUBROUTINE

Compile to flag the error:


S:lang>ifort /warn:all boggs.f90

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 13.0.1.119 Build 20121008

Copyright (C) 1985-2012 Intel Corporation.  All rights reserved.
boggs.f90(4): error #7978: Required interface for passing assumed shape array is missing from original source   [PICKLIST]

CALL EDCELL (PICKLIST)

-------------^

compilation aborted for boggs.f90 (code 1)

Quite frequently, and especially in the context of subprogram arguments, assumed shape arrays and assumed size arrays are not interchangeable.

And similar to C, C++ where forward function references require function prototype, FORTRAN programs require an equivilent prototype when passing assumed shape arrays. FOTRAN calls these interfaces.


INTERFACE

SUBROUTINE EDCELL (PICKLIST)

CHARACTER(*) :: PICKLIST(:)

END SUBROUTINE

END INTERFACE

Note, in C/C++ the types are declared in the argument list. In FORTRAN you surround and empty body subroutine.function with INTERFACE and END INTERFACE. The interface(s) are best placed in a module, but when used, say within one compilation unit, you can also place in the body of the calling proceedure (before first statement in calling subroutine/function).

Jim Dempsey

www.quickthreadprogramming.com

I think there is a concise answer to the original question, being that the following two declarations are different.
CHARACTER(*) :: PICKLIST(:)
CHARACTER(*) :: PICKLIST(*)
.
The first uses an assumed shape argument, so it requires (demands) an interface to provide the array dimension.
The second uses an assumed size argument, which says that the character array is of unknown size, but does not receive the array size.
CHARACTER(*) implies that both receive the byte size of each element of the character array.
.
Compiling the following (revised) example should show the difference.
.
CHARACTER(4) :: PICKLIST_sha(7)
CHARACTER(5) :: PICKLIST_siz(3)
integer*4 i
!
INTERFACE
subroutine test_shape (picklist_shape)
CHARACTER(*) :: PICKLIST_shape(:)
end subroutine test_shape
END INTERFACE
!
do i = 1,7
write (picklist_sha(i),1001) 'sh_',i
end do
do i = 1,3
write (picklist_siz(i),1001) 'si_',i
end do
1001 format (a,i0)
!
call test_shape (picklist_sha)
call test_size (picklist_siz)
!
end
!
subroutine test_shape (picklist_shape)
!
CHARACTER(*) :: PICKLIST_shape(:)
!
write (*,*) picklist_shape(1), len(picklist_shape), size (picklist_shape)
!
end subroutine test_shape
!
subroutine test_size (picklist_size)
!
CHARACTER(*) :: PICKLIST_size(*)
!
write (*,*) picklist_size(1), len(picklist_size) ! , size (picklist_size) ! size fails here
!
end subroutine test_size

Thanks for this clarification John. I understand that when I use an assumed size array argument it is up to me to insure that in the subroutine I do not overwrite the size of the array or nasty things may happen; whereas in an assumed shape argument the compiler knows the sizes and takes care of it for me--as long as an interface is provided.

But I have trouble coming to grips with recommended practice. I have about 30 old F77 programs that I must upgrade. Many of these used assumed length arguments. Apparently this is still fine, but from my readings I concluded that the practice is now frowned upon and should be avoided, using instead assumed-shape arguments "due to the additional capabilities available." This is the only reason I had tried the CHARACTER(*)::PICKLIST(:) syntax. I didn't know that an explicit interface was required. I am alarmed to see that it works sometimes without an explicit interface, but when I move the source to another location on my computer, or hand the source off to someone else, then it may not work. IF IT CAN'T BE GUARANTEED TO WORK WITHOUT AN EXPLICIT INTERFACE, THEN WHY DOESN'T THE COMPILER GIVE AN ERROR! I would have straightened out much earlier if it did.

What I read about obsolescent, obsolete, deleted, and recommended practice on this matter is quite confusing. Is there any good reason why I should not continue to use assumed-size array arguments, especially on existing programs where they already exist and have demonstrated bug-free use for many years?

In the case where you pass a procedure as an argument and then call it from another routine, the compiler can't know what is being called from where so can't give you an error. It will normally give an error if you call a procedure that requires an explicit interface where there isn't one, if you call it directly and have the "Check Routine Interfaces" option on (it is on by default in a Debug configuration.)

There is no reason to change code just because the usage is obsolete. But in this case, be aware that the use of assumed-length character functions is error-prone and many programmers misunderstand what it means.

Steve - Intel Developer Support

I didn't pass a procedure as an argument and then call it from another routine (I don't even know how to do that). Here is a simple test program:

Program AssumedSizeArgument
     ! Testing for the legality of passing an assumed-shape array without an interface.
     Implicit none
     integer:: ia(5)
     integer:: i
     do i = 1, 5
          ia(i) = i
     end do
     call sub (ia)
end program
Subroutine sub (ia)
     integer :: ia(:)
     print *, ia
end subroutine

When I compile this, provided I have the default show all warnings on (/warn:all), then I will get a warning about the lack of an interface. But if the program and the subroutine are in two separate files, no warning is given. (I don't know about the "check routine interfaces" option, where is it set?) Depending on environment, sometime the program builds and executes OK, sometimes it builds but gives a runtime error, and dometimes it fails to link.

After investigating this at some length it seems to me that the lack of an interface definitely lies outside the F90+ rules. Why doesn't the compiler show an error, or even a warning if the subroutine is in a different file from the calling program (as is very often the case, especially if it is in a library)?

(Also: how do I get a program sample or fragment pasted into this window and have it nicely formatted?)

Imagine in the case that the two program units are in different files, that subroutine sub is compiled a week later than the main program, by a different person, on a different machine.  Until the subroutine is compiled the compiler doesn't know that the main program is in error.  Given the way Fortran processors are typically implemented the only way that the error can be discovered is by some link time magic (that step could possibly take place a week later still, by a third person, on a third machine!).  This is not so easy to arrange - the linker is typically language agnostic. 

(Perhaps procedures that required an explicit interface in the calling scope could have their linker name mangled differently (?), but the resulting error message is not likely to be all that illuminating for users anyway.)

If assumed size works for you, then leave it alone. The main reason for moving away from assumed size in my mind is that the syntax for using
the rather handy array operations that F90 onward provide becomes more convoluted if you want to use those in any modifications that you subsequently do.  But assumed size arguments are not formally obsolete and there are some use cases where they are still required in new code.

(Why is your dummy argument assumed size versus explicit size?  If the answer is "I don't know the size of the array in the calling scope", then you can't use explicit shape, or assumed shape for that matter.)

(Outside of those use cases I always prefer assumed shape to assumed size (or explicit size even) in new code, indeed in many instances my new code uses features that exclude assumed size, so the preference is moot.)

Opinionated babble following: of more concern from a style/practice point of view to me would be that you have procedures being invoked that don't have an explicit interface, regardless of whether they are using F90 argument capabilities or not. In the absence of some select reasons to the contrary all your procedures should be internal procedures or module procedures. If I was actively maintaining a code base then fixing that would be much, much higher in priority than switching from assumed size to assumed shape.

(Assumed length character functions referred to above are a different beastie - they are obsolete and rather evil, but as part of moving all procedures into modules you would need to eliminate them anyway.)

Generated interface checking can tell you about problems in separate files, but only if the called routine is compiled first.

To paste Fortran code and have it formatted, see the fourth bullet in the text below the post entry box.

The reason I said you were calling PICKLIST as a passed routine is that the partial code you showed in the first post indicated you were doing that. You passed PICKLIST as an argument to EDCELL but never showed EDCELL. I assumed you called PICKLIST indirectly from EDCELL.

Steve - Intel Developer Support

Zitat:

After investigating this at some length it seems to me that the lack of an interface definitely lies outside the F90+ rules.
What? Your program does not provide a required interface, and according to the Fortran standard the program is in error. There is nothing "outside the ..rules" here.

Zitat:

Why doesn't the compiler show an error, or even a warning if the subroutine is in a different file from the calling program (as is very often the case, especially if it is in a library)?
Programmers are good at deceiving the compiler. If the compiler has not been shown the declaration of the subroutine, it cannot know whether the argument passed to the subroutine is assumed size or assumed shape. Fortran 77 and earlier had only assumed size, so the compiler defaults to "assumed size" if you do not give it the necessary information regarding assumed shape arrays. If the called subroutine is in a library, neither the compiler nor you can know whether the argument is assumed shape or assumed size -- that information has to come from source code, correctly written documentation or a module file.

A compiler is not required to detect all programmer errors. Even when some types of error checking are possible, there is an associated cost to that checking and in practice only limited (if any) checking is compiled into production code.

Why does your buggy code "work" sometimes? Most commonly, for an assumed shape array argument a descriptor is passed. Often (this is implementation-dependent) the first member of the descriptor is the address of the array, following which there can be information about size, upper and lower bounds, etc. If the subroutine uses only the array, and none of the other items, it picks up the correct address and may work "correctly". However, the program is still in error and you are required to remove the error, lest you encounter catastrophic failure of your application when using a different compiler, different compiler switches, different OS, etc.

Ian's position of "Assumed length character functions referred to above are a different beastie - they are obsolete and rather evil" looks to be a bit extreme and baseless to me. Alternatively, it could be reasonably argued that the whole INTERFACE structure is flawed, as duplicate declarations of the called routine interface is a bad concept, prone to error.
There is an alternative, which is the F77 approach of including the array size as an argument. This could be a good comprimise for F77 style code, although if the original code works, do you need to add the array size checking?
.
CHARACTER(5) :: PICKLIST_siz(3)
integer*4 i
!
do i = 1,size (picklist_siz)
write (picklist_siz(i),1001) 'si_',i
end do
1001 format (a,i0)
!
call test_size (picklist_siz, size (picklist_siz))
!
end

subroutine test_size (picklist_size, n)
!
integer*4 n
CHARACTER(*) :: PICKLIST_size(n)
!
write (*,*) picklist_size(1), len(picklist_size), size (picklist_size) ! size works now
!
end subroutine test_size

John

PS: for some reason, unknown to me, the comment box is using rich text and changing the post format. Could it be my explorer settings ?

Thanks everyone for their comments. Let me try to clarify some things.

I am well aware of the traditional F77 technique of passing the length of the array argument as an accompanying argument. I do that wherevery possible. Sometimes it is not, or at least very inconvenient. I am also well aware of the benefits of internal procedures and modules in this matter. Sometimes they just have to be external.

As to mecej4's discussion of not being able to tell an assumed size array from an assumed length, I thought it was in the declaration syntax: a(*) means assumed size and a(:) means assumed shape.

We could probably go on and on about good vs. bad practice, but that's not what I'm questioning here. The simple demo program I gave was only to illustrate the error/warning behavior of the compiler.

But I think I now understand that the compiler is simply unable to detect whether the calling routine provided an explicit interface or not, so it cannot report an error. However, when compiling an external subroutine with a dummary array declared a(:), it should know that an interface is required, however, and it would be "nice" if it gave a warning to that effect. When it sees the dummy array declared a(*) it should know that an explicit interface is not required, so no warning would be expected. In my case a small clan of programmers struggled with the development of a library subroutine in which the original coder carelessly assumed he should change the orginal (*) syntax to the new (:) syntax, and he distributed it to others that way for testing and further development. For everyone the compiler always reported "0 errors 0 warnings." Sometimes the resulting program would work and sometimes it would not, causing a range of problems from linker errors to runtime. This set us back a couple of weeks in understanding the problem. A compiler warning would have led us to it almost immediately. 

 

As I said, the compiler does have this ability - but it is dependent on which source it compiles first.

Your later posted code doesn't look like what you posted initially, so I am unsure what your real application looks like.

Steve - Intel Developer Support

Zitat:

John Campbell schrieb:

Ian's position of "Assumed length character functions referred to above are a different beastie - they are obsolete and rather evil" looks to be a bit extreme and baseless to me.

Perhaps - but while the "evil" bit is certainly just a matter of my opinion, their obsolescense is a matter of fact.  Do you actually use them?  They are pretty bizarre. 

(I think they only got introduced into the thread because of a naming error in the initial example?)

I agree that duplicating the source declaration of a procedure is error prone - which is why you only do it when you absolutely have to and use modules for everything else (and if you are using modules, I think the language rules say you can't use assumed length character functions, but perhaps I'm hallucinating from the heat again).

I realize that I got confused by your use of the name PICKLIST for two different things - I should have been paying closer attention. You can ignore what I said about passing routines as arguments.

Steve - Intel Developer Support

From my example above, the two calls are:
call test_shape (picklist_sha)
call test_size (picklist_siz)
.
Without the use of an INTERFACE definition or if the calling syntax of the two routines is available to the compiler via a USE module, how can the compiler differentiate between an assumed size call or an assumed shape call ?
The more general problem is that the argument list transfer syntax available has not been capable of transferring the necessary information to describe this more effectively. This has been a long term problem that INTERFACE tried to address, but only partially. We needed a F_EXTERNAL calling convention, but that was never agreed.
Until that ever comes, (inter-operability means never), you have to be careful if using assumed shape arguments. They might be the new way, but hardly robust.
.
John

Could you elaborate how you think some sort of new calling convention would fix the issue? 

Upthread I was thinking that any external procedure that used language features that required an explicit interface (bar BIND(C)) could have something like "$dear_programmer_you_forgot_to_provide_an_explicit_interface" appended to its linker name.  In the calling scope the compiler in the absence of an interface block would generate the the wrong name (nothing appended) for the reference.  If there was an explicit interface available in the calling scope the compiler could use that to determine whether the procedure met the criteria of requiring an explicit interface and then generate the appropriate linker name.  Fortran-fortran libraries that used the affected procedures would need to be recompiled (or the additional mangling suppressed by compiler switch), but I'd expect the number of use cases of people "interfacing" outside of Fortran with the sort of procedure that would have its linker name mangled in such a way would be small.

A warning that I think would be more useful than the one dboggs suggested ("external procedure using language features that requrie an explicit interface be accessible where the procedure is invoked") would be to warn when the compiler sees any procedure without an explicit interface.  I think that's been discussed here recently.  Other compilers I use do this. 

(I appreciate that you would want to be able to control this warning as it would drive you nuts when compiling old code (in the same manner as warning about implicit typing), but in large modern code bases where all procedures have explicit interfaces it similarly drives me nuts to have to wait around for the link stage in order to find out that you mispelled some procedure call early on in the compile.)

As you say - the issue is that the compiler needs to have explicit knowledge about the nature of some called procedures at the time that it encounters the calls.  I disagree, though, that the language has failed to solve this robustly - as the use of modules guarantees that the compiler explicitly has this information - the compiler must have seen the definition of the module prior to its point of use.  If you are required to use interface blocks to provide that explicit knowledge to the compiler (explicit interfaces) in clean-slate modern Fortran code today it is typically (always?) because you as a programmer cannot practically arrange for the definition of the procedure to be fed to the Fortran compiler before the call, perhaps because of some circular dependency, or an impractically large source base, or because the called procedure isn't written in Fortran.  If you are not using the available robust solution (modules) because of a legacy code base, then I think all other solutions to the problem would similarly be not available.

(The existance of valid reasons in the rules of the language (independent of style) for being forced to use interface blocks for procedures that require an explicit interface be available in the calling scope is one of the reasons why I'm not so keen on dbogg's suggested warning message (don't warn me about something that the language is forcing me to do in new code).  While always having an interface available is a practice/style issue, I don't think there is anything in the language rules that prevent you from always providing such an interface in new code (you can fix your code to avoid the warning).)

(If your two example calls are in response to me they both involve assumed length character arguments (very much on my "good" list), not assumed length character functions ("evil", more so than statement functions even...).)

We appear to have disparate views on the benefits/dangers of using assumed-shape array arguments (and, for similar reasons, optional and allocatable arguments). Please permit me to state a pragmatic point of view.

Assume that we wish to access subprograms which, according to the Fortran standard, require an explicit interface, and are part of a pre-compiled library or DLL; we want to write code with calls to those subprograms.

(i) If we have module files containing, among other things, the required interfaces, we should include the appropriate USE statements in our code. The compiler can then warn if our calls do not adhere to the interface. This is the approach used in commercial libraries such as IMSL and MKL.

(ii) If we wish to use a library as in (i) but do not have the module files, or the module files are not compatible with our Fortran compiler, we need to write INTERFACE blocks or modules containing interfaces by consulting the documentation of the library routines, and make these interfaces available in each caller.

(iii) If we are unable to provide the required interfaces, we should not link against the library, because the resulting code will probably be unstable and error-prone, and the compiler cannot give any warnings or run-time errors related to the missing interfaces.

Re: "If we are unable to provide the required interfaces, we should not link against the library...the compiler cannot give any warnings..."

Yes it can--just do it! There is a well defined set of criteria for when an interface is required, and if the compiler cannot tell if one was provided (i.e. the procedure is not a module or internal), then I think it should give a warning. In the example at hand, there is a subroutine with array argument A declared as A(:), and it caused trouble. On the other hand the declaration A(*) did not cause trouble. OK, the first method is more robust (safer), but only if the interface is provided. It would have saved a lot of trouble if the compiler had simply warned that an explicit array must be provided. Here is a case where the A(*) (assumed length) technique actually caused less trouble, only because the coder didn't realize that A(:) required an interface.

(To clarify: using A(*) the code consistently compiles and links OK, and runs OK as long as the programmer is careful that the subroutine code does not overwrite the bounds of A. Using A(:), without an interface, the program consistently compiles OK, but doesn't always link, and when it does link, it runs OK sometimes and fails other times, even when the code does not overwrite the bounds of A. So I feel that the assumed length A(*) method is more reliable than the assumed shape A(:) method, UNLESS THE COMPILER ISSUES A WARNING ABOUT NEEDING AN INTERFACE.)

I once tried a coding approach to provide the calling information for all routines in a project. I defined a single module with interface definitions for all routines. Unfortunately, when I compiled it with the compiler I was using at that time, it failed as I could not have an interface defined within the same subroutine. If this was accepted, this could be a very good outcome, as the compiler could then check the interface definition ( which is used throughout the project) against the actual routine definition.
This would negate the main objection I have with the INTERFACE structure, which is the duplicate definition of the interface. It could be argued that the INTERFACE definition could be used in this way as the definition of the calling interface for the routine.
Does anyone else see the benefit of what I am proposing ?
.
What can be done is to create a module of interface definitions for all external libraries I use. This is a good coding practice. Unfortunately with the present limitations, this must be done carefully, as the interface is not checked against the actual routine.
.
To answer part of Ian's question, the main functionality of argument list checking that I had wanted (and requested) was merely a check on the argument list count. This simple test could have removed many errors in coding, before IDE's were available. Numerous times, in the 80's I tried out a new workstation fortran compiler, where the compiler developer introduced checks on the type and kind of each argument. For those familiar with memory management prior to F90, this was never a welcome error test, which had to be disabled, often to the strong objections of the compiler developer. Salesmen can be helpful some times!
What could be helpful is that for each argument, the kind, rank and size could be supplied automatically, to be used if required.
Another special case is to identify arguments that are constants ( eg 1.0 ), that should be flagged as INTENT=IN.
However there remains a requirement that all you are transferring is an address, to be used as the called routine requires. This option should never be excluded.
This approach might not appeal to some compiler developers or computer scientists, but it would answer the needs of this fortran programmer, who actually graduated with a computer science major in 1973. There have been many good programming rules come and go since then.
.
John

Zitat:

mecej4 schrieb:
(ii) If we wish to use a library as in (i) but do not have the module files, or the module files are not compatible with our Fortran compiler, we need to write INTERFACE blocks or modules containing interfaces by consulting the documentation of the library routines, and make these interfaces available in each caller.

If the module files are not compatible with your Fortran compiler, you are simply dead meat. That means that the Fortran procedures that require an explicit interface will not be compatible with your Fortran compiler, either.

Regarding another comment, permit me to remark that you can check an interface definition against the actual procedure if you provide code within the procedure to do it.

module ifaces
   implicit none
   interface
      subroutine s(x)
         real x(:)
      end subroutine s
   end interface
end module ifaces
subroutine s(x)
   use ifaces
   use ifaces, only: chk => s
   implicit none
   real x(:)
   procedure(chk), pointer :: p
   if(.FALSE.) p => s
   x = 1
end subroutine s
program p
   use ifaces
   implicit none
   real x(5)
   call s(x)
   write(*,*) x
end program p

Subroutine s here uses the module that provides an explicit interface for it. As is, the code compiles and runs. However if the interface body is changed to something incompatible, for e.g.,

interface
      subroutine s(x)
         real x(:,:)
      end subroutine s
   end interface

Then the compiler (gfortran) errors out. The checking should not cost anything at runtime because dead code and unused local variable elimination should throw it out.

Zitat:

Repeat Offender schrieb:
Regarding another comment, permit me to remark that you can check an interface definition against the actual procedure if you provide code within the procedure to do it.

(Do you have a stray "use ifaces" in your subroutine?  Assuming so...)

I don't think (and I'm far from sure about it) this is legal code.  The procedure defined by the external subprogram named "s" has two explicit specific interfaces available inside the scope of s - one from the use associated interface block and one from the specification statements of the subprogram itself.  F2008 12.4.3.2p7 doesn't like that.  The fact that those two different interfaces for the same procedure have different local names is not relevant.  This would not be something the compiler would be required to diagnose. 

Why the rules are this way I don't know, but them's the rules.

(ifort 13.0.1 gives an error for this example that I don't expect or understand, but as (I think) the program is non-conforming it could well be argued it is a valid response.)

The first "use ifaces" was there because normally one of your library procedures needs the explicit interfaces of the others. The second was there so that the name "s" referred only to the subroutine being defined, not the interface.

It may be possible that by ordering the words in the paragraph cited in some anagram as is your wont one might come up with a meaning that allows one to arrive at the conclusion that my code is nonconforming. No matter:

module ifaces
   implicit none
   abstract interface
      subroutine s_abstract(x)
         real x(:)
      end subroutine s_abstract
   end interface
   procedure(s_abstract) s
end module ifaces
subroutine s(x)
   use ifaces
   use ifaces, only: chk => s
   implicit none
   real x(:)
   procedure(s_abstract), pointer :: p
   if(.FALSE.) p => s
   x = 1
end subroutine s
program p
   use ifaces
   implicit none
   real x(5)
   call s(x)
   write(*,*) x
end program p

Anagrams are fun! 

The reason that I queried the first use statement is that it makes the ONLY: option on the second use redundant, plus wouldn't the "s" name clash inside the sub be nonconforming?  Change those use's to a single "use iface, only: s_abstract" and then I think I have to conceed to your point.

No, the rules for the USE statement bear a paradoxicality worthy of C. The "use ifaces, only: chk => s" hides the name "s" from ifaces so the only "s" is the name of the subroutine being defined. Unfortunately hiding the name "s" doesn't actually hide the interface for "s" so I may have to change to

module ifaces
   implicit none
   abstract interface
      subroutine s_abstract(x)
         real x(:)
      end subroutine s_abstract
   end interface
   procedure(s_abstract) s
end module ifaces
subroutine s(x)
   use ifaces, only: s_abstract
   implicit none
   real x(:)
   procedure(s_abstract), pointer :: p
   if(.FALSE.) p => s
   x = 1
end subroutine s
program p
   use ifaces
   implicit none
   real x(5)
   call s(x)
   write(*,*) x
end program p

as you said to make you happy. Is ifort similary joyful?

ifort isn't happy.  It gives the same error message that I didn't "expect or understand" before.

>ifort /check:all /warn:all /standard-semantics "2013-01-14 intf.f90"
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 13.0.1.119 Build 20121008
Copyright (C) 1985-2012 Intel Corporation.  All rights reserved.
2013-01-14 intf.f90(15): error #8191: The procedure target must be a procedure or a procedure pointer.   [S]
   if(.FALSE.) p => s
--------------------^
compilation aborted for 2013-01-14 intf.f90 (code 1)

Looking at F2008 C729 it could possibly be justified.  In terms of having a procedure name as a proc target...

"A procedure name shall be the name of ... an external procedure that is accessed by use or host association and is referenced in the scoping unit as a procedure or that has the EXTERNAL attribute..."

I don't know what the precedence of the last (bolded) "or" is supposed to be relative to the bolded "and".  Is "an external procedure ... that has the external attribute" valid in its own right, or must it be also accessed via host or use association.  I suspect the latter.

Since and is logical product and or is logical sum, and has precedence just like in Fortran, so my last example is conforming, unless you really prefer anagrams.
An example of how use, only: hides names from simple use:

module m1
   implicit none
   contains
      subroutine s
         write(*,'(a)') 'The host associated subroutine was called.'
      end subroutine s
end module m1
module m2
   implicit none
   contains
      subroutine s
         write(*,'(a)') 'The use associated subroutine was called.'
      end subroutine s
end module m2
module m3
   use m1, only: s => s
   implicit none
   contains
      subroutine t
         use m2
         use m2, only: chk => s
         call s
      end subroutine t
end module m3
program p
   use m3
   implicit none
   call t
end program p

gfortran and I vote for calling the host associated subroutine. g95 and ftn95 vote for the use associated subroutine. How do you and ifort vote?

Ifort agrees with you, after remarking about the ONLY.  Reading F2008 I can now see why.  There you go!

Not quite sure that I agree that the rules of "and" and "or" in the English language follow that of Fortran precedence, but this is not the first occasion that I'd have preferred the language to use parentheses for clarity...

I think I have decoded the meaning of C279. Section 5.3.9 says

subroutine s(x)
   implicit none
   character(*) x
   write(*,'(a)') 'Subroutine s was called '//x//'.'
end subroutine s
subroutine t(s)
   implicit none
   call s('from t')
end subroutine t
program p
   implicit none
   procedure(), pointer :: pp
   call s('legally')
   pp => s ! Illegal, see 5.3.9 p2
   call pp('illegally')
   call t(s) ! Also illegal, see 5.3.9 p2
end program p

is illegal, but C279 allows
subroutine s(x)
   implicit none
   character(*) x
   write(*,'(a)') 'Subroutine s was called '//x//'.'
end subroutine s
subroutine u(x)
   implicit none
   character(*) x
   write(*,'(a)') 'Subroutine u was called '//x//'.'
end subroutine u
program p
   implicit none
   external u
   call s('once')
   call t
   contains
      subroutine t
         procedure(), pointer :: pp
         pp => s ! Legal, see C729
         call pp('again')
         pp => u ! Legal, see C729
         call pp('from t')
      end subroutine t
end program p

However, both gfortran and g95 like the first example, and while g95 compiles the second example, it causes an ICE in gfortran.
If the main program of the first example is changed to
subroutine s(x)
   implicit none
   character(*) x
   write(*,'(a)') 'Subroutine s was called '//x//'.'
end subroutine s
subroutine t(s)
   implicit none
   call s('from t')
end subroutine t
program p
   implicit none
   procedure(), pointer :: pp
   pp => s ! Illegal, see 5.3.9 p2
   call pp('illegally')
   call t(s) ! Also illegal, see 5.3.9 p2
   call s('legally')
end program p

then g95 still likes it, but gfortran gets some kind of wierd error at link time. Any comments?

Kommentar hinterlassen

Bitte anmelden, um einen Kommentar hinzuzufügen. Sie sind noch nicht Mitglied? Jetzt teilnehmen