Skip to content

Commit 3559e0a

Browse files
authored
Merge pull request #31 from sourceryinstitute/shallow-copy-test
Shallow copy test
2 parents b315ccf + 02b1632 commit 3559e0a

File tree

9 files changed

+206
-42
lines changed

9 files changed

+206
-42
lines changed

.github/workflows/deploy-docs.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on: [push, pull_request]
55

66
jobs:
77
Build:
8-
runs-on: ubuntu-latest
8+
runs-on: ubuntu-22.04
99

1010
steps:
1111
- name: Checkout code
@@ -14,8 +14,8 @@ jobs:
1414
- name: Install Dependencies Ubuntu
1515
run: |
1616
sudo apt-get update
17-
sudo apt install -y python-dev python build-essential graphviz
18-
sudo pip install ford
17+
sudo apt install -y python3-dev python3 build-essential graphviz
18+
sudo pip install ford markdown==3.3.4
1919
2020
- name: Build Developer Documenation
2121
run: |

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ to finalize objects. The table below summarizes the observed compiler behaviors
6666

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

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

7678
Downloading, Building, and Testing
7779
----------------------------------
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
module finalizable_m
2+
!! This module supports the specification_expression_finalization main program
3+
!! (at the bottom of this file), which in turn supports the check_specification_expression
4+
!! unit-test function in ../test/compiler_test.f90.
5+
implicit none
6+
7+
private
8+
public :: finalizable_t, component
9+
10+
type finalizable_t
11+
private
12+
integer, pointer :: component_ => null()
13+
contains
14+
final :: finalize
15+
end Type
16+
17+
interface finalizable_t
18+
module procedure construct
19+
end interface
20+
21+
contains
22+
23+
pure function construct(component) result(finalizable)
24+
integer, intent(in) :: component
25+
type(finalizable_t) finalizable
26+
allocate(finalizable%component_, source = component)
27+
end function
28+
29+
pure function component(self) result(self_component)
30+
type(finalizable_t), intent(in) :: self
31+
integer self_component
32+
if (.not. associated(self%component_)) error stop "component: unassociated component"
33+
self_component = self%component_
34+
end function
35+
36+
pure subroutine finalize(self)
37+
type(finalizable_t), intent(inout) :: self
38+
if (associated(self%component_)) deallocate(self%component_)
39+
error stop "finalize: intentional error termination to verify finalization"
40+
end subroutine
41+
42+
end module
43+
44+
program specification_expression_finalization
45+
!! Test the finalization of a function result in a specification expression
46+
use finalizable_m, only : finalizable_t, component
47+
implicit none
48+
49+
call finalize_specification_expression_result
50+
51+
contains
52+
53+
subroutine finalize_specification_expression_result
54+
real tmp(component(finalizable_t(component=0))) !! Finalizes the finalizable_t function result
55+
end subroutine
56+
57+
end program

fpm.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name = "reference-counter"
1+
name = "reference_counter"
22
version = "1.0.0"
33
license = "BSD"
44
author = ["Damian Rouson, Karla Morris, and Jim Xia"]
@@ -9,4 +9,5 @@ copyright = "2020-2022 Sourcery Institute"
99
assert = {git = "https://github.com/sourceryinstitute/assert", tag = "1.3.0"}
1010

1111
[dev-dependencies]
12-
vegetables = {git = "https://gitlab.com/everythingfunctional/vegetables", tag = "v7.4.2"}
12+
veggies = {git = "https://gitlab.com/everythingfunctional/veggies", tag = "v1.0.4"}
13+
iso_varying_string = {git = "https://gitlab.com/everythingfunctional/iso_varying_string", tag = "v3.0.2"}

