# Debugging and PURE procedure cascade

**URL:** <https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937>\
**Category:** Help\
**Created:** [December 6, 2023, 11:33am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937 "2023-12-06T11:33:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mfurquan](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mfurquan](https://fortran-lang.discourse.group/u/mfurquan)\
**Post date:** [December 6, 2023, 11:33am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/1 "2023-12-06T11:33:54Z")

</div>

Printing selected values from an array is often required during debugging (selection criteria are hard to impose in debuggers). But, printing inside PURE procedures is restricted. Being an avid user of small PURE functions and do concurrent, in other words functional style, I have to modify the code unnecessarily just for debugging. Moreover, this leads to a cascade of changes as PURE procedures can only call PURE procedures, and thus I need to modify every other PURE procedure that calls the one under consideration.

There are three ways out that I can think of:

1. Use preprocessor to change from PURE to non PURE procedures, from DO CONCURRENT to simple DO in debugging mode. But, this will be non standard.

2. Use error stop cleverly. It cannot cover all use cases, however.

3. Carry around an extra argument for storing the desired value(s) and print it after you have exited all pure procedures. This will only work for pure subroutines.

Which way, from or other than those listed, is better?

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [December 6, 2023, 1:24pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/2 "2023-12-06T13:24:47Z")

</div>

In comp.lang.fortran in 2010, in response to the same question, Nick Maclaren [wrote](https://comp.lang.fortran.narkive.com/tiFi1246/pure-procedure#post2)

> You need to fool the compiler. You can write an external procedure  
> that just prints an error message and is not pure, and declare it  
> in a module as PURE. That might work.
> 
> If not, you can do the same trick by calling a jiffy little C  
> function to do the same, though I recommend using standard error  
> and not standard output. Again, that might work.
> 
> Beyond that, there are some system-dependent tricks that bypass  
> anything that Fortran knows about, but I don’t recommend most  
> people to use them. WTO under MVS, syslog under Unix, and so on.
> 
> But there is no guarantee that ANYTHING will work if the compiler  
> is sufficiently sensitive. That’s extremely unlikely, but it’s  
> not a good idea to rely on this trick being safe.

Here is an example with an external procedure. The following program,

```auto
subroutine thrice(x, y)
real, intent(in) :: x
real, intent(out) :: y
y = 3*x
print*,"x, y =", x, y 
end subroutine thrice
!
module m
implicit none
interface
pure subroutine thrice(x, y)
real, intent(in) :: x
real, intent(out) :: y
end subroutine thrice
end interface
contains
pure subroutine thrice_vec(x, y)
real, intent(in) :: x(:)
real, intent(out) :: y(:)
integer :: i
do i=1,size(x)
   call thrice(x(i), y(i))
end do
end subroutine thrice_vec
end module m
!
program main
use m
implicit none
real, dimension(2) :: x, y
x = [5.0, 6.0]
call thrice_vec(x, y)
print*,y
end program main

```

if the subroutine, module, and main program are stored in separate files, compiles and runs with gfortran, giving output

```auto
 x, y = 5.00000000 15.0000000    
 x, y = 6.00000000 18.0000000    
   15.0000000 18.000000

```

Your idea of using a preprocessor was discussed at [fortran - Gfortran: Treat pure functions as normal functions for debugging purposes? - Stack Overflow](https://stackoverflow.com/questions/19037789/gfortran-treat-pure-functions-as-normal-functions-for-debugging-purposes)

---

<div class="post-metadata">

**Author:** ![tyranids](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tyranids](https://fortran-lang.discourse.group/u/tyranids)\
**Post date:** [December 6, 2023, 2:15pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/3 "2023-12-06T14:15:35Z")

</div>

It’s pretty crazy to me that this works honestly. Once again, personally, I really dislike how weak `pure` is. I’ve never seen a routine that compiled to anything faster because it was `pure` (or `elemental` for that matter, in fact `elemental` is only ever _slower_, if it measures differently at all), and the supposed promise that “`pure` routines won’t have side effects” is too easy to get around. Also in this bucket is modifying `intent(in)` arguments.

I had to check, Fortran 95 introduced user-written `pure` and `elemental` procedures. 28 years later and they still seem more like just ideas rather than features that actually add any capability.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [December 6, 2023, 2:35pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/4 "2023-12-06T14:35:16Z")

</div>

Arguably the production version of a code should have all procedures in modules, in which case the compiler won’t be tricked. The procedures called within a `do-concurrent` block must be pure, and some [research](https://arxiv.org/abs/2110.10151) has found that do-concurrent can often replace directives. Elemental procedures are convenient, even if they are not faster, obviating the need to write versions of a function with permutations of scalar, 1D and 2D arguments, and the introduction of `impure elemental` procedures is a nice generalization.

Similarly, argument `intent`s are not guaranteed to be respected if a procedure calls other procedures without intents. but they are still beneficial in expressing the intent of the programmer.

---

<div class="post-metadata">

**Author:** ![tyranids](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tyranids](https://fortran-lang.discourse.group/u/tyranids)\
**Post date:** [December 6, 2023, 2:47pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/5 "2023-12-06T14:47:45Z")

</div>

I agree on all points. The unfortunate reality is that for a lot of legacy (i.e. “real”) Fortran projects, everything isn’t in modules. In that case, things like pure and argument intent sometimes trick a reader of the code into a false sense of understanding.

Honestly I would probably have preferred a compiler error be issued if pure or intent in is specified but the compiler cannot verify it. Just prevent people from keeping around code with incorrect tags. This is similar to comments that describe functionality, but are unmaintained or just incorrect in general.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [December 6, 2023, 2:53pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/6 "2023-12-06T14:53:01Z")

</div>

> [@tyranids](#):
>
> Honestly I would probably have preferred a compiler error be issued if pure or intent in is specified but the compiler cannot verify it. Just prevent people from keeping around code with incorrect tags. This is similar to comments that describe functionality, but are unmaintained or just incorrect in general.

That would make sense if Fortran 90 were starting from scratch, but when argument intents were introduced in Fortran 90, all the existing Fortran 77 and earlier code did not have intents, so not allowing a procedure with declared intents to call such code would have greatly reduced the applicability of argument intents.

---

<div class="post-metadata">

**Author:** ![tyranids](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tyranids](https://fortran-lang.discourse.group/u/tyranids)\
**Post date:** [December 6, 2023, 2:53pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/7 "2023-12-06T14:53:44Z")

</div>

Well, no. They can be used in modules. New feature only works in the new style, that’s the rule.

Also, it could still call them, but if my subroutine has argument `a` marked `intent(in)`, then I can’t supply `a` to another procedure down the call stack as anything other than verifiable `intent(in)`. I could still have local variables with no intents that get passed around like normal.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [December 6, 2023, 3:12pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/8 "2023-12-06T15:12:42Z")

</div>

> [@Beliavsky](#):
>
> argument `intent`s are not guaranteed to be respected if a procedure calls other procedures without intents

This is only true when calling procedures without explicit interfaces. The compiler just assumes you know what you’re doing if you’re calling procedures with implicit interfaces (because that’s what is backwards compatible). But, if you want to be warned about such things then add

```auto
implicit none (type, external)

```

I’m in favor of @Beliavsky approach to solving the “print in a pure procedure” problem, but ONLY FOR DEBUGGING. NEVER USE THE TRICK IN REAL CODE. Once you turn on optimizations, multi-threading, etc., you’re likely to hit race conditions in run-time and system libraries that make output inconsistent, and possibly even cause corruption.

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [December 6, 2023, 5:21pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/9 "2023-12-06T17:21:28Z")

</div>

How about using a block statement? Here is a modified example by @Beliavsky.

```auto
module m
   implicit none
contains
   pure subroutine thrice_vec(x, y)
      real, intent(in) :: x(:)
      real, intent(out) :: y(:)
      integer :: i
      do concurrent (i=1: size(x))
         y(i) = 3*x(i)
         DEBUG: block
            print*,"x, y =", x(i), y(i)
         end block DEBUG
      end do
   end subroutine thrice_vec
end module m
!
program main
   use m
   implicit none
   real, dimension(2) :: x, y
   x = [5.0, 6.0]
   call thrice_vec(x, y)
   print*,y
end program main

```

---

<div class="post-metadata">

**Author:** ![danielc](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/danielc/32/3774_2.png) [@danielc](https://fortran-lang.discourse.group/u/danielc)\
**Post date:** [December 7, 2023, 5:59am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/10 "2023-12-07T05:59:29Z")

</div>

> [@Ali](#):
>
> How about using a block statement? Here is a modified example by @Beliavsky.

I don’t think that a block statement removes the purity guarantee. I tried your code and GFortran gave me an error:

```plaintext
block.f90:12:39:

   12 | print*,"x, y =", x(i), y(i)
      | 1
Error: PRINT statement at (1) not allowed within PURE procedure

```

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [December 7, 2023, 7:03am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/11 "2023-12-07T07:03:01Z")

</div>

Yes `gfortran` gives error. `ifort` and `ifx` execute without any issues and `nvfortran` shows a warning but still displays the results:

```auto
ifort (IFORT) 2021.11.0 20231010
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 x, y = 5.000000 15.00000    
 x, y = 6.000000 18.00000    
   15.00000 18.00000

```

```auto
ifx (IFX) 2024.0.0 20231017
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 x, y = 5.000000 15.00000    
 x, y = 6.000000 18.00000    
   15.00000 18.00000

```

```auto
nvfortran 23.7-0 64-bit target on x86-64 Linux -tp haswell 
NVIDIA Compilers and Tools
Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
NVFORTRAN-W-0155-thrice_vec - PURE subprograms may not contain external I/O statements (deb.f90: 11)
  0 inform, 1 warnings, 0 severes, 0 fatal for thrice_vec
 x, y = 5.000000 15.00000    
 x, y = 6.000000 18.00000    
    15.00000 18.00000 

```

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [December 7, 2023, 9:09am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/12 "2023-12-07T09:09:41Z")

</div>

> [@tyranids](#):
>
> Well, no. They can be used in modules. New feature only works in the new style, that’s the rule.

Putting the legacy code as is in a module is not enough here, you would also have to add intents to all dummy arguments.

---

<div class="post-metadata">

**Author:** ![tyranids](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tyranids](https://fortran-lang.discourse.group/u/tyranids)\
**Post date:** [December 7, 2023, 11:30am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/13 "2023-12-07T11:30:00Z")

</div>

> [@PierU](#):
>
> > [@tyranids](#):
> >
> > Well, no. They can be used in modules. New feature only works in the new style, that’s the rule.
> > 
> > Also, it could still call them, but if my subroutine has argument `a` marked `intent(in)`, then I can’t supply `a` to another procedure down the call stack as anything other than verifiable `intent(in)`. I could still have local variables with no intents that get passed around like normal.
> 
> Putting the legacy code as is in a module is not enough here, you would also have to add intents to all dummy arguments.

My mistake - the original message was unclear: Argument `intent` could be used in modules. As the “new feature” being discussed, they would only be usable/applicable alongside the other new feature, modules. Yes, simply copy/paste old code in would be insufficient, and that is ok.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [December 7, 2023, 1:58pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/14 "2023-12-07T13:58:17Z")

</div>

Even in modern programming there are many situations where the developer makes promises that the compilers cannot verify. For instance when writing a parallel loop (with do concurrent or OpenMP), the developer is essentially saying that there is no dependency between the iterations, and in the general case the compiler cannot know if it’s correct or not.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [December 7, 2023, 2:32pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/15 "2023-12-07T14:32:54Z")

</div>

> [@Ali](#):
>
> `ifort` and `ifx` execute without any issues and `nvfortran` shows a warning but still displays the results

😱

---

<div class="post-metadata">

**Author:** ![mfurquan](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@mfurquan](https://fortran-lang.discourse.group/u/mfurquan)\
**Post date:** [December 8, 2023, 5:20am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/16 "2023-12-08T05:20:56Z")

</div>

But who can guarantee that a future version of ifx won’t bother?

I tried fpp, but putting ‘‘pure &’’ everywhere looks ugly!

Why can’t we have a dedicated debugging unit enabled only with -g compiler option?

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [December 8, 2023, 2:31pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/17 "2023-12-08T14:31:16Z")

</div>

> [@mfurquan](#):
>
> dedicated debugging unit

🤔

And a statement in the standard along the lines of “Output to the preconnected file identified by `DEBUGGING_UNIT` is allowed in `pure` and `simple` procedures, but it is processor dependent whether such output is externally observable” with probably some wordsmithing to say it just right. Now I’m sure there’s nuances and gotchas here I’m not thinking about, but it seems like an idea worth considering.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [December 8, 2023, 2:57pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/18 "2023-12-08T14:57:25Z")

</div>

The thread [Attribute for “pure” procedures that do I/O](https://fortran-lang.discourse.group/t/attribute-for-pure-procedures-that-do-i-o/2694) was about debugging, and in it @plevold mentioned the project [GitHub - plevold/fortran-debug-utils: Some debug utilities for Fortran](https://github.com/plevold/fortran-debug-utils)

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [December 8, 2023, 5:53pm UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/19 "2023-12-08T17:53:44Z")

</div>

> [@everythingfunctional](#):
>
> And a statement in the standard along the lines of “Output to the preconnected file identified by `DEBUGGING_UNIT` is allowed in `pure` and `simple` procedures, but it is processor dependent whether such output is externally observable” with probably some wordsmithing to say it just right.

I think this is a good idea in general. ERROR\_UNIT is already defined in the standard, and most shells already have ways to direct and redirect this output to various places (screen, named file, pipe, combined with standard output, etc.), so why not just use that unit number with its established functionality instead of introducing a new one?

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [December 13, 2023, 8:57am UTC](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937/20 "2023-12-13T08:57:47Z")

</div>

> [@Beliavsky](#):
>
> @plevold mentioned the project [GitHub - plevold/fortran-debug-utils: Some debug utilities for Fortran](https://github.com/plevold/fortran-debug-utils)

Inspired by this project, I developed [ForDebug](https://github.com/gha3mi/fordebug). This tool allows printing or writing variables of different types and kinds to the terminal or a file. Additionally, it is capable of measuring elapsed time in pure procedures.

[Next page](https://fortran-lang.discourse.group/t/debugging-and-pure-procedure-cascade/6937.md?page=2)
