2006-04-16 Paul Thomas <pault@gcc.gnu.org>
authorpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Apr 2006 03:45:24 +0000 (03:45 +0000)
committerpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Apr 2006 03:45:24 +0000 (03:45 +0000)
PR fortran/26822
* intrinsic.c (add_functions): Mark LOGICAL as elemental.

PR fortran/26787
* expr.c (gfc_check_assign): Extend scope of error to include
assignments to a procedure in the main program or, from a
module or internal procedure that is not that represented by
the lhs symbol. Use VARIABLE rather than l-value in message.

PR fortran/27096
* trans-array.c (gfc_trans_deferred_array): If the backend_decl
is not a descriptor, dereference and then test and use the type.

PR fortran/25597
* trans-decl.c (gfc_trans_deferred_vars): Check if an array
result, is also automatic character length.  If so, process
the character length.

PR fortran/18803
PR fortran/25669
PR fortran/26834
* trans_intrinsic.c (gfc_walk_intrinsic_bound): Set
data.info.dimen for bound intrinsics.
* trans_array.c (gfc_conv_ss_startstride): Pick out LBOUND and
UBOUND intrinsics and supply their shape information to the ss
and the loop.

PR fortran/27124
* trans_expr.c (gfc_trans_function_call):  Add a new block, post,
in to which all the argument post blocks are put.  Add this block
to se->pre after a byref call or to se->post, otherwise.

2006-04-16  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/26787
* gfortran.dg/proc_assign_1.f90: New test.
* gfortran.dg/procedure_lvalue.f90: Change message.
* gfortran.dg/namelist_4.f90: Add new error.

PR fortran/27096
* gfortran.dg/auto_pointer_array_result_1.f90

PR fortran/27089
* gfortran.dg/specification_type_resolution_1.f90

PR fortran/18803
PR fortran/25669
PR fortran/26834
* gfortran.dg/bounds_temporaries_1.f90: New test.

PR fortran/27124
* gfortran.dg/array_return_value_1.f90: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112981 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/fortran/ChangeLog
gcc/fortran/expr.c
gcc/fortran/intrinsic.c
gcc/fortran/resolve.c
gcc/fortran/trans-array.c
gcc/fortran/trans-decl.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/array_return_value_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/auto_char_pointer_array_result_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/auto_pointer_array_result_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/bounds_temporaries_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/namelist_4.f90
gcc/testsuite/gfortran.dg/proc_assign_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/procedure_lvalue.f90
gcc/testsuite/gfortran.dg/specification_type_resolution_1.f90 [new file with mode: 0644]

index df5a576..24af5f6 100644 (file)
@@ -1,3 +1,37 @@
+2006-04-16  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/26822
+       * intrinsic.c (add_functions): Mark LOGICAL as elemental.
+
+       PR fortran/26787
+       * expr.c (gfc_check_assign): Extend scope of error to include
+       assignments to a procedure in the main program or, from a
+       module or internal procedure that is not that represented by
+       the lhs symbol. Use VARIABLE rather than l-value in message.
+
+       PR fortran/27096
+       * trans-array.c (gfc_trans_deferred_array): If the backend_decl
+       is not a descriptor, dereference and then test and use the type.
+
+       PR fortran/25597
+       * trans-decl.c (gfc_trans_deferred_vars): Check if an array
+       result, is also automatic character length.  If so, process
+       the character length.
+
+       PR fortran/18803
+       PR fortran/25669
+       PR fortran/26834
+       * trans_intrinsic.c (gfc_walk_intrinsic_bound): Set
+       data.info.dimen for bound intrinsics.
+       * trans_array.c (gfc_conv_ss_startstride): Pick out LBOUND and
+       UBOUND intrinsics and supply their shape information to the ss
+       and the loop.
+
+       PR fortran/27124
+       * trans_expr.c (gfc_trans_function_call):  Add a new block, post,
+       in to which all the argument post blocks are put.  Add this block
+       to se->pre after a byref call or to se->post, otherwise.
+
 2006-04-14  Roger Sayle  <roger@eyesopen.com>
 
        * trans-io.c (set_string): Use fold_build2 and build_int_cst instead