test/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Compiler Support Status
2+
=======================
3+
4+
This directory contains two categories of unit tests separated into two files:
5+
6+
* `usage_test.f90` exercises the reference-counter library, whereas
7+
* `compiler_test.f90` tests the compiler without using reference-counter,
8+
9+
`compiler_test.f90` verifies that a compiler calls a type's final subroutine
10+
in each of the scenarios in which the Fortran standard requires finalization
11+
to occur.
12+
13+
`nagfor` 7.1.0
14+
--------------
15+
:trophy: The Numerical Algorithms Group (NAG) Fortran [compiler] passes all
16+
reference-counter tests.
17+
18+
`gfortran` 12.2.0
19+
-----------------
20+
Because the first usage test listed below causes a segmentation fault,
21+
obtaining the `gfortran` test results requires skipping that test by,
22+
for example, running running individual tests as follows:
23+
```
24+
fpm test -- -f "<description>"
25+
```
26+
Replace <description> above with one of the enumerated test descriptions
27+
below or with a corresponding substring not contained in the first usage
28+
test description.
29+
30+
### Failing checks in `compiler_test.f90`
31+
1. finalizes a non-allocatable object on the LHS of an intrinsic assignment
32+
2. finalizes an allocated allocatable LHS of an intrinsic assignment
33+
3. finalizes a function reference on the RHS of an intrinsic assignment
34+
4. finalizes a function reference on the RHS of an intrinsic assignment
35+
5. finalizes a specification expression function result
36+
37+
### Failing checks in `usage_test.f90`
38+
1. copy points to the same resource as the original
39+
2. has zero references after a shallow copy goes out of scope
40+
41+
[compiler]: https://www.nag.com/content/nag-fortran-compiler

test/compiler_test.f90

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module compiler_test
2-
use vegetables, only: result_t, test_item_t, describe, it, assert_equals
2+
!! Test compiler conformance with each scenario in which the Fortran 2018
3+
!! standard mandates type finalization.
4+
use veggies, only: result_t, test_item_t, describe, it, assert_equals, assert_that
35
implicit none
46

57
private
@@ -54,7 +56,8 @@ subroutine count_finalizations(self)
5456
end subroutine
5557

5658
function check_lhs_object() result(result_)
57-
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 1 behavior: "not an unallocated allocatable variable"
59+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 1 behavior:
60+
!! "not an unallocated allocatable variable"
5861
type(object_t) lhs, rhs
5962
type(result_t) result_
6063
integer initial_tally
@@ -68,7 +71,8 @@ function check_lhs_object() result(result_)
6871
end function
6972

7073
function check_allocated_allocatable_lhs() result(result_)
71-
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 1 behavior: "allocated allocatable variable"
74+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 1 behavior:
75+
!! "allocated allocatable variable"
7276
type(object_t), allocatable :: lhs
7377
type(object_t) rhs
7478
type(result_t) result_
@@ -84,7 +88,8 @@ function check_allocated_allocatable_lhs() result(result_)
8488
end function
8589

8690
function check_target_deallocation() result(result_)
87-
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 2 behavior: "pointer is deallocated"
91+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 2 behavior:
92+
!! "pointer is deallocated"
8893
type(object_t), pointer :: object_ptr => null()
8994
type(result_t) result_
9095
integer initial_tally
@@ -98,7 +103,7 @@ function check_target_deallocation() result(result_)
98103
end function
99104

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

126131
function check_finalize_on_deallocate() result(result_)
127-
!! Tests 7.5.6.3, paragraph 2: "allocatable entity is deallocated"
132+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 2:
133+
!! "allocatable entity is deallocated"
128134
type(object_t), allocatable :: object
129135
type(result_t) result_
130136
integer initial_tally
@@ -139,7 +145,8 @@ function check_finalize_on_deallocate() result(result_)
139145
end function
140146

141147
function check_finalize_on_end() result(result_)
142-
!! Tests 7.5.6.3, paragraph 3: "before return or END statement"
148+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 3:
149+
!! "before return or END statement"
143150
type(result_t) result_
144151
integer initial_tally
145152

@@ -159,7 +166,8 @@ subroutine finalize_on_end_subroutine()
159166
end function
160167

161168
function check_block_finalization() result(result_)
162-
!! Tests 7.5.6.3, paragraph 4: "termination of the BLOCK construct"
169+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 4:
170+
!! "termination of the BLOCK construct"
163171
type(result_t) result_
164172
integer initial_tally
165173

@@ -174,7 +182,8 @@ function check_block_finalization() result(result_)
174182
end function
175183

