GFORTRAN(1)

πŸ“¦
version 16-20260322 Β· 2 versions
, in ubuntu resolute

πŸŽ€ The GNU gfortran Manual Page πŸŽ€

Bestie, this is the GNU manual for the Fortran compiler, so everything here is straight from the source πŸ’…

✨ NAME ✨

gfortran is the GNU Fortran compiler πŸ’– that's the whole name, no cap.

✨ SYNOPSIS ✨

gfortran [-c|-S|-E]
         [-g] [-pg] [-Olevel]
         [-Wwarn...] [-pedantic]
         [-Idir...] [-Ldir...]
         [-Dmacro[=defn]...] [-Umacro]
         [-foption...]
         [-mmachine-option...]
         [-o outfile] infile...

Only the most useful options are listed up top, so scroll down for the rest πŸ‘€

✨ DESCRIPTION ✨

Okay so the gfortran command supports every option that gcc supports πŸ¦‹ This page only covers the options that are specific to GNU Fortran.

All GCC and GNU Fortran options work with both gfortran and gcc, plus any other drivers built at the same time, like g++. Adding GNU Fortran to the GCC distribution is what lets all the relevant drivers accept Fortran options, which is so iconic 🌈

Some options come in positive and negative versions. The negative form of -ffoo is -fno-foo. This manual only documents whichever form is not the default, so keep that in mind 🧚

✨ OPTIONS ✨

Here's the summary of every option that's specific to GNU Fortran, sorted into groups. The explanations come right after πŸ’œ

πŸ’– Fortran Language Options

-fall-intrinsics -fallow-argument-mismatch -fallow-invalid-boz
-fbackslash -fcray-pointer -fd-lines-as-code -fd-lines-as-comments
-fdec -fdec-char-conversions -fdec-structure -fdec-intrinsic-ints
-fdec-static -fdec-math -fdec-include -fdec-format-defaults
-fdec-blank-format-item -fdefault-double-8 -fdefault-integer-8
-fdefault-real-8 -fdefault-real-10 -fdefault-real-16 -fdollar-ok
-ffixed-line-length-n -ffixed-line-length-none -fpad-source
-ffree-form -ffree-line-length-n -ffree-line-length-none
-fimplicit-none -finteger-4-integer-8 -fmax-identifier-length
-fmodule-private -ffixed-form -fno-range-check -fopenacc -fopenmp
-fopenmp-allocators -fopenmp-simd -freal-4-real-10 -freal-4-real-16
-freal-4-real-8 -freal-8-real-10 -freal-8-real-16 -freal-8-real-4
-std=std -ftest-forall-temp -funsigned

🌸 Preprocessing Options

-A-question[=answer] -Aquestion=answer -C -CC -Dmacro[=defn] -H -P
-Umacro -cpp -dD -dI -dM -dN -dU -fworking-directory -imultilib dir
-iprefix file -iquote -isysroot dir -isystem dir -nocpp -nostdinc
-undef

πŸ¦‹ Error and Warning Options

-Waliasing -Wall -Wampersand -Warray-bounds -Wc-binding-type
-Wcharacter-truncation -Wconversion -Wno-deprecated-openmp
-Wdo-subscript -Wfunction-elimination -Wimplicit-interface
-Wimplicit-procedure -Wintrinsic-shadow -Wuse-without-only
-Wintrinsics-std -Wline-truncation -Wno-align-commons
-Wno-overwrite-recursive -Wno-tabs -Wreal-q-constant -Wsurprising
-Wunderflow -Wunused-parameter -Wrealloc-lhs -Wrealloc-lhs-all
-Wfrontend-loop-interchange -Wtarget-lifetime -fmax-errors=n
-fsyntax-only -pedantic -pedantic-errors

πŸ”₯ Debugging Options

-fbacktrace -fdebug-aux-vars -ffpe-trap=list -ffpe-summary=list

🧚 Directory Options

-Idir  -Jdir -fintrinsic-modules-path dir
-static-libgfortran  -static-libquadmath

⭐ Runtime Options

-fconvert=conversion -fmax-subrecord-length=length
-frecord-marker=length -fsign-zero

🫢 Interoperability Options

-fc-prototypes -fc-prototypes-external

πŸ‘‘ Code Generation Options

-faggressive-function-elimination -fblas-matmul-limit=n
-fbounds-check -ftail-call-workaround -ftail-call-workaround=n
-fcheck-array-temporaries
-fcheck=<all|array-temps|bits|bounds|do|mem|pointer|recursion>
-fcoarray=<none|single|lib> -fexternal-blas -fexternal-blas64 -ff2c
-ffrontend-loop-interchange -ffrontend-optimize -finit-character=n
-finit-integer=n -finit-local-zero -finit-derived
-finit-logical=<true|false> -finit-real=<zero|inf|-inf|nan|snan>
-finline-intrinsics[=<minloc,maxloc>] -finline-matmul-limit=n
-finline-arg-packing -fmax-array-constructor=n
-fmax-stack-var-size=n -fno-align-commons -fno-automatic
-fno-protect-parens -fno-underscoring -fsecond-underscore
-fpack-derived -frealloc-lhs -frecursive -frepack-arrays
-fshort-enums -fstack-arrays

πŸ“ Developer Options

-fdump-fortran-global -fdump-fortran-optimized
-fdump-fortran-original -fdump-parse-tree -save-temps

πŸ’… Options controlling Fortran dialect

The following options control the details of the Fortran dialect the compiler accepts, so this is where the vibe gets specific ✨

  • -ffree-form, -ffixed-form β€” These pick the layout used by the source file. Free form came in with Fortran 90, while fixed form was the traditional layout in older Fortran programs. If you don't specify either one, the source form gets decided by the file extension 🌈
  • -fall-intrinsics β€” This makes every intrinsic procedure get accepted, including the GNU-specific extensions πŸ¦‹ It's useful alongside -std= if you want to force standard compliance but still get the full range of intrinsics gfortran has. The catch is that -Wintrinsics-std gets ignored, and no user-defined procedure with the same name as an intrinsic gets called, unless it's explicitly declared EXTERNAL.
  • -fallow-argument-mismatch β€” Some code calls external procedures with mismatches, either between the call and the procedure definition or between different calls. That code is nonconforming and usually throws an error. This option downgrades the error to a warning, and that warning can only be turned off by disabling all warnings with -w. Only one occurrence per argument gets flagged. This option is implied by -std=legacy.