index dfbbed2..5ecc829 100644 (file)
@@ -1863,13 +1863,49 @@ gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
       return FAILURE;
     }
 
-  if (sym->attr.flavor == FL_PROCEDURE && sym->attr.use_assoc)
+/* 12.5.2.2, Note 12.26: The result variable is very similar to any other
+   variable local to a function subprogram.  Its existence begins when
+   execution of the function is initiated and ends when execution of the
+   function is terminated.....
+   Therefore, the left hand side is no longer a varaiable, when it is:*/
+  if (sym->attr.flavor == FL_PROCEDURE
+       && sym->attr.proc != PROC_ST_FUNCTION
+       && !sym->attr.external)
     {
-      gfc_error ("'%s' in the assignment at %L cannot be an l-value "
-                "since it is a procedure", sym->name, &lvalue->where);
-      return FAILURE;
-    }
+      bool bad_proc;
+      bad_proc = false;
+
+      /* (i) Use associated; */
+      if (sym->attr.use_assoc)
+       bad_proc = true;
+
+      /* (ii) The assignement is in the main program; or  */
+      if (gfc_current_ns->proc_name->attr.is_main_program)
+       bad_proc = true;
+
+      /* (iii) A module or internal procedure....  */
+      if ((gfc_current_ns->proc_name->attr.proc == PROC_INTERNAL
+            || gfc_current_ns->proc_name->attr.proc == PROC_MODULE)
+         && gfc_current_ns->parent
+         && (!(gfc_current_ns->parent->proc_name->attr.function
+                 || gfc_current_ns->parent->proc_name->attr.subroutine)
+             || gfc_current_ns->parent->proc_name->attr.is_main_program))
+       {
+         /* .... that is not a function.... */ 
+         if (!gfc_current_ns->proc_name->attr.function)
+           bad_proc = true;
+
+         /* .... or is not an entry and has a different name.  */
+         if (!sym->attr.entry && sym->name != gfc_current_ns->proc_name->name)
+           bad_proc = true;
+       }
 