176184
function check_rhs_function_reference() result(result_)
177-
!! Verify Fortran 2018 clause 7.5.6.3, paragraph 5 behavior: "nonpointer function result"
185+
!! Test conformance with Fortran 2018 clause 7.5.6.3, paragraph 5 behavior:
186+
!! "nonpointer function result"
178187
type(object_t), allocatable :: object
179188
type(result_t) result_
180189
integer initial_tally
@@ -187,27 +196,25 @@ function check_rhs_function_reference() result(result_)
187196
end function
188197

189198
function check_specification_expression() result(result_)
190-
!! Tests 7.5.6.3, paragraph 6: "specification expression function result"
199+
!! Test conformance with Fortran 2018 standard clause 7.5.6.3, paragraph 6:
200+
!! "specification expression function result"
191201
type(result_t) result_
192-
integer initial_tally
193-
194-
initial_tally = finalizations
195-
call finalize_specification_expression
196-
associate(delta => finalizations - initial_tally)
197-
result_ = assert_equals(1, delta)
198-
end associate
199-
200-
contains
201-
202-
subroutine finalize_specification_expression
203-
character(len=size([object_t(dummy=this_image())])) :: string ! Finalizes RHS function reference
204-
string = ""
205-
end subroutine
202+
integer exit_status
203+
logical error_termination_occurred
204+
205+
call execute_command_line( &
206+
command = "fpm run --example specification_expression_finalization > /dev/null 2>&1", &
207+
wait = .true., &
208+
exitstat = exit_status &
209+
)
210+
error_termination_occurred = exit_status /=0
211+
result_ = assert_that(error_termination_occurred)
206212

207213
end function
208214

209215
function check_intent_out_finalization() result(result_)
210-
!! Tests 7.5.6.3, paragraph 7: "nonpointer, nonallocatable, INTENT (OUT) dummy argument"
216+
!! Test conformance with Fortran 2018 standard clause 7.5.6.3, paragraph 7:
217+
!! "nonpointer, nonallocatable, INTENT (OUT) dummy argument"
211218
type(result_t) result_
212219
type(object_t) object
213220
integer initial_tally

test/main.f90

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
! Generated by make_vegetable_driver. DO NOT EDIT
1+
! Generated by cart. DO NOT EDIT
22
program main
33
implicit none
44

5-
call run()
5+
if (.not.run()) stop 1
66
contains
7-
subroutine run()
7+
function run() result(passed)
88
use compiler_test, only: &
99
compiler_ref_reference => &
1010
test_ref_reference
1111
use usage_test, only: &
1212
usage_usage => &
1313
test_usage
14-
use vegetables, only: test_item_t, test_that, run_tests
14+
use veggies, only: test_item_t, test_that, run_tests
1515

1616

1717

18+
logical :: passed
19+
1820
type(test_item_t) :: tests
1921
type(test_item_t) :: individual_tests(2)
2022

@@ -23,7 +25,7 @@ subroutine run()
2325
tests = test_that(individual_tests)
2426

2527

26-
call run_tests(tests)
28+
passed = run_tests(tests)
2729

28-
end subroutine
30+
end function
2931
end program

test/shallow_m.f90

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module shallow_m
2+
use reference_counter_m, only: ref_reference_t
3+
4+
implicit none
5+
private
6+
public :: shallow_t, resource_freed
7+
8+
type, extends(ref_reference_t) :: shallow_t
9+
integer, pointer :: ref => null()
10+
contains
11+
procedure :: free
12+
end type
13+
14+
interface shallow_t
15+
module procedure construct
16+
end interface
17+
18+
integer, allocatable, target, save :: resource
19+
logical, save :: resource_freed = .false.
20+
21+
contains
22+
function construct() result(shallow)
23+
type(shallow_t) :: shallow
24+
25+
resource = 42
26+
shallow%ref => resource
27+
call shallow%start_ref_counter
28+
end function
29+
30+
subroutine free(self)
31+
class(shallow_t), intent(inout) :: self
32+
33+
deallocate(resource)
34+
nullify(self%ref)
35+
resource_freed = .true.
36+
end subroutine
37+
38+
end module

0 commit comments

Comments
 (0)