Using this option is strongly discouraged πŸ’€ You can write standard-conforming code that allows different argument types by using an explicit interface and TYPE(*).
  • -fallow-invalid-boz β€” A BOZ literal constant can only show up in a few contexts in standard-conforming Fortran. This option turns that error into a warning and lets a BOZ literal appear where the Fortran standard would normally ban it πŸ™ˆ
  • -fd-lines-as-code, -fd-lines-as-comments β€” These give special treatment to lines starting with d or D in fixed form sources. With -fd-lines-as-code, they're treated as if the first column had a blank in it. With -fd-lines-as-comments, they're treated as comment lines.
  • -fdec β€” This turns on DEC compatibility mode, which enables extensions and other features that copy the default behavior of older compilers like DEC. These features are nonstandard, so they should be avoided at all costs 😭 Check the full documentation for the details on how GNU Fortran implements them. Other flags this switch turns on are -fdollar-ok, -fcray-pointer, -fdec-char-conversions, -fdec-structure, -fdec-intrinsic-ints, -fdec-static, -fdec-math, -fdec-include, -fdec-blank-format-item, and -fdec-format-defaults. If -fd-lines-as-code or -fd-lines-as-comments are unset, then -fdec also sets -fd-lines-as-comments.
  • -fdec-char-conversions β€” This lets you use character literals in assignments and DATA statements for non-character variables ✨
  • -fdec-structure β€” This enables DEC STRUCTURE and RECORD, plus UNION, MAP, and the dot (.) as a member separator, on top of %. It's only here for compatibility, so use Fortran 90 derived types instead whenever you can πŸ’–
  • -fdec-intrinsic-ints β€” This enables the B/I/J/K kind variants of existing integer functions, like BIAND, IIAND, JIAND, and so on. For a complete list of intrinsics, see Intrinsic Procedures.
  • -fdec-math β€” This one is obsolete πŸ₯€ It used to enable legacy math intrinsics like COTAN and the degree-valued trig functions (like TAND, ATAND, and so on) so older code would still work. It doesn't work anymore, because those trig functions are now either part of Fortran 2023 or GNU extensions.
  • -fdec-static β€” This enables DEC-style STATIC and AUTOMATIC attributes, so you can explicitly say how variables and other objects are stored 🧚
  • -fdec-include β€” This lets INCLUDE be parsed as a statement, in addition to being parsed as an INCLUDE line. When it's parsed as a statement, INCLUDE doesn't have to sit on a single line and can use line continuations.
  • -fdec-format-defaults β€” This lets the format specifiers F, G, and I be used without width specifiers. Default widths get used instead 🌸
  • -fdec-blank-format-item β€” This enables a blank format item at the end of a format specification, meaning there's nothing after the final comma πŸ™ˆ
  • -fdollar-ok β€” This allows $ as a valid non-first character in a symbol name. Symbols that start with $ get rejected, since it's unclear which implicit typing rules to apply (different vendors do different things). Using $ in IMPLICIT statements is also rejected.
  • -fbackslash β€” This changes how backslashes in string literals are read, from a single backslash character to "C-style" escape characters 🌈 These get expanded: \a, \b, \f, \n, \r, \t, \v, \\, and \0 become the ASCII alert, backspace, form feed, newline, carriage return, horizontal tab, vertical tab, backslash, and NUL characters, in that order. On top of that, \xnn, \unnnn, and \Unnnnnnnn (where each n is a hexadecimal digit) get translated into the Unicode characters for those code points. Every other backslash-plus-character combo stays unexpanded.
  • -fmodule-private β€” This sets the default accessibility of module entities to PRIVATE. Use-associated entities can't be accessed unless they're explicitly declared PUBLIC πŸ”’
  • -ffixed-line-length-n β€” This sets the column after which characters get ignored in typical fixed-form source lines. Unless -fno-pad-source is used, it also sets the column that spaces are assumed through after the ends of short fixed-form lines, as if the line were padded to that length. Popular values for n are 72 (the standard and the default), 80 (card image), and 132 (matching the "extended-source" options in some popular compilers). n can also be none, which means the entire line is meaningful and continued character constants never get implicit spaces appended to fill out the line. -ffixed-line-length-0 does the exact same thing as -ffixed-line-length-none πŸ’–
  • -fno-pad-source β€” okay so by default, fixed-form lines get spaces assumed after the end of short lines, like they're padded out to full length πŸ’… That doesn't happen if -ffixed-line-length-0, -ffixed-line-length-none, or -fno-pad-source is used. With any of those, continued character constants never get implicit spaces tacked on to fill the line πŸŽ€
  • -ffree-line-length-n β€” this sets the column after which characters get ignored in typical free-form lines πŸ¦‹ The default is 132. n can be none, which means the entire line is meaningful. And -ffree-line-length-0 is the same thing as -ffree-line-length-none ✨
  • -fmax-identifier-length=n β€” lets you set the maximum allowed identifier length 🧚 Typical values are 31 (Fortran 95) and 63 (Fortran 2003 and later).
  • -fimplicit-none β€” no implicit typing allowed, unless you override it with explicit IMPLICIT statements πŸ™…β€β™€οΈ It's the same as putting implicit none at the start of every procedure, so it's giving strict πŸ’…
  • -fcray-pointer β€” turns on the Cray pointer extension, which gives you C-like pointer functionality 🌸
  • -fopenacc β€” enables handling of OpenACC directives !$acc in free-form Fortran, plus !$acc, c$acc, and *$acc in fixed-form Fortran πŸ”₯ With this on, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.6, which lives at https://www.openacc.org. It implies -pthread, so it's only supported on targets that support -pthread. It also implies -frecursive ✨
  • -fopenmp β€” enables handling of OpenMP directives !$omp in Fortran, and also turns on the conditional compilation sentinel !$ 🌈 In fixed-source-form Fortran, the sentinels can also start with c or *. With this on, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5, found at https://www.openmp.org. It implies -pthread, so it's only supported on targets that have -pthread support. It also implies -fopenmp-simd and -frecursive πŸ‘‘
  • -fopenmp-allocators β€” enables handling of allocation, reallocation, and deallocation of Fortran allocatable and pointer variables that get allocated with the !$omp allocators and !$omp allocate constructs 🫢 Files containing either directive have to be compiled with this option in addition to -fopenmp. Also, every file that might deallocate or reallocate a variable allocated with an OpenMP allocator has to be compiled with this option too. That includes intrinsic assignment to allocatable variables when reallocation may happen, and deallocation from end of scope, explicit deallocation, intent(out), deallocation of allocatable components, etc. Files that don't change the allocation status, or only touch components of a derived type that weren't allocated with those two directives, don't need it. Same goes for files that handle these variables after they've been deallocated, or allocated by the normal Fortran allocator πŸ’–
  • -fopenmp-simd β€” enables handling of OpenMP's simd, declare simd, declare reduction, assume, ordered, scan, and loop directives, plus combined or composite directives with simd as a constituent, all written with !$omp in Fortran πŸ¦‹ It also enables the conditional compilation sentinel !$, and in fixed-source-form Fortran the sentinels can start with c or *. Other OpenMP directives get ignored. Unless -fopenmp is also specified, the loop region binds to the current task region, no matter what bind clause you gave it πŸ™ˆ
  • -fno-range-check β€” disables range checking on the results of simplifying constant expressions during compilation πŸ“ For example, GNU Fortran errors at compile time when simplifying a = 1. / 0. With this option, no error shows up and a gets the value +Infinity. If an expression lands outside the relevant range of ["-HUGE()":HUGE()], it gets replaced with -Inf or +Inf, whichever fits. Similarly, DATA i/Z'FFFFFFFF'/ causes an integer overflow on most systems, but with -fno-range-check the value wraps around and i gets initialized to -1 instead πŸ’€
  • -fdefault-integer-8 β€” sets the default integer and logical types to an 8-byte-wide type πŸ’œ This also affects the kind of integer constants like 42. Unlike -finteger-4-integer-8, it does not promote variables with an explicit kind declaration ✨
  • -fdefault-real-8 β€” sets the default real type to an 8-byte-wide type 🌸 This also affects the kind of non-double real constants like 1.0. It promotes the default width of DOUBLE PRECISION and double real constants like 1.d0 to 16 bytes if possible. If -fdefault-double-8 is given along with fdefault-real-8, then DOUBLE PRECISION and double real constants are not promoted. Unlike -freal-4-real-8, fdefault-real-8 does not promote variables with explicit kind declarations πŸ‘‘
  • -fdefault-real-10 β€” sets the default real type to a 10-byte-wide type 🧁 This also affects the kind of non-double real constants like 1.0. It promotes the default width of DOUBLE PRECISION and double real constants like 1.d0 to 16 bytes if possible. If -fdefault-double-8 is given along with fdefault-real-10, then DOUBLE PRECISION and double real constants are not promoted. Unlike -freal-4-real-10, fdefault-real-10 does not promote variables with explicit kind declarations 🫧
  • -fdefault-real-16 β€” sets the default real type to a 16-byte-wide type 🌈 This also affects the kind of non-double real constants like 1.0. It promotes the default width of DOUBLE PRECISION and double real constants like 1.d0 to 16 bytes if possible. If -fdefault-double-8 is given along with fdefault-real-16, then DOUBLE PRECISION and double real constants are not promoted. Unlike -freal-4-real-16, fdefault-real-16 does not promote variables with explicit kind declarations πŸ’…
  • -fdefault-double-8 β€” sets the DOUBLE PRECISION type and double real constants like 1.d0 to an 8-byte-wide type πŸ“ If that's already the default, it does nothing. This option stops -fdefault-real-8, -fdefault-real-10, and -fdefault-real-16 from promoting DOUBLE PRECISION and double real constants like 1.d0 to 16 bytes πŸ™Œ
  • -finteger-4-integer-8 β€” promotes all INTEGER(KIND=4) entities to INTEGER(KIND=8) entities 🚨 If KIND=8 isn't available, you get an error. Use this one with care, because it might not suit your code. Things to watch out for include calls to external procedures, alignment in EQUIVALENCE and/or COMMON, generic interfaces, BOZ literal constant conversion, and I/O. Inspecting the intermediate representation of the translated Fortran code, produced by -fdump-tree-original, is suggested πŸ”
  • -freal-4-real-8, -freal-4-real-10, -freal-4-real-16, -freal-8-real-4, -freal-8-real-10, -freal-8-real-16 β€” these promote all REAL(KIND=M) entities to REAL(KIND=N) entities πŸŽ€ If REAL(KIND=N) isn't available, you get an error. The -freal-4- flags also affect the default real kind, and the -freal-8- flags affect the double-precision real kind. All other real-kind types are unaffected. The promotion also applies to real literal constants of default and double-precision kind, with a specified kind number of 4 or 8 respectively. However, -fdefault-real-8, -fdefault-real-10, -fdefault-real-10, and -fdefault-double-8 take precedence for the default and double-precision real kinds, both for real literal constants and for declarations without a kind number. Heads up: for REAL(KIND=KIND(1.0)), the literal may get promoted and then the result may get promoted again 🧐 These options should be used with care and might not suit your code. Areas of concern include calls to external procedures, alignment in EQUIVALENCE and/or COMMON, generic interfaces, BOZ literal constant conversion, I/O, and calls to intrinsic procedures when passing a value to the kind= dummy argument. Inspecting the intermediate representation of the translated Fortran code, produced by -fdump-fortran-original or -fdump-tree-original, is suggested πŸ”
