C Is Not a Low-level Language

Outside of the rules, any result is as good as any other.

Count yourself lucky, because now you know you did not follow the rules. Count yourself doubly lucky if this has prompted you to invest in better tools for the next time you will inadvertently not follow the rules.

If a handyman turned up to do a job for you but only brought whatever tools were lying around on the street and then makes a hash of the job, would you hire him again?

1 Like

@thermos,

Would you know whether NAG Fortran compiler alerts the paying customer re: the scenario below when -C=alias option is specified? Not sure whether you have continued access to that compiler.

module m
contains
   subroutine sub1(arg1, arg2)
      real, intent(in) :: arg1
      real, intent(out) :: arg2
      arg2 = arg1*10.0
   end subroutine
   subroutine sub2()
      real, target :: t
      real, pointer :: p1, p2
      p1 => t ; p2 => t
      call sub1( p1, p2 )
   end subroutine
end module

I am temporarily without access to that compiler.

Ok.

The website suggests it is a run-time option and for scalar received arguments which is quite limiting.

The point by @tyranids then remains valid the compilers cannot offer much of any compile-time help here but which is understandable.

The counterargument to @tyranids is, as always with many things in Fortran, it is kind of like a honor code signed up to by the program author to not alias and thus the processor is permitted to attempt further code optimizations - take it or leave it.

nagfor gives no compile time diagnostic for this code, but calling sub2 when compiled with the -C=alias option does produce a runtime error. i.e.

use m
call sub2
end
(base) [stray:~/scratch] nagfor -C=alias random.f90
NAG Fortran Compiler Release 7.1(Hanzomon) Build 7127
[NAG Fortran Compiler normal termination]
(base) [stray:~/scratch] ./a.out 
Runtime Error: random.f90, line 6: Assignment to ARG2 affects dummy argument ARG1
Program terminated by fatal error
zsh: IOT instruction (core dumped)  ./a.out
2 Likes

Thanks. But a run-time error and scalar arguments is rather limiting. Those who are unable or unwilling to procure a commercial product in NAG Fortran can figure out a preprocessor based option to first replicate and then automate across large codes the same facility, say along the following lines:

module m
contains
   subroutine sub1(arg1, arg2)
      integer, intent(in) :: arg1(:)
      integer, intent(out) :: arg2(:)
#ifdef DEBUG
      if ( aliased(arg1, arg2 ) ) error stop "sub1: arg1 and arg2 are aliased; assignment to one affects the other" 
#endif
      arg2 = arg1*10.0
#ifdef DEBUG
   contains
      function aliased( a1, a2 ) result(r)
         use, intrinsic :: iso_c_binding, only : c_loc, c_associated
         ! Argument list
         type(*), intent(in), target :: a1(..)
         type(*), intent(in), target :: a2(..)
         ! Function result
         logical :: r
         r = c_associated( c_loc(a1), c_loc(a2) )
      end function 
#endif
   end subroutine
   subroutine sub2()
      integer, target :: t(2)
      integer, pointer :: p1(:), p2(:)
      t = [ 1, 2 ]
      p1 => t ; p2 => t
      call sub1( p1, p2 )
      print *, u
   end subroutine
end module
   use m
   call sub2()
end
C:\temp>gfortran -cpp -ffree-form -DDEBUG p.f -o p.exe

C:\temp>p.exe
ERROR STOP sub1: arg1 and arg2 are aliased; assignment to one affects the other

Error termination. Backtrace:
...
1 Like

I wonder about this difference in semantics. I know some of the issues but only superficially. Is there any reference for this? I am interested to know more, out of basic curiosity, nothing else.

A reference to differences between C and Fortran semantics? I don’t know of one. What I recall is efforts by the Fortran team to work around C-centric concepts baked into the back-end (this happened with the migration of DEC Fortran to Intel Fortran too, discarding the DEC-developed GEM multi-language back-end and switching to the Intel C-centric IL0 backend.) With LLVM, I recall in the early days that it didn’t even have the concept of a complex datatype. Fortran COMMON is another thing that isn’t exactly like C extern. Sometimes the back-end needs additional IL to support Fortran.

1 Like

Pity. Well, thanks anyway. (Re complex: the absence of such a data type has always amazed me, even though I do not use it myself all that often).

Re: “Fortran COMMON is another thing that isn’t exactly like C extern”, but BIND(C) clause indeed makes it like a C extern to a struct datatype.

#include <stdio.h>

typedef struct {
   int n;
} foo_c;
extern foo_c foo;

// Fortran function
void Fsub();

int main()
{
   Fsub();
   printf("In C main: foo.n = %d\n", foo.n);
   return 0;
}
subroutine Fsub() bind(C, name="Fsub")
   use, intrinsic :: iso_c_binding, only : c_int
   integer(c_int) :: n
   common / foo / n
   bind(C, name="foo") :: / foo /
   n = 42
   return 
end subroutine 
C:\temp>gfortran -ffree-form c.c s.f -o c.exe
cc1.exe: warning: command-line option '-ffree-form' is valid for Fortran but not for C

C:\temp>c.exe
In C main: foo.n = 42
1 Like

With some restrictions, yes, but most uses of COMMON are not BIND(C) and there are additional quirks. Consider blank common, for example. My general point was that back ends written initially to target C usually need some work to accommodate Fortran.

1 Like

Yes, common can be quite tricky in the backend. There are several ways to implement it, but my experience generally mirrors what @sblionel wrote as well.

1 Like