+      if (bad_proc)
+       {
+         gfc_error ("'%s' at %L is not a VALUE", sym->name, &lvalue->where);
+         return FAILURE;
+       }
+    }
 
   if (rvalue->rank != 0 && lvalue->rank != rvalue->rank)
     {
index 707fe5b..7828922 100644 (file)
@@ -1670,7 +1670,7 @@ add_functions (void)
 
   make_generic ("log10", GFC_ISYM_LOG10, GFC_STD_F77);
 
-  add_sym_2 ("logical", 0, 1, BT_LOGICAL, dl, GFC_STD_F95,
+  add_sym_2 ("logical", 1, 1, BT_LOGICAL, dl, GFC_STD_F95,
             gfc_check_logical, gfc_simplify_logical, gfc_resolve_logical,
             l, BT_LOGICAL, dl, REQUIRED, kind, BT_INTEGER, di, OPTIONAL);
 
index bde11a5..f7acb73 100644 (file)
@@ -952,9 +952,17 @@ resolve_generic_f0 (gfc_expr * expr, gfc_symbol * sym)
        {
          expr->value.function.name = s->name;
          expr->value.function.esym = s;
-         expr->ts = s->ts;
+
+         if (s->ts.type != BT_UNKNOWN)
+           expr->ts = s->ts;
+         else if (s->result != NULL && s->result->ts.type != BT_UNKNOWN)
+           expr->ts = s->result->ts;
+
          if (s->as != NULL)
            expr->rank = s->as->rank;
+         else if (s->result != NULL && s->result->as != NULL)
+           expr->rank = s->result->as->rank;
+
          return MATCH_YES;
        }
 
index 4bdc784..fe8d13c 100644 (file)
@@ -2393,6 +2393,18 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
          loop->dimen = ss->data.info.dimen;
          break;
 
+       /* As usual, lbound and ubound are exceptions!.  */
+       case GFC_SS_INTRINSIC:
+         switch (ss->expr->value.function.isym->generic_id)
+           {
+           case GFC_ISYM_LBOUND:
+           case GFC_ISYM_UBOUND:
+             loop->dimen = ss->data.info.dimen;
+
+           default:
+             break;
+           }
+
        default:
          break;
        }
@@ -2418,6 +2430,17 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
            gfc_conv_section_startstride (loop, ss, n);
          break;
 
+       case GFC_SS_INTRINSIC:
+         switch (ss->expr->value.function.isym->generic_id)
+           {
+           /* Fall through to supply start and stride.  */
+           case GFC_ISYM_LBOUND:
+           case GFC_ISYM_UBOUND:
+             break;
+           default:
+             continue;
+           }
+
        case GFC_SS_CONSTRUCTOR:
        case GFC_SS_FUNCTION:
          for (n = 0; n < ss->data.info.dimen; n++)
@@ -4391,7 +4414,14 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
 
   /* Get the descriptor type.  */
   type = TREE_TYPE (sym->backend_decl);
-  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  if (!GFC_DESCRIPTOR_TYPE_P (type))
+    {
+      /* If the backend_decl is not a descriptor, we must have a pointer
+        to one.  */
+      descriptor = build_fold_indirect_ref (sym->backend_decl);
+      type = TREE_TYPE (descriptor);
+      gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+    }
 
   /* NULLIFY the data pointer.  */
   gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
index 2a9c0db..4efe4bd 100644 (file)
@@ -2536,6 +2536,12 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
        {
          tree result = TREE_VALUE (current_fake_result_decl);
          fnbody = gfc_trans_dummy_array_bias (proc_sym, result, fnbody);
+
+         /* An automatic character length, pointer array result.  */
+         if (proc_sym->ts.type == BT_CHARACTER
+               && TREE_CODE (proc_sym->ts.cl->backend_decl) == VAR_DECL)
+           fnbody = gfc_trans_dummy_character (proc_sym, proc_sym->ts.cl,
+                                               fnbody);
        }
       else if (proc_sym->ts.type == BT_CHARACTER)
        {
index 81e0a7c..4eceab6 100644 (file)
@@ -1832,6 +1832,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
   gfc_charlen cl;
   gfc_expr *e;
   gfc_symbol *fsym;
+  stmtblock_t post;
 
   arglist = NULL_TREE;
   retargs = NULL_TREE;
@@ -1861,6 +1862,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
   else
     info = NULL;
 
+  gfc_init_block (&post);
   gfc_init_interface_mapping (&mapping);
   need_interface_mapping = ((sym->ts.type == BT_CHARACTER
                                  && sym->ts.cl->length
@@ -1970,7 +1972,7 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
        gfc_add_interface_mapping (&mapping, fsym, &parmse);
 
       gfc_add_block_to_block (&se->pre, &parmse.pre);
-      gfc_add_block_to_block (&se->post, &parmse.post);
+      gfc_add_block_to_block (&post, &parmse.post);
 
       /* Character strings are passed as two parameters, a length and a
          pointer.  */
@@ -2177,6 +2179,12 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
        }
     }
 
+  /* Follow the function call with the argument post block.  */
+  if (byref)
+    gfc_add_block_to_block (&se->pre, &post);
+  else
+    gfc_add_block_to_block (&se->post, &post);
+
   return has_alternate_specifier;
 }
 
index b69ffef..1abc79a 100644 (file)
@@ -3710,6 +3710,7 @@ gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr)
   newss->type = GFC_SS_INTRINSIC;
   newss->expr = expr;
   newss->next = ss;
+  newss->data.info.dimen = 1;
 
   return newss;
 }
index f8f2c51..d02f439 100644 (file)
@@ -1,3 +1,25 @@
+2006-04-16  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/26787
+       * gfortran.dg/proc_assign_1.f90: New test.
+       * gfortran.dg/procedure_lvalue.f90: Change message.
+       * gfortran.dg/namelist_4.f90: Add new error.
+
+       PR fortran/25597
+       PR fortran/27096
+       * gfortran.dg/auto_pointer_array_result_1.f90
+
+       PR fortran/27089
+       * gfortran.dg/specification_type_resolution_1.f90
+
+       PR fortran/18803
+       PR fortran/25669
+       PR fortran/26834
+       * gfortran.dg/bounds_temporaries_1.f90: New test.
+
+       PR fortran/27124
+       * gfortran.dg/array_return_value_1.f90: New test.
+
 2006-04-15  Jerry DeLisle <jvdelisle@gcc.gnu.org>
 
        PR fortran/25336
