Bug 47399

Summary: [OOP] ICE with TBP of a PARAMETER
Product: gcc Reporter: Tobias Burnus <burnus>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: janus
Priority: P3 Keywords: ice-on-valid-code
Version: 4.6.0   
Target Milestone: 4.7.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2012-01-28 00:00:00

Description Tobias Burnus 2011-01-21 15:08:45 UTC
Found by Wolfgang Kilian, cf http://groups.google.com/group/comp.lang.fortran/msg/e6a865eda59e86db (Whole c.l.f thread: http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/69220fdd4c2715c0 )

The following program ICEs for variant #3, where one uses a TBP of a PARAMETER.

The variants #1 and #2 compile with -std=f2003/f2008/gnu and print "13". Variant #1 with the TBP comment out compiles also with -std=f95.


The ICE is by definition wrong. I have not checked whether the program is valid or not. My feeling is that variant #1 (with TBP comment) is at least invalid in -std=f95, but I might be wrong.

Ifort fails with: "An automatic object is invalid in a main program." If this is not changed and applies here, one should check for it using a subroutine and not a main program. -- If one does so, ifort compiles #1 and #3 but rejects #2. NAG v5.1 does the same for the subroutine version.
gfortran behaves identical for program and subroutine.


TODO:
a) Fix ICE
b) Check whether the code is valid Fortran 2008
c) Check whether some diagnostic is needed for Fortran 95/2003/2008
d) Do (b) and (c) for program replaced by subroutine.


The ICE is:

test.f90:19:0: internal compiler error: in gfc_match_varspec, at fortran/primary.c:1846



module mytypes
   implicit none
   private
   public :: mytype, get_i

   integer, save :: i_priv = 13

   type :: mytype
      integer :: dummy
    contains
      procedure, nopass :: i => get_i
   end type mytype

 contains

   pure function get_i () result (i)
     integer :: i
     i = i_priv
   end function get_i

end module mytypes

program test
   use mytypes
   implicit none

   type(mytype) :: a
   type(mytype), parameter :: a_const = mytype (0)

!   integer, dimension (get_i()) :: x            ! #1
!   integer, dimension (a%i()) :: x              ! #2
   integer, dimension (a_const%i()) :: x        ! #3

   print *, size (x)
end program test
Comment 1 Tobias Burnus 2011-01-21 20:31:30 UTC
The ICE is due to an overly eager ASSERT check and can be removed with the following patch. 

TODO: A proper check with an error message for the invalid case.

--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1844,5 +1844,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
 
          gcc_assert (!tail || !tail->next);
-         gcc_assert (primary->expr_type == EXPR_VARIABLE);
+         gcc_assert (primary->expr_type == EXPR_VARIABLE
+                     || (primary->expr_type == EXPR_STRUCTURE
+                         && primary->symtree && primary->symtree->n.sym
+                         && primary->symtree->n.sym->attr.flavor));
 
          if (tbp->n.tb->is_generic)
Comment 2 Tobias Burnus 2011-01-22 00:06:43 UTC
In Fortran 2003 the constraint was:

"C1103 (R1101) An automatic object shall not appear in the specification-part (R204) of a main program."

"C1106 (R1104) An automatic object shall not appear in the specification-part of a module."


In Fortran 2008 the same exists - but a bit more subtle:

"C513 An automatic object shall not have the SAVE attribute."

And "5.3.16 SAVE attribute" has: "A variable, common block, or procedure pointer declared in the scoping unit of a main program, module, or submodule implicitly has the SAVE attribute, which may be conrmed by explicit specification."


Except for the less-helpful wording in case of character lengths ("must have constant character length in this context" [which context?]) the checks exist.For strings it seems to work, for arrays the call to is_non_constant_shape_array in resolve_fl_variable does not seem to work.


The reason is: resolve_index_expr checks for:

  if (gfc_specification_expr (e) == FAILURE)
    return FAILURE;

The problem is: We do have a specification expression, but not an initialization expression.

We run -- again -- into the following issue in gfc_is_constant_expr:

      /* Specification functions are constant.  */
      /* F95, 7.1.6.2; F2003, 7.1.7  */
      if (sym
          && sym->attr.function
          && sym->attr.pure
          && !sym->attr.intrinsic
          && !sym->attr.recursive
          && sym->attr.proc != PROC_INTERNAL
          && sym->attr.proc != PROC_ST_FUNCTION
          && sym->attr.proc != PROC_UNKNOWN
          && sym->formal == NULL)
        return 1;

There are more bugs of this kind.

Fortran 2008 defines:

"7.1.11 Specication expression"
* "specification expression is an expression with limitations that make it suitable for use in specications such as length type parameters (C404) and array bounds (R517, R518). [...]"
* "A restricted expression is an expression in which each operation is intrinsic or dened by a specication function and [...]"

"7.1.12 Constant expression"
"A constant expression is an expression with limitations that make it suitable for use as a kind type parameter, initializer, or named constant. [...]"

Fortran 2003 uses:

"7.1.6 Specification expression"
* "A specification expression is an expression with limitations that make it suitable for use in specifications such as length type parameters (C501) and array bounds (R512, R513)."
* "A restricted expression is an expression in which each operation is intrinsic and [...]"
"7.1.7 Initialization expression
An initialization expression is an expression with limitations that make it suitable for use as a kind type parameter, initializer, or named constant."

Fortran 95 used the terms:

"7.1.6.2 Specification expression"
"A specification expression is an expression with limitations that make it suitable for use in specifications such as character lengths (R510) and array bounds (R515, R516). A constant specification expression is a specification expression that is also a constant expression."
"A restricted expression is an expression in which each operation is intrinsic and ..."

"7.1.6.1 Constant expression"
"A constant expression is an expression in which each operation is intrinsic and ..."
"An initialization expression is a constant expression in which the exponentiation operation is permitted only with an integer power, and ..."


Thus:
      /* Specification functions are constant.  */
      /* F95, 7.1.6.2; F2003, 7.1.7  */

Is nonsense. In the Fortran 2008 sense constant means that it can be simplified at compile time to a constant (a number, a string literal, ...). In the Fortran 2003 sense, that's an initialization expression ("constant expression" does not exist). While also in the Fortran 95 sense a "constant expression" is something where a number can be returned. That's given in 7.1.6.2 while 7.1.6.2 is about "specification expressions", "constant specification expressions" and "restricted expressions".

 * * *

Thus, the proper change is to simply delete that invalid part. The only catch is: That will cause problems with sections of gfortran which call gfc_constant_expr but do not want to have a constant expression but a specification expression!

There was some PR before: Namely PR 44962, cf. http://gcc.gnu.org/ml/fortran/2010-07/msg00285.html
Comment 3 Tobias Burnus 2011-01-22 13:50:28 UTC
Author: burnus
Date: Sat Jan 22 13:50:25 2011
New Revision: 169126

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=169126
Log:
2011-01-22  Tobias Burnus  <burnus@net-b.de>

        PR fortran/47399
        * primary.c (gfc_match_varspec): Relax gcc_assert to allow for
        PARAMETER TBP.

2011-01-22  Tobias Burnus  <burnus@net-b.de>

        PR fortran/47399
        * gfortran.dg/typebound_proc_19.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/typebound_proc_19.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/primary.c
    trunk/gcc/testsuite/ChangeLog
Comment 4 Tobias Burnus 2011-01-22 19:22:46 UTC
The ICE is fixed (cf. comment 1), but the issue of comment 2 (spec-expr vs. init/constant-expr) still exists; for this PR itself, the issue is about the missing diagnostic for automatic objects in PROGRAM and MODULE declarations.

Steve pointed out on fortran@gcc that at least the following PRs are related:
PR 25095, PR 25104, PR 29962, PR 31292, PR 31560, PR 31592, PR 32365, PR 34663, PR 35040, and PR 38822.
Comment 5 Tobias Burnus 2011-12-12 08:07:23 UTC
Since the commit for PR 41539, the example(s) of comment 0 (#1, #2, #3) compile and print "13" at run time.

TODO: Check whether we now allow invalid code. Check the c.l.f thread.
Comment 6 Dominique d'Humieres 2012-01-28 20:33:33 UTC
> TODO: Check whether we now allow invalid code. Check the c.l.f thread.

I have had a look at the thread, and it seems that NAG is complaining for the test in comment #0. For those who have access to it (and other compilers), is it still true? 

Note that the test and some avatars compile with -std=f2003.
Comment 7 Dominique d'Humieres 2013-09-01 14:38:37 UTC
One year and a half, I asked:

> > TODO: Check whether we now allow invalid code. Check the c.l.f thread.
>
> I have had a look at the thread, and it seems that NAG is complaining 
> for the test in comment #0. For those who have access to it (and other
> compilers), is it still true? 
>
> Note that the test and some avatars compile with -std=f2003.

Should not this PR closed as FIXED?
Comment 8 Dominique d'Humieres 2013-12-14 20:17:07 UTC
No feedback since three months. Closing as FIXED. Please open a new PR if
I have missed any remaining issue.