All, Another quirk of legacy compilers is their syntax for PARAMETER statements. Such statements are similar to standard PARAMETER statements but lack parentheses following the PARAMETER keyword. There is a good reason the standard doesn't support this - because the statement becomes ambiguous with assignment statements in fixed form. Consider the following:
parameter pi = 3.14d0 In fixed form, spaces are ignored so in standard Fortran the above looks like an assignment to the variable "parameterpi". In legacy compilers, the above is instead interpreted as parameter (pi = 3.14d0) which of course declares the variable 'pi' to be a parameter with the value 3.14. Attached is a patch for the GNU Fortran front-end which allows the compiler to interpret these legacy PARAMETER statements. The patch in its current form does this without warning through -std=legacy (warning for -std=gnu, error for -std=f*). Bootstraps and regtests on x86_64-redhat-linux. However, note that this would change by default the compiler's interpretation of fixed-form variables starting with the string "parameter", if any such cases existed in real code. IMO fixed form code is isomorphic to legacy code, so I imagine most users writing fixed-form/legacy code would intend for a legacy PARAMETER statement, rather than assignment to variable PARAMETERPI, when writing such a statement. Beyond compatibility, one motivation for acceptance/recognizance of these statements in GNU Fortran is the counterintuitive compile errors currently seen when compiling legacy code which uses this type of statement. Because the legacy PARAMETER statement is currently interpreted as an assignment in fixed-form, and parameter statements often precede other specification statements in real code, GNU Fortran complains not about the parameter statement itself but often the following line with "Unexpected data declaration" or similar. This serves to confuse the user. An example of this can be seen by compiling the attached dec_parameter_1.f in fixed form with the current build of GNU Fortran. I am amenable to only enabling support for legacy PARAMETER statements through -fdec, so that the default (-std=gnu) behavior is unchanged for such cases in fixed form. But this would leave the esoteric "Unexpected data declaration statement" errors for legacy code without -fdec. The case would be difficult to detect and work around specifically since the entire parameter "assignment" statement is eaten by the time the error comes about. What do you think? --- Fritz Reese Author: Fritz O. Reese <fritzore...@gmail.com> Date: Tue Nov 1 12:26:57 2016 -0400 Support legacy PARAMETER statements with -std=legacy. gcc/fortran/ * decl.c (gfc_match_parameter): Allow omitted '()' with -std=legacy. * parse.c (decode_statement): Match "parmeter" before assignments. * gfortran.texi: Document. gcc/testsuite/gfortran.dg/ * dec_parameter_1.f: New test. * dec_parameter_2.f90: Likewise. * dec_parameter_3.f90: Likewise. * dec_parameter_4.f90: Likewise. gcc/fortran/decl.c | 10 +++- gcc/fortran/gfortran.texi | 16 ++++++ gcc/fortran/parse.c | 4 +- gcc/testsuite/gfortran.dg/dec_parameter_1.f | 64 +++++++++++++++++++++++++ gcc/testsuite/gfortran.dg/dec_parameter_2.f90 | 63 ++++++++++++++++++++++++ gcc/testsuite/gfortran.dg/dec_parameter_3.f90 | 13 +++++ gcc/testsuite/gfortran.dg/dec_parameter_4.f90 | 13 +++++ 7 files changed, 180 insertions(+), 3 deletions(-)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index f18eb41..0120ceb 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -7821,10 +7821,16 @@ cleanup: match gfc_match_parameter (void) { + const char *term = " )%t"; match m; if (gfc_match_char ('(') == MATCH_NO) - return MATCH_NO; + { + /* With legacy PARAMETER statements, don't expect a terminating ')'. */ + if (!gfc_notify_std (GFC_STD_LEGACY, "PARAMETER without '()' at %C")) + return MATCH_NO; + term = " %t"; + } for (;;) { @@ -7832,7 +7838,7 @@ gfc_match_parameter (void) if (m != MATCH_YES) break; - if (gfc_match (" )%t") == MATCH_YES) + if (gfc_match (term) == MATCH_YES) break; if (gfc_match_char (',') != MATCH_YES) diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 85ab31b..1d60551 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -1472,6 +1472,7 @@ compatibility extensions along with those enabled by @option{-std=legacy}. * Bitwise logical operators:: * Extended I/O specifiers:: * Default exponents:: +* Legacy PARAMETER statements:: @end menu @node Old-style kind specifications @@ -2705,6 +2706,21 @@ For compatibility, GNU Fortran supports a default exponent of zero in real constants with @option{-fdec}. For example, @code{9e} would be interpreted as @code{9e0}, rather than an error. +@node Legacy PARAMETER statements +@subsection Legacy PARAMETER statements +@cindex PARAMETER + +For compatibility, GNU Fortran supports legacy PARAMETER statements without +parentheses with @option{-std=legacy}. A warning is emitted if used with +@option{-std=gnu}, and an error is acknowledged with a real Fortran standard +flag (@option{-std=f95}, etc...). These statements take the following form: + +@smallexample +implicit real (E) +parameter e = 2.718282 +real c +parameter c = 3.0e8 +@end smallexample @node Extensions not implemented in GNU Fortran @section Extensions not implemented in GNU Fortran diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 2aa2afc..0ee054a 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -352,6 +352,9 @@ decode_statement (void) } gfc_matching_function = false; + /* Legacy parameter statements are ambiguous with assignments so try parameter + first. */ + match ("parameter", gfc_match_parameter, ST_PARAMETER); /* Match statements whose error messages are meant to be overwritten by something better. */ @@ -528,7 +531,6 @@ decode_statement (void) case 'p': match ("print", gfc_match_print, ST_WRITE); - match ("parameter", gfc_match_parameter, ST_PARAMETER); match ("pause", gfc_match_pause, ST_PAUSE); match ("pointer", gfc_match_pointer, ST_ATTR_DECL); if (gfc_match_private (&st) == MATCH_YES) diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_1.f b/gcc/testsuite/gfortran.dg/dec_parameter_1.f new file mode 100644 index 0000000..69ffa53 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dec_parameter_1.f @@ -0,0 +1,64 @@ + ! { dg-do run } + ! { dg-options "-ffixed-form -std=legacy" } + ! + ! Test DEC-style PARAMETER statements without parentheses in + ! fixed form. + ! + + subroutine sub1(t, x, y) + implicit real(8) (A-H,O-Z) + parameter (pi_1 = 3.141592654d0, f_1 = 3.d08) + parameter pi_2 = 3.141592654d0, f_2 = 3.d08 + ! Note that if the parameter statements above are matched + ! incorrectly as assignments, the below specification + ! statements will be considered out-of-order and we see + ! 'unexpected specification statement'. A PARAMETER + ! statement should still be a specification statement. + + real(8), intent(in) :: t + real(8), intent(out) :: x, y + + real(8), volatile :: two + two = 2.0d0 + x = two * pi_1 * f_1 * t + y = two * pi_2 * f_2 * t + z = two * pi_3 * f_3 * t + return + end subroutine + + subroutine sub2(t, x, y, z) + implicit none + real(8) :: pi_1, pi_2, f_1, f_2 + parameter (pi_1 = 3.141592654d0, f_1 = 3.d08) + parameter pi_2 = 3.141592654d0, f_2 = 3.d08 + real(8), parameter :: pi_3 = 3.141592654d0, f_3 = 3.d08 + ! Ditto sub1 + + real(8), intent(in) :: t + real(8), intent(out) :: x, y, z + + real(8), volatile :: two + two = 2.0d0 + x = two * pi_1 * f_1 * t + y = two * pi_2 * f_2 * t + z = two * pi_3 * f_3 * t + end subroutine + + implicit none + real(8) :: x1, x2, y1, y2, z2 + real(8), volatile :: t + t = 1.5e-6 + + call sub1(t, x1, y1) + call sub2(t, x2, y2, z2) + + write(*,'(4D18.5)') t, x1, y1 + write(*,'(4D18.5)') t, x2, y2, z2 + + if (x1 .ne. x2 .or. y1 .ne. y2 + & .or. x1 .ne. y1 .or. x2 .ne. y2 + & .or. y2 .ne. z2) then + call abort() + endif + + end diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_2.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_2.f90 new file mode 100644 index 0000000..280f000 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dec_parameter_2.f90 @@ -0,0 +1,63 @@ +! { dg-do run } +! { dg-options "-ffree-form -std=legacy" } +! +! Test DEC-style PARAMETER statements without parentheses in free form. +! + +subroutine sub1(t, x, y) + implicit real(8) (A-H,O-Z) + parameter (pi_1 = 3.141592654d0, f_1 = 3.d08) + parameter pi_2 = 3.141592654d0, f_2 = 3.d08 ! legacy PARAMETER + ! Note that if the parameter statements above are matched + ! incorrectly as assignments, the below specification + ! statements will be considered out-of-order and we see + ! 'unexpected specification statement'. A PARAMETER + ! statement should still be a specification statement. + + real(8), intent(in) :: t + real(8), intent(out) :: x, y + + real(8), volatile :: two + two = 2.0d0 + x = two * pi_1 * f_1 * t + y = two * pi_2 * f_2 * t + z = two * pi_3 * f_3 * t + return +end subroutine + +subroutine sub2(t, x, y, z) + implicit none + real(8) :: pi_1, pi_2, f_1, f_2 + parameter (pi_1 = 3.141592654d0, f_1 = 3.d08) + parameter pi_2 = 3.141592654d0, f_2 = 3.d08 ! legacy PARAMETER + real(8), parameter :: pi_3 = 3.141592654d0, f_3 = 3.d08 + ! Ditto sub1 + + real(8), intent(in) :: t + real(8), intent(out) :: x, y, z + + real(8), volatile :: two + two = 2.0d0 + x = two * pi_1 * f_1 * t + y = two * pi_2 * f_2 * t + z = two * pi_3 * f_3 * t +end subroutine + +implicit none +real(8) :: x1, x2, y1, y2, z2 +real(8), volatile :: t +t = 1.5e-6 + +call sub1(t, x1, y1) +call sub2(t, x2, y2, z2) + +write(*,'(4D18.5)') t, x1, y1 +write(*,'(4D18.5)') t, x2, y2, z2 + +if (x1 .ne. x2 .or. y1 .ne. y2 & + .or. x1 .ne. y1 .or. x2 .ne. y2 & + .or. y2 .ne. z2) then + call abort() +endif + +end diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_3.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_3.f90 new file mode 100644 index 0000000..92f0f61 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dec_parameter_3.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-options "-ffree-form -std=gnu" } +! +! Test warnings for DEC-style PARAMETER statements with std=gnu. +! + +subroutine sub() + implicit real(8) (A-Z) + parameter pi = 3.1415926535d0 ! { dg-warning "Legacy Extension: PARAMETER" } + print *, pi +end subroutine + +end diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_4.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_4.f90 new file mode 100644 index 0000000..280d56c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dec_parameter_4.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-options "-ffree-form -std=f95" } +! +! Test errors for DEC-style PARAMETER statements with a real standard. +! + +subroutine sub() + implicit real(8) (A-Z) + parameter pi = 3.1415926535d0 ! { dg-error "Legacy Extension: PARAMETER" } + print *, pi +end subroutine + +end