Skip to content

Commit bba4ef6

Browse files
authored
Expand parsing to include abstract interfaces (#1074)
2 parents 448d47c + 6722dab commit bba4ef6

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

src/fpm_source_parsing.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ function parse_f_source(f_filename,error) result(f_source)
153153
end if
154154

155155
! Detect beginning of interface block
156-
if (index(file_lines_lower(i)%s,'interface') == 1) then
156+
if (index(file_lines_lower(i)%s,'interface') == 1 &
157+
.or. parse_sequence(file_lines_lower(i)%s,'abstract','interface')) then
157158

158159
inside_interface = .true.
159160
cycle

test/fpm_test/test_source_parsing.f90

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ subroutine collect_source_parsing(testsuite)
3030
& new_unittest("module", test_module), &
3131
& new_unittest("module-with-subprogram", test_module_with_subprogram), &
3232
& new_unittest("module-with-c-api", test_module_with_c_api), &
33+
& new_unittest("module-with-abstract-interface",test_module_with_abstract_interface), &
3334
& new_unittest("module-end-stmt", test_module_end_stmt), &
3435
& new_unittest("program-with-module", test_program_with_module), &
36+
& new_unittest("program-with-abstract-interface", test_program_with_abstract_interface), &
3537
& new_unittest("submodule", test_submodule), &
3638
& new_unittest("submodule-ancestor", test_submodule_ancestor), &
3739
& new_unittest("subprogram", test_subprogram), &
@@ -632,6 +634,37 @@ subroutine test_module_with_c_api(error)
632634

633635
end subroutine test_module_with_c_api
634636

637+
!> Check parsing of module exporting an abstract interface
638+
!> See also https://github.com/fortran-lang/fpm/issues/1073
639+
subroutine test_module_with_abstract_interface(error)
640+
type(error_t), allocatable, intent(out) :: error
641+
642+
integer :: unit
643+
character(:), allocatable :: temp_file
644+
type(srcfile_t) :: f_source
645+
646+
allocate(temp_file,source=get_temp_filename())
647+
open(file=temp_file,newunit=unit)
648+
write(unit, '(A)') &
649+
& 'module foo', &
650+
& 'abstract interface', &
651+
& ' subroutine bar1()', &
652+
& ' end subroutine', &
653+
& ' subroutine bar2() bind(c)', &
654+
& ' end subroutine', &
655+
& 'end interface', &
656+
& 'end module foo'
657+
close(unit)
658+
659+
f_source = parse_f_source(temp_file,error)
660+
if (allocated(error)) return
661+
if (f_source%unit_type /= FPM_UNIT_MODULE) then
662+
call test_failed(error,'Wrong unit type detected - expecting FPM_UNIT_MODULE')
663+
return
664+
end if
665+
call f_source%test_serialization('srcfile_t: serialization', error)
666+
end subroutine test_module_with_abstract_interface
667+
635668

636669
!> Try to parse combined fortran module and program
637670
!> Check that parsed unit type is FPM_UNIT_PROGRAM
@@ -697,6 +730,64 @@ subroutine test_program_with_module(error)
697730

698731
end subroutine test_program_with_module
699732

733+
!> Check parsing of interfaces within program unit
734+
!> See also https://github.com/fortran-lang/fpm/issues/1073
735+
subroutine test_program_with_abstract_interface(error)
736+
737+
!> Error handling
738+
type(error_t), allocatable, intent(out) :: error
739+
740+
integer :: unit
741+
character(:), allocatable :: temp_file
742+
type(srcfile_t), allocatable :: f_source
743+
744+
allocate(temp_file, source=get_temp_filename())
745+
746+
open(file=temp_file, newunit=unit)
747+
write(unit, '(a)') &
748+
& 'program my_program', &
749+
& 'implicit none', &
750+
& 'abstract interface', &
751+
& ' function cmpfunc(a,b) bind(c)', &
752+
& ' use, intrinsic :: iso_c_binding', &
753+
& ' type(c_ptr), intent(in), value :: a, b', &
754+
& ' integer(c_int) :: cmpfunc', &
755+
& ' end function', &
756+
& 'end interface', &
757+
& 'interface', &
758+
& ' subroutine qsort(ptr,count,size,comp) bind(c,name="qsort")', &
759+
& ' use, intrinsic :: iso_c_binding', &
760+
& ' type(c_ptr), value :: ptr', &
761+
& ' integer(c_size_t), value :: count, size', &
762+
& ' type(c_funptr), value :: comp', &
763+
& 'end interface', &
764+
& 'end program my_program'
765+
close(unit)
766+
767+
f_source = parse_f_source(temp_file,error)
768+
if (allocated(error)) then
769+
return
770+
end if
771+
772+
if (f_source%unit_type /= FPM_UNIT_PROGRAM) then
773+
call test_failed(error,'Wrong unit type detected - expecting FPM_UNIT_PROGRAM')
774+
return
775+
end if
776+
777+
if (size(f_source%modules_provided) /= 0) then
778+
call test_failed(error,'Unexpected modules_provided - expecting zero')
779+
return
780+
end if
781+
782+
! Intrinsic modules are not counted in `modules_used` (!)
783+
if (size(f_source%modules_used) /= 0) then
784+
call test_failed(error,'Incorrect number of modules_used - expecting zero')
785+
return
786+
end if
787+
788+
call f_source%test_serialization('srcfile_t: serialization', error)
789+
790+
end subroutine test_program_with_abstract_interface
700791

701792
!> Try to parse fortran submodule for ancestry
702793
subroutine test_submodule(error)

0 commit comments

Comments
 (0)