diff --git a/Checks/PWR064/README.md b/Checks/PWR064/README.md new file mode 100644 index 0000000..2f52a38 --- /dev/null +++ b/Checks/PWR064/README.md @@ -0,0 +1,71 @@ +# PWR064: Precision loss in floating-point constant + +### Issue + +An unsuffixed real literal has default precision, which may cause precision loss +if the value is actually destined for a wider variable. + +### Actions + +Suffix the floating-point literal with an appropriately precise `kind` derived +from either `selected_real_kind()` or the `iso_fortran_env` module. + +### Relevance + +Floating-point literals without a `kind` suffix have default precision, which +may offer inconsistent behavior across compilers or compilation flags. The +default `kind` behavior is the same as for variables, see [PWR071: Prefer +real(kind=kind_value) for declaring consistent floating +types](../PWR071/README.md) for more details. + +> [!WARNING] +> Avoid the use of compilation flags such as GNU's `-fdefault-real-8` to +> increase the precision of unsuffixed literals. While many compilers interpret +> these correctly, they are ultimately not part of the Fortran standard, and +> thus code relying on them may silently break on other compilers. + +> [!NOTE] +> Unlike their C analogue, the default `kind` of unsuffixed literals is *not* +> that of `double precision`. + +### Code example + +In the following example, an unsuffixed literal is used to initialize a +`parameter` with an explicitly specified `kind`: + +```fortran +! example.f90 +program test_literal_without_suffix + implicit none + integer, parameter :: dp = selected_real_kind(15, 307) + real(kind=dp), parameter :: e = 2.718281828459045 + print *, e +end program test_literal_without_suffix +``` + +In many implementations the default real `kind` is not precise enough, so +rounding errors will be introduced to the literal before it is assigned. To +prevent this, suffix the literal with the same `kind` as the variable: + +```fortran +! solution.f90 +program test_literal_with_suffix + implicit none + integer, parameter :: dp = selected_real_kind(15, 307) + real(kind=dp), parameter :: e = 2.718281828459045_dp + print *, e +end program test_literal_with_suffix +``` + +### Related resources + +- [PWR064 examples](https://github.com/codee-com/open-catalog/tree/test_literal_suffix/Checks/PWR064/) + +- [PWR071: Prefer real(kind=kind_value) for declaring consistent floating +types](../PWR071/README.md) + +### References + +- ["It Takes All KINDs - Doctor +Fortran"](https://stevelionel.com/drfortran/2017/03/27/doctor-fortran-in-it-takes-all-kinds/), +Steve Lionel. [last checked Apr 2026] diff --git a/Checks/PWR064/example.f90 b/Checks/PWR064/example.f90 new file mode 100644 index 0000000..992e21d --- /dev/null +++ b/Checks/PWR064/example.f90 @@ -0,0 +1,8 @@ +! PWR064: Precision loss in floating-point constant + +program test_literal_without_suffix + implicit none + integer, parameter :: dp = selected_real_kind(15, 307) + real(kind=dp), parameter :: e = 2.718281828459045 + print *, e +end program test_literal_without_suffix diff --git a/Checks/PWR064/solution.f90 b/Checks/PWR064/solution.f90 new file mode 100644 index 0000000..11c985f --- /dev/null +++ b/Checks/PWR064/solution.f90 @@ -0,0 +1,8 @@ +! PWR064: Precision loss in floating-point constant + +program test_literal_with_suffix + implicit none + integer, parameter :: dp = selected_real_kind(15, 307) + real(kind=dp), parameter :: e = 2.718281828459045_dp + print *, e +end program test_literal_with_suffix diff --git a/README.md b/README.md index 690d9d4..99a59d4 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ designed to demonstrate: | [PWR060](Checks/PWR060/) | Consider loop fission to separate gather memory access pattern | optimization | | | | | ✓ | ✓ | ✓ | | | [PWR062](Checks/PWR062/) | Consider loop interchange by removing accumulation on array value | optimization | | | | | ✓ | ✓ | ✓ | | | [PWR063](Checks/PWR063/) | Avoid using legacy Fortran constructs | correctness, modernization, security | [CWE-477](https://cwe.mitre.org/data/definitions/477.html), [CWE-1075](https://cwe.mitre.org/data/definitions/1075.html), [CWE-1119](https://cwe.mitre.org/data/definitions/1119.html) | [6.27](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.28](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.31](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.54](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.58](https://j3-fortran.org/doc/year/23/23-241.pdf) | | | | ✓ | | | +| [PWR064](Checks/PWR064/) | PWR064: Precision loss in floating-point constant | correctness, security | [CWE-197](https://cwe.mitre.org/data/definitions/197.html) | [6.2](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.6](https://j3-fortran.org/doc/year/23/23-241.pdf) | [FLP34-C](https://wiki.sei.cmu.edu/confluence/display/c/FLP34-C.+Ensure+that+floating-point+conversions+are+within+range+of+the+new+type) | | | ✓ | | | | [PWR068](Checks/PWR068/) | Call procedures through explicit interfaces, preferably as module procedures | correctness, modernization, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html) | [6.8](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.9](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.10](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.11](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.34](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.53](https://j3-fortran.org/doc/year/23/23-241.pdf) | [DCL07-C](https://wiki.sei.cmu.edu/confluence/display/c/DCL07-C.+Include+the+appropriate+type+information+in+function+declarators), [DCL31-C](https://wiki.sei.cmu.edu/confluence/display/c/DCL31-C.+Declare+identifiers+before+using+them), [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments) | | | ✓ | | | | [PWR069](Checks/PWR069/) | Use the keyword only to explicitly state what to import from a module | correctness, modernization, security | | [6.21](https://j3-fortran.org/doc/year/23/23-241.pdf) | [DCL23-C](https://wiki.sei.cmu.edu/confluence/display/c/DCL23-C.+Guarantee+that+mutually+visible+identifiers+are+unique) | | | ✓ | | ✓[^1] | | [PWR070](Checks/PWR070/) | Declare array dummy arguments as assumed-shape arrays | correctness, modernization, security | [CWE-130](https://cwe.mitre.org/data/definitions/130.html) | [6.8](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.9](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.10](https://j3-fortran.org/doc/year/23/23-241.pdf) | [API02-C](https://wiki.sei.cmu.edu/confluence/display/c/API02-C.+Functions+that+read+or+write+to+or+from+an+array+should+take+an+argument+to+specify+the+source+or+target+size) | | | ✓ | | |