This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
Here's a patch that does the parsing and some error checking of deferred type parameter. It is accomplished by adding a bool to gfc_typespec to note when a deferred type parameter is encountered. Currently, the patch does 1) Checks that a deferred type parameter does not appear in an array constructor, ie, s = [character(len=:) :: 'ab', 'cd'] ! Invalid. 2) Checks that a deferred type parameter does not appear in an allocate statement, ie, allocate(character(len=:) :: s) ! Invalid. 3) Checks that a variable declared with a deferred type parameter has either the pointer or allocatable attribute. 4) Checks that a variable with a deferred type parameter does not appear in a specification or initialization expression, ie, character(len=:), allocatable :: s integer, parameter :: n = len(s) 5) Prevents errors about assumed shaped arrays and assumed length characters when a deferred type parameter is encountered. For now, if a variable with a deferred type parameter is used in a program gfortran issues an error that this feature is not implemented. Two items are left: 1) Check for any restrictions with actual and dummy arguments. 2) Write the code for trans-* to actually make this feature work. I suspect that I can use some help from others here; otherwise, it may take months (years?) to finish this up. I have only written some limted tests, so I suspect that there may be issues with things like components of derived types that use deferred type parameters and function results. Anyway, to keep this patch from getting lost again in a dusty corner of my hard drive, I thought I would post it here. -- Steve
Attachment:
deferred.log
Description: Text document
Index: gcc/testsuite/gfortran.dg/initialization_9.f90
===================================================================
--- gcc/testsuite/gfortran.dg/initialization_9.f90 (revision 163263)
+++ gcc/testsuite/gfortran.dg/initialization_9.f90 (working copy)
@@ -5,7 +5,7 @@
integer function xstrcmp(s1)
character*(*), intent(in) :: s1
- integer :: n1 = len(s1) ! { dg-error "Assumed character length variable" }
+ integer :: n1 = len(s1) ! { dg-error "Assumed or deferred character length variable" }
n1 = 1
return
end function xstrcmp
Index: gcc/testsuite/gfortran.dg/allocate_derived_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/allocate_derived_1.f90 (revision 163263)
+++ gcc/testsuite/gfortran.dg/allocate_derived_1.f90 (working copy)
@@ -32,7 +32,7 @@
allocate(t1 :: x(2))
allocate(t2 :: x(3))
allocate(t3 :: x(4))
- allocate(tx :: x(5)) ! { dg-error "is not an accessible derived type" }
+ allocate(tx :: x(5)) ! { dg-error "not a nonprocedure pointer" }
allocate(u0 :: x(6)) ! { dg-error "may not be ABSTRACT" }
allocate(v1 :: x(7)) ! { dg-error "is type incompatible with typespec" }
Index: gcc/testsuite/gfortran.dg/initialization_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/initialization_1.f90 (revision 163263)
+++ gcc/testsuite/gfortran.dg/initialization_1.f90 (working copy)
@@ -24,7 +24,7 @@ contains
real :: z(2, 2)
! However, this gives a warning because it is an initialization expression.
- integer :: l1 = len (ch1) ! { dg-warning "Assumed character length variable" }
+ integer :: l1 = len (ch1) ! { dg-warning "Assumed or deferred character length variable" }
! These are warnings because they are gfortran extensions.
integer :: m3 = size (x, 1) ! { dg-error "Assumed size array" }
Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c (revision 163263)
+++ gcc/fortran/decl.c (working copy)
@@ -647,16 +647,27 @@ match_intent_spec (void)
/* Matches a character length specification, which is either a
- specification expression or a '*'. */
+ specification expression, '*', or ':'. */
static match
-char_len_param_value (gfc_expr **expr)
+char_len_param_value (gfc_expr **expr, bool *deferred)
{
match m;
+ *expr = NULL;
+ *deferred = false;
+
if (gfc_match_char ('*') == MATCH_YES)
+ return MATCH_YES;
+
+ if (gfc_match_char (':') == MATCH_YES)
{
- *expr = NULL;
+ if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: deferred type "
+ "parameter at %C") == FAILURE)
+ return MATCH_ERROR;
+
+ *deferred = true;
+
return MATCH_YES;
}
@@ -701,6 +712,7 @@ match_char_length (gfc_expr **expr)
{
int length;
match m;
+ bool deferred = false;
m = gfc_match_char ('*');
if (m != MATCH_YES)
@@ -722,7 +734,7 @@ match_char_length (gfc_expr **expr)
if (gfc_match_char ('(') == MATCH_NO)
goto syntax;
- m = char_len_param_value (expr);
+ m = char_len_param_value (expr, &deferred);
if (m != MATCH_YES && gfc_matching_function)
{
gfc_undo_symbols ();
@@ -2246,11 +2258,13 @@ gfc_match_char_spec (gfc_typespec *ts)
gfc_charlen *cl;
gfc_expr *len;
match m;
+ bool deferred;
len = NULL;
seen_length = 0;
kind = 0;
is_iso_c = 0;
+ deferred = false;
/* Try the old-style specification first. */
old_char_selector = 0;
@@ -2284,7 +2298,7 @@ gfc_match_char_spec (gfc_typespec *ts)
if (gfc_match (" , len =") == MATCH_NO)
goto rparen;
- m = char_len_param_value (&len);
+ m = char_len_param_value (&len, &deferred);
if (m == MATCH_NO)
goto syntax;
if (m == MATCH_ERROR)
@@ -2297,7 +2311,7 @@ gfc_match_char_spec (gfc_typespec *ts)
/* Try to match "LEN = <len-param>" or "LEN = <len-param>, KIND = <int>". */
if (gfc_match (" len =") == MATCH_YES)
{
- m = char_len_param_value (&len);
+ m = char_len_param_value (&len, &deferred);
if (m == MATCH_NO)
goto syntax;
if (m == MATCH_ERROR)
@@ -2317,7 +2331,7 @@ gfc_match_char_spec (gfc_typespec *ts)
}
/* Try to match ( <len-param> ) or ( <len-param> , [ KIND = ] <int> ). */
- m = char_len_param_value (&len);
+ m = char_len_param_value (&len, &deferred);
if (m == MATCH_NO)
goto syntax;
if (m == MATCH_ERROR)
@@ -2376,6 +2390,7 @@ done:
ts->u.cl = cl;
ts->kind = kind == 0 ? gfc_default_character_kind : kind;
+ ts->deferred = deferred;
/* We have to know if it was a c interoperable kind so we can
do accurate type checking of bind(c) procs, etc. */
@@ -2833,7 +2848,7 @@ gfc_match_implicit (void)
/* Last chance -- check <TYPE> <SELECTOR> (<RANGE>). */
if (ts.type == BT_CHARACTER)
- m = gfc_match_char_spec (&ts);
+ m = gfc_match_char_spec (&ts);
else
{
m = gfc_match_kind_spec (&ts, false);
Index: gcc/fortran/array.c
===================================================================
--- gcc/fortran/array.c (revision 163263)
+++ gcc/fortran/array.c (working copy)
@@ -1043,6 +1043,13 @@ gfc_match_array_constructor (gfc_expr **
if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Array constructor "
"including type specification at %C") == FAILURE)
goto cleanup;
+
+ if (ts.deferred == true)
+ {
+ gfc_error ("Type-spec at %L cannot contain a deferred "
+ "type parameter", &where);
+ goto cleanup;
+ }
}
}
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h (revision 163263)
+++ gcc/fortran/gfortran.h (working copy)
@@ -860,7 +860,7 @@ typedef struct gfc_charlen
struct gfc_charlen *next;
bool length_from_typespec; /* Length from explicit array ctor typespec? */
tree backend_decl;
- tree passed_length; /* Length argument explicitelly passed. */
+ tree passed_length; /* Length argument explicitly passed. */
int resolved;
}
@@ -885,6 +885,7 @@ typedef struct
int is_c_interop;
int is_iso_c;
bt f90_type;
+ bool deferred;
}
gfc_typespec;
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (revision 163263)
+++ gcc/fortran/expr.c (working copy)
@@ -2292,10 +2292,13 @@ check_inquiry (gfc_expr *e, int not_rest
with LEN, as required by the standard. */
if (i == 5 && not_restricted
&& ap->expr->symtree->n.sym->ts.type == BT_CHARACTER
- && ap->expr->symtree->n.sym->ts.u.cl->length == NULL)
+ && (ap->expr->symtree->n.sym->ts.u.cl->length == NULL
+ || ap->expr->symtree->n.sym->ts.deferred))
{
- gfc_error ("Assumed character length variable '%s' in constant "
- "expression at %L", e->symtree->n.sym->name, &e->where);
+ gfc_error ("Assumed or deferred character length variable '%s' "
+ " in constant expression at %L",
+ ap->expr->symtree->n.sym->name,
+ &ap->expr->where);
return MATCH_ERROR;
}
else if (not_restricted && check_init_expr (ap->expr) == FAILURE)
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (revision 163263)
+++ gcc/fortran/resolve.c (working copy)
@@ -9136,7 +9136,9 @@ resolve_index_expr (gfc_expr *e)
return SUCCESS;
}
-/* Resolve a charlen structure. */
+
+/* Resolve a charlen structure.
+ FIXME: do we need to do anything here for deferred type parameters. */
static gfc_try
resolve_charlen (gfc_charlen *cl)
@@ -9448,6 +9450,7 @@ apply_default_init_local (gfc_symbol *sy
build_init_assign (sym, init);
}
+
/* Resolution of common features of flavors variable and procedure. */
static gfc_try
@@ -9458,7 +9461,8 @@ resolve_fl_var_and_proc (gfc_symbol *sym
{
if (sym->attr.allocatable)
{
- if (sym->attr.dimension)
+ if (sym->attr.dimension
+ && !(sym->ts.type == BT_CHARACTER && sym->ts.deferred))
{
gfc_error ("Allocatable array '%s' at %L must have "
"a deferred shape", sym->name, &sym->declared_at);
@@ -9470,13 +9474,13 @@ resolve_fl_var_and_proc (gfc_symbol *sym
return FAILURE;
}
- if (sym->attr.pointer && sym->attr.dimension)
+ if (sym->attr.pointer && sym->attr.dimension
+ && !(sym->ts.type == BT_CHARACTER && sym->ts.deferred))
{
gfc_error ("Array pointer '%s' at %L must have a deferred shape",
sym->name, &sym->declared_at);
return FAILURE;
}
-
}
else
{
@@ -9610,12 +9614,23 @@ resolve_fl_variable (gfc_symbol *sym, in
return FAILURE;
}
+ /* Constraints on deferred type parameter. */
+ if (sym->ts.type == BT_CHARACTER && sym->ts.deferred
+ && !(sym->attr.pointer || sym->attr.allocatable))
+ {
+ gfc_error ("Entity '%s' at %L has a deferred type parameter and "
+ "requires either the pointer or allocatable attribute",
+ sym->name, &sym->declared_at);
+ return FAILURE;
+ }
+
if (sym->ts.type == BT_CHARACTER)
{
/* Make sure that character string variables with assumed length are
dummy arguments. */
e = sym->ts.u.cl->length;
- if (e == NULL && !sym->attr.dummy && !sym->attr.result)
+ if (e == NULL && !sym->attr.dummy && !sym->attr.result
+ && !sym->ts.deferred)
{
gfc_error ("Entity with assumed character length at %L must be a "
"dummy argument or a PARAMETER", &sym->declared_at);
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c (revision 163263)
+++ gcc/fortran/trans-decl.c (working copy)
@@ -3267,6 +3267,10 @@ gfc_trans_deferred_vars (gfc_symbol * pr
}
else if (sym_has_alloc_comp)
gfc_trans_deferred_array (sym, block);
+ else if (sym->ts.type == BT_CHARACTER && sym->ts.deferred)
+ {
+ gfc_fatal_error ("Deferred type parameter not supported");
+ }
else if (sym->ts.type == BT_CHARACTER)
{
gfc_get_backend_locus (&loc);
Index: gcc/fortran/match.c
===================================================================
--- gcc/fortran/match.c (revision 163263)
+++ gcc/fortran/match.c (working copy)
@@ -2738,8 +2738,6 @@ match_type_spec (gfc_typespec *ts)
}
return MATCH_YES;
}
- else if (m == MATCH_ERROR && gfc_match (" :: ") == MATCH_YES)
- return MATCH_ERROR;
gfc_current_locus = old_locus;
@@ -2774,7 +2772,10 @@ match_type_spec (gfc_typespec *ts)
if (gfc_match ("character") == MATCH_YES)
{
ts->type = BT_CHARACTER;
- goto char_selector;
+ m = gfc_match_char_spec (ts);
+ if (m == MATCH_NO)
+ m = MATCH_YES; /* No kind specifier found. */
+ return m;
}
if (gfc_match ("logical") == MATCH_YES)
@@ -2803,15 +2804,6 @@ kind_selector:
m = MATCH_YES; /* No kind specifier found. */
return m;
-
-char_selector:
-
- m = gfc_match_char_spec (ts);
-
- if (m == MATCH_NO)
- m = MATCH_YES; /* No kind specifier found. */
-
- return m;
}
@@ -2825,12 +2817,12 @@ gfc_match_allocate (void)
gfc_typespec ts;
gfc_symbol *sym;
match m;
- locus old_locus;
- bool saw_stat, saw_errmsg, saw_source, saw_mold, b1, b2, b3;
+ locus old_locus, deferred_locus;
+ bool saw_stat, saw_errmsg, saw_source, saw_mold, saw_deferred, b1, b2, b3;
head = tail = NULL;
stat = errmsg = source = mold = tmp = NULL;
- saw_stat = saw_errmsg = saw_source = saw_mold = false;
+ saw_stat = saw_errmsg = saw_source = saw_mold = saw_deferred = false;
if (gfc_match_char ('(') != MATCH_YES)
goto syntax;
@@ -2849,6 +2841,13 @@ gfc_match_allocate (void)
if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: typespec in "
"ALLOCATE at %L", &old_locus) == FAILURE)
goto cleanup;
+
+ if (ts.type == BT_CHARACTER && ts.deferred)
+ {
+ gfc_error ("Type-spec at %L cannot contain a deferred "
+ "type parameter", &old_locus);
+ goto cleanup;
+ }
}
else
{
@@ -2882,6 +2881,18 @@ gfc_match_allocate (void)
goto cleanup;
}
+ /* FIXME: allocation of deferred type parameter entities is not
+ currently implemented. */
+ if (tail->expr->ts.deferred)
+ {
+ saw_deferred = true;
+ deferred_locus = tail->expr->where;
+
+ gfc_error ("Entity with a deferred type parameter at %C currently "
+ "not supported");
+ goto cleanup;
+ }
+
/* The ALLOCATE statement had an optional typespec. Check the
constraints. */
if (ts.type != BT_UNKNOWN)
@@ -3072,6 +3083,25 @@ alloc_opt_list:
&mold->where, &source->where);
goto cleanup;
}
+
+ /* Check F03:C623, */
+ if (saw_deferred)
+ {
+ if (ts.type == BT_UNKNOWN && !source)
+ {
+ gfc_error ("Allocate-object at %L with a deferred type parameter "
+ "requires either a type-spec or SOURCE tag",
+ &deferred_locus);
+ goto cleanup;
+ }
+
+ if (source && source->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("Types of SOURCE tag and allocate-object must "
+ "be CHARACTER");
+ goto cleanup;
+ }
+ }
new_st.op = EXEC_ALLOCATE;
new_st.expr1 = stat;
Index: gcc/fortran/misc.c
===================================================================
--- gcc/fortran/misc.c (revision 163263)
+++ gcc/fortran/misc.c (working copy)
@@ -77,6 +77,7 @@ gfc_clear_ts (gfc_typespec *ts)
ts->f90_type = BT_UNKNOWN;
/* flag that says whether it's from iso_c_binding or not */
ts->is_iso_c = 0;
+ ts->deferred = false;
}
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |