aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Builtin-options.md1
-rw-r--r--docs/markdown/Configuring-a-build-directory.md1
-rw-r--r--docs/markdown/snippets/fortran_std.md14
-rw-r--r--mesonbuild/compilers/fortran.py54
-rw-r--r--test cases/fortran/19 fortran_std/legacy.f7
-rw-r--r--test cases/fortran/19 fortran_std/meson.build27
-rw-r--r--test cases/fortran/19 fortran_std/std2003.f9036
-rw-r--r--test cases/fortran/19 fortran_std/std2008.f9032
-rw-r--r--test cases/fortran/19 fortran_std/std2018.f9034
-rw-r--r--test cases/fortran/19 fortran_std/std95.f9013
10 files changed, 218 insertions, 1 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index f406067..9eac371 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -146,6 +146,7 @@ compiler being used:
| cpp_eh | default | none, default, a, s, sc | C++ exception handling type |
| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) |
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
+| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use |
The default values of `c_winlibs` and `cpp_winlibs` are in compiler-specific
argument forms, but the libraries are: kernel32, user32, gdi32, winspool,
diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md
index b0fb574..1387a46 100644
--- a/docs/markdown/Configuring-a-build-directory.md
+++ b/docs/markdown/Configuring-a-build-directory.md
@@ -65,6 +65,7 @@ sample output for a simple project.
cpp_debugstl false [true, false] STL debug mode
cpp_link_args [] Extra arguments passed to the C++ linker
cpp_std c++11 [none, c++98, c++03, c++11, c++14, c++17, c++1z, c++2a, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, gnu++2a] C++ language standard to use
+ fortran_std [] [none, legacy, f95, f2003, f2008, f2018] language standard to use
Directories:
Option Current Value Description
diff --git a/docs/markdown/snippets/fortran_std.md b/docs/markdown/snippets/fortran_std.md
new file mode 100644
index 0000000..2170a5e
--- /dev/null
+++ b/docs/markdown/snippets/fortran_std.md
@@ -0,0 +1,14 @@
+## `fortran_std` option
+
+**new in 0.53.0**
+Akin to the `c_std` and `cpp_std` options, the `fortran_std` option sets Fortran compilers to warn or error on non-Fortran standard code.
+Only the Gfortran and Intel Fortran compilers have support for this option.
+Other Fortran compilers ignore the `fortran_std` option.
+
+Supported values for `fortran_std` include:
+
+* `legacy` for non-conforming code--this is especially important for Gfortran, which by default errors on old non-compliant Fortran code
+* `f95` for Fortran 95 compliant code.
+* `f2003` for Fortran 2003 compliant code.
+* `f2008` for Fortran 2008 compliant code.
+* `f2018` for Fortran 2018 compliant code. \ No newline at end of file
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 5a2766e..3003fcd 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -17,6 +17,7 @@ from typing import List
import subprocess, os
import typing
+from .. import coredata
from .compilers import (
clike_debug_args,
Compiler,
@@ -32,7 +33,7 @@ from .mixins.pgi import PGICompiler
from .. import mlog
from mesonbuild.mesonlib import (
- EnvironmentException, MesonException, MachineChoice, LibType
+ version_compare, EnvironmentException, MesonException, MachineChoice, LibType
)
if typing.TYPE_CHECKING:
@@ -179,6 +180,25 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic', '-fimplicit-none']}
+ def get_options(self):
+ opts = FortranCompiler.get_options(self)
+ fortran_stds = ['legacy', 'f95', 'f2003']
+ if version_compare(self.version, '>=4.4.0'):
+ fortran_stds += ['f2008']
+ if version_compare(self.version, '>=8.0.0'):
+ fortran_stds += ['f2018']
+ opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none')})
+ return opts
+
+ def get_option_compile_args(self, options) -> typing.List[str]:
+ args = []
+ std = options['fortran_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
def get_dependency_gen_args(self, outtarget, outfile):
# Disabled until this is fixed:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
@@ -269,6 +289,22 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
'2': default_warn_args + ['-warn', 'unused'],
'3': ['-warn', 'all']}
+ def get_options(self):
+ opts = FortranCompiler.get_options(self)
+ fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
+ opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none')})
+ return opts
+
+ def get_option_compile_args(self, options) -> typing.List[str]:
+ args = []
+ std = options['fortran_std']
+ stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
+ if std.value != 'none':
+ args.append('-stand=' + stds[std.value])
+ return args
+
def get_preprocess_only_args(self):
return ['-cpp', '-EP']
@@ -312,6 +348,22 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
'2': default_warn_args + ['/warn:unused'],
'3': ['/warn:all']}
+ def get_options(self):
+ opts = FortranCompiler.get_options(self)
+ fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
+ opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none')})
+ return opts
+
+ def get_option_compile_args(self, options) -> typing.List[str]:
+ args = []
+ std = options['fortran_std']
+ stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
+ if std.value != 'none':
+ args.append('/stand:' + stds[std.value])
+ return args
+
def get_module_outdir_args(self, path) -> List[str]:
return ['/module:' + path]
diff --git a/test cases/fortran/19 fortran_std/legacy.f b/test cases/fortran/19 fortran_std/legacy.f
new file mode 100644
index 0000000..339064d
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/legacy.f
@@ -0,0 +1,7 @@
+ ! non-integer loop indices are deleted in Fortran 95 standard
+ real a
+
+ do 10 a=0,0.5,0.1
+10 continue
+
+ end program \ No newline at end of file
diff --git a/test cases/fortran/19 fortran_std/meson.build b/test cases/fortran/19 fortran_std/meson.build
new file mode 100644
index 0000000..f46f8ff
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/meson.build
@@ -0,0 +1,27 @@
+project('FortranStd', 'fortran',
+ default_options: ['warning_level=0'])
+# As with C and C++, each Fortran compiler + version has a subset of supported Fortran standards
+# Additionally, a necessary option for non-standard Fortran projects is the "legacy"
+# option, which allows non-standard syntax and behavior quirks.
+# Thus "legacy" is a necessity for some old but important Fortran projects.
+# By default, popular Fortran compilers disallow these quirks without "legacy" option.
+
+fc = meson.get_compiler('fortran')
+
+executable('stdnone', 'std95.f90')
+
+executable('std_legacy', 'legacy.f', override_options : ['fortran_std=legacy'])
+
+executable('std_95', 'std95.f90', override_options : ['fortran_std=f95'])
+
+executable('std_f2003', 'std2003.f90', override_options : ['fortran_std=f2003'])
+
+executable('std_f2008', 'std2008.f90', override_options : ['fortran_std=f2008'])
+
+if fc.get_id() == 'gcc'
+ if fc.version().version_compare('>=8.0')
+ executable('std_f2018', 'std2018.f90', override_options : ['fortran_std=f2018'])
+ endif
+else
+ executable('std_f2018', 'std2018.f90', override_options : ['fortran_std=f2018'])
+endif \ No newline at end of file
diff --git a/test cases/fortran/19 fortran_std/std2003.f90 b/test cases/fortran/19 fortran_std/std2003.f90
new file mode 100644
index 0000000..08d2f50
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/std2003.f90
@@ -0,0 +1,36 @@
+use, intrinsic :: iso_fortran_env, only : error_unit
+implicit none
+
+! http://fortranwiki.org/fortran/show/Real+precision
+integer, parameter :: sp = selected_real_kind(6, 37)
+integer, parameter :: dp = selected_real_kind(15, 307)
+
+real(sp) :: a32
+real(dp) :: a64
+
+real(sp), parameter :: pi32 = 4*atan(1._sp)
+real(dp), parameter :: pi64 = 4*atan(1._dp)
+
+if (pi32 == pi64) stop 1
+
+call timestwo(a32)
+call timestwo(a64)
+
+contains
+
+elemental subroutine timestwo(a)
+
+class(*), intent(inout) :: a
+
+select type (a)
+ type is (real(sp))
+ a = 2*a
+ type is (real(dp))
+ a = 2*a
+ type is (integer)
+ a = 2*a
+end select
+
+end subroutine timestwo
+
+end program \ No newline at end of file
diff --git a/test cases/fortran/19 fortran_std/std2008.f90 b/test cases/fortran/19 fortran_std/std2008.f90
new file mode 100644
index 0000000..e7887ae
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/std2008.f90
@@ -0,0 +1,32 @@
+use, intrinsic :: iso_fortran_env, only : error_unit, sp=>real32, dp=>real64
+implicit none
+
+real(sp) :: a32
+real(dp) :: a64
+
+real(sp), parameter :: pi32 = 4*atan(1._sp)
+real(dp), parameter :: pi64 = 4*atan(1._dp)
+
+if (pi32 == pi64) error stop 'real32 values generally do not exactly equal real64 values'
+
+call timestwo(a32)
+call timestwo(a64)
+
+contains
+
+elemental subroutine timestwo(a)
+
+class(*), intent(inout) :: a
+
+select type (a)
+ type is (real(sp))
+ a = 2*a
+ type is (real(dp))
+ a = 2*a
+ type is (integer)
+ a = 2*a
+end select
+
+end subroutine timestwo
+
+end program \ No newline at end of file
diff --git a/test cases/fortran/19 fortran_std/std2018.f90 b/test cases/fortran/19 fortran_std/std2018.f90
new file mode 100644
index 0000000..9a326b1
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/std2018.f90
@@ -0,0 +1,34 @@
+use, intrinsic :: iso_fortran_env, only : error_unit, sp=>real32, dp=>real64
+implicit none
+
+real(sp) :: a32
+real(dp) :: a64
+
+real(sp), parameter :: pi32 = 4*atan(1._sp)
+real(dp), parameter :: pi64 = 4*atan(1._dp)
+
+if (pi32 == pi64) error stop 'real32 values generally do not exactly equal real64 values'
+
+call timestwo(a32)
+call timestwo(a64)
+
+contains
+
+elemental subroutine timestwo(a)
+
+class(*), intent(inout) :: a
+
+select type (a)
+ type is (real(sp))
+ a = 2*a
+ type is (real(dp))
+ a = 2*a
+ type is (integer)
+ a = 2*a
+ class default
+ error stop 'requires real32, real64 or integer'
+end select
+
+end subroutine timestwo
+
+end program \ No newline at end of file
diff --git a/test cases/fortran/19 fortran_std/std95.f90 b/test cases/fortran/19 fortran_std/std95.f90
new file mode 100644
index 0000000..8518df1
--- /dev/null
+++ b/test cases/fortran/19 fortran_std/std95.f90
@@ -0,0 +1,13 @@
+implicit none
+
+integer :: i, j
+integer, parameter :: N=3
+real :: A(N,N)
+
+A = 0
+
+forall (i=1:N, j=1:N)
+ A(i,j) = 1
+end forall
+
+end program \ No newline at end of file