Skip to content

Shallow copy test #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: [push, pull_request]

jobs:
Build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- name: Checkout code
Expand All @@ -14,8 +14,8 @@ jobs:
- name: Install Dependencies Ubuntu
run: |
sudo apt-get update
sudo apt install -y python-dev python build-essential graphviz
sudo pip install ford
sudo apt install -y python3-dev python3 build-essential graphviz
sudo pip install ford markdown==3.3.4

- name: Build Developer Documenation
run: |
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ to finalize objects. The table below summarizes the observed compiler behaviors

| _Compiler_ | _Test failures_ | _Version tested_ |
| :--- | :---: | :--- |
| NAG | 1 | `nagfor` 7.1 |
| GCC | 4 | `gfortran` 11.3.0, 12.1.0 |
| NAG | 0 | `nagfor` 7.1 Build 7113 |
| GCC | 6 | `gfortran` 12.2.0 |
| Intel | 2 | `ifort` 2021.5.0 Build 20211109\_000000 |
| NVIDIA | Fails to build (ICE) | `nvfortran` 2022.2 |
| AMD | Fails to build (ICE) | `flang` 13.0.0 (AOCC_3.2.0-Build\#128 2021\_11\_12) |

See the [test suite README.md](./test/README.md) for more details on each compiler's test
failures.

Downloading, Building, and Testing
----------------------------------
Expand Down
57 changes: 57 additions & 0 deletions example/specification_expression_finalization.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module finalizable_m
!! This module supports the specification_expression_finalization main program
!! (at the bottom of this file), which in turn supports the check_specification_expression
!! unit-test function in ../test/compiler_test.f90.
implicit none

private
public :: finalizable_t, component

type finalizable_t
private
integer, pointer :: component_ => null()
contains
final :: finalize
end Type

interface finalizable_t
module procedure construct
end interface

contains

pure function construct(component) result(finalizable)
integer, intent(in) :: component
type(finalizable_t) finalizable
allocate(finalizable%component_, source = component)
end function

pure function component(self) result(self_component)
type(finalizable_t), intent(in) :: self
integer self_component
if (.not. associated(self%component_)) error stop "component: unassociated component"
self_component = self%component_
end function

pure subroutine finalize(self)
type(finalizable_t), intent(inout) :: self
if (associated(self%component_)) deallocate(self%component_)
error stop "finalize: intentional error termination to verify finalization"
end subroutine

end module

program specification_expression_finalization
!! Test the finalization of a function result in a specification expression
use finalizable_m, only : finalizable_t, component
implicit none

call finalize_specification_expression_result

contains

subroutine finalize_specification_expression_result
real tmp(component(finalizable_t(component=0))) !! Finalizes the finalizable_t function result
end subroutine

end program
5 changes: 3 additions & 2 deletions fpm.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = "reference-counter"
name = "reference_counter"
version = "1.0.0"
license = "BSD"
author = ["Damian Rouson, Karla Morris, and Jim Xia"]
Expand All @@ -9,4 +9,5 @@ copyright = "2020-2022 Sourcery Institute"
assert = {git = "https://github.com/sourceryinstitute/assert", tag = "1.3.0"}

[dev-dependencies]
vegetables = {git = "https://gitlab.com/everythingfunctional/vegetables", tag = "v7.4.2"}
veggies = {git = "https://gitlab.com/everythingfunctional/veggies", tag = "v1.0.4"}
iso_varying_string = {git = "https://gitlab.com/everythingfunctional/iso_varying_string", tag = "v3.0.2"}
41 changes: 41 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Compiler Support Status
=======================

This directory contains two categories of unit tests separated into two files:

* `usage_test.f90` exercises the reference-counter library, whereas
* `compiler_test.f90` tests the compiler without using reference-counter,

`compiler_test.f90` verifies that a compiler calls a type's final subroutine
in each of the scenarios in which the Fortran standard requires finalization
to occur.

`nagfor` 7.1.0
--------------
:trophy: The Numerical Algorithms Group (NAG) Fortran [compiler] passes all
reference-counter tests.

`gfortran` 12.2.0
-----------------
Because the first usage test listed below causes a segmentation fault,
obtaining the `gfortran` test results requires skipping that test by,
for example, running running individual tests as follows:
```
fpm test -- -f "<description>"
```
Replace <description> above with one of the enumerated test descriptions
below or with a corresponding substring not contained in the first usage
test description.

### Failing checks in `compiler_test.f90`
1. finalizes a non-allocatable object on the LHS of an intrinsic assignment
2. finalizes an allocated allocatable LHS of an intrinsic assignment
3. finalizes a function reference on the RHS of an intrinsic assignment
4. finalizes a function reference on the RHS of an intrinsic assignment
5. finalizes a specification expression function result

### Failing checks in `usage_test.f90`
1. copy points to the same resource as the original
2. has zero references after a shallow copy goes out of scope

[compiler]: https://www.nag.com/content/nag-fortran-compiler
57 changes: 32 additions & 25 deletions test/compiler_test.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module compiler_test
use vegetables, only: result_t, test_item_t, describe, it, assert_equals
!! Test compiler conformance with each scenario in which the Fortran 2018
!! standard mandates type finalization.
use veggies, only: result_t, test_item_t, describe, it, assert_equals, assert_that
implicit none

private
Expand Down Expand Up @@ -54,7 +56,8 @@ subroutine count_finalizations(self)
end subroutine

function check_lhs_object() result(result_)
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 1 behavior: "not an unallocated allocatable variable"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 1 behavior:
!! "not an unallocated allocatable variable"
type(object_t) lhs, rhs
type(result_t) result_
integer initial_tally
Expand All @@ -68,7 +71,8 @@ function check_lhs_object() result(result_)
end function

function check_allocated_allocatable_lhs() result(result_)
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 1 behavior: "allocated allocatable variable"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 1 behavior:
!! "allocated allocatable variable"
type(object_t), allocatable :: lhs
type(object_t) rhs
type(result_t) result_
Expand All @@ -84,7 +88,8 @@ function check_allocated_allocatable_lhs() result(result_)
end function

function check_target_deallocation() result(result_)
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 2 behavior: "pointer is deallocated"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 2 behavior:
!! "pointer is deallocated"
type(object_t), pointer :: object_ptr => null()
type(result_t) result_
integer initial_tally
Expand All @@ -98,7 +103,7 @@ function check_target_deallocation() result(result_)
end function

function check_allocatable_component_finalization() result(result_)
!! Tests 7.5.6.3, para. 2 ("allocatable entity is deallocated")
!! Test conformance with Fortran 2018 clause 7.5.6.3, para. 2 ("allocatable entity is deallocated")
!! + 9.7.3.2, para. 6 ("INTENT(OUT) allocatable dummy argument is deallocated")
type(wrapper_t), allocatable :: wrapper
type(result_t) result_
Expand All @@ -124,7 +129,8 @@ subroutine finalize_intent_out_component(output)
end function

function check_finalize_on_deallocate() result(result_)
!! Tests 7.5.6.3, paragraph 2: "allocatable entity is deallocated"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 2:
!! "allocatable entity is deallocated"
type(object_t), allocatable :: object
type(result_t) result_
integer initial_tally
Expand All @@ -139,7 +145,8 @@ function check_finalize_on_deallocate() result(result_)
end function

function check_finalize_on_end() result(result_)
!! Tests 7.5.6.3, paragraph 3: "before return or END statement"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 3:
!! "before return or END statement"
type(result_t) result_
integer initial_tally

Expand All @@ -159,7 +166,8 @@ subroutine finalize_on_end_subroutine()
end function

function check_block_finalization() result(result_)
!! Tests 7.5.6.3, paragraph 4: "termination of the BLOCK construct"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 4:
!! "termination of the BLOCK construct"
type(result_t) result_
integer initial_tally

Expand All @@ -174,7 +182,8 @@ function check_block_finalization() result(result_)
end function

function check_rhs_function_reference() result(result_)
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 5 behavior: "nonpointer function result"
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 5 behavior:
!! "nonpointer function result"
type(object_t), allocatable :: object
type(result_t) result_
integer initial_tally
Expand All @@ -187,27 +196,25 @@ function check_rhs_function_reference() result(result_)
end function

function check_specification_expression() result(result_)
!! Tests 7.5.6.3, paragraph 6: "specification expression function result"
!! Test conformance with Fortran 2018 standard clause 7.5.6.3, paragraph 6:
!! "specification expression function result"
type(result_t) result_
integer initial_tally

initial_tally = finalizations
call finalize_specification_expression
associate(delta => finalizations - initial_tally)
result_ = assert_equals(1, delta)
end associate

contains

subroutine finalize_specification_expression
character(len=size([object_t(dummy=this_image())])) :: string ! Finalizes RHS function reference
string = ""
end subroutine
integer exit_status
logical error_termination_occurred

call execute_command_line( &
command = "fpm run --example specification_expression_finalization > /dev/null 2>&1", &
wait = .true., &
exitstat = exit_status &
)
error_termination_occurred = exit_status /=0
result_ = assert_that(error_termination_occurred)

end function

function check_intent_out_finalization() result(result_)
!! Tests 7.5.6.3, paragraph 7: "nonpointer, nonallocatable, INTENT (OUT) dummy argument"
!! Test conformance with Fortran 2018 standard clause 7.5.6.3, paragraph 7:
!! "nonpointer, nonallocatable, INTENT (OUT) dummy argument"
type(result_t) result_
type(object_t) object
integer initial_tally
Expand Down
14 changes: 8 additions & 6 deletions test/main.f90
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
! Generated by make_vegetable_driver. DO NOT EDIT
! Generated by cart. DO NOT EDIT
program main
implicit none

call run()
if (.not.run()) stop 1
contains
subroutine run()
function run() result(passed)
use compiler_test, only: &
compiler_ref_reference => &
test_ref_reference
use usage_test, only: &
usage_usage => &
test_usage
use vegetables, only: test_item_t, test_that, run_tests
use veggies, only: test_item_t, test_that, run_tests



logical :: passed

type(test_item_t) :: tests
type(test_item_t) :: individual_tests(2)

Expand All @@ -23,7 +25,7 @@ subroutine run()
tests = test_that(individual_tests)


call run_tests(tests)
passed = run_tests(tests)

end subroutine
end function
end program
38 changes: 38 additions & 0 deletions test/shallow_m.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module shallow_m
use reference_counter_m, only: ref_reference_t

implicit none
private
public :: shallow_t, resource_freed

type, extends(ref_reference_t) :: shallow_t
integer, pointer :: ref => null()
contains
procedure :: free
end type

interface shallow_t
module procedure construct
end interface

integer, allocatable, target, save :: resource
logical, save :: resource_freed = .false.

contains
function construct() result(shallow)
type(shallow_t) :: shallow

resource = 42
shallow%ref => resource
call shallow%start_ref_counter
end function

subroutine free(self)
class(shallow_t), intent(inout) :: self

deallocate(resource)
nullify(self%ref)
resource_freed = .true.
end subroutine

end module
Loading