diff --git a/src/assert/assert_subroutine_m.F90 b/src/assert/assert_subroutine_m.F90 index cdaadfe..8fd0a68 100644 --- a/src/assert/assert_subroutine_m.F90 +++ b/src/assert/assert_subroutine_m.F90 @@ -7,6 +7,8 @@ ! #include "assert_macros.h" +#include "assert_features.h" + module assert_subroutine_m !! summary: Utility for runtime enforcement of logical assertions. !! usage: error-terminate if the assertion fails: @@ -66,9 +68,10 @@ pure subroutine assert_error_stop_interface(stop_code_char) #endif logical, parameter :: enforce_assertions=USE_ASSERTIONS - interface - pure module subroutine assert(assertion, description) +contains + + pure subroutine assert(assertion, description) !! If assertion is .false. and enforcement is enabled (e.g. via -DASSERTIONS=1), !! then error-terminate with a character stop code that contains the description argument if present implicit none @@ -76,15 +79,50 @@ pure module subroutine assert(assertion, description) !! Most assertions will be expressions such as i>0 character(len=*), intent(in) :: description !! A brief statement of what is being asserted such as "i>0" or "positive i" - end subroutine - pure module subroutine assert_always(assertion, description) + toggle_assertions: & + if (enforce_assertions) then + call assert_always(assertion, description) + end if toggle_assertions + + end subroutine + + pure subroutine assert_always(assertion, description) !! Same as above but always enforces the assertion (regardless of ASSERTIONS) implicit none logical, intent(in) :: assertion character(len=*), intent(in) :: description - end subroutine + character(len=:), allocatable :: message + integer me - end interface + check_assertion: & + if (.not. assertion) then + +#if ASSERT_MULTI_IMAGE +# if ASSERT_PARALLEL_CALLBACKS + me = assert_this_image() +# else + me = this_image() +# endif + block + character(len=128) image_number + write(image_number, *) me + message = 'Assertion failure on image ' // trim(adjustl(image_number)) // ':' // description + end block +#else + message = 'Assertion failure: ' // description + me = 0 ! avoid a harmless warning +#endif + +#if ASSERT_PARALLEL_CALLBACKS + call assert_error_stop(message) +#else + error stop message, QUIET=.false. +#endif + + end if check_assertion + + end subroutine end module assert_subroutine_m + diff --git a/src/assert/assert_subroutine_s.F90 b/src/assert/assert_subroutine_s.F90 deleted file mode 100644 index d73901f..0000000 --- a/src/assert/assert_subroutine_s.F90 +++ /dev/null @@ -1,79 +0,0 @@ -! -! (c) 2019-2020 Guide Star Engineering, LLC -! This Software was developed for the US Nuclear Regulatory Commission (US NRC) under contract -! "Multi-Dimensional Physics Implementation into Fuel Analysis under Steady-state and Transients (FAST)", -! contract # NRC-HQ-60-17-C-0007 -! - -#include "assert_features.h" - -submodule(assert_subroutine_m) assert_subroutine_s - implicit none - -contains - - module procedure assert - - toggle_assertions: & - if (enforce_assertions) then - call assert_always(assertion, description) - end if toggle_assertions - - end procedure - - module procedure assert_always - character(len=:), allocatable :: message - integer me - - check_assertion: & - if (.not. assertion) then - -#if ASSERT_MULTI_IMAGE -# if ASSERT_PARALLEL_CALLBACKS - me = assert_this_image() -# else - me = this_image() -# endif - message = 'Assertion failure on image ' // string(me) // ':' // description -#else - message = 'Assertion failure: ' // description - me = 0 ! avoid a harmless warning -#endif - -#if ASSERT_PARALLEL_CALLBACKS - call assert_error_stop(message) -#else - error stop message, QUIET=.false. -#endif - - end if check_assertion - - contains - - pure function string(numeric) result(number_as_string) - !! Result is a string represention of the numeric argument - class(*), intent(in) :: numeric - integer, parameter :: max_len=128 - character(len=max_len) :: untrimmed_string - character(len=:), allocatable :: number_as_string - - select type(numeric) - type is(complex) - write(untrimmed_string, *) numeric - type is(integer) - write(untrimmed_string, *) numeric - type is(logical) - write(untrimmed_string, *) numeric - type is(real) - write(untrimmed_string, *) numeric - class default - error stop "Internal error in subroutine 'assert': unsupported type in function 'string'." - end select - - number_as_string = trim(adjustl(untrimmed_string)) - - end function string - - end procedure - -end submodule assert_subroutine_s diff --git a/test/test-assert-subroutine-error-termination.F90 b/test/test-assert-subroutine-error-termination.F90 index 07ac2d3..ea94fbd 100644 --- a/test/test-assert-subroutine-error-termination.F90 +++ b/test/test-assert-subroutine-error-termination.F90 @@ -27,7 +27,8 @@ program test_assert_subroutine_error_termination #elif _CRAYFTN command = "fpm run --example false-assertion --profile release --compiler crayftn.sh --flag '-DASSERTIONS' > /dev/null 2>&1", & #else - command = "echo 'example/false_assertion.F90: unsupported compiler' && exit 1", & + ! For all other compilers, we assume that the default fpm command works + command = "fpm run --example false-assertion --profile release --flag '-DASSERTIONS -ffree-line-length-0' > /dev/null 2>&1", & #endif wait = .true., & exitstat = exit_status & @@ -47,15 +48,18 @@ program test_assert_subroutine_error_termination end if end if end block +#else +#ifdef __LFORTRAN__ + print *,trim(merge("passes","FAILS ",exit_status/=0)) // " on error-terminating when assertion = .false." #else block integer unit open(newunit=unit, file="build/exit_status", status="old") read(unit,*) exit_status - print *,trim(merge("passes","FAILS ",exit_status/=0)) // " on error-terminating when assertion = .false." close(unit) end block #endif +#endif contains