History, Standards and Compilers
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This section is written against Fortran 2023 (ISO/IEC 1539-1:2023, read here through the free final draft J3/23-007r1). Every
example was checked on 2026-10-18 with GNU Fortran (gfortran) 16.2 using
-std=f2023 -Wall -Wextra -pedantic -fimplicit-none -fcheck=all, and, where the example says so, also with LLVM Flang 23.
Fortran is the oldest high-level programming language still in wide use, and it is also a language that keeps being revised:
eight standards between 1966 and 2023, with a ninth, Fortran 2028, at Committee Draft stage. Knowing which revision a feature
belongs to, who decides what goes into the next one, and which compilers implement it is not trivia. It decides whether a
program written today compiles on the cluster you were given, and whether a 1990s code base can be modernized in place.
This page covers four things. First, the history: what each revision added and which technical reports (TRs) and technical specifications (TSs) were folded into later standards. Second, how the standard is produced and what "conforming" means for a program and for a compiler. Third, the compiler landscape. Fourth, a table of compiler support for every Fortran 2023 feature, which other pages of this section link to whenever they show a Fortran 2023 feature. The examples follow the running heatflow project (a 2D heat diffusion solver) introduced in Getting Started.
Related pages: Compilers and Compiler Options (installing and driving each compiler), Legacy Features and Modernization (the obsolescent and deleted features in depth), What’s New and Fortran 2028 Preview (the Fortran 2023 additions in detail and the 2028 work items), and Intrinsic Modules and iso_fortran_env.
A short history
Fortran (FORTRAN until Fortran 90, from "formula translation") was designed by a team at IBM led by John Backus. The first
compiler shipped in 1957 for the IBM 704. Its aim was to let scientists write formulas instead of machine code and still obtain
code almost as fast as hand-written assembly, an aim that has shaped every later revision: Fortran gives the compiler enough
information (no aliasing between dummy arguments, whole-array semantics, do concurrent) to optimize aggressively.
Vendors soon diverged, so the American standards body standardized the language. The first ISO designation, ISO R 1539-1972, is what everyone calls Fortran 66. Since then each edition has an official designation and an informal name. S 4.3.1 lists them all; the table below adds the headline contribution of each revision. The informal names are the ones used in compiler manuals and in this section.
| Informal name | Official designation | What it added (headline features) |
|---|---|---|
FORTRAN I (1957), II (1958), IV (1962) |
vendor languages |
Formulas, |
Fortran 66 |
ISO R 1539-1972 (ANSI X3.9-1966) |
The first standard: a portable subset of the vendor dialects. |
FORTRAN 77 |
ISO 1539-1980 (ANSI X3.9-1978) |
|
Fortran 90 |
ISO/IEC 1539:1991 |
The major break: free source form, modules, derived types, whole-array operations and sections, |
Fortran 95 |
ISO/IEC 1539-1:1997 |
|
Fortran 2003 |
ISO/IEC 1539-1:2004 |
Object orientation (type extension, polymorphism, type-bound procedures, |
Fortran 2008 |
ISO/IEC 1539-1:2010 |
Coarrays and the image model, submodules, |
Fortran 2018 |
ISO/IEC 1539-1:2018 |
Teams, events, collectives, atomics and failed-image support (from TS 18508), assumed-rank and further C interoperability (from TS 29113), |
Fortran 2023 |
ISO/IEC 1539-1:2023 (Nov 2023); Cor 1:2026 (Jan 2026) |
10,000-character lines, |
Fortran 2028 |
Committee Draft stage (WG5 N2258, not public); public working draft J3/26-007r1 |
Templates and generic subprograms, source-location intrinsics and further additions. Described only as "upcoming" in this section; see What’s New and Fortran 2028 Preview. |
The WG5 paper N2212, written by John Reid, summarizes the Fortran 2023 additions in prose and notes the alternation between major and minor revisions (1978 minor, 1991 major, 1997 minor, 2004 major, 2010 minor; 2018 avoided being major to give implementers time, and 2023 was planned as minor too): WG5 N2212, The new features of Fortran 2023. The equivalent papers for the earlier revisions are N2161 (Fortran 2018), N1891 (Fortran 2008) and N1648 (Fortran 2003).
The diagram shows the same history as a timeline.
Technical reports and specifications folded into later standards
Between two revisions, WG5 sometimes publishes a technical report (TR) or technical specification (TS) that specifies a large feature early, so that implementers can gain experience before it is promised forever. The feature then moves into the next revision, normally with small changes. A compiler manual that says "supports TS 29113" or "supports the TS 18508 features" therefore refers to a subset of a later standard.
| Document | Subject | Folded into |
|---|---|---|
TR 15580 and TR 15581 |
Floating-point exception handling (the |
Fortran 2003 |
TR 19767 |
Enhanced module facilities: submodules and separate module procedures |
Fortran 2008 |
ISO/IEC TS 29113:2012 |
Further interoperability of Fortran with C: assumed-type |
Fortran 2018 |
TS 18508 |
Additional parallel features: teams, events, collectives, atomics, failed images |
Fortran 2018 |
Source: GNU Fortran manual: Standards
A consequence for library authors: code that needs only the TS 29113 features can be described as "Fortran 2018", but
processors that never reached full F2018 may still offer the TS. gfortran documents full support for TS 29113, and a partial
implementation of the TS 18508 parallel features (the gfortran manual lists the polymorphic-type gap in
co_min, co_max, co_sum, co_broadcast and co_reduce).
Deleted and obsolescent features
Fortran is unusual in how seldom it deletes anything. S 4.4 states the policy: the standard "protects the users' investment in existing software" and keeps all but six language elements of Fortran 90 that are not processor dependent. It identifies two categories:
-
Deleted features were redundant already in FORTRAN 77 and largely unused in Fortran 90. There are two groups. The first group was dropped with Fortran 95 (real and double precision
dovariables, branching toend iffrom outside the block,pause,assignand assignedgo to/assigned formats, theHedit descriptor, and vertical format control). The second group (the arithmeticifstatement and the nonblockdoconstruct) was still in Fortran 2008 and is deleted from the current standard. -
Obsolescent features were redundant already in Fortran 90 and 95 but are still frequently used. Annex B lists alternate return, computed
go to, statement functions,dataamong executable statements, assumed-length character functions, fixed source form, thecharacter*nform,entry, the labelleddo,common/equivalence/block data, specific names of intrinsic functions, andforall.
Deleted does not mean unsupported by compilers: gfortran, for instance, accepts most of them in its default -std=gnu mode and
only rejects them under -std=f2023. A processor is required to be able to report both categories (S 4.2, below). This section
shows these features only on
Legacy Features and Modernization, next to the
modern replacement.
How Fortran is standardized
Three organizations are involved, with deliberately different roles.
| Body | Role |
|---|---|
ISO/IEC JTC 1/SC 22/WG 5 (WG5) |
The international working group for Fortran. It chooses the content of each revision through resolutions at its meetings, publishes numbered papers (the N documents such as N2212, N2244 and N2258) and keeps the schedule. Its site is the index of the standards and of the committee papers. |
J3 |
The US Fortran committee (the technical committee called INCITS PL22.3 and, long ago, ANSI X3J3). J3 is the US national body for WG5 and is the primary development body for Fortran 95 and later: it writes the technical content, and its website publishes the papers, draft and interpretation on its website. Membership and meetings are open to anyone worldwide. |
ISO |
Publishes the standard as ISO/IEC 1539-1 (Part 1, Base language). This is the document the section describes. |
Source: J3 Fortran: home page
Source: WG5 Fortran: home page
The diagram shows how an idea becomes part of the standard, and how the standard is maintained afterwards.
Revision cycle, interpretations and corrigenda
-
Revisions arrive about every five to eight years (1991, 1997, 2004, 2010, 2018, 2023). WG5 votes a work list, J3 turns it into a working draft named
J3/yy-007(yyis the year,007the fixed number of the draft andr1its first revision), and the draft goes through Committee Draft and ISO ballots. -
Interpretations answer questions about what the published text means. J3 and WG5 process each one, and an accepted answer that fixes a defect becomes a corrigendum.
-
Corrigenda are small published corrections to a standard. Fortran 2018 received two. Fortran 2023 has Corrigendum 1 (ISO/IEC 1539-1:2023/Cor 1:2026, January 2026; WG5 paper N2244).
-
The free text of a standard is the final draft: J3/23-007r1 (13 June 2023) is what this section cites with clause numbers. The authoritative document is the ISO text, which is sold by ISO and may differ editorially from the last J3 draft. For contractual or certification work, check the clause against the ISO publication and the corrigendum.
-
Proposals for the next revision are discussed in public on the GitHub repository j3-fortran/fortran_proposals: an idea is opened as an issue, discussed by the community, and, if it has merit and a committee member willing to advocate it, written up as a text-file proposal for J3. Negative feedback closes the issue with documented reasons; a new issue can ask for reconsideration.
Source: WG5: Fortran 2023
The history of the standardization meetings from 1963 to 2026 is in WG5 N2263.
Conformance: what the standard requires of programs and compilers
Fortran standardizes two things: the programs that are allowed, and what a processor must do with them. "Processor" is the standard’s word for compiler plus runtime plus hardware. S 4.2 defines both sides.
A standard-conforming program uses only the forms and relationships described by the standard, and has an interpretation according to it. A program unit conforms if it can be included in a program in a way that allows the program to be standard-conforming. Conformance does not guarantee portable behaviour: a conforming program may depend on things outside the standard (for example external procedures written in C) or on processor-dependent behaviour, whose semantics the standard leaves to the processor (Annex A lists them).
A standard-conforming processor must:
-
execute any conforming program as the standard specifies, subject to documented limits on size and complexity;
-
be able to detect and report use of an obsolescent form, where this can be determined from the numbered syntax rules and constraints;
-
be able to detect and report any form not permitted by the syntax rules or constraints, including the deleted features;
-
detect and report an intrinsic type with an unsupported kind;
-
detect and report source form or characters not permitted by Clause 6;
-
detect and report name usage that violates the scope rules;
-
detect and report use of a nonstandard intrinsic procedure or nonstandard intrinsic module, or of a procedure of a standard intrinsic module that the standard does not define;
-
detect and report the reason for rejecting a program.
"Detect and report" means the processor can do so, not that it does so by default. This is why compiler options such as
-std=f2023 exist: they switch the reporting on. A processor may also allow additional forms and relationships (extensions),
provided they do not conflict with the standard, and may add intrinsic procedures even if this clashes with a name used by a
conforming program (unless that name has the external attribute where it is used). A conforming program must not use the
processor’s added intrinsics. The processor should also come with documentation of its limits, its extensions and how their use
is reported.
The first example below shows a processor reporting a nonstandard intrinsic. The program is intentionally non-conforming:
getpid is a GNU extension. By default gfortran accepts it silently (it compiles and runs), while under -std=f2023 the name
is not an intrinsic, so with implicit none it is rejected.
! INTENTIONALLY NON-CONFORMING: GETPID is a GNU extension, not a standard
! intrinsic, so a conforming processor must be able to report its use (4.2).
program nonstandard_intrinsic
implicit none
integer :: pid
pid = getpid()
print '(a)', 'process id obtained'
end program nonstandard_intrinsic
gfortran 07_nonstandard_intrinsic.f90 -o nonstandard && ./nonstandard
gfortran -std=f2023 07_nonstandard_intrinsic.f90 -o nonstandard
process id obtained
07_nonstandard_intrinsic.f90:6:8:
6 | pid = getpid()
| 1
Error: Function 'getpid' at (1) has no IMPLICIT type
LLVM Flang 23 accepted the same file without a diagnostic, even with -pedantic: reporting extensions is a processor choice,
and compilers differ in how much they report. If you target several compilers, compile with each of them.
Compatibility between revisions
The compatibility subclauses (S 4.3) state that each revision is an upward-compatible extension of the previous one, except for a short, explicit list. A standard-conforming Fortran 2018 program that avoids those items is a conforming Fortran 2023 program. The items in S 4.3.3 that can change meaning or stop being permitted are:
-
system_clock: all integer arguments of one reference must now have the same kind, with a decimal exponent range at least that of default integer, and a processor may provide several clocks selected by the kind of the arguments; -
a variable of a
blockconstruct declared only by adatastatement can no longer be used before thedatastatement; -
the
pointerandtargetarguments ofassociatedcan no longer have different ranks; -
deferred-length allocatable character variables assigned by
iomsg=,errmsg=, an internalwriteor an intent-out argument of an intrinsic subroutine now get intrinsic-assignment semantics, so their length can differ from Fortran 2018; -
ieee_max_num,ieee_min_numand their_magvariants return the number when the other argument is a signaling NaN.
The system_clock change is a good example of a rule that compilers enforce under -std=f2023. The conforming form uses
one kind (here the 64-bit lp from the heatflow kinds module) for every integer argument:
module heatflow_kinds
use, intrinsic :: iso_fortran_env, only: int64, real64
implicit none
private
public :: dp, lp
integer, parameter :: dp = real64
integer, parameter :: lp = int64
end module heatflow_kinds
program system_clock_f2023
use heatflow_kinds, only: dp, lp
implicit none
integer(lp) :: t0, t1, rate, i
real(dp) :: s
call system_clock(t0, rate) ! all integer arguments have the same kind
s = 0.0_dp
do i = 1_lp, 2000000_lp
s = s + 1.0_dp / real(i, dp)
end do
call system_clock(t1)
print '(a,l1)', 'clock is running: ', rate > 0_lp
print '(a,l1)', 'elapsed time is non-negative: ', t1 >= t0
print '(a,f8.5)', 'harmonic sum: ', s
end program system_clock_f2023
clock is running: T
elapsed time is non-negative: T
harmonic sum: 15.08587
The next program is intentionally non-conforming to Fortran 2023 (it is valid Fortran 2018): it mixes a default-kind and a
64-bit integer in one system_clock reference. gfortran rejects it under -std=f2023; Flang 23 accepts it (checked: it
compiles and runs without any message), so the rule is not enforced uniformly yet.
! INTENTIONALLY NON-CONFORMING to Fortran 2023: the integer arguments of one
! SYSTEM_CLOCK reference have different kinds (allowed by Fortran 2018).
program system_clock_mixed
use, intrinsic :: iso_fortran_env, only: int32, int64
implicit none
integer(int32) :: count
integer(int64) :: rate
call system_clock(count, rate)
print '(a)', 'this line is never reached under -std=f2023'
end program system_clock_mixed
06b_system_clock_mixed_kinds.f90:8:27:
8 | call system_clock(count, rate)
| 1
Error: Prohibited in Fortran 2023: integer arguments to SYSTEM_CLOCK at (1) with different kind parameters
The compiler landscape
There is no reference implementation of Fortran, and the standard is large enough that no compiler implements every part of
every revision at once. The list below is based on the fortran-lang.org compilers page and on each vendor’s own manual. The
fortran-lang page is a useful index but it is not always current: on the check date it listed Intel ifort as a mature
compiler with full Fortran 2018 support, although ifort was discontinued with oneAPI 2025.0, and it listed NAG 7.0 as the
latest NAG release although the NAG manual set includes Release 7.2.
| Compiler | Vendor and licence | Notes |
|---|---|---|
gfortran (GNU Fortran, GCC 16.2) |
GNU project, GPL |
Part of the GNU Compiler Collection and the most widely available compiler. "Almost all" of Fortran 2003 and 2008, partial Fortran 2018, selected Fortran 2023 features through |
LLVM Flang (LLVM 23) |
LLVM project, Apache 2.0 with LLVM exceptions |
The executable is called |
Intel ifx (oneAPI 2026.1) |
Intel, proprietary (free to download) |
LLVM-based, Linux and Windows on x86-64. Intel states full support for the standards through Fortran 2018 and "several" Fortran 2023 features (see the table below). It replaces |
NAG Fortran (Release 7.2) |
NAG, commercial |
Traditionally the strictest checker of the standard, widely used to validate that code is portable. Release 7.2 supports all of Fortran 2018 and lists a few Fortran 2023 features in its release notes. |
HPE Cray CCE (Cray Compiling Environment 21) |
HPE, with Cray systems |
The compiler of Cray supercomputers. Fortran 2018 is described as fully supported, and Fortran 2023 support is documented with a single named exception, the |
NVIDIA nvfortran (HPC SDK) |
NVIDIA, free |
Descended from the PGI compiler. OpenACC, CUDA Fortran, and offload of |
AMD compilers (AOCC, and an LLVM-Flang-based compiler for ROCm) |
AMD, free |
Flang-derived compilers for AMD CPUs and GPUs. |
IBM XL Fortran |
IBM, commercial (community edition free) |
For Power systems on Linux and AIX. |
LFortran (0.67) |
LFortran project, BSD-3 |
A new LLVM-based compiler with an interactive mode, a WebAssembly target and several back ends. Its own site still describes it as alpha: it is not expected to work on arbitrary third-party code. |
Source: fortran-lang.org: Compilers
Source: GNU Fortran manual: Standards
Source: LFortran
Which compiler to start with depends on the goal. Use gfortran for daily development and Flang or ifx as a second opinion, because a program that two independent compilers accept is much more likely to be conforming. Add NAG (if you have access) for the strictest checking. For a cluster, use whatever the site provides (often Cray CCE, ifx or nvfortran) and test with it early. The installation, the option sets and the diagnostics are in Compilers and Compiler Options.
Selecting a standard on the command line
The option that makes a compiler enforce a revision is the first thing to learn, because the default is usually not standard-conforming.
| gfortran option | Meaning |
|---|---|
|
The default. All GNU extensions, with warnings for obsolete ones. |
|
As |
|
Strict conformance to that revision. Extensions are errors; permitted but obsolescent features are warned about. |
|
Fortran 2023 plus experimental proposed features. They may change or disappear. |
|
Accept all intrinsics, including GNU extensions, even under |
|
Not language selectors, but the usual companions: disable implicit typing everywhere, warn about extensions, and enable runtime checks. All examples of this section are compiled with these options. |
The effect of -std is visible with a Fortran 2023 intrinsic. The module below builds the initial temperature field of
heatflow, one half sine wave across the plate in each direction. It uses sinpi (sine of a multiple of pi, new in Fortran
2023) so that no value of pi has to be written down, and sind (sine of an angle in degrees).
module heatflow_kinds
use, intrinsic :: iso_fortran_env, only: real64
implicit none
private
public :: dp
integer, parameter :: dp = real64
end module heatflow_kinds
module heatflow_profile
use heatflow_kinds, only: dp
implicit none
private
public :: sine_plate
contains
! Initial temperature field: one half sine wave across each direction
! (Fortran 2023 sinpi works in half-revolutions, so no pi constant is needed).
pure function sine_plate(nx, ny) result(u)
integer, intent(in) :: nx, ny
real(dp) :: u(nx, ny)
integer :: i, j
do j = 1, ny
do i = 1, nx
u(i, j) = sinpi(real(i - 1, dp) / real(nx - 1, dp)) &
* sinpi(real(j - 1, dp) / real(ny - 1, dp))
end do
end do
end function sine_plate
end module heatflow_profile
program degree_and_pi_trig
use heatflow_kinds, only: dp
use heatflow_profile, only: sine_plate
implicit none
real(dp) :: u(5, 5)
u = sine_plate(5, 5)
print '(a,f6.3)', 'centre value = ', u(3, 3)
print '(a,f6.3)', 'corner value = ', u(1, 1)
print '(a,f6.3)', 'sind(30.0_dp) = ', sind(30.0_dp)
print '(a,f6.3)', 'cosd(60.0_dp) = ', cosd(60.0_dp)
end program degree_and_pi_trig
centre value = 1.000
corner value = 0.000
sind(30.0_dp) = 0.500
cosd(60.0_dp) = 0.500
The output is identical with LLVM Flang 23. To see the revision boundary, ask gfortran to compile the same file as Fortran 2018. This second command is intentionally run on a file that uses Fortran 2023 features, and it fails as it should (the later errors are consequences of the first):
gfortran -std=f2018 -c 02_degree_and_pi_trig.f90
02_degree_and_pi_trig.f90:23:23:
23 | u(i, j) = sinpi(real(i - 1, dp) / real(nx - 1, dp)) &
| 1
Error: Function 'sinpi' at (1) has no IMPLICIT type
Source: GNU Fortran manual: SINPI
Identifying the compiler from the program
Portable code sometimes needs to report, or branch on, the compiler that built it, for example in a bug report or a
benchmark log. Fortran 2008 added two functions to iso_fortran_env for that purpose: compiler_version() returns a string
identifying the compiler, and compiler_options() returns the options used to compile the program (the content of both strings
is processor dependent). Parsing the strings to select code paths is fragile; prefer build-system feature tests or
the preprocessor macros of each compiler, and use these functions for logging.
module heatflow_kinds
use, intrinsic :: iso_fortran_env, only: int32, int64, real32, real64
implicit none
private
public :: sp, dp, ip, lp
integer, parameter :: sp = real32
integer, parameter :: dp = real64
integer, parameter :: ip = int32
integer, parameter :: lp = int64
end module heatflow_kinds
program compiler_identity
use, intrinsic :: iso_fortran_env, only: compiler_version, compiler_options
use heatflow_kinds, only: dp
implicit none
print '(a)', 'compiler: ' // compiler_version()
print '(a,i0)', 'working precision: digits = ', digits(1.0_dp)
print '(a,l1)', 'options string present: ', len(compiler_options()) > 0
end program compiler_identity
Output with gfortran 16.2:
compiler: GCC version 16.2.0
working precision: digits = 53
options string present: T
Output with LLVM Flang 23:
compiler: Debian flang version 23.1.4
working precision: digits = 53
options string present: T
(Flang 23.1.4 is the build from the LLVM apt repository used for these checks; the upstream release is
23.1.x, so name "LLVM 23" in your own documentation unless you know the exact build.) This module is the same
heatflow_kinds that every later page of the section uses.
Compiler support for every Fortran 2023 feature
Support for Fortran 2023 is uneven, and the published status pages are not uniform: the GNU Fortran manual has none, LLVM publishes a per-feature table, Intel and NAG describe what they added release by release, and HPE states the support in prose. So the table below combines two kinds of evidence, on the check date 2026-10-18:
-
the gfortran 16.2 and LLVM Flang 23 columns come from small probe programs I compiled and ran with those compilers (
gfortran -std=f2023andflang, with-fcoarray=singleadded for gfortran so that coarray syntax is accepted); -
the ifx, NAG and Cray columns repeat what the vendor’s own release notes or manual state. A dash means that the page I could read does not mention the feature, which is not the same as "unsupported". Vendors change this quickly: use the manual of your installed release.
Legend: Y the probe compiled and gave the expected result (or the vendor lists the feature); A the compiler accepts the
syntax, but the behaviour was not run; N rejected, or the behaviour was wrong or the runtime failed; a dash, not stated.
Where the Flang manual’s table disagrees with the probe (the manual lists at, simple, conditional expressions and several
others as not implemented while the 23.1.4 build from apt.llvm.org accepted them), the table below gives the probe, since the
probe tests the compiler you can install today. Always re-probe your own build.
| Feature (J3/23-007r1 clause) | Part | gfortran 16.2 | Flang 23 | ifx 2026.1 | NAG 7.2 | Cray CCE |
|---|---|---|---|---|---|---|
Long lines (10,000 characters) and statements (1,000,000), no continuation limit (6.3.2) |
source form |
Y |
Y |
- |
Y |
- |
Deferred-length allocatable character allocated by the processor for |
data |
N |
N |
- |
- |
- |
|
data |
N |
A ( |
- |
- |
- |
Conditional expressions (10.1.2.3) |
expressions |
Y |
Y |
Y |
- |
Y |
Conditional arguments, including |
procedures |
N |
N |
- |
- |
N |
Extended BOZ constants (7.7) |
data |
N |
Y |
- |
- |
- |
|
intrinsics |
Y |
Y |
- |
- |
Y |
|
intrinsics |
N (link error) |
Y |
- |
- |
Y |
Trigonometry in degrees: |
intrinsics |
Y |
Y |
- |
- |
- |
Trigonometry in half-revolutions: |
intrinsics |
Y |
Y |
- |
- |
- |
|
intrinsics |
Y |
Y |
- |
Y |
- |
|
modules |
Y |
Y |
- |
Y (logical) |
Y |
|
intrinsics |
Y |
N (mixed kinds not diagnosed) |
- |
- |
- |
IEEE 60559:2020: |
modules |
N |
Y |
- |
- |
- |
|
C interop |
Y |
Y |
- |
- |
- |
|
C interop |
Y |
Y |
- |
- |
- |
|
C interop |
N (link error) |
Y |
- |
- |
- |
|
I/O |
N |
Y |
- |
Y |
Y |
Leading-zero control: |
I/O |
N |
Y |
Y |
- |
- |
Public namelist group with private objects (8.9) |
I/O |
N |
N |
- |
- |
- |
Coarray ultimate components in arrays and allocatables |
coarrays |
N |
A |
- |
- |
- |
|
coarrays |
N |
- |
Y |
- |
- |
Error conditions in collective subroutines (16.6) |
coarrays |
- |
- |
- |
- |
- |
|
procedures |
N |
Y |
- |
- |
- |
Integer arrays as subscripts, the multiple subscript |
arrays |
N |
N |
- |
- |
- |
Integer arrays for bounds in declarations, |
arrays |
N |
N (reported as not yet implemented) |
- |
- |
- |
Integer constant for rank: the |
arrays |
N |
Y |
- |
- |
- |
|
parallel |
Y |
Y |
- |
- |
- |
Enumeration types (7.6.2) |
types |
N |
N |
- |
- |
- |
Notes on the table:
-
Cray CCE. HPE’s Cray Compiler Overview states that Fortran 2023 language features are supported with the exception of
.nil.(conditional arguments), and its list of new intrinsics namestokenizeandsplit; it also names conditional expressions, theatedit descriptor and theiso_fortran_envkind updates. I could read this only for CCE 20, through a search result: the HPE documentation server failed TLS verification when fetched, so the CCE 21 page was not read. Treat the Cray column as the vendor’s statement for the CCE 20/21 line, not as a result verified for CCE 21. -
ifx. The Intel pages for 2026.0 and 2026.1 list conditional expressions, the leading-zero edit mode and the
notify=specifier as new Fortran 2023 features. The 2026.1 conformance page states that the release adds no further Fortran 2023 features. The per-feature page of the Developer Guide could not be read in full, so the dashes mean "not stated on the pages read". -
NAG. The Release 7.2 notes have a "Fortran 2023 support" section listing exactly four items: long free-form lines,
selected_logical_kind, thelogical8tological64constants, and theatedit descriptor. -
gfortran needs
-std=f2023(or-std=f202y) to enforce the revision, and on a 16.2 installationtokenizeandc_f_strpointercompile but fail at link time (undefined reference tothe library symbol), which is a good reason to test a feature with a link, not only with a syntax check.real16is -2 on the aarch64 host used here (no 16-bit real; larger kinds exist) and 2 with Flang, which supports half precision: kind constants are processor dependent, and the negative values -1 and -2 mean "no such kind" and "no such kind but a larger one exists". -
Flang did not run multi-image programs in these checks: coarray features need
-fcoarray, and the compiler describes them as experimental. -
Enumeration types (
enumeration type) are the one Fortran 2023 data-declaration feature that neither installed compiler accepts. The heatflow boundary condition kinds therefore use the interoperableenum, bind(c)form, which both compilers accept and which is also valid Fortran 2023.
The probe method is deliberately simple, and you can repeat it for your own compiler: one tiny file per feature, compiled with
-std=f2023 (or its equivalent) and, if it compiles, run, because several rejections only appear at link or run time.
for f in probe_*.f90; do
if gfortran -std=f2023 -fcoarray=single "$f" -o probe.out 2> probe.err; then
echo "$f: compiled -> $(./probe.out 2>&1 | head -n 2 | tr '\n' ' ')"
else
echo "$f: rejected -> $(head -n 3 probe.err | tr '\n' ' ')"
fi
done
Checking features with real programs
The two programs below were used as part of the probes and are runnable examples in their own right. They are part of the heatflow project and use features that both gfortran 16.2 and Flang 23 accept.
The first reads simple key=value pairs from a text line with the Fortran 2023 intrinsic subroutine split, which moves a
position to the next separator, one token at a time. The heatflow application reads a namelist file for its real run (see
Internal Files, Namelist and Non-Advancing I/O);
this is the same idea for a quick command-line style string. The array form tokenize returns all tokens at once, but the
gfortran 16.2 library does not provide it (the link error in the table), so the portable choice today is split.
module heatflow_kinds
use, intrinsic :: iso_fortran_env, only: int32, real64
implicit none
private
public :: dp, ip
integer, parameter :: dp = real64
integer, parameter :: ip = int32
end module heatflow_kinds
program split_config
use heatflow_kinds, only: dp, ip
implicit none
character(len=*), parameter :: line = 'nx=64;ny=32;alpha=0.01'
integer(ip) :: nx, ny
real(dp) :: alpha
integer :: start, finish, eq, ios
character(len=:), allocatable :: item, key
nx = 0_ip
ny = 0_ip
alpha = 0.0_dp
start = 1
finish = 0
do
! split moves finish to the next ';' (or len(line)+1 when there is none)
call split(line, ';', finish)
item = line(start:finish - 1)
eq = index(item, '=')
key = item(1:eq - 1)
select case (key)
case ('nx')
read (item(eq + 1:), *, iostat=ios) nx
case ('ny')
read (item(eq + 1:), *, iostat=ios) ny
case ('alpha')
read (item(eq + 1:), *, iostat=ios) alpha
case default
print '(a)', 'unknown key: ' // key
end select
start = finish + 1
if (finish > len(line)) exit
end do
print '(a,i0,a,i0,a,f5.3)', 'nx=', nx, ' ny=', ny, ' alpha=', alpha
end program split_config
nx=64 ny=32 alpha=0.010
The output is identical with Flang 23. With gfortran 15 and earlier, split does not exist, and the build stops with an error
about an undefined subroutine, so a library that must support older gfortran releases should keep its own tokenizer.
Source: GNU Fortran manual: SPLIT
The second program uses a conditional expression, a Fortran 2023 form ( condition ? value : condition ? value : value )
that selects one of several values, and evaluates only the chosen one. Here it chooses the time step of the explicit
(forward-time, centred-space) heat scheme: a request of zero or less means "use the stability limit", a request above the limit
is clamped to it, and anything else is accepted. The stability limit of the scheme on a grid of spacing dx by dy is
computed by stable_dt in the code. Before Fortran 2023 this took a function with an if chain, or a combination of
merge and an extra evaluation of both branches.
module heatflow_kinds
use, intrinsic :: iso_fortran_env, only: real64
implicit none
private
public :: dp
integer, parameter :: dp = real64
end module heatflow_kinds
module heatflow_timestep
use heatflow_kinds, only: dp
implicit none
private
public :: stable_dt, clamp_dt, describe
contains
! Largest time step the explicit FTCS scheme allows on a dx-by-dy grid.
pure function stable_dt(alpha, dx, dy) result(dt)
real(dp), intent(in) :: alpha, dx, dy
real(dp) :: dt
dt = 0.5_dp * (dx * dx * dy * dy) / (alpha * (dx * dx + dy * dy))
end function stable_dt
! Fortran 2023 conditional expression: a value chosen by a chain of tests.
pure function clamp_dt(requested, alpha, dx, dy) result(dt)
real(dp), intent(in) :: requested, alpha, dx, dy
real(dp) :: dt
dt = (requested <= 0.0_dp ? stable_dt(alpha, dx, dy) &
: requested > stable_dt(alpha, dx, dy) ? stable_dt(alpha, dx, dy) &
: requested)
end function clamp_dt
pure function describe(dt, limit) result(text)
real(dp), intent(in) :: dt, limit
character(len=:), allocatable :: text
text = (dt >= limit ? 'at the stability limit' : 'below the stability limit')
end function describe
end module heatflow_timestep
program conditional_expression
use heatflow_kinds, only: dp
use heatflow_timestep, only: stable_dt, clamp_dt, describe
implicit none
real(dp), parameter :: alpha = 0.01_dp, dx = 0.1_dp, dy = 0.1_dp
real(dp) :: limit, requested(3), dt
integer :: k
limit = stable_dt(alpha, dx, dy)
requested = [0.0_dp, 0.1_dp, 0.5_dp * limit]
print '(a,es10.3)', 'stability limit = ', limit
do k = 1, size(requested)
dt = clamp_dt(requested(k), alpha, dx, dy)
print '(a,es10.3,a,es10.3,2a)', 'requested ', requested(k), ' -> dt ', dt, &
': ', describe(dt, limit)
end do
end program conditional_expression
stability limit = 2.500E-01
requested 0.000E+00 -> dt 2.500E-01: at the stability limit
requested 1.000E-01 -> dt 1.000E-01: below the stability limit
requested 1.250E-01 -> dt 1.250E-01: below the stability limit
Both gfortran 16.2 and Flang 23 give this output. The conditional argument form, call sub(x, (flag ? y : .nil.)), which
passes an absent optional argument when the condition is false, was rejected by both compilers in the probes, so this section
does not use it. Conditional expressions are described fully on
Expressions and Assignment.
The last program prints the kind constants that Fortran 2023 added to iso_fortran_env (logical8 to logical64, real16)
together with selected_logical_kind. Run it with both compilers and the two answers for real16 differ, which is a correct
demonstration that the values of kind constants are processor dependent and that a negative value is a legal answer.
program kind_constants
use, intrinsic :: iso_fortran_env, only: logical8, logical16, logical32, logical64, &
real16, real32, real64, real128
implicit none
print '(a,4(1x,i0))', 'logical kinds 8/16/32/64:', logical8, logical16, logical32, logical64
print '(a,4(1x,i0))', 'real kinds 16/32/64/128: ', real16, real32, real64, real128
print '(a,i0)', 'selected_logical_kind(16) = ', selected_logical_kind(16)
print '(a,i0)', 'selected_logical_kind(8) = ', selected_logical_kind(8)
end program kind_constants
gfortran 16.2 (aarch64):
logical kinds 8/16/32/64: 1 2 4 8
real kinds 16/32/64/128: -2 4 8 16
selected_logical_kind(16) = 2
selected_logical_kind(8) = 1
LLVM Flang 23 (aarch64):
logical kinds 8/16/32/64: 1 2 4 8
real kinds 16/32/64/128: 2 4 8 16
selected_logical_kind(16) = 2
selected_logical_kind(8) = 1
Fortran 2028 in brief
Fortran 2028 (formerly "F202Y") is the next revision. On the check date WG5 lists the Committee Draft (N2258) as not a public
document, and the latest public working draft is J3/26-007r1. The stage and the ballot outcome are therefore not documented
publicly here, and this section describes Fortran 2028 only as "upcoming". The main item is templates: a new clause for
parameterized generic programming with requirements, instantiation and generic subprograms. The Fortran 2023 text of this
section is the stable baseline; What’s New and Fortran 2028 Preview
lists the 2028 work items. Compilers expose proposed features of the next revision through -std=f202y (gfortran), which
changes between releases.
Source: WG5: Fortran 2028
Where the books are outdated
The book Modern Fortran Explained: Incorporating Fortran 2023 covers the standards in its first chapter and is current for the language itself. What it cannot give is what happened afterwards, and what compilers do:
-
It gives no ISO number or publication date for Fortran 2023 (ISO/IEC 1539-1:2023, November 2023), and does not know Corrigendum 1 (2026).
-
It speaks of templates only as a future direction. Fortran 2028 is now at Committee Draft stage with templates and generic subprograms in the working draft.
-
It contains no compiler-support information, and its only compiler version string is an old NAG release. The table above replaces that gap for gfortran, Flang, ifx, NAG and Cray.
-
It cites IEEE 754-2008 and ISO/IEC/IEEE 60559:2011 for floating-point arithmetic. Fortran 2023 adopts ISO/IEC 60559:2020 (IEEE 754-2019); see Floating-Point and IEEE Arithmetic.
-
Its Appendix A lists the authors' recommended deprecations, which are not the standard’s obsolescent or deleted lists; the standard’s own lists are the ones summarized above and in Annex B.
-
It mentions only
makefor the recompilation problem; the tools used today are described on Building with Make, CMake and Meson and Fortran Package Manager (fpm).
Common pitfalls
-
Trusting the default compiler mode. gfortran’s default
-std=gnuaccepts extensions silently and the deleted features with only a warning. A program that compiles by default is not necessarily conforming. Add-std=f2023 -Wall -Wextra -pedanticin development. -
Using a Fortran 2023 feature without checking the oldest compiler you support. The last two rows of the table are the usual traps: an intrinsic that exists in the compiler manual but is missing from its library (
tokenize,c_f_strpointerin gfortran 16.2), and a feature accepted by one compiler and rejected by another. Test with a link and a run, not only a syntax check. -
Reading a status page as a promise. The fortran-lang compilers page and a compiler’s status page can lag the compiler you installed, in either direction.
-
Citing a draft as the standard. J3/23-007r1 is the free final draft; for formal citation use ISO/IEC 1539-1:2023 and its Corrigendum 1:2026.
-
Equating "obsolescent" with "unsupported". Obsolescent and deleted features still compile on most processors; the standard only requires that the processor can report them. Do not rely on that for new code.
-
Assuming kind values are portable.
real16was -2 with gfortran and 2 with Flang in the example above. Useselected_real_kindandselected_logical_kind, or theiso_fortran_envconstants with a check that they are positive.
References
-
J3/23-007r1: Fortran 2023 final draft (clauses 4.2 to 4.4, 6.3, 7.3, 7.6, 7.7, 8.5, 10.1, 11.6, 13, 15.8, 16.9, 16.10, 17.11, 18.2, Annex B)
-
WG5 N2212: The new features of Fortran 2023, N2244: Fortran 2023 Corrigendum 1, N2161: Fortran 2018, N1891: Fortran 2008, N1648: Fortran 2003, N2263: history of Fortran standardization meetings
-
GNU Fortran: Standards, Fortran 2018 status, Dialect options, GCC 16 changes
-
Intel Fortran Compiler: conformance, compatibility and Fortran features (2026.1), release notes 2026