diff --git a/gcc/testsuite/gfortran.dg/array_return_value_1.f90 b/gcc/testsuite/gfortran.dg/array_return_value_1.f90
new file mode 100644 (file)
index 0000000..45699ff
--- /dev/null
@@ -0,0 +1,24 @@
+! { dg-do run }
+! Tests the fix for PR27124 in which the unpacking of argument
+! temporaries and of array result temporaries occurred in the
+! incorrect order.
+! 
+! Test is based on the original example, provided by
+! Philippe Schaffnit <P.Schaffnit@access.rwth-aachen.de>
+!
+  PROGRAM Test
+    INTEGER :: Array(2, 3) = reshape ((/1,4,2,5,3,6/),(/2,3/))
+    integer :: Brray(2, 3) = 0
+    Brray(1,:) = Function_Test (Array(1,:))
+    if (any(reshape (Brray, (/6/)) .ne. (/11, 0, 12, 0, 13, 0/))) call abort ()
+    Array(1,:) = Function_Test (Array(1,:))
+    if (any(reshape (Array, (/6/)) .ne. (/11, 4, 12, 5, 13, 6/))) call abort ()
+
+  contains
+      FUNCTION Function_Test (Input)
+          INTEGER, INTENT(IN) :: Input(1:3)
+          INTEGER :: Function_Test(1:3)
+          Function_Test = Input + 10
+      END FUNCTION Function_Test
+  END PROGRAM Test
+
diff --git a/gcc/testsuite/gfortran.dg/auto_char_pointer_array_result_1.f90 b/gcc/testsuite/gfortran.dg/auto_char_pointer_array_result_1.f90
new file mode 100644 (file)
index 0000000..8e3eb94
--- /dev/null
@@ -0,0 +1,36 @@
+! { dg-do run }
+! Tests the fixes for PR25597 and PR27096.
+!
+! This test combines the PR testcases.
+!
+  character(10), dimension (2) :: implicit_result
+  character(10), dimension (2) :: explicit_result
+  character(10), dimension (2) :: source
+  source = "abcdefghij"
+  explicit_result = join_1(source)
+  if (any (explicit_result .ne. source)) call abort () 
+
+  implicit_result = reallocate_hnv (source, size(source, 1), LEN (source))
+  if (any (implicit_result .ne. source)) call abort () 
+
+contains
+
+! This function would cause an ICE in gfc_trans_deferred_array.
+  function join_1(self) result(res)
+    character(len=*), dimension(:) :: self
+    character(len=len(self)), dimension(:), pointer :: res
+    allocate (res(2))
+    res = self
+  end function
+
+! This function originally ICEd and latterly caused a runtime error.
+  FUNCTION reallocate_hnv(p, n, LEN)
+    CHARACTER(LEN=LEN), DIMENSION(:), POINTER :: reallocate_hnv
+    character(*), dimension(:) :: p
+    ALLOCATE (reallocate_hnv(n))
+    reallocate_hnv = p
+  END FUNCTION reallocate_hnv
+
+end
+
diff --git a/gcc/testsuite/gfortran.dg/auto_pointer_array_result_1.f90 b/gcc/testsuite/gfortran.dg/auto_pointer_array_result_1.f90
new file mode 100644 (file)
index 0000000..7e7cde5
--- /dev/null
@@ -0,0 +1,36 @@
+! { dg-do run }
+! Tests the fixes for PR25597 and PR27096.
+!
+! This test combines the PR testcases.
+!
+  character(10), dimension (2) :: implicit_result
+  character(10), dimension (2) :: explicit_result
+  character(10), dimension (2) :: source
+  source = "abcdefghij"
+  explicit_result = join_1(source)
+  if (any (explicit_result .ne. source)) call abort () 
+
+  implicit_result = reallocate_hnv (source, size(source, 1), LEN (source))
+  if (any (implicit_result .ne. source)) call abort () 
+
+contains
+
+! This function would cause an ICE in gfc_trans_deferred_array.
+  function join_1(self) result(res)
+    character(len=*), dimension(:) :: self
+    character(len=len(self)), dimension(:), pointer :: res
+    allocate (res(2))
+    res = self
+  end function
+
+! This function originally ICEd and latterly caused a runtime error.
+  FUNCTION reallocate_hnv(p, n, LEN)
+    CHARACTER(LEN=LEN), DIMENSION(:), POINTER :: reallocate_hnv
+    character(*), dimension(:) :: p
+    ALLOCATE (reallocate_hnv(n))
+    reallocate_hnv = p
+  END FUNCTION reallocate_hnv
+
+end
+
+
diff --git a/gcc/testsuite/gfortran.dg/bounds_temporaries_1.f90 b/gcc/testsuite/gfortran.dg/bounds_temporaries_1.f90
new file mode 100644 (file)
index 0000000..a277566
--- /dev/null
@@ -0,0 +1,64 @@
+! { dg-do compile }
+! This tests the fix for PRs 26834, 25669 and 18803, in which
+! shape information for the lbound and ubound intrinsics was not
+! transferred to the scalarizer.  For this reason, an ICE would
+! ensue, whenever these functions were used in temporaries.
+!
+! The tests are lifted from the PRs and some further checks are
+! done to make sure that nothing is broken.
+!
+! This is PR26834
+subroutine gfcbug34 ()
+  implicit none
+  type t
+     integer, pointer :: i (:) => NULL ()
+  end type t
+  type(t), save :: gf
+  allocate (gf%i(20))
+  write(*,*) 'ubound:', ubound (gf% i)
+  write(*,*) 'lbound:', lbound (gf% i)
+end subroutine gfcbug34
+
+! This is PR25669
+subroutine foo (a)
+  real a(*)
+  call bar (a, LBOUND(a),2)
+end subroutine foo
+subroutine bar (b, i, j)
+  real b(i:j)
+  print *, i, j
+  print *, b(i:j)
+end subroutine bar
+
+! This is PR18003
+subroutine io_bug()
+  integer :: a(10)
+  print *, ubound(a)
+end subroutine io_bug
+
+! This checks that lbound and ubound are OK in  temporary
+! expressions.
+subroutine io_bug_plus()
+  integer :: a(10, 10), b(2)
+  print *, ubound(a)*(/1,2/)
+  print *, (/1,2/)*ubound(a)
+end subroutine io_bug_plus
+
+  character(4) :: ch(2), ech(2) = (/'ABCD', 'EFGH'/)
+  real(4) :: a(2)
+  equivalence (ech,a)  ! { dg-warning "default CHARACTER EQUIVALENCE statement" }
+  integer(1) :: i(8) = (/(j, j = 1,8)/)
+
+! Check that the bugs have gone
+  call io_bug ()
+  call io_bug_plus ()
+  call foo ((/1.0,2.0,3.0/))
+  call gfcbug34 ()
+
+! Check that we have not broken other intrinsics.
+  print *, cos ((/1.0,2.0/))
+  print *, transfer (a, ch)
+  print *, i(1:4) * transfer (a, i, 4) * 2
+end
+
+
index 9e62a1f..52a5bc9 100644 (file)
@@ -28,8 +28,9 @@ program P1
 CONTAINS\r
 ! This has the additional wrinkle of a reference to the object.\r
   INTEGER FUNCTION F1()\r
