Repository: stfc/PSyclone

Issue:
[fparser2-FE] CONTAINS section of derived type definition is lost
Processing:

     TYPE fobe_sdv_typ

       TYPE(ctlvec) :: sdv

     CONTAINS

        PROCEDURE :: init        => obesdv_setup
        PROCEDURE :: dealloc     => obesdv_dealloc
        PROCEDURE :: multiply    => obesdv_multiply
        PROCEDURE :: invMultiply => obesdv_invMultiply

     END TYPE fobe_sdv_typ

and re-generating gives:

    type, public :: fobe_sdv_typ
      type(ctlvec), public :: sdv
    end type fobe_sdv_typ

which is not ideal.

Discussion:

Patch:
diff --git a/changelog b/changelog
index 96aff2908..ce12f068b 100644
--- a/changelog
+++ b/changelog
@@ -113,6 +113,9 @@
 	37) PR #1565 for #1505. Fix bug with UnknownFortranTypes inside other
 	fparser frontend declarations.
 
+	38) PR #1603 for #1566. Fparser reader parses derived types with
+	contains statements as UnknownFortranType.
+
 release 2.1.0 3rd November 2021
 
 	1) PR #1183 for #1075. Improves (tightens) the checking performed
diff --git a/src/psyclone/psyir/frontend/fparser2.py b/src/psyclone/psyir/frontend/fparser2.py
index adbd44ccc..e335145be 100644
--- a/src/psyclone/psyir/frontend/fparser2.py
+++ b/src/psyclone/psyir/frontend/fparser2.py
@@ -1882,6 +1882,13 @@ class Fparser2Reader(object):
         # Populate this StructureType by processing the components of
         # the derived type
         try:
+            # We don't yet support derived-type definitions with a CONTAINS
+            # section.
+            contains = walk(decl, Fortran2003.Contains_Stmt)
+            if contains:
+                raise NotImplementedError(
+                    "Derived-type definition has a CONTAINS statement.")
+
             # Re-use the existing code for processing symbols
             local_table = SymbolTable(
                 default_visibility=default_compt_visibility)


Test patch:
diff --git a/src/psyclone/tests/psyir/frontend/fparser2_derived_type_test.py b/src/psyclone/tests/psyir/frontend/fparser2_derived_type_test.py
index 70f431f78..4c514fd85 100644
--- a/src/psyclone/tests/psyir/frontend/fparser2_derived_type_test.py
+++ b/src/psyclone/tests/psyir/frontend/fparser2_derived_type_test.py
@@ -1,7 +1,7 @@
 # -----------------------------------------------------------------------------
 # BSD 3-Clause License
 #
-# Copyright (c) 2020-2021, Science and Technology Facilities Council.
+# Copyright (c) 2020-2022, Science and Technology Facilities Council.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -242,6 +242,35 @@ def test_parse_derived_type(use_stmt, type_name):
     assert var.datatype is sym
 
 
+@pytest.mark.usefixtures("f2008_parser")
+def test_derived_type_contains():
+    ''' Check that we get a DataTypeSymbol of UnknownFortranType if a
+    derived-type definition has a CONTAINS section. '''
+    fake_parent = KernelSchedule("dummy_schedule")
+    symtab = fake_parent.symbol_table
+    processor = Fparser2Reader()
+    reader = FortranStringReader("type my_type\n"
+                                 "  integer :: flag\n"
+                                 "  real, dimension(3) :: posn\n"
+                                 "contains\n"
+                                 "  procedure :: init => obesdv_setup\n"
+                                 "end type my_type\n"
+                                 "type(my_type) :: var\n")
+    fparser2spec = Fortran2003.Specification_Part(reader)
+    processor.process_declarations(fake_parent, fparser2spec.content, [])
+    sym = symtab.lookup("my_type")
+    # It should still be a DataTypeSymbol but its type is unknown.
+    assert isinstance(sym, DataTypeSymbol)
+    assert isinstance(sym.datatype, UnknownFortranType)
+    assert sym.datatype.declaration == '''\
+TYPE :: my_type
+  INTEGER :: flag
+  REAL, DIMENSION(3) :: posn
+  CONTAINS
+  PROCEDURE :: init => obesdv_setup
+END TYPE my_type'''
+
+
 @pytest.mark.usefixtures("f2008_parser")
 @pytest.mark.parametrize("type_name", ["my_type", "MY_TYPE", "mY_type"])
 def test_derived_type_self_ref(type_name):