decl.c (gfc_match_implicit_range): Don't use typespec.

* decl.c (gfc_match_implicit_range): Don't use typespec.
	(gfc_match_implicit): Handle character selectors.
	* gfortran.h (gfc_set_implicit): Remove prototype.
	(gfc_add_new_implicit_range, gfc_merge_new_implicit): Update.
	* parse.c (accept_statement): Don't call gfc_set_implicit.
	* symbol.c (new_ts): Remove.
	(gfc_set_implicit_none): Use same loop bounds as other functions.
	(gfc_set_implicit): Remove.
	(gfc_clear_new_implicit, gfc_add_new_implicit_range): Only set flags.
	(gfc_merge_new_implicit): Combine with gfc_set_implicit.
testsuite/
	* gfortran.fortran-torture/compile/implicit_1.f90: New test.

From-SVN: r84063
This commit is contained in:
Paul Brook 2004-07-03 23:25:46 +00:00
parent 614ed70a59
commit 1107b970c6
7 changed files with 127 additions and 86 deletions

View File

@ -1,3 +1,16 @@
2004-07-04 Paul Brook <paul@codesourcery.com>
* decl.c (gfc_match_implicit_range): Don't use typespec.
(gfc_match_implicit): Handle character selectors.
* gfortran.h (gfc_set_implicit): Remove prototype.
(gfc_add_new_implicit_range, gfc_merge_new_implicit): Update.
* parse.c (accept_statement): Don't call gfc_set_implicit.
* symbol.c (new_ts): Remove.
(gfc_set_implicit_none): Use same loop bounds as other functions.
(gfc_set_implicit): Remove.
(gfc_clear_new_implicit, gfc_add_new_implicit_range): Only set flags.
(gfc_merge_new_implicit): Combine with gfc_set_implicit.
2004-06-30 Richard Henderson <rth@redhat.com> 2004-06-30 Richard Henderson <rth@redhat.com>
* match.c (var_element): Remove unused variable. * match.c (var_element): Remove unused variable.

View File

@ -1001,7 +1001,7 @@ gfc_match_implicit_none (void)
/* Match the letter range(s) of an IMPLICIT statement. */ /* Match the letter range(s) of an IMPLICIT statement. */
static match static match
match_implicit_range (gfc_typespec * ts) match_implicit_range (void)
{ {
int c, c1, c2, inner; int c, c1, c2, inner;
locus cur_loc; locus cur_loc;
@ -1068,7 +1068,7 @@ match_implicit_range (gfc_typespec * ts)
conflicts with whatever earlier IMPLICIT statements may have conflicts with whatever earlier IMPLICIT statements may have
set. This is done when we've successfully finished matching set. This is done when we've successfully finished matching
the current one. */ the current one. */
if (gfc_add_new_implicit_range (c1, c2, ts) != SUCCESS) if (gfc_add_new_implicit_range (c1, c2) != SUCCESS)
goto bad; goto bad;
} }
@ -1116,11 +1116,11 @@ gfc_match_implicit (void)
return MATCH_ERROR; return MATCH_ERROR;
} }
/* First cleanup. */
gfc_clear_new_implicit ();
do do
{ {
/* First cleanup. */
gfc_clear_new_implicit ();
/* A basic type is mandatory here. */ /* A basic type is mandatory here. */
m = match_type_spec (&ts, 1); m = match_type_spec (&ts, 1);
if (m == MATCH_ERROR) if (m == MATCH_ERROR)
@ -1129,39 +1129,56 @@ gfc_match_implicit (void)
goto syntax; goto syntax;
cur_loc = gfc_current_locus; cur_loc = gfc_current_locus;
m = match_implicit_range (&ts); m = match_implicit_range ();
if (m != MATCH_YES && ts.type == BT_CHARACTER)
{
/* looks like we are matching CHARACTER (<len>) (<range>) */
m = match_char_spec (&ts);
}
if (m == MATCH_YES) if (m == MATCH_YES)
{ {
/* Looks like we have the <TYPE> (<RANGE>). */ /* We may have <TYPE> (<RANGE>). */
gfc_gobble_whitespace (); gfc_gobble_whitespace ();
c = gfc_next_char (); c = gfc_next_char ();
if ((c == '\n') || (c == ',')) if ((c == '\n') || (c == ','))
continue; {
/* Check for CHARACTER with no length parameter. */
if (ts.type == BT_CHARACTER && !ts.cl)
{
ts.kind = gfc_default_character_kind ();
ts.cl = gfc_get_charlen ();
ts.cl->next = gfc_current_ns->cl_list;
gfc_current_ns->cl_list = ts.cl;
ts.cl->length = gfc_int_expr (1);
}
/* Record the Successful match. */
if (gfc_merge_new_implicit (&ts) != SUCCESS)
return MATCH_ERROR;
continue;
}
gfc_current_locus = cur_loc; gfc_current_locus = cur_loc;
} }
/* Last chance -- check <TYPE> (<KIND>) (<RANGE>). */ /* Discard the (incorrectly) matched range. */
m = gfc_match_kind_spec (&ts); gfc_clear_new_implicit ();
/* Last chance -- check <TYPE> <SELECTOR> (<RANGE>). */
if (ts.type == BT_CHARACTER)
m = match_char_spec (&ts);
else
{
m = gfc_match_kind_spec (&ts);
if (m == MATCH_NO)
{
m = gfc_match_old_kind_spec (&ts);
if (m == MATCH_ERROR)
goto error;
if (m == MATCH_NO)
goto syntax;
}
}
if (m == MATCH_ERROR) if (m == MATCH_ERROR)
goto error; goto error;
if (m == MATCH_NO)
{
m = gfc_match_old_kind_spec (&ts);
if (m == MATCH_ERROR)
goto error;
if (m == MATCH_NO)
goto syntax;
}
m = match_implicit_range (&ts); m = match_implicit_range ();
if (m == MATCH_ERROR) if (m == MATCH_ERROR)
goto error; goto error;
if (m == MATCH_NO) if (m == MATCH_NO)
@ -1172,14 +1189,12 @@ gfc_match_implicit (void)
if ((c != '\n') && (c != ',')) if ((c != '\n') && (c != ','))
goto syntax; goto syntax;
if (gfc_merge_new_implicit (&ts) != SUCCESS)
return MATCH_ERROR;
} }
while (c == ','); while (c == ',');
/* All we need to now is try to merge the new implicit types back return MATCH_YES;
into the existing types. This will fail if another implicit
type is already defined for a letter. */
return (gfc_merge_new_implicit () == SUCCESS) ?
MATCH_YES : MATCH_ERROR;
syntax: syntax:
gfc_syntax_error (ST_IMPLICIT); gfc_syntax_error (ST_IMPLICIT);