-    NAMELIST /NML3/ F2 ! { dg-error "PROCEDURE attribute conflicts" }\r
-    f2 = 1     ! Used to ICE here\r
+    NAMELIST /NML3/ F2 ! { dg-error "PROCEDURE attribute conflicts" }
+! Used to ICE here\r
+    f2 = 1             ! { dg-error "is not a VALUE" }\r
     F1=1\r
   END FUNCTION\r
   INTEGER FUNCTION F2()\r
diff --git a/gcc/testsuite/gfortran.dg/proc_assign_1.f90 b/gcc/testsuite/gfortran.dg/proc_assign_1.f90
new file mode 100644 (file)
index 0000000..a0f7250
--- /dev/null
@@ -0,0 +1,78 @@
+! { dg-do compile }\r
+! This tests the patch for PR26787 in which it was found that setting\r
+! the result of one module procedure from within another produced an\r
+! ICE rather than an error.\r
+!\r
+! This is an "elaborated" version of the original testcase from\r
+! Joshua Cogliati  <jjcogliati-r1@yahoo.com>\r
+!\r
+function ext1 ()\r
+    integer ext1, ext2, arg\r
+    ext1 = 1\r
+    entry ext2 (arg)\r
+    ext2 = arg\r
+contains\r
+    subroutine int_1 ()\r
+        ext1 = arg * arg     ! OK - host associated.\r
+    end subroutine int_1\r
+end function ext1\r
+\r
+module simple\r
+    implicit none\r
+contains\r
+    integer function foo () \r
+         foo = 10            ! OK - function result\r
+         call foobar ()\r
+    contains\r
+        subroutine foobar ()\r
+            integer z\r
+            foo = 20         ! OK - host associated.\r
+        end subroutine foobar\r
+    end function foo\r
+    subroutine bar()         ! This was the original bug.\r
+        foo = 10             ! { dg-error "is not a VALUE" }\r
+    end subroutine bar\r
+    integer function oh_no ()\r
+        oh_no = 1\r
+        foo = 5              ! { dg-error "is not a VALUE" }\r
+    end function oh_no\r
+end module simple\r
+\r
+module simpler\r
+    implicit none\r
+contains\r
+    integer function foo_er () \r
+         foo_er = 10         ! OK - function result\r
+    end function foo_er\r
+end module simpler\r
+\r
+    use simpler\r
+    real w, stmt_fcn\r
+    interface\r
+       function ext1 ()\r
+           integer ext1\r
+       end function ext1\r
+       function ext2 (arg)\r
+           integer ext2, arg\r
+       end function ext2\r
+    end interface\r
+    stmt_fcn (w) = sin (w)     \r
+    call x (y ())\r
+    x = 10                   ! { dg-error "Expected VARIABLE" }\r
+    y = 20                   ! { dg-error "is not a VALUE" }\r
+    foo_er = 8               ! { dg-error "is not a VALUE" }\r
+    ext1 = 99                ! { dg-error "is not a VALUE" }\r
+    ext2 = 99                ! { dg-error "is not a VALUE" }\r
+    stmt_fcn = 1.0           ! { dg-error "Expected VARIABLE" }\r
+    w = stmt_fcn (1.0)\r
+contains\r
+    subroutine x (i)\r
+        integer i\r
+        y = i                ! { dg-error "is not a VALUE" }\r
+    end subroutine x\r
+    function y ()\r
+        integer y\r
+        y = 2                ! OK - function result\r
+    end function y\r
+end\r
+! { dg-final { cleanup-modules "simple simpler" } }
\ No newline at end of file
index 2a2c355..634eaca 100644 (file)
@@ -14,7 +14,7 @@ end module t
 
 subroutine r
   use t