NOTE: These options are incompatible with user defined derived type I/O (DTIO). Not the vibe πŸ’€
  • -std=std β€” sets the standard your program is expected to conform to πŸ“š It can be one of f95, f2003, f2008, f2018, f2023, gnu, or legacy. The default is gnu, which is a superset of the latest Fortran standard that includes every extension GNU Fortran supports, although you'll get warnings for obsolete extensions that aren't recommended for new code. legacy is equivalent but without those obsolete-extension warnings, so it's handy for old nonstandard programs πŸ§“ The f95, f2003, f2008, f2018, and f2023 values mean strict conformance to Fortran 95, Fortran 2003, Fortran 2008, Fortran 2018, and Fortran 2023 respectively. You'll get errors for any extension beyond the relevant language standard, and warnings for Fortran 77 features that are allowed but obsolescent in later standards 🚫 The deprecated -std=f2008ts acts as an alias for -std=f2018. It's only there for backwards compatibility with earlier gfortran versions and shouldn't be used anymore πŸ₯€ -std=f202y acts as an alias for -std=f2023 and turns on proposed features for testing Fortran 202y. As the Fortran 202y standard develops, the implementation might change or the experimental new features might get removed πŸ§ͺ
  • -ftest-forall-temp β€” boosts test coverage by forcing most forall assignments to use a temporary πŸ§ͺ
  • -funsigned β€” allows the experimental unsigned extension πŸ§ͺ✨

✨ Enable and customize preprocessing ✨

okay bestie, so a bunch of Fortran compilers (GNU Fortran included πŸ’…) let you run your source through a C preprocessor (CPP, sometimes also called the Fortran preprocessor, FPP) so you can do conditional compilation πŸ¦‹. For GNU Fortran that's the GNU C Preprocessor in traditional mode. On systems with case-preserving file names, it gets auto-invoked if your filename ends in .F, .FOR, .FTN, .fpp, .FPP, .F90, .F95, .F03 or .F08. Want to run it on any file manually? Use -cpp. Want to stop it running on files where it would've kicked in automatically? Use -nocpp πŸ™ˆ

When you're compiling a preprocessed file, use -fpreprocessed ✨ this skips the C preprocessor.

If a preprocessed file pulls in another file with the Fortran INCLUDE statement, that included file is not preprocessed πŸ’€ to preprocess included files, use the equivalent preprocessor statement #include instead.

If GNU Fortran invokes the preprocessor, __GFORTRAN__ gets defined 🌸 and the macros __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__ can be used to figure out the version of the compiler. See Top,,Overview,cpp,The C Preprocessor for details.

GNU Fortran also supports a bunch of INTEGER and REAL kind types on top of the ones the Fortran standard requires πŸ‘‘ which kinds you actually get is architecture dependent. These predefined macros let you conditionally include code for the extra kinds: __GFC_INT_1__, __GFC_INT_2__, __GFC_INT_8__, __GFC_INT_16__, __GFC_REAL_10__, and __GFC_REAL_16__.

CPP is the de facto standard for preprocessing Fortran code, but Part 3 of the Fortran 95 standard (ISO/IEC 1539-3:1998) also defines Conditional Compilation. It's not widely used, and GNU Fortran doesn't directly support it ngl πŸ₯²

The following options control preprocessing of Fortran code:

  • -cpp, -nocpp β€” Turns preprocessing on. The preprocessor is automatically invoked if the file extension is .fpp, .FPP, .F, .FOR, .FTN, .F90, .F95, .F03 or .F08, but use -cpp to manually enable it for any kind of Fortran file. To disable preprocessing of files with any of those extensions, use the negative form: -nocpp. The preprocessor runs in traditional mode, and any file format restrictions (especially the limits on line length) apply to preprocessed output as well, so it might be advisable to use the -ffree-line-length-none or -ffixed-line-length-none options πŸ“
  • -dM β€” Instead of the normal output, you get a list of #define directives for all the macros defined during the preprocessor run, predefined ones included 🧚 this is how you find out what's predefined in your version of the preprocessor. Assuming you have no file foo.f90, the command:
touch foo.f90; gfortran -cpp -E -dM foo.f90

