Repository: stfc/PSyclone (python)

Issue:
[WW3] sub-string of character string causes crash
Asif has reported that the WW3 code uses a character variable:

      CHARACTER(256)          :: LINE, TEST
    100 CONTINUE
      ! read line
      READ ( NDSI, 900, END=800, ERR=801, IOSTAT=IERR, IOMSG=MSG ) LINE
      ! leading blanks removed and placed on the right
      TEST = ADJUSTL ( LINE )
      IF ( TEST(1:1).EQ.CHCKC .OR. LEN_TRIM(TEST).EQ.0 ) THEN

and PSyclone falls over in `ArrayMixin.is_lower_bound` when examinging `TEST(1:1)` because it assumes it is of ArrayType whereas it is in fact of UnknownFortranType (because we don't support Character variables).

Pull request description:
(Closes #1893) allow for Symbol in is_upper/lower_bound
A second small bug fix to allow for the case where we have no type information at all.

Patch:
diff --git a/changelog b/changelog
index 1ad6370b0..d15d7cff3 100644
--- a/changelog
+++ b/changelog
@@ -145,6 +145,9 @@
 	52) PR #1853 for #1829. Add OMP teams distribute parallel do directive
 	and refactor OMPLoopTrans.
 
+	53) PR #1900 for #1893. Fix bug in is_upper/lower_bound for non-typed
+	Symbols.
+
 release 2.3.1 17th of June 2022
 
 	1) PR #1747 for #1720. Adds support for If blocks to PSyAD.
diff --git a/src/psyclone/psyir/nodes/array_mixin.py b/src/psyclone/psyir/nodes/array_mixin.py
index 11c1e0f0c..80cc3116a 100644
--- a/src/psyclone/psyir/nodes/array_mixin.py
+++ b/src/psyclone/psyir/nodes/array_mixin.py
@@ -49,7 +49,7 @@ from psyclone.psyir.nodes.member import Member
 from psyclone.psyir.nodes.operation import Operation, BinaryOperation
 from psyclone.psyir.nodes.ranges import Range
 from psyclone.psyir.nodes.reference import Reference
-from psyclone.psyir.symbols import SymbolError
+from psyclone.psyir.symbols import SymbolError, DataSymbol
 from psyclone.psyir.symbols.datatypes import (ScalarType, ArrayType,
                                               INTEGER_TYPE)
 
@@ -151,6 +151,10 @@ class ArrayMixin(metaclass=abc.ABCMeta):
         if isinstance(lower, Literal):
             try:
                 symbol = self.scope.symbol_table.lookup(self.name)
+                if not isinstance(symbol, DataSymbol):
+                    # We don't have any type information on this symbol
+                    # (probably because it originates from a wildcard import).
+                    return False
                 datatype = symbol.datatype
                 # Check that the symbol is of ArrayType. (It may be of
                 # UnknownFortranType if the symbol is of e.g. character type.)
@@ -215,6 +219,10 @@ class ArrayMixin(metaclass=abc.ABCMeta):
         if isinstance(upper, Literal):
             try:
                 symbol = self.scope.symbol_table.lookup(self.name)
+                if not isinstance(symbol, DataSymbol):
+                    # We don't have any type information on this symbol
+                    # (probably because it originates from a wildcard import).
+                    return False
                 datatype = symbol.datatype
                 # Check that the symbol is of ArrayType. (It may be of
                 # UnknownFortranType if the symbol is of e.g. character type.)


Test patch:
diff --git a/src/psyclone/tests/psyir/nodes/array_mixin_test.py b/src/psyclone/tests/psyir/nodes/array_mixin_test.py
index 5460dea35..c68d3438c 100644
--- a/src/psyclone/tests/psyir/nodes/array_mixin_test.py
+++ b/src/psyclone/tests/psyir/nodes/array_mixin_test.py
@@ -80,10 +80,12 @@ def test_is_upper_lower_bound(fortran_reader):
     '''
     code = (
         "subroutine test()\n"
+        "use some_mod\n"
         "real a(10)\n"
         "character(10) my_str\n"
         "a(1:10) = 0.0\n"
         "my_str(2:2) = 'b'\n"
+        "var1(3:4) = 0\n"
         "end subroutine\n")
 
     # Return True as the literal values or the declaration and array
@@ -115,6 +117,12 @@ def test_is_upper_lower_bound(fortran_reader):
     assert not array_ref.is_lower_bound(0)
     assert not array_ref.is_upper_bound(0)
 
+    # Return False if the symbol has no associated type information.
+    array_ref = assigns[2].lhs
+    assert not isinstance(array_ref.symbol, DataSymbol)
+    assert not array_ref.is_lower_bound(0)
+    assert not array_ref.is_upper_bound(0)
+
 
 def test_get_effective_shape(fortran_reader, fortran_writer):
     '''Tests for the _get_effective_shape() method.'''