To: J3 J3/26-124 From: Lorri Menard & JoR Subject: US11 - Specifications for intrinsics for source location Date: 2026-February-23 Reference: 23-193r1 I Introduction Paper 23-193r1 notes that users have requested a way to get the source name and source line in their programs, as well as the current procedure name. Uses for this would be for debugging, for logging purposes, etc. This request is being addressed in the preprocessor work via __FILE__ and __LINE__, however there are some uses for intrinsic routines for source name and line, as well as for current procedure name. II Use cases It is useful to be able to pass the name of the current module/procedure to diagnostic layers such as error handlers, progress reporters, etc. While a developer could readily produce such a string, that string will often become incorrect as code undergoes other refactoring. Further, experience shows that developers often use cut-and-paste when developing new procedures, ending up with wildly wrong names being passed to the diagnostic layer. A preprocessor directive in a TEMPLATE declaration will be resolved at compile-time of the TEMPLATE. However, instantiation of that template will happen in other files at other lines. For debugging or logging purposes the value of __FILE__ and/or __LINE__ might not be helpful. The current preprocessing standardization effort (25-142r2) does not anticipate adding preprocessor support for procedure name. This paper proposes adding three new intrinsic functions to the ISO_FORTRAN_ENV module to provide relevant information that could be useful for diagnosing problems at a later date. III Specifications SOURCE_FILE([CONTEXT]) Description. Processor-dependent string that describes the name of the source input to the translation phase of program execution. Class. Transformational function Argument. CONTEXT(optional) Shall be of type logical. It is an INTENT(IN) argument. Result Characteristics. The result is a default character scalar with processor-dependent length. Result Value. If CONTEXT is not present or has the value .FALSE. the processor shall return a processor-dependent value representing the name of the source input. If CONTEXT is present and has the value .TRUE. the result shall be a processor-dependent value representing a potentially more detailed name of the source input If no information is available the value is the string "UNKNOWN". ****Straw vote: Is there a better value? UNKNOWN FILE UNKNOWN INPUT Something else? Example. SOURCE_FILE() might have the value 'program.F90' and SOURCE_FILE(.true.) might have the value '/usr/src/program.F90'. SOURCE_LINE() Description. Returns the current source line Class. Transformational function Argument. None Result characteristics. Default integer. Result value. A positive value representing the index of the invoking line within the Fortran program, computed in a processor-dependent manner. If the processor includes a preprocessor, it is recommended that SOURCE_LINE() return the same value reported by the preprocessor. PROCEDURE_NAME([CONTEXT]) Description. Processor-dependent string that describes the name of the current procedure being executed. Class. Transformational function Argument. CONTEXT(optional) Shall be of type logical. It is an INTENT(IN) argument. Result characteristics. Default character scalar with processor-dependent length Result value. If CONTEXT is not present or has the value .FALSE. the following information will be returned. In the case of a MODULE procedure the name will be the original name from the module (not a possible rename). In the case of an instantiated TEMPLATE procedure, the name will be the one given by the user. In the case this is used to create a PARAMETER constant in the specifications section it will return the name of the program unit. If the program unit is an unnamed main program, it will return the string "MAIN PROGRAM". ****Straw vote: Is there a better value? MAIN MAIN PROGRAM UNNAMED [PROGRAM] Something else? If CONTEXT is present and has the value .TRUE. a single string will be returned that gives full context of the procedure name in the following format: [module[(submodule)]:]subprogram[.internal][=binding_name] ****Straw vote: Should this be module(submodule) or (module)submodule to match the submodule syntax? (reference example 3) module(submodule) (module)submodule module/submodule something else? Examples for PROCEDURE_NAME(context): Example 1: program main print*, procedure_name() ! 'MAIN' print*, procedure_name(.TRUE.)! 'MAIN' contains subroutine s() print*, procedure_name() ! 'S' print*, procedure_name(.TRUE.) ! 'MAIN.S' end subroutine s end program main Example 2: module A character(*), parameter :: mod_name = procedure_name() ! 'A' character(*), parameter :: full_mod_name = procedure_name(.TRUE.) ! 'A:' contains subroutine s() print*, procedure_name() ! 'S' print*, procedure_name(.TRUE.) ! 'A:S' contains subroutine inner() print*, procedure_name() ! 'INNER' print*, procedure_name(.TRUE.)! 'A:S.INNER' end subroutine inner end subroutine s subroutine s2() bind(C,name='qQ') print*, procedure_name() ! 'S2' print*, procedure_name(.TRUE.) ! 'A:S2=qQ' end subroutine s2 end module A Example 3: submodule (A) B character(*), parameter :: submod_name = procedure_name() ! 'B' character(*), parameter :: full = procedure_name(.TRUE.) ! 'A(B):' ! (or '(A)B:') ! (or 'A/B:') contains subroutine s() print*, procedure_name() ! 'S' print*, procedure_name(.TRUE.) ! 'A(B):S' or '(A)B:S'or 'A/B:S' contains subroutine inner() print*, procedure_name() ! 'inner' print*, procedure_name(.TRUE.) ! 'A(B):s.inner' or ! '(A)B:s.inner' or ! 'A/B:S.inner' end subroutine inner end subroutine s end submodule