-  b = 1.       ! { dg-error "l-value since it is a procedure" }
+  b = 1.       ! { dg-error "is not a VALUE" }
   y = a(1.)
 end subroutine r
 
diff --git a/gcc/testsuite/gfortran.dg/specification_type_resolution_1.f90 b/gcc/testsuite/gfortran.dg/specification_type_resolution_1.f90
new file mode 100644 (file)
index 0000000..b830b5d
--- /dev/null
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! Test of the fix of PR27089, where gfortran was unable to resolve the
+! type of n_elements_uncommon_with_ in the specification expression on
+! line 21.
+!
+! Test extracted from vec{int}.F90 of tonto.
+!
+module test
+   public    n_elements_uncommon_with_
+   interface n_elements_uncommon_with_
+      module procedure n_elements_uncommon_with
+   end interface
+contains
+   pure function n_elements_uncommon_with(x) result(res)
+      integer(4), dimension(:), intent(in) :: x
+      integer(4) :: res
+      res = size (x, 1)
+   end function
+   pure function elements_uncommon_with(x) result(res)
+      integer(4), dimension(:), intent(in) :: x
+      integer(4), dimension(n_elements_uncommon_with_(x)) :: res
+      res = x
+   end function
+end module test
+   use test
+   integer(4) :: z(4)
+   z = 1
+   print *, elements_uncommon_with (z)
+   print *, n_elements_uncommon_with_ (z)
+end
+! { dg-final { cleanup-modules "test" } }