View File

@ -1435,10 +1435,9 @@ extern int gfc_index_integer_kind;
/* symbol.c */ /* symbol.c */
void gfc_clear_new_implicit (void); void gfc_clear_new_implicit (void);
try gfc_add_new_implicit_range (int, int, gfc_typespec *); try gfc_add_new_implicit_range (int, int);
try gfc_merge_new_implicit (void); try gfc_merge_new_implicit (gfc_typespec *);
void gfc_set_implicit_none (void); void gfc_set_implicit_none (void);
void gfc_set_implicit (void);
gfc_typespec *gfc_get_default_type (gfc_symbol *, gfc_namespace *); gfc_typespec *gfc_get_default_type (gfc_symbol *, gfc_namespace *);
try gfc_set_default_type (gfc_symbol *, int, gfc_namespace *); try gfc_set_default_type (gfc_symbol *, int, gfc_namespace *);

View File

@ -1019,7 +1019,6 @@ accept_statement (gfc_statement st)
break; break;
case ST_IMPLICIT: case ST_IMPLICIT:
gfc_set_implicit ();
break; break;
case ST_FUNCTION: case ST_FUNCTION:

View File

@ -96,13 +96,9 @@ static gfc_symbol *changed_syms = NULL;
/*********** IMPLICIT NONE and IMPLICIT statement handlers ***********/ /*********** IMPLICIT NONE and IMPLICIT statement handlers ***********/
/* The following static variables hold the default types set by /* The following static variable indicates whether a particular element has
IMPLICIT statements. We have to store kind information because of been explicitly set or not. */
IMPLICIT DOUBLE PRECISION statements. IMPLICIT NONE stores a
BT_UNKNOWN into all elements. The arrays of flags indicate whether
a particular element has been explicitly set or not. */
static gfc_typespec new_ts[GFC_LETTERS];
static int new_flag[GFC_LETTERS]; static int new_flag[GFC_LETTERS];
@ -113,48 +109,30 @@ gfc_set_implicit_none (void)
{ {
int i; int i;
for (i = 'a'; i <= 'z'; i++) for (i = 0; i < GFC_LETTERS; i++)
{ {
gfc_clear_ts (&gfc_current_ns->default_type[i - 'a']); gfc_clear_ts (&gfc_current_ns->default_type[i]);
gfc_current_ns->set_flag[i - 'a'] = 1; gfc_current_ns->set_flag[i] = 1;
} }
} }
/* Sets the implicit types parsed by gfc_match_implicit(). */ /* Reset the implicit range flags. */
void void
gfc_set_implicit (void) gfc_clear_new_implicit (void)
{ {
int i; int i;
for (i = 0; i < GFC_LETTERS; i++) for (i = 0; i < GFC_LETTERS; i++)
if (new_flag[i]) new_flag[i] = 0;
{
gfc_current_ns->default_type[i] = new_ts[i];
gfc_current_ns->set_flag[i] = 1;
}
} }
/* Wipe anything a previous IMPLICIT statement may have tried to do. */ /* Prepare for a new implicit range. Sets flags in new_flag[]. */
void gfc_clear_new_implicit (void)
{
int i;
for (i = 0; i < GFC_LETTERS; i++) try
{ gfc_add_new_implicit_range (int c1, int c2)
gfc_clear_ts (&new_ts[i]);
if (new_flag[i])
new_flag[i] = 0;
}
}
/* Prepare for a new implicit range. Sets flags in new_flag[] and
copies the typespec to new_ts[]. */
try gfc_add_new_implicit_range (int c1, int c2, gfc_typespec * ts)
{ {
int i; int i;
@ -170,7 +148,6 @@ try gfc_add_new_implicit_range (int c1, int c2, gfc_typespec * ts)
return FAILURE; return FAILURE;
} }
new_ts[i] = *ts;
new_flag[i] = 1; new_flag[i] = 1;
} }
@ -178,27 +155,29 @@ try gfc_add_new_implicit_range (int c1, int c2, gfc_typespec * ts)
} }
/* Add a matched implicit range for gfc_set_implicit(). An implicit /* Add a matched implicit range for gfc_set_implicit(). Check if merging
statement has been fully matched at this point. We now need to the new implicit types back into the existing types will work. */
check if merging the new implicit types back into the existing
types will work. */
try try
gfc_merge_new_implicit (void) gfc_merge_new_implicit (gfc_typespec * ts)
{ {
int i; int i;
for (i = 0; i < GFC_LETTERS; i++) for (i = 0; i < GFC_LETTERS; i++)
if (new_flag[i]) {
{ if (new_flag[i])
if (gfc_current_ns->set_flag[i]) {
{
gfc_error ("Letter %c already has an IMPLICIT type at %C",
i + 'A');
return FAILURE;
}
}
if (gfc_current_ns->set_flag[i])
{
gfc_error ("Letter %c already has an IMPLICIT type at %C",
i + 'A');
return FAILURE;
}
gfc_current_ns->default_type[i] = *ts;
gfc_current_ns->set_flag[i] = 1;
}
}
return SUCCESS; return SUCCESS;
} }