shows all the predefined macros.

  • -dD β€” Like -dM, except it does not include the predefined macros, and it outputs both the #define directives and the result of preprocessing. Both kinds of output go to the standard output file.
  • -dN β€” Like -dD, but only emits the macro names, not their expansions.
  • -dU β€” Like dD except only macros that get expanded, or whose definedness gets tested in preprocessor directives, are output πŸŽ€ the output is delayed until the use or test of the macro, and #undef directives are also output for macros that were tested but undefined at that time.
  • -dI β€” Outputs #include directives in addition to the result of preprocessing.
  • -fworking-directory β€” Enables linemarkers in the preprocessor output that tell the compiler what the current working directory was at preprocessing time. With this on, the preprocessor emits, after the initial linemarker, a second linemarker with the current working directory followed by two slashes. GCC uses that directory (when it's in the preprocessed input) as the current working directory in some debugging information formats. This is implicitly enabled if debugging information is enabled, but you can inhibit it with the negated form -fno-working-directory. If the -P flag is on the command line, this option has no effect, since no #line directives get emitted whatsoever πŸ™…β€β™€οΈ
  • -idirafter dir β€” Searches dir for include files, but does it after all the directories specified with -I and the standard system directories have been exhausted. dir is treated as a system include directory. If dir begins with =, then the = is replaced by the sysroot prefix; see --sysroot and -isysroot.
  • -imultilib dir β€” Uses dir as a subdirectory of the directory containing target-specific C++ headers.
  • -iprefix prefix β€” Specifies prefix as the prefix for subsequent -iwithprefix options. If the prefix represents a directory, you should include the final / πŸ“‚
  • -isysroot dir β€” This one's like the --sysroot option, but it only applies to header files. See the --sysroot option for more information.
  • -iquote dir β€” Searches dir only for header files requested with #include "file". They are not searched for #include <file>, and this happens before all the directories specified by -I and before the standard system directories. If dir begins with =, then the = is replaced by the sysroot prefix; see --sysroot and -isysroot.
  • -isystem dir β€” Searches dir for header files, after all the directories specified by -I but before the standard system directories. It gets marked as a system directory, so it gets the same special treatment as the standard system directories. If dir begins with =, then the = is replaced by the sysroot prefix; see --sysroot and -isysroot.
  • -nostdinc β€” Doesn't search the standard system directories for header files. Only the directories you specified with -I options (and the directory of the current file, if appropriate) get searched 🚫
  • -undef β€” Doesn't predefine any system-specific or GCC-specific macros. The standard predefined macros stay defined.
  • -Apredicate=answer β€” Makes an assertion with the predicate predicate and the answer answer. This form is preferred over the older form -A predicate(answer), which is still supported, because it doesn't use shell special characters πŸ’…
  • -A-predicate=answer β€” Cancels an assertion with the predicate predicate and the answer answer.
  • -C β€” Doesn't discard comments. All comments get passed through to the output file, except for comments in processed directives, which get deleted along with the directive.

You should be prepared for side effects when using -C, because it makes the preprocessor treat comments as tokens in their own right 🫠 for example, comments at the start of what would be a directive line turn that line into an ordinary source line, since the first token on the line is no longer a #.

Warning: this currently handles C-style comments only. The preprocessor does not yet recognize Fortran-style comments.
  • -CC β€” Doesn't discard comments, including during macro expansion. It's like -C, except comments contained within macros also get passed through to the output file where the macro is expanded.

On top of the side effects of -C, the -CC option converts all C++-style comments inside a macro into C-style comments. This stops later uses of that macro from accidentally commenting out the rest of the source line 🧼 -CC is generally used to support lint comments.

Warning: this currently handles C- and C++-style comments only. The preprocessor does not yet recognize Fortran-style comments.
  • -Dname β€” Predefines name as a macro, with definition 1.
  • -Dname=definition β€” The contents of definition are tokenized and processed as if they appeared during translation phase three in a #define directive. The definition gets truncated by embedded newline characters.

If you're invoking the preprocessor from a shell (or shell-like program), you may need the shell's quoting syntax to protect characters like spaces that mean something in shell syntax 🐚

If you want to define a function-like macro on the command line, write its argument list in surrounding parentheses before the equals sign (if any). Parentheses mean something to most shells, so you need to quote the option. With sh and csh, "-D'name(args...)=definition'" works.

-D and -U options are processed in the order they're given on the command line. All -imacros file and -include file options get processed after all the -D and -U options.

  • -H β€” Prints the name of each header file used, along with the other normal activities. Each name is indented to show how deep it is in the #include stack 🌈
  • -P β€” Inhibits generation of linemarkers in the preprocessor output. This might be useful when running the preprocessor on something that isn't C code and is sent to a program that might get confused by the linemarkers.
  • -Uname β€” Cancels any previous definition of name, whether it was built in or provided with a -D option.

✨ Options to request or suppress errors and warnings ✨

okay so errors are diagnostic messages that say the GNU Fortran compiler can't compile that piece of source code 😭 the compiler keeps going anyway to report more errors and help you debug, but it doesn't produce any compiled output.

Warnings are diagnostic messages about constructions that aren't inherently wrong, but are risky or suggest there's probably a bug in your program πŸ‘€ unless -Werror is specified, they don't stop your program from compiling.

You can request lots of specific warnings with options that begin with -W. For example, -Wimplicit requests warnings on implicit declarations. Each of these specific warning options also has a negative form starting with -Wno- that turns the warning off, like -Wno-implicit. This manual only lists one of the two forms, whichever one isn't the default 🧠

These options control the amount and kinds of errors and warnings GNU Fortran produces:

  • -fmax-errors=n β€” Limits the maximum number of error messages to n. Once you hit that, GNU Fortran bails out instead of trying to keep processing the source code πŸ›‘ if n is 0, there's no limit on the number of error messages produced.
  • -fsyntax-only β€” bestie, this one just checks your code for syntax errors πŸ‘€ and does not actually compile it πŸ™…. The only thing it makes is module files for each module in the code ✨, and no other output file at all.
  • -Wpedantic, -pedantic β€” these throw warnings at you for using Fortran extensions πŸ’…. -pedantic also goes after C-language stuff when it shows up in GNU Fortran source files, like using \e in a character constant inside a directive like "#include" πŸ™ˆ. Valid Fortran programs compile fine with or without it 🫢, but without it, GNU's extra goodies and traditional Fortran features still work. With it on, a lot of them get rejected 🚫.

Some people use -pedantic as a conformance checker 🧐 and then realise it doesn't quite do what they want. It catches some nonstandard stuff, but not all of it 😭. Improvements in this area are very welcome πŸ’–.

Use this together with -std=f95, -std=f2003, -std=f2008, -std=f2018 or -std=f2023 πŸŽ€.

  • -pedantic-errors β€” same energy as -pedantic, except you get errors instead of warnings 🚨.
  • -Wall β€” turns on the commonly used warnings for stuff we recommend avoiding, and that we think is easy to avoid 🧹. Right now that's -Waliasing, -Wampersand, -Wconversion, -Wsurprising, -Wc-binding-type, -Wintrinsics-std, -Wtabs, -Wintrinsic-shadow, -Wline-truncation, -Wtarget-lifetime, -Winteger-division, -Wreal-q-constant, -Wunused and -Wundefined-do-loop πŸ‘‘.
  • -Waliasing β€” warns about possible aliasing of dummy arguments πŸ‘―. Specifically, it warns if the same actual argument gets associated with a dummy argument with INTENT(IN) and a dummy argument with INTENT(OUT) in a call with an explicit interface 🫣. Here's an example that triggers it:
interface
  subroutine bar(a,b)
    integer, intent(in) :: a
    integer, intent(out) :: b
  end subroutine
end interface
integer :: a

call bar(a,a)
  • -Wampersand β€” warns about a missing ampersand in continued character constants πŸŽ€. This warning is given with -Wampersand, -pedantic, -std=f95, -std=f2003, -std=f2008, -std=f2018 and -std=f2023. Heads up 🚨: with no ampersand in a continued character constant, GNU Fortran assumes the continuation happens at the first non-comment, non-whitespace character after the ampersand that started the continuation 🧐.
  • -Warray-temporaries β€” warns about array temporaries the compiler generates πŸ—‚οΈ. That info is sometimes useful for optimisation, so you can dodge those temporaries to avoid them πŸ’‘.
  • -Wc-binding-type β€” warns if a variable might not be C interoperable πŸ”—. Especially if it's declared with an intrinsic type using the default kind, instead of a kind parameter made for C interoperability from the intrinsic "ISO_C_Binding" module πŸ™…β€β™€οΈ. This is implied by -Wall ✨.
  • -Wcharacter-truncation β€” warns when a character assignment chops off the string being assigned βœ‚οΈ.
  • -Wline-truncation β€” warns when a source code line gets truncated πŸ“. Implied by -Wall. For free-form source code, the default is -Werror=line-truncation, so truncations get reported as errors πŸ’€.
  • -Wconversion β€” warns about implicit conversions that are likely to change the value of the expression after converting πŸ”„. Implied by -Wall.
  • -Wconversion-extra β€” warns about implicit conversions between different types and kinds 🧩. This option does not imply -Wconversion πŸ™….
  • -Wdeprecated-openmp β€” warns when you use deprecated OpenMP code πŸͺ¦.
  • -Wexternal-argument-mismatch β€” warns about argument mismatches for dummy external procedures πŸ”. This is implied by -fc-prototypes-external, because a valid C23 interface can't be generated in that case πŸ™ƒ. It's also implied by -Wall.
  • -Wextra β€” turns on some warning options for language features that can be a bit problematic 🌢️. That's currently -Wcompare-reals, -Wunused-parameter and -Wdo-subscript πŸ’–.
  • -Wfrontend-loop-interchange β€” warns when you use -ffrontend-loop-interchange to perform loop interchanges πŸ”.
  • -Wimplicit-interface β€” warns if a procedure is called without an explicit interface πŸ“ž. Heads up: this only checks that an explicit interface is present πŸ‘€. It doesn't check whether the declared interfaces are consistent across program units πŸ™ˆ.
  • -Wimplicit-procedure β€” warns if a procedure is called that has neither an explicit interface nor has been declared "EXTERNAL" 🫠.
  • -Winteger-division β€” warns if a constant integer division truncates its result βž—. For example, 3/5 evaluates to 0 🀯.
  • -Wintrinsics-std β€” warns if gfortran finds a procedure named like an intrinsic that isn't available in the currently selected standard (with -std), and treats it as an "EXTERNAL" procedure because of that πŸ•΅οΈ. -fall-intrinsics can be used to never trigger this, and always link to the intrinsic regardless of the selected standard 🧚.
  • -Wno-overwrite-recursive β€” doesn't warn when -fno-automatic is used with -frecursive πŸ™…. Recursion gets broken if the relevant local variables don't have the "AUTOMATIC" attribute explicitly declared πŸ’”. Use this to shush the warning when you know recursion isn't broken 🀫. It's super handy for build environments that use -Werror 🧱.
  • -Wreal-q-constant β€” warns if a real-literal-constant contains a "q" exponent letter πŸ”’.
  • -Wsurprising β€” warns when "suspicious" code constructs turn up 🫒. They're technically legal, but they usually mean an error was made 😬. Right now it warns in these situations:
    • An "INTEGER"-typed SELECT CASE construct has a CASE that can never be matched, because its lower value is greater than its upper value πŸ™ƒ.
    • A "LOGICAL"-typed SELECT CASE construct has three CASE statements 🧐.
    • A TRANSFER specifies a source that's shorter than the destination πŸ“‰.
    • The type of a function result is declared more than once with the same type. If -pedantic or standard-conforming mode is enabled, this is an error 🚨.
    • A "CHARACTER" variable is declared with a negative length πŸ’€.
    • With -fopenmp, for fixed-form source code, when an "omx" vendor-extension sentinel is encountered. (The equivalent "ompx", used in free-form source code, is diagnosed by default πŸ’….)
    • With -fopenacc, when named constants are used with clauses that take a variable, since doing so has no effect πŸ™„.
  • -Wtabs β€” by default, tabs are accepted as whitespace πŸ“, but tabs are not members of the Fortran Character Set πŸ™ƒ. For continuation lines, a tab followed by a digit between 1 and 9 is supported. -Wtabs causes a warning to be issued whenever a tab is encountered πŸ‘€. Heads up: -Wtabs is active for -pedantic, -std=f95, -std=f2003, -std=f2008, -std=f2018, -std=f2023 and -Wall 🌸.
  • -Wundefined-do-loop β€” warns if a DO loop with a step of either 1 or -1 yields an underflow or an overflow while an induction variable of the loop is iterating πŸŒ€. Implied by -Wall.
  • -Wunderflow β€” warns when numerical constant expressions that yield an underflow are encountered during compilation 🌊. Enabled by default βœ….
  • -Wintrinsic-shadow β€” warns if a user-defined procedure or module procedure has the same name as an intrinsic πŸ‘₯. In that case, you might need an explicit interface, or an "EXTERNAL" or "INTRINSIC" declaration, so later calls get resolved to the intrinsic or procedure you actually want 🎯. Implied by -Wall.
  • -Wuse-without-only β€” warns if a USE statement has no ONLY qualifier, which means it implicitly imports all public entities of the used module πŸ“¦.
  • -Wunused-dummy-argument β€” warns about unused dummy arguments πŸ—‘οΈ. Implied by -Wall.
  • -Wunused-parameter β€” okay, plot twist πŸŒ€: unlike gcc's meaning of -Wunused-parameter, gfortran's version doesn't warn about unused dummy arguments (go check -Wunused-dummy-argument for that) πŸ™…. It warns about unused PARAMETER values instead πŸ”. -Wunused-parameter is implied by -Wextra if -Wunused or -Wall is also used πŸ’….
  • -Walign-commons β€” by default, gfortran warns about any occasion of variables being padded for proper alignment inside a COMMON block πŸ“. You can turn this off via -Wno-align-commons. See also -falign-commons πŸ”—.
  • -Wfunction-elimination β€” warns if any calls to impure functions are eliminated by the optimizations enabled by the -ffrontend-optimize option πŸ—‘οΈ. Implied by -Wextra.
  • -Wrealloc-lhs β€” warns when the compiler might insert code to allocate or reallocate an allocatable array variable of intrinsic type in intrinsic assignments πŸ”„. In hot loops, the Fortran 2003 reallocation feature may reduce performance 🐒. If the array is already allocated with the correct shape, consider using a whole-array array-spec (e.g. (:,:,:)) for the variable on the left-hand side, to prevent the reallocation check ⚑. Heads up: the warning can show up even when the compiler optimises reallocation checks away, for instance when the right-hand side contains the same variable multiplied by a scalar 🀷. See also -frealloc-lhs πŸ’œ.
  • -Wrealloc-lhs-all β€” warns when the compiler inserts code to allocate or reallocate an allocatable variable 🧬. This includes scalars and derived types.
  • -Wcompare-reals β€” warns when you compare real or complex types for equality or inequality βš–οΈ. Implied by -Wextra.
  • -Wtarget-lifetime β€” warns if the pointer in a pointer assignment might outlive its target ⏳. Implied by -Wall.
  • -Wzerotrip β€” warns if a DO loop is known to execute zero times at compile time πŸ™ˆ. Implied by -Wall.
  • -Wdo-subscript β€” warns if an array subscript inside a DO loop could lead to an out-of-bounds access, even if the compiler can't prove that the statement is actually executed 😱. Here's the kind of thing it catches:
real a(3)
do i=1,4
  if (condition(i)) then
    a(i) = 1.2
  end if
end do

Implied by -Wextra.

  • -Werror β€” turns all warnings into errors πŸš¨πŸ’€.

Heads up bestie, some of these have no effect when you're compiling Fortran programs πŸ™ˆ so don't panic if nothing changes. πŸ’…


✨ Options for debugging your program ✨

GNU Fortran has a whole kit of special options for debugging your program πŸ” main character debugging energy, honestly.

  • -fdebug-aux-vars β€” renames the internal variables the gfortran front end creates and makes them visible to a debugger πŸ”Ž. Their names start with uppercase letters followed by an underscore. It's super useful for debugging the compiler's code generation alongside -fdump-tree-original, and for debugging the executable itself with -g or -ggdb3 🧚.
  • -ffpe-trap=list β€” lets you pick which floating point exception traps to turn on 🚨 Normally, if a floating point exception happens and its trap is enabled, a SIGFPE signal gets sent and the program is aborted, leaving behind a core file you can debug with πŸ’€. list is a (possibly empty) comma-separated list of either none (which clears the whole set of trapped exceptions) or any of these:
    • invalid β€” an invalid floating point operation, such as SQRT(-1.0)
    • zero β€” division by zero
    • overflow β€” overflow in a floating point operation
    • underflow β€” underflow in a floating point operation
    • inexact β€” loss of precision during an operation
    • denormal β€” an operation performed on a denormal value

The first five line up with the five IEEE 754 exceptions. denormal isn't part of IEEE 754, but it's available on some common architectures like x86 πŸ–₯️.

The first three (invalid, zero, and overflow) often mean something serious went wrong. Unless your program has a plan for dealing with them, turning on traps for those three is probably a good idea 🫢.

If you use the option more than once on the command line, the lists get joined: -ffpe-trap=list1 followed by -ffpe-trap=list2 is equivalent to -ffpe-trap=list1,list2 πŸ”—.

Once an exception is enabled, it can't be disabled with a negative form (there isn't one). The only way to clear them is to clear all traps by specifying none πŸ™…β€β™€οΈ

