re PR fortran/16161 ([gfortran] IMPLICIT CHARACTER not implemented)
fortran/ PR fortran/16161 * decl.c (gfc_match_type_spec): Rename second argument to 'implicit_flag', reverse meaning. Don't match_char_spec if 'implicit_flag' is set. Rename to ... (match_type_spec): ... this. (gfc_match_implicit_none, match_implicit_range): Move here from match.c. (gfc_match_implicit): Move here from match.c, try to match_char_len if match_implicit_range doesn't succeed for CHARACTER implicits. Call renamed fucntion match_type_spec. (gfc_match_data_decl, match_prefix): Call renamed function match_type_spec. * match.c (gfc_match_implicit_none, match_implicit_range, gfc_match_implicit): Move to decl.c. * match.h (gfc_match_implicit_none, gfc_match_implicit): Move protoypes to section 'decl.c'. (gfc_match_type_spec): Remove prototype. testsuite/ PR fortran/16161 * gfortran.fortran-torture/compile/implicit.f90: Add test for implicit character. From-SVN: r83907
This commit is contained in:
parent
521903292c
commit
e5ddaa24be
@ -1,3 +1,23 @@
|
||||
2004-06-30 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
|
||||
|
||||
PR fortran/16161
|
||||
* decl.c (gfc_match_type_spec): Rename second argument to
|
||||
'implicit_flag', reverse meaning. Don't match_char_spec if
|
||||
'implicit_flag' is set. Rename to ...
|
||||
(match_type_spec): ... this.
|
||||
(gfc_match_implicit_none, match_implicit_range): Move here
|
||||
from match.c.
|
||||
(gfc_match_implicit): Move here from match.c, try to
|
||||
match_char_len if match_implicit_range doesn't succeed for
|
||||
CHARACTER implicits. Call renamed fucntion match_type_spec.
|
||||
(gfc_match_data_decl, match_prefix): Call renamed function
|
||||
match_type_spec.
|
||||
* match.c (gfc_match_implicit_none, match_implicit_range,
|
||||
gfc_match_implicit): Move to decl.c.
|
||||
* match.h (gfc_match_implicit_none, gfc_match_implicit):
|
||||
Move protoypes to section 'decl.c'.
|
||||
(gfc_match_type_spec): Remove prototype.
|
||||
|
||||
2004-06-29 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
|
||||
|
||||
* decl.c, interface.c, symbol.c, trans-common.c: Add 2004 to
|
||||
|
@ -874,12 +874,12 @@ done:
|
||||
to the matched specification. This is necessary for FUNCTION and
|
||||
IMPLICIT statements.
|
||||
|
||||
If kind_flag is nonzero, then we check for the optional kind
|
||||
specification. Not doing so is needed for matching an IMPLICIT
|
||||
If implicit_flag is nonzero, then we don't check for the optional
|
||||
kind specification. Not doing so is needed for matching an IMPLICIT
|
||||
statement correctly. */
|
||||
|
||||
match
|
||||
gfc_match_type_spec (gfc_typespec * ts, int kind_flag)
|
||||
static match
|
||||
match_type_spec (gfc_typespec * ts, int implicit_flag)
|
||||
{
|
||||
char name[GFC_MAX_SYMBOL_LEN + 1];
|
||||
gfc_symbol *sym;
|
||||
@ -898,7 +898,10 @@ gfc_match_type_spec (gfc_typespec * ts, int kind_flag)
|
||||
if (gfc_match (" character") == MATCH_YES)
|
||||
{
|
||||
ts->type = BT_CHARACTER;
|
||||
return match_char_spec (ts);
|
||||
if (implicit_flag == 0)
|
||||
return match_char_spec (ts);
|
||||
else
|
||||
return MATCH_YES;
|
||||
}
|
||||
|
||||
if (gfc_match (" real") == MATCH_YES)
|
||||
@ -960,7 +963,7 @@ gfc_match_type_spec (gfc_typespec * ts, int kind_flag)
|
||||
get_kind:
|
||||
/* For all types except double, derived and character, look for an
|
||||
optional kind specifier. MATCH_NO is actually OK at this point. */
|
||||
if (kind_flag == 0)
|
||||
if (implicit_flag == 1)
|
||||
return MATCH_YES;
|
||||
|
||||
if (gfc_current_form == FORM_FREE)
|
||||
@ -982,6 +985,210 @@ get_kind:
|
||||
}
|
||||
|
||||
|
||||
/* Match an IMPLICIT NONE statement. Actually, this statement is
|
||||
already matched in parse.c, or we would not end up here in the
|
||||
first place. So the only thing we need to check, is if there is
|
||||
trailing garbage. If not, the match is successful. */
|
||||
|
||||
match
|
||||
gfc_match_implicit_none (void)
|
||||
{
|
||||
|
||||
return (gfc_match_eos () == MATCH_YES) ? MATCH_YES : MATCH_NO;
|
||||
}
|
||||
|
||||
|
||||
/* Match the letter range(s) of an IMPLICIT statement. */
|
||||
|
||||
static match
|
||||
match_implicit_range (gfc_typespec * ts)
|
||||
{
|
||||
int c, c1, c2, inner;
|
||||
locus cur_loc;
|
||||
|
||||
cur_loc = gfc_current_locus;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if (c != '(')
|
||||
{
|
||||
gfc_error ("Missing character range in IMPLICIT at %C");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
inner = 1;
|
||||
while (inner)
|
||||
{
|
||||
gfc_gobble_whitespace ();
|
||||
c1 = gfc_next_char ();
|
||||
if (!ISALPHA (c1))
|
||||
goto bad;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ')':
|
||||
inner = 0; /* Fall through */
|
||||
|
||||
case ',':
|
||||
c2 = c1;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
gfc_gobble_whitespace ();
|
||||
c2 = gfc_next_char ();
|
||||
if (!ISALPHA (c2))
|
||||
goto bad;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
|
||||
if ((c != ',') && (c != ')'))
|
||||
goto bad;
|
||||
if (c == ')')
|
||||
inner = 0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (c1 > c2)
|
||||
{
|
||||
gfc_error ("Letters must be in alphabetic order in "
|
||||
"IMPLICIT statement at %C");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* See if we can add the newly matched range to the pending
|
||||
implicits from this IMPLICIT statement. We do not check for
|
||||
conflicts with whatever earlier IMPLICIT statements may have
|
||||
set. This is done when we've successfully finished matching
|
||||
the current one. */
|
||||
if (gfc_add_new_implicit_range (c1, c2, ts) != SUCCESS)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return MATCH_YES;
|
||||
|
||||
bad:
|
||||
gfc_syntax_error (ST_IMPLICIT);
|
||||
|
||||
gfc_current_locus = cur_loc;
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Match an IMPLICIT statement, storing the types for
|
||||
gfc_set_implicit() if the statement is accepted by the parser.
|
||||
There is a strange looking, but legal syntactic construction
|
||||
possible. It looks like:
|
||||
|
||||
IMPLICIT INTEGER (a-b) (c-d)
|
||||
|
||||
This is legal if "a-b" is a constant expression that happens to
|
||||
equal one of the legal kinds for integers. The real problem
|
||||
happens with an implicit specification that looks like:
|
||||
|
||||
IMPLICIT INTEGER (a-b)
|
||||
|
||||
In this case, a typespec matcher that is "greedy" (as most of the
|
||||
matchers are) gobbles the character range as a kindspec, leaving
|
||||
nothing left. We therefore have to go a bit more slowly in the
|
||||
matching process by inhibiting the kindspec checking during
|
||||
typespec matching and checking for a kind later. */
|
||||
|
||||
match
|
||||
gfc_match_implicit (void)
|
||||
{
|
||||
gfc_typespec ts;
|
||||
locus cur_loc;
|
||||
int c;
|
||||
match m;
|
||||
|
||||
/* We don't allow empty implicit statements. */
|
||||
if (gfc_match_eos () == MATCH_YES)
|
||||
{
|
||||
gfc_error ("Empty IMPLICIT statement at %C");
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
/* First cleanup. */
|
||||
gfc_clear_new_implicit ();
|
||||
|
||||
do
|
||||
{
|
||||
/* A basic type is mandatory here. */
|
||||
m = match_type_spec (&ts, 1);
|
||||
if (m == MATCH_ERROR)
|
||||
goto error;
|
||||
if (m == MATCH_NO)
|
||||
goto syntax;
|
||||
|
||||
cur_loc = gfc_current_locus;
|
||||
m = match_implicit_range (&ts);
|
||||
|
||||
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)
|
||||
{
|
||||
/* Looks like we have the <TYPE> (<RANGE>). */
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if ((c == '\n') || (c == ','))
|
||||
continue;
|
||||
|
||||
gfc_current_locus = cur_loc;
|
||||
}
|
||||
|
||||
/* Last chance -- check <TYPE> (<KIND>) (<RANGE>). */
|
||||
m = gfc_match_kind_spec (&ts);
|
||||
if (m == MATCH_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);
|
||||
if (m == MATCH_ERROR)
|
||||
goto error;
|
||||
if (m == MATCH_NO)
|
||||
goto syntax;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if ((c != '\n') && (c != ','))
|
||||
goto syntax;
|
||||
|
||||
}
|
||||
while (c == ',');
|
||||
|
||||
/* All we need to now is try to merge the new implicit types back
|
||||
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:
|
||||
gfc_syntax_error (ST_IMPLICIT);
|
||||
|
||||
error:
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Matches an attribute specification including array specs. If
|
||||
successful, leaves the variables current_attr and current_as
|
||||
holding the specification. Also sets the colon_seen variable for
|
||||
@ -1242,7 +1449,7 @@ gfc_match_data_decl (void)
|
||||
gfc_symbol *sym;
|
||||
match m;
|
||||
|
||||
m = gfc_match_type_spec (¤t_ts, 1);
|
||||
m = match_type_spec (¤t_ts, 0);
|
||||
if (m != MATCH_YES)
|
||||
return m;
|
||||
|
||||
@ -1332,7 +1539,7 @@ match_prefix (gfc_typespec * ts)
|
||||
|
||||
loop:
|
||||
if (!seen_type && ts != NULL
|
||||
&& gfc_match_type_spec (ts, 1) == MATCH_YES
|
||||
&& match_type_spec (ts, 0) == MATCH_YES
|
||||
&& gfc_match_space () == MATCH_YES)
|
||||
{
|
||||
|
||||
|
@ -2048,204 +2048,6 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
/* Match an IMPLICIT NONE statement. Actually, this statement is
|
||||
already matched in parse.c, or we would not end up here in the
|
||||
first place. So the only thing we need to check, is if there is
|
||||
trailing garbage. If not, the match is successful. */
|
||||
|
||||
match
|
||||
gfc_match_implicit_none (void)
|
||||
{
|
||||
|
||||
return (gfc_match_eos () == MATCH_YES) ? MATCH_YES : MATCH_NO;
|
||||
}
|
||||
|
||||
|
||||
/* Match the letter range(s) of an IMPLICIT statement. */
|
||||
|
||||
static match
|
||||
match_implicit_range (gfc_typespec * ts)
|
||||
{
|
||||
int c, c1, c2, inner;
|
||||
locus cur_loc;
|
||||
|
||||
cur_loc = gfc_current_locus;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if (c != '(')
|
||||
{
|
||||
gfc_error ("Missing character range in IMPLICIT at %C");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
inner = 1;
|
||||
while (inner)
|
||||
{
|
||||
gfc_gobble_whitespace ();
|
||||
c1 = gfc_next_char ();
|
||||
if (!ISALPHA (c1))
|
||||
goto bad;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ')':
|
||||
inner = 0; /* Fall through */
|
||||
|
||||
case ',':
|
||||
c2 = c1;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
gfc_gobble_whitespace ();
|
||||
c2 = gfc_next_char ();
|
||||
if (!ISALPHA (c2))
|
||||
goto bad;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
|
||||
if ((c != ',') && (c != ')'))
|
||||
goto bad;
|
||||
if (c == ')')
|
||||
inner = 0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (c1 > c2)
|
||||
{
|
||||
gfc_error ("Letters must be in alphabetic order in "
|
||||
"IMPLICIT statement at %C");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* See if we can add the newly matched range to the pending
|
||||
implicits from this IMPLICIT statement. We do not check for
|
||||
conflicts with whatever earlier IMPLICIT statements may have
|
||||
set. This is done when we've successfully finished matching
|
||||
the current one. */
|
||||
if (gfc_add_new_implicit_range (c1, c2, ts) != SUCCESS)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return MATCH_YES;
|
||||
|
||||
bad:
|
||||
gfc_syntax_error (ST_IMPLICIT);
|
||||
|
||||
gfc_current_locus = cur_loc;
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Match an IMPLICIT statement, storing the types for
|
||||
gfc_set_implicit() if the statement is accepted by the parser.
|
||||
There is a strange looking, but legal syntactic construction
|
||||
possible. It looks like:
|
||||
|
||||
IMPLICIT INTEGER (a-b) (c-d)
|
||||
|
||||
This is legal if "a-b" is a constant expression that happens to
|
||||
equal one of the legal kinds for integers. The real problem
|
||||
happens with an implicit specification that looks like:
|
||||
|
||||
IMPLICIT INTEGER (a-b)
|
||||
|
||||
In this case, a typespec matcher that is "greedy" (as most of the
|
||||
matchers are) gobbles the character range as a kindspec, leaving
|
||||
nothing left. We therefore have to go a bit more slowly in the
|
||||
matching process by inhibiting the kindspec checking during
|
||||
typespec matching and checking for a kind later. */
|
||||
|
||||
match
|
||||
gfc_match_implicit (void)
|
||||
{
|
||||
gfc_typespec ts;
|
||||
locus cur_loc;
|
||||
int c;
|
||||
match m;
|
||||
|
||||
/* We don't allow empty implicit statements. */
|
||||
if (gfc_match_eos () == MATCH_YES)
|
||||
{
|
||||
gfc_error ("Empty IMPLICIT statement at %C");
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
/* First cleanup. */
|
||||
gfc_clear_new_implicit ();
|
||||
|
||||
do
|
||||
{
|
||||
/* A basic type is mandatory here. */
|
||||
m = gfc_match_type_spec (&ts, 0);
|
||||
if (m == MATCH_ERROR)
|
||||
goto error;
|
||||
if (m == MATCH_NO)
|
||||
goto syntax;
|
||||
|
||||
cur_loc = gfc_current_locus;
|
||||
m = match_implicit_range (&ts);
|
||||
|
||||
if (m == MATCH_YES)
|
||||
{
|
||||
/* Looks like we have the <TYPE> (<RANGE>). */
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if ((c == '\n') || (c == ','))
|
||||
continue;
|
||||
|
||||
gfc_current_locus = cur_loc;
|
||||
}
|
||||
|
||||
/* Last chance -- check <TYPE> (<KIND>) (<RANGE>). */
|
||||
m = gfc_match_kind_spec (&ts);
|
||||
if (m == MATCH_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);
|
||||
if (m == MATCH_ERROR)
|
||||
goto error;
|
||||
if (m == MATCH_NO)
|
||||
goto syntax;
|
||||
|
||||
gfc_gobble_whitespace ();
|
||||
c = gfc_next_char ();
|
||||
if ((c != '\n') && (c != ','))
|
||||
goto syntax;
|
||||
|
||||
}
|
||||
while (c == ',');
|
||||
|
||||
/* All we need to now is try to merge the new implicit types back
|
||||
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:
|
||||
gfc_syntax_error (ST_IMPLICIT);
|
||||
|
||||
error:
|
||||
return MATCH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Given a name, return a pointer to the common head structure,
|
||||
creating it if it does not exist.
|
||||
TODO: Add to global symbol tree. */
|
||||
|
@ -75,8 +75,6 @@ match gfc_match_deallocate (void);
|
||||
match gfc_match_return (void);
|
||||
match gfc_match_call (void);
|
||||
match gfc_match_common (void);
|
||||
match gfc_match_implicit_none (void);
|
||||
match gfc_match_implicit (void);
|
||||
match gfc_match_block_data (void);
|
||||
match gfc_match_namelist (void);
|
||||
match gfc_match_module (void);
|
||||
@ -98,7 +96,6 @@ gfc_common_head *gfc_get_common (char *);
|
||||
match gfc_match_null (gfc_expr **);
|
||||
match gfc_match_kind_spec (gfc_typespec *);
|
||||
match gfc_match_old_kind_spec (gfc_typespec *);
|
||||
match gfc_match_type_spec (gfc_typespec *, int);
|
||||
|
||||
match gfc_match_end (gfc_statement *);
|
||||
match gfc_match_data_decl (void);
|
||||
@ -108,6 +105,9 @@ match gfc_match_entry (void);
|
||||
match gfc_match_subroutine (void);
|
||||
match gfc_match_derived_decl (void);
|
||||
|
||||
match gfc_match_implicit_none (void);
|
||||
match gfc_match_implicit (void);
|
||||
|
||||
/* Matchers for attribute declarations */
|
||||
match gfc_match_allocatable (void);
|
||||
match gfc_match_dimension (void);
|
||||
|
@ -1,4 +1,10 @@
|
||||
2004-06-30 David Billinghurst (David.Billinghurst@riotinto.com)
|
||||
2004-06-30 Tobias Schlueter <tobias.shclueter@physik.uni-muenchen.de>
|
||||
|
||||
PR fortran/16161
|
||||
* gfortran.fortran-torture/compile/implicit.f90: Add test
|
||||
for implicit character.
|
||||
|
||||
2004-06-30 David Billinghurst (David.Billinghurst@riotinto.com)
|
||||
|
||||
PR fortran/16289
|
||||
* gfortran.fortran-torture/execute/intrinsic_nearest.f90
|
||||
|
@ -6,3 +6,8 @@ d = 1.0e2
|
||||
y = d
|
||||
z = a
|
||||
end
|
||||
! test prompted by PR 16161
|
||||
! we used to match "character (c)" wrongly in the below, confusing the parser
|
||||
subroutine b
|
||||
implicit character (c)
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user