View File

@ -1,7 +1,11 @@
2004-07-03 Scott Brumbaugh <scottb.lists@verizon.net> 2004-07-04 Paul Brook <paul@codesourcery.com>
PR c++/3761 * gfortran.fortran-torture/compile/implicit_1.f90: New test.
* g++.dg/lookup/crash4.C: New test.
2004-07-03 Scott Brumbaugh <scottb.lists@verizon.net>
PR c++/3761
* g++.dg/lookup/crash4.C: New test.
2004-07-02 Zack Weinberg <zack@codesourcery.com> 2004-07-02 Zack Weinberg <zack@codesourcery.com>

View File

@ -0,0 +1,32 @@
! Test implicit character declarations.
! This requires some coordination between the typespec and variable name range
! matchers to get it right.
module implicit_1
integer, parameter :: x = 10
integer, parameter :: y = 6
integer, parameter :: z = selected_int_kind(4)
end module
subroutine foo(n)
use implicit_1
! Test various combinations with and without character length
! and type kind specifiers
implicit character(len=5) (a)
implicit character(n) (b)
implicit character*6 (c-d)
implicit character (e)
implicit character(x-y) (f)
implicit integer(z) (g)
implicit character (z)
a1 = 'Hello'
b1 = 'world'
c1 = 'wibble'
d1 = 'hmmm'
e1 = 'n'
f1 = 'test'
g1 = 1
x1 = 1.0
y1 = 2.0
z1 = 'A'
end