Most floating point operations lose some precision due to rounding, so -ffpe-trap=inexact is likely to be pretty uninteresting in practice 😴.

By default, no exception traps are enabled.

  • -ffpe-summary=list β€” picks which floating-point exceptions get their flag status printed to ERROR_UNIT whenever STOP or ERROR STOP runs πŸ“‹ list can be none, all, or a comma-separated list of invalid, zero, overflow, underflow, inexact and denormal. (Peek at -ffpe-trap for what each exception means 🧐)
    • If the option shows up more than once on the command line, only the last one is used.
    • By default, you get a summary for all exceptions except inexact.
  • -fno-backtrace β€” stops the Fortran runtime library from trying to print a backtrace when a serious runtime error or a deadly signal hits πŸ™…β€β™€οΈ That includes segmentation fault, illegal instruction, bus error, floating-point exception, and any other POSIX signals whose action is core. This option only has influence for compilation of the Fortran main program.

These options decide how GNU Fortran hunts down files pulled in by the INCLUDE directive, and where it looks for previously compiled modules πŸ•΅οΈ They also change the search paths cpp uses when it preprocesses Fortran source.

  • -Idir β€” affects how INCLUDE gets interpreted (and the #include directive from the cpp preprocessor too) πŸ—‚οΈ
    • The general behaviour of -I and INCLUDE is pretty much the same as -I with #include in cpp, when it comes to looking for header.gcc files and other stuff like that.
    • This path also gets searched for .mod files when previously compiled modules are needed by a USE statement.
  • -Jdir β€” says where to put the .mod files for compiled modules πŸ“¦ It also gets added to the list of directories a USE statement searches.
    • The default is the current directory.
  • -fintrinsic-modules-path dir β€” tells the compiler where the pre-compiled intrinsic modules live, if they're not in the default spot it expects πŸ“

πŸ”— Influencing the linking step πŸ”—

These options only come into play when the compiler links object files into an executable output file. If the compiler isn't doing a link step, they're meaningless 🫠

  • -static-libgfortran β€” on systems that provide libgfortran as both a shared and a static library, this forces the static version 🧊 If no shared version of libgfortran was built when the compiler was configured, this option has no effect.
  • -static-libquadmath β€” same vibe, but for libquadmath 🧊 On systems that provide it as both shared and static, this forces the static version. If no shared version of libquadmath was built when the compiler was configured, nothing happens.
    • Please note that the libquadmath runtime library is licensed under the GNU Lesser General Public License (LGPL), and linking it statically introduces requirements when you redistribute the resulting binaries βš–οΈ

πŸƒβ€β™€οΈ Influencing runtime behavior πŸƒβ€β™€οΈ

These options affect the runtime behaviour of programs compiled with GNU Fortran ⚑

  • -fconvert=conversion β€” sets how data is represented in unformatted files πŸ’Ύ On most systems, the valid values for conversion are:
    • native β€” the default
    • swap β€” swaps between big- and little-endian
    • big-endian β€” uses big-endian representation for unformatted files
    • little-endian β€” uses little-endian representation for unformatted files

On POWER systems that support -mabi=ieeelongdouble, there are additional options too, which can be combined with the others using commas. They are:

  • r16_ieee β€” uses IEEE 128-bit format for REAL(KIND=16)
  • r16_ibm β€” uses IBM long double format for REAL(KIND=16)

This option only has an effect when used in the main program. The CONVERT specifier and the GFORTRAN_CONVERT_UNIT environment variable override the default specified by -fconvert πŸ₯‡

  • -frecord-marker=length β€” sets the length of record markers for unformatted files πŸ“ Valid values for length are 4 and 8, and the default is 4. This is different from older gfortran versions, which used a default record marker length of 8 on most systems. If you want to read or write files compatible with earlier versions of gfortran, use -frecord-marker=8 πŸ•°οΈ
  • -fmax-subrecord-length=length β€” sets the maximum length for a subrecord πŸ“ The maximum permitted value for length is 2147483639, which is also the default. It's only really useful for the gfortran testsuite πŸ§ͺ
  • -fsign-zero β€” when enabled, floating point numbers with a value of zero but the sign bit set get written as negative numbers in formatted output, and get treated as negative by the SIGN intrinsic βž– -fno-sign-zero doesn't print the negative sign of zero values (or values rounded to zero for I/O), and treats zero as a positive number in the SIGN intrinsic, for compatibility with Fortran 77 πŸ§“ The default is -fsign-zero.

πŸ› οΈ GNU Fortran Developer Options πŸ› οΈ

GNU Fortran has various special options that are used for debugging the GNU Fortran compiler itself 🧠

  • -fdump-fortran-global β€” outputs a list of the global identifiers after translating into middle-end representation πŸ“œ It's mostly useful for debugging the GNU Fortran compiler itself.
  • -fdump-fortran-optimized β€” outputs the parse tree after front-end optimization 🌳 It's mostly useful for debugging the GNU Fortran compiler itself.
  • -fdump-fortran-original β€” outputs the internal parse tree after translating the source program into internal representation 🌲 It's mostly useful for debugging the GNU Fortran compiler itself.
For -fdump-fortran-global, -fdump-fortran-optimized and -fdump-fortran-original, the output might change between releases, and the option may also generate internal compiler errors for features that have only recently been added. 😬
  • -fdump-parse-tree β€” outputs the internal parse tree after translating the source program into internal representation 🌳 It's mostly useful for debugging the GNU Fortran compiler itself. The output might change between releases, and this option may also generate internal compiler errors for features that have only recently been added.
    • This option is deprecated; use -fdump-fortran-original instead ⚠️
  • -save-temps β€” stores the usual "temporary" intermediate files permanently, naming them as auxiliary output files, as described under GCC -dumpbase and -dumpdir πŸ’Ύ
gfortran -save-temps -c foo.F90

This preprocesses the input file foo.F90 to foo.fii, compiles to an intermediate foo.s, and then assembles to the (implied) output file foo.o, whereas:

gfortran -save-temps -S foo.F

saves the preprocessor output in foo.fi, and then compiles to the (implied) output file foo.s.


🧢 Options for code generation conventions 🧢

These machine-independent options control the interface conventions used in code generation πŸŽ€

Most of them have both positive and negative forms. The negative form of -ffoo would be -fno-foo. The list below only shows one of the forms, the one that is not the default. You can figure out the other form by either removing no- or adding it 🧩

  • -fno-automatic β€” treats each program unit (except those marked as RECURSIVE) as if the SAVE statement were specified for every local variable and array referenced in it 🧷 It does not affect common blocks. (Some Fortran compilers provide this option under the name -static or -save.) The default, which is -fautomatic, uses the stack for local variables smaller than the value given by -fmax-stack-var-size. Use the option -frecursive to use no static memory 🧠
    • Local variables or arrays having an explicit SAVE attribute are silently ignored unless the -pedantic option is added 🀫
  • -ff2c β€” okay bestie, this one is for the vintage crowd πŸ§“ It makes your code vibe with the stuff compiled by g77 and f2c ✨ It generates code designed to be compatible with code generated by g77 and f2c.

The g77 calling conventions (originally from f2c) are a little extra. Functions that return default REAL have to actually return the C type double, and functions that return COMPLEX send their value back through an extra argument in the calling sequence, which points to where the result gets stored πŸ’… Under the default GNU calling conventions, it's a different energy. Default REAL functions just return the C type float, and COMPLEX functions return the GNU C type complex, same as they would in GNU C πŸ’– Also, -ff2c implies -fsecond-underscore, unless you explicitly ask for -fno-second-underscore 🫢

This doesn't change the code that interfaces with the libgfortran library 🌸

⚠️ Caution, bestie: it's not a good idea to mix Fortran code compiled with -ff2c with code compiled with the default -fno-f2c calling conventions! Calling COMPLEX or default REAL functions between program parts compiled with different calling conventions will break at execution time πŸ’€
⚠️ Caution: this breaks code that passes intrinsic functions of type default REAL or COMPLEX as actual arguments, because the library implementations use the -fno-f2c calling conventions 😭
  • -fno-underscoring β€” no appended underscores for you! πŸ™…β€β™€οΈ It tells GNU Fortran not to transform names of entities from your Fortran source by adding underscores to them.

Normally, with -funderscoring in effect, GNU Fortran tacks one underscore onto external names. That's so the code plays nice with lots of UNIX Fortran compilers πŸ¦‹ This doesn't apply to names declared with C binding, or to names within a module.

⚠️ Caution: the default behavior of GNU Fortran is incompatible with f2c and g77. If you want your object files to be compatible with object code made by these tools, use the -ff2c option πŸŽ€

Honestly, using -fno-underscoring isn't recommended unless you're experimenting with stuff like fitting GNU Fortran into existing system environments (think existing libraries, tools, and so on) πŸ§ͺ

Here's the tea. Say j() and max_count() are external functions, while my_var and lvar are local variables. A Fortran statement like this:

I = J() + MAX_COUNT (MY_VAR, LVAR)

gets implemented as something akin to this C code:

i = j_() + max_count_(&my_var, &lvar);

But with -fno-underscoring, the same statement is implemented as:

i = j() + max_count(&my_var, &lvar);

So -fno-underscoring lets you use your own names directly while debugging, and when you're interfacing GNU Fortran code with other languages 🌈

Quick reality check though: just because the names match doesn't mean the interface GNU Fortran uses for an external name matches the interface some other language uses for that same name. Getting GNU Fortran code to link to code from another compiler, by this or any other method, can be just a small part of the whole deal. Getting both compilers to agree on stuff besides naming can take serious effort, and unlike naming disagreements, linkers normally can't detect disagreements in those other areas πŸ₯²

Also, with -fno-underscoring, the lack of appended underscores creates a very real possibility that a user-defined external name conflicts with a name in a system library 😰 That could make finding unresolved-reference bugs super hard in some cases. They might only happen at program run time and show up as buggy behavior at run time.

Last thing: declaring symbols as bind(C) is a more robust way to interface with code written in other languages, or compiled with different Fortran compilers, than the command-line options in this section πŸ‘‘

  • -fsecond-underscore β€” the double-underscore glow-up πŸ’œ By default, GNU Fortran appends an underscore to external names. If you use this option, GNU Fortran appends two underscores to names that already have underscores, and one underscore to names with no underscores.

For example, an external name such as MAX_COUNT is implemented as a reference to the link-time external symbol max_count__, instead of max_count_. This is required for compatibility with g77 and f2c, and it's implied by use of the -ff2c option 🧚

This option has no effect if -fno-underscoring is in effect. It's implied by the -ff2c option too 🌸

  • -fcoarray=<keyword> β€” coarray support, but make it a choice πŸ“ Here are the keywords:
    • none β€” disables coarray support! Using coarray declarations and image-control statements produces a compile-time error. (Default)
    • single β€” single-image mode, so num_images() is always one 1️⃣
    • lib β€” library-based coarray parallelization πŸš€ A suitable GNU Fortran coarray library, such as <http://opencoarrays.org>, needs to be linked. Alternatively, GCC's libcaf_single library can be linked, albeit it only supports a single image.
  • -fcheck=<keyword> β€” turns on run-time checks, the ultimate safety net πŸ•ΈοΈ The argument has to be a comma-delimited list of the keywords below. Prefixing a check with no- disables it if it was activated by a previous specification πŸ™ˆ
    • all β€” enables all run-time tests of -fcheck.
    • array-temps β€” warns at run time when, for passing an actual argument, a temporary array had to be generated. The info from this warning is sometimes useful for optimization, so you can avoid such temporaries 🧹
      • Note: the warning is only printed once per location.
    • bits β€” enables generation of run-time checks for invalid arguments to the bit manipulation intrinsics πŸ”’
    • bounds β€” enables generation of run-time checks for array subscripts and against the declared minimum and maximum values πŸ“ It also checks array indices for assumed and deferred shape arrays against the actual allocated bounds, and makes sure all string lengths are equal for character array constructors without an explicit typespec.
      • Some checks require that -fcheck=bounds is set for the compilation of the main program.
      • Note: in the future this may also include other forms of checking, e.g., checking substring references.
    • do β€” enables generation of run-time checks for invalid modification of loop iteration variables πŸ”
    • mem β€” enables generation of run-time checks for memory allocation 🧠
      • Note: this option does not affect explicit allocations using the ALLOCATE statement, which are always checked.
    • pointer β€” enables generation of run-time checks for pointers and allocatables πŸ‘‰
    • recursion β€” enables generation of run-time checks for recursively called subroutines and functions that aren't marked as recursive. See also -frecursive.
      • Note: this check does not work for OpenMP programs, and it's disabled if used together with -frecursive and -fopenmp.

Example time! Assuming you have a file foo.f90, the command:

gfortran -fcheck=all,no-array-temps foo.f90

compiles the file with all checks enabled as specified above, except for the warnings about generated array temporaries ✨

  • -fbounds-check β€” a deprecated alias for -fcheck=bounds. Retired, but still in the group chat πŸ‘»
  • -ftail-call-workaround, -ftail-call-workaround=n β€” okay, this one is a whole mood 😀 Some C interfaces to Fortran code violate the gfortran ABI by omitting the hidden character length arguments as described in (the page cuts off right there, bestie πŸ’€). This can lead to crashes, because pushing arguments for tail calls can overflow the stack.

To provide a workaround for existing binary packages, this option disables tail call optimization for gfortran procedures with character arguments. With -ftail-call-workaround=2, tail call optimization is disabled in all gfortran procedures with character arguments. With -ftail-call-workaround=1 or the equivalent -ftail-call-workaround, it's only disabled in gfortran procedures with character arguments that call implicitly prototyped procedures 🧩

⚠️ Warning: using this option can lead to problems, including crashes due to insufficient stack space.

It is very strongly recommended to fix the code in question 🫠 The -fc-prototypes-external option can be used to generate prototypes that conform to gfortran's ABI, for inclusion in the source code.

Support for this option will likely be withdrawn in a future release of gfortran πŸ‘‹

The negative form, -fno-tail-call-workaround or the equivalent -ftail-call-workaround=0, can be used to disable this option.

Default is currently -ftail-call-workaround, but this will change in future releases.


  • -fcheck-array-temporaries β€” a deprecated alias for -fcheck=array-temps. Same vibes, new name πŸ¦‹
  • -fmax-array-constructor=n β€” need a bigger array constructor? This option raises the upper limit permitted in array constructors πŸ“ˆ The code below requires this option to expand the array at compile time:

program test implicit none integer j integer, parameter :: n = 100000 integer, parameter :: i(n) = (/ (2*j, j = 1, n) /) print '(10(I0,1X))', i end program test

⚠️ Caution: this option can lead to long compile times and excessively large object files 🐒

The default value for n is 65535.

  • -fmax-stack-var-size=n β€” the stack size limit for arrays πŸ₯ž This option specifies the size in bytes of the largest array that gets put on the stack. If the size is exceeded, static memory is used instead (except in procedures marked as RECURSIVE). Use the option -frecursive to allow for recursive procedures that don't have a RECURSIVE attribute, or for parallel programs. Use -fno-automatic to never use the stack πŸ™…

This option currently only affects local arrays declared with constant bounds, and it may not apply to all character variables. Future versions of GNU Fortran may improve this behavior 🌱

The default value for n is 65536.

  • -fstack-arrays β€” puts all arrays of unknown size, plus array temporaries, onto stack memory πŸ₯³ If your program uses very large local arrays, you might have to extend your runtime limits for stack memory on some operating systems. This flag is enabled by default at optimization level -Ofast, unless -fmax-stack-var-size is specified 🏎️
  • -fpack-derived β€” okay bestie, this one tells GNU Fortran to pack derived type members as closely as possible πŸ“¦βœ¨. Heads up though: code compiled with it is likely to be incompatible with code compiled without it, and it may execute slower πŸ’€.
  • -frepack-arrays β€” ngl this one is a whole mood 🌸. Sometimes GNU Fortran passes assumed shape array sections using a descriptor that describes a noncontiguous area of memory. With this flag, it adds code to the function prologue that repacks the data into a contiguous block at runtime 🧚. That should make accesses to the array faster, BUT it can add significant overhead to the function call, especially when the passed data is noncontiguous 😭.
  • -fshort-enums β€” this one's all about interop 🀝. It exists so you can play nice with C code that was compiled with -fshort-enums. GNU Fortran picks the smallest INTEGER kind that a given enumerator set fits in, then gives all of its enumerators that kind πŸ’œ.
  • -finline-arg-packing β€” okay, this one is a little spicy 🌢️. When you pass an assumed-shape argument of a procedure as an actual argument to an assumed-size or explicit size argument, or as an argument to a procedure that doesn't have an explicit interface, that argument may have to be packed, which means shoved into contiguous memory πŸ“¦. The classic example is the call to foo in this little snippet:
subroutine foo(a)
   real, dimension(*) :: a
end subroutine foo
subroutine bar(b)
   real, dimension(:) :: b
   call foo(b)
end subroutine bar

With -finline-arg-packing in effect, that packing is done by inline code πŸ”₯. That allows for more optimization, but the code size goes up πŸ“ˆ.

-finline-arg-packing is implied by any of the -O options, except when you're optimizing for size with -Os. If your code has a very large number of arguments that have to be packed, the code size and compilation time can get excessive πŸ™ˆ. If that's the case, it may be better to disable this option. You can find where packing happens by using -Warray-temporaries.

  • -fexternal-blas β€” this one hands the heavy lifting to someone else πŸ‘‘. It makes gfortran generate calls to BLAS functions for some matrix operations like MATMUL, instead of using its own algorithms, as long as the matrices involved are larger than a given limit (see -fblas-matmul-limit). This can be a win if an optimized vendor BLAS library is available. The BLAS library has to be specified at link time. This option specifies a BLAS library with integer arguments of default kind (32 bits). It cannot be used together with -fexternal-blas64.
  • -fexternal-blas64 β€” same energy as the one above, just bigger πŸ¦‹. gfortran generates calls to BLAS functions for some matrix operations like MATMUL, instead of its own algorithms, if the matrices are larger than a given limit (see -fblas-matmul-limit). This may be profitable if an optimized vendor BLAS library is available, and the BLAS library has to be specified at link time. This one specifies a BLAS library with integer arguments of KIND=8 (64 bits). It cannot be used together with -fexternal-blas, and it requires a 64-bit system. It also requires -ffrontend-optimize.
  • -fblas-matmul-limit=n β€” only matters when -fexternal-blas or -fexternal-blas64 is in effect πŸŽ€. Matrix multiplication of matrices with a size larger than or equal to n gets handed off to BLAS functions, while smaller ones are handled by gfortran's internal algorithms. If the matrices involved aren't square, the size comparison uses the geometric mean of the dimensions of the argument and result matrices.

The default value for n is 30.

  • -finline-intrinsics, -finline-intrinsics=intr1,intr2,... β€” okay this one is giving "you pick the vibe" 🧚. It tells the compiler to prefer generating inline code over calls to libgfortran functions when implementing intrinsics.

Intrinsics can be implemented either by calling a libgfortran library function or by generating inline code directly. For most intrinsics there's only one variant, so there's no choice to make. Some intrinsics can use either a library function or inline code, and inline code usually leaves room for extra optimization over a library function. With -finline-intrinsics=... or -fno-inline-intrinsics=..., the choice only applies to the intrinsics in the comma-separated list you give as the argument.

For each intrinsic, if neither flag variant made a choice, the default depends on optimization: library calls get generated when you're not optimizing or when you're optimizing for size, and otherwise inline code is preferred ✨.

The intrinsics you can pass to -finline-intrinsics= are currently limited to MAXLOC and MINLOC. The effect is also limited to calls of those intrinsics without a DIM argument and with an ARRAY of a non-CHARACTER type. The rank-1 case with a DIM argument present, i.e. MAXLOC(A(:),DIM=1) or MINLOC(A(:),DIM=1), is inlined unconditionally for a numeric rank-1 array argument A πŸ’….

  • -finline-matmul-limit=n β€” when front-end optimization is active, some calls to the MATMUL intrinsic function get inlined πŸ¦‹. This can increase code size if the size of the matrix can't be determined at compile time, since code for both cases gets generated. Setting -finline-matmul-limit=0 disables inlining in all cases. Setting it to a value of n produces inline code for matrices with a size up to n. If the matrices involved aren't square, the size comparison uses the geometric mean of the dimensions of the argument and result matrices.

The default value for n is 30. The -fblas-matmul-limit can be used to change this value.

  • -frecursive β€” allows indirect recursion by forcing all local arrays to be allocated on the stack 🌈. This flag can't be used together with -fmax-stack-var-size= or -fno-automatic.
  • -finit-local-zero β€” the initialization main character πŸ“. It tells the compiler to initialize local INTEGER, REAL, and COMPLEX variables to zero, LOGICAL variables to false, and CHARACTER variables to a string of null bytes. If you want finer control, there are more options: -finit-integer=n, -finit-real=<zero|inf|-inf|nan|snan> (which also initializes the real and imaginary parts of local COMPLEX variables), -finit-logical=<true|false>, and -finit-character=n (where n is an ASCII character value).
  • -finit-derived β€” components of derived type variables get initialized according to these flags 🧸. Components whose type isn't covered by an explicit -finit-* flag are treated as described above with -finit-local-zero.
  • -finit-integer=n β€” this one parses the value into an integer of type INTEGER(kind=C_LONG) on the host πŸ”’. That value then gets assigned to the integer variables in your Fortran code. If the value is too large for the kind, it might wrap around 😬.
  • -finit-real=<zero|inf|-inf|nan|snan> β€” initializes REAL and COMPLEX variables with a quiet NaN 🫢. For a signalling NaN, use -finit-real=snan.
Be careful with snan! Compile-time optimizations may convert signalling NaNs into quiet NaNs, and trapping needs to be enabled (e.g. via -ffpe-trap).
  • -finit-logical=<true|false> β€” sets LOGICAL variables to the value you pick βœ….
  • -finit-character=n β€” sets CHARACTER variables to the ASCII character value n πŸ”€.

Okay, but these options do NOT initialize:

  • objects with the POINTER attribute
  • allocatable arrays
  • variables that appear in an EQUIVALENCE statement

(These limitations may be removed in future releases.)

Heads up: enabling any of the -finit-* options silences warnings that would have been emitted by -Wuninitialized for the affected local variables πŸ™ˆ.
  • -falign-commons β€” by default, gfortran enforces proper alignment of all variables in a COMMON block by padding them as needed πŸ“. On some platforms this is mandatory, and on others it increases performance. If a COMMON block isn't declared with consistent data types everywhere, this padding can cause trouble, and -fno-align-commons can be used to turn off the automatic alignment. Use the same form of this option for all files that share a COMMON block. To avoid potential alignment issues in COMMON blocks, it's recommended to order objects from largest to smallest πŸ’–.
  • -fno-protect-parens β€” by default, parentheses in expressions are honored at all optimization levels, so the compiler doesn't do any reassociation πŸ”’. Using -fno-protect-parens lets the compiler reorder REAL and COMPLEX expressions to produce faster code.
For the reassociation optimization, -fno-signed-zeros and -fno-trapping-math need to be in effect too. The parentheses protection is enabled by default, unless -Ofast is given.
  • -frealloc-lhs β€” an allocatable left-hand side of an intrinsic assignment is automatically (re)allocated if it's either unallocated or has a different shape 🧁. This option is enabled by default except when -std=f95 is given. See also -Wrealloc-lhs.
  • -faggressive-function-elimination β€” functions with identical argument lists get eliminated within statements, whether or not they're marked PURE πŸ—‘οΈ. For example, in this line:
a = f(b,c) + f(b,c)

there is only a single call to f. This option only works if -ffrontend-optimize is in effect.

  • -ffrontend-optimize β€” this one performs front-end optimization by manipulating parts of the Fortran parse tree 🌟. It's enabled by default by any -O option except -O0 and -Og. The optimizations enabled by this option include:
    • inlining calls to MATMUL
    • elimination of identical function calls within expressions
    • removing unnecessary calls to TRIM in comparisons and assignments
    • replacing TRIM(a) with a(1:LEN_TRIM(a))
    • short-circuiting of logical operators (.AND. and .OR.)

It can be deselected by specifying -fno-frontend-optimize πŸ™…β€β™€οΈ.

  • -ffrontend-loop-interchange β€” attempts to interchange loops in the Fortran front end wherever it's profitable πŸ”„. It's enabled by default by any -O option. Right now, this option only affects FORALL and DO CONCURRENT statements with several forall triplets.

🌸 ENVIRONMENT 🌸

okay so gfortran is lowkey chill about env vars πŸ’… It doesn't use any environment variables to control its operation beyond the ones that already affect gcc. So if you're already tweaking gcc's env vars, gfortran is gonna listen to those too ✨

πŸ¦‹ BUGS πŸ¦‹

found a bug?! πŸ™ˆ bestie, the instructions for reporting it live in <file:///usr/share/doc/gcc-16/README.Bugs> πŸ› go read that before you file anything πŸ’–

πŸ”₯ SEE ALSO πŸ”₯

if you want more, these are absolutely worth your time:

πŸ‘‘ AUTHOR πŸ‘‘

the people who built GCC and GNU Fortran are all listed in the Info entry for gfortran 🫢 that's where the whole crew gets their credit.

Copyright (c) 2004-2026 Free Software Foundation, Inc. 🌸

so you're allowed to copy, distribute and/or modify this doc under the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation πŸ“œ The Invariant Sections are "Funding Free Software", the Front-Cover Texts are (a) (see below), and the Back-Cover Texts are (b) (see below). A copy of the license is included in the gfdl(7) man page πŸ¦‹

(a) The FSF's Front-Cover Text is:

A GNU Manual

(b) The FSF's Back-Cover Text is:

You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.

And that's the whole page, bestie! 🧚 This one comes from the gcc-16 docs and was last dated 2026-03-22 πŸ’– Stay curious, stay slay πŸ’…βœ¨

πŸ“¦ where this page comes from