~~NOTOC~~ ====== Coding Convention Messages ====== ===== c001 ===== ⚠️ ''Found ${statement} with unchecked STAT in "${proc}"'' ✅ Please always check the content of the variable passed to ''STAT='' in the very next statement. ---- ===== c002 ===== ⚠️ ''Module "${mod}" USEd without ONLY clause or not PRIVATE'' ✅ Please start every Fortran module with ''PRIVATE'' to prevent accidental leakage of symbols. This message can also appear when a module is used without an ''ONLY'' clause. However, in that case the compiler warning ''-Wuse-without-only'' will also be triggered. ---- ===== c003 ===== ⚠️ ''Symbol "${var}" in procedure "${proc}" is IMPLICIT-SAVE'' ✅ Please either move the variable initialization to the routine body or add an explicit ''SAVE'' attribute. In Fortran, assigning a variable at declaration implicitly adds the [[https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/s-1/save.html|SAVE]] attribute. As an [[https://www.fortran90.org/src/gotchas.html#variable-initialization-using-initialization-expression|unexpected]] consequence the variable gets persevered across subroutine invocations. In the C programming language these are called static variables. ---- ===== c004 ===== ⚠️ ''Symbol "${var}" in procedure "${proc}" is IMPLICIT-TYPE'' ✅ Please start every Fortran module with ''IMPLICIT NONE'' to disable [[https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/h-to-i/implicit.html | implicit typing]]. ---- ===== c005 ===== ⚠️ ''Symbol "${var}" in procedure "${proc}" is THREADPRIVATE'' ✅ Please don't use thread-private variables because they break easily. The OpenMP standard guaranteed the persistence of thread-private variables only between consecutive parallel regions and only under very specific conditions. Since any subroutine can open a parallel regions (or might in the future) this construct is very brittle. As a workaround simply allocate an array of size ''omp_get_max_threads()''. ---- ===== c006 ===== ⚠️ ''OMP PARALLEL without DEFAULT(NONE) found in "${proc}"'' ✅ Please always include ''DEFAULT(NONE)'' when opening an OpenMP parallel region to avoid sharing a variable accidentally. ---- ===== c007 ===== ⚠️ ''Found CALL with NULL() as argument in procedure "${proc}"'' ---- ===== c008 ===== ⚠️ ''Found ASSOCIATE statement inside OMP PARALLEL region in procedure "${proc}"'' ✅ Please don't use [[https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/a-to-b/associate.html|ASSOCIATE]] inside an OpenMP parallel region because some compilers get it wrong. See [[https://github.com/cp2k/cp2k/issues/2668#issuecomment-1464056199|#2668]] for details. ---- ===== c012 ===== ⚠️ ''Found WRITE statement with hardcoded unit in "${proc}"'' ✅ Please don't writing to stdout directly, but instead use a [[dev:printkey]]. Printkeys allow the user to [[printkey|control]] the verbosity of the output. ---- ===== c013 ===== ⚠️ ''Found DEALLOCATE with STAT argument in "${proc}"'' ✅ Please don't ''STAT='' to ''DEALLOCATE'' to ensure that the program stops after a failure. A failed deallocation is always indicative of a bug (e.g. double free or segmentation fault) and the program should not continue afterwards. ---- ===== c014 ===== ⚠️ ''Found FLOAT in "${proc}"'' ---- ===== c015 ===== ⚠️ ''Found lossy conversion ${m.group(1)} without KIND argument in "${proc}"'' ---- ===== c016 ===== ⚠️ ''Found type ${derived_type} without initializer'' ✅ Please add [[https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/data-types-constants-and-variables/derived-data-types/default-initialization.html|default initialization]] to every derived type, for example like this: TYPE foo_type ! Primitive types. INTEGER :: my_int = -1 REAL(dp) :: my_real = 0.0_dp LOGICAL :: my_logical = .FALSE. CHARACTER(LEN=42) :: my_string = "" REAL(dp), DIMENSION(3) :: my_array = [1.0_dp, 2.0_dp, 3.0_dp] ! Arrays can also be initialized via broadcasting of a scalar. REAL(dp), DIMENSION(3) :: my_array2 = 0.0_dp ! Pointers should be nullified. REAL(dp), DIMENSION(:), POINTER :: my_pointer1 => NULL() TYPE(bar_type), POINTER :: my_pointer2 => NULL() ! Derived types can be initialized through their constructor. TYPE(bar_type) :: my_derived = bar_type() ! Allocatables get automatically nullified. REAL(dp), DIMENSION(:), ALLOCATABLE :: my_alloc ! Allocatables of derived types get auto initialized upon allocation. TYPE(bar_type), ALLOCATABLE :: my_derived_alloc END TYPE foo_type ---- ===== c101 ===== ⚠️ ''Found CALL cp_fm_gemm in procedure "${proc}"'' ✅ Please don't call ''cp_fm_gemm'' directly, but instead use ''parallel_gemm'' from [[src>src/parallel_gemm_api.F]]. It allows for [[inp>GLOBAL/FM#TYPE_OF_MATRIX_MULTIPLICATION|switching]] between different implementation - in particular ScaLAPACK and [[https://github.com/eth-cscs/COSMA|COSMA]]. ---- ===== c102 ===== ⚠️ ''Found CALL m_abort in procedure "${proc}"'' ✅ Please don't call ''m_abort'' directly, but instead use the [[dev:error_handling|error handling]] macro ''CPABORT("message")''. ---- ===== c103 ===== ⚠️ ''Found CALL mp_abort in procedure "${proc}"'' ✅ Please don't call ''mp_abort'' directly, but instead use the [[dev:error_handling|error handling]] macro ''CPABORT("message")''. ---- ===== c104 ===== ⚠️ ''Found CALL RANDOM_NUMBER in procedure "${proc}"'' ✅ Please don't call ''RANDOM_NUMBER'', but instead use [[src>src/common/parallel_rng_types.F]]. ---- ===== c105 ===== ⚠️ ''Found CALL RANDOM_SEED in procedure "${proc}"'' ✅ Please don't call ''RANDOM_SEED'', but instead use [[src>src/common/parallel_rng_types.F]]. ---- ===== c106 ===== ⚠️ ''Found CALL EXECUTE_COMMAND_LINE in procedure "${proc}"'' ✅ Please don't call ''EXECUTE_COMMAND_LINE'', but instead use a workflow engine like [[https://www.aiida.net|AiiDA]]. ---- ===== c201 ===== ⚠️ ''Found GOTO statement in procedure "${proc}"'' ✅ Please don't use the ''GOTO'' statement because it's [[doi>10.1145/362929.362947 | harmful]] and [[http://xkcd.com/292/ | dangerous]]. ---- ===== c202 ===== ⚠️ ''Found FORALL statement in procedure "${proc}"'' ✅ Please don't use the ''FORALL'' statement because it's deprecated since Fortran 2018. ---- ===== c203 ===== ⚠️ ''Found OPEN statement in procedure "${proc}"'' ✅ Please don't call ''OPEN'' directly, but instead use the wrappers from [[src>src/common/cp_files.F]]. ---- ===== c204 ===== ⚠️ ''Found CLOSE statement in procedure "${proc}"'' ✅ Please don't call ''CLOSE'' directly, but instead use the wrappers from [[src>src/common/cp_files.F]]. ---- ===== c205 ===== ⚠️ ''Found STOP statement in procedure "${proc}"'' ✅ Please don't call ''STOP'' directly, but instead use the [[dev:error_handling|error handling]] macro ''CPABORT("message")''. ----