aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/primary.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2017-09-09 11:10:42 +0000
committerPaul Thomas <pault@gcc.gnu.org>2017-09-09 11:10:42 +0000
commit5bab4c9631c478b7940e952ea57de680321d5a8e (patch)
treefe34213cb8a220dbd5072eaf2b7addbbc4709085 /gcc/fortran/primary.c
parent66c9b3f50f70b1503629b94cc2e33f7e5df64b08 (diff)
downloadgcc-5bab4c9631c478b7940e952ea57de680321d5a8e.zip
gcc-5bab4c9631c478b7940e952ea57de680321d5a8e.tar.gz
gcc-5bab4c9631c478b7940e952ea57de680321d5a8e.tar.bz2
decl.c: Add decl_type_param_list...
2017-09-09 Paul Thomas <pault@gcc.gnu.org> * decl.c : Add decl_type_param_list, type_param_spec_list as static variables to hold PDT spec lists. (build_sym): Copy 'type_param_spec_list' to symbol spec_list. (build_struct): Copy the 'saved_kind_expr' to the component 'kind_expr'. Check that KIND or LEN components appear in the decl_type_param_list. These should appear as symbols in the f2k_derived namespace. If the component is itself a PDT type, copy the decl_type_param_list to the component param_list. (gfc_match_kind_spec): If the KIND expression is parameterized set KIND to zero and store the expression in 'saved_kind_expr'. (insert_parameter_exprs): New function. (gfc_insert_kind_parameter_exprs): New function. (gfc_insert_parameter_exprs): New function. (gfc_get_pdt_instance): New function. (gfc_match_decl_type_spec): Match the decl_type_spec_list if it is present. If it is, call 'gfc_get_pdt_instance' to obtain the specific instance of the PDT. (match_attr_spec): Match KIND and LEN attributes. Check for the standard and for type/kind of the parameter. They are also not allowed outside a derived type definition. (gfc_match_data_decl): Null the decl_type_param_list and the type_param_spec_list on entry and free them on exit. (gfc_match_formal_arglist): If 'typeparam' is true, add the formal symbol to the f2k_derived namespace. (gfc_match_derived_decl): Register the decl_type_param_list if this is a PDT. If this is a type extension, gather up all the type parameters and put them in the right order. *dump-parse-tree.c (show_attr): Signal PDT templates and the parameter attributes. (show_components): Output parameter atrributes and component parameter list. (show_symbol): Show variable parameter lists. * expr.c (expr.c): Copy the expression parameter list. (gfc_is_constant_expr): Pass on symbols representing PDT parameters. (gfc_check_init_expr): Break on PDT KIND parameters and PDT parameter expressions. (gfc_check_assign): Assigning to KIND or LEN components is an error. (derived_parameter_expr): New function. (gfc_derived_parameter_expr): New function. (gfc_spec_list_type): New function. * gfortran.h : Add enum gfc_param_spec_type. Add the PDT attrs to the structure symbol_attr. Add the 'kind_expr' and 'param_list' field to the gfc_component structure. Comment on the reuse of the gfc_actual_arglist structure as storage for type parameter spec lists. Add the new field 'spec_type' to this structure. Add 'param_list' fields to gfc_symbol and gfc_expr. Add prototypes for gfc_insert_kind_parameter_exprs, gfc_insert_parameter_exprs, gfc_add_kind, gfc_add_len, gfc_derived_parameter_expr and gfc_spec_list_type. * interface.c (gfc_compare_derived_types): Treat PDTs in the same way as sequence types. * match.c : Add variable 'type_param_spec_list'. (gfc_op2string, gfc_match_member_sep, gfc_match_label): Remove trailing whitespace. (match_derived_type_spec): Match PDTs and find specific instance. (gfc_match_type_spec): Remove more trailing whitespace. (gfc_match_allocate): Assumed or deferred parameters cannot appear here. Copy the type parameter spec list to the expr for the allocatable entity. Free 'type_param_spec_list'. (gfc_match_common, gfc_match_namelist, gfc_match_module): Still more trailing whitespace to remove. (gfc_match_type_is): Allow PDT typespecs. * match.h : Modify prototypes for gfc_match_formal_arglist and gfc_match_actual_arglist. * module.c (ab_attribute, mstring attr_bits): PDT attributes added. (mio_symbol_attribute): PDT attributes handled. (mio_component): Deal with 'kind_expr' field. (mio_full_f2k_derived): For PDT templates, transfer the formal namespace symroot to the f2k_derived namespace. *primary.c (match_keyword_arg, gfc_match_actual_arglist): Add modifications to handle PDT spec lists. These are flagged in both cases by new boolean arguments, whose prototype defaults are false. (gfc_match_structure_constructor, match_variable): Remove yet more trailing whitespace. * resolve.c (get_pdt_spec_expr, get_pdt_constructor): New functions. (resolve_structure_cons): If the constructor is a PDT template, call get_pdt_constructor to build it using the parameter lists and then get the specific instance of the PDT. (resolve_component): PDT strings need a hidden string length component like deferred characters. (resolve_symbol): Dummy PDTs cannot have deferred parameters. * symbol.c (gfc_add_kind, gfc_add_len): New functions. (free_components): Free 'kind_expr' and 'param_list' fields. (gfc_free_symbol): Free the 'param_list' field. (gfc_find_sym_tree): If the current state is a PDT template, look for the symtree in the f2k_derived namspaces. trans-array.c (structure_alloc_comps): Allocate and deallocate PDTs. Check dummy arguments for compliance of LEN parameters. Add the new functions to the preceeding enum. (gfc_allocate_pdt_comp, gfc_deallocate_pdt_comp and gfc_check_pdt_dummy): New functions calling above. * trans-array.h : Add prototypes for these functions. trans-decl.c (gfc_get_symbol_decl): Call gfc_defer_symbol_init as appropriate for PDT symbols. (gfc_trans_deferred_vars): Allocate/deallocate PDT entities as they come into and out of scope. Exclude pdt_types from being 'gcc_unreachable'. (gfc_trans_subcomponent_assign): PDT array components must be handles as if they are allocatable. * trans-stmt.c (gfc_trans_allocate): Handle initialization of PDT entities. (gfc_trans_deallocate): Likewise. * trans-types.c (gfc_get_derived_type): PDT templates must not arrive here. PDT string components are handles as if deferred. Similarly, PDT arrays are treated as if allocatable. PDT strings are pointer types. * trans.c (gfc_deferred_strlen): Handle PDT strings in the same way as deferred characters. 2017-09-09 Paul Thomas <pault@gcc.gnu.org> * gfortran.dg/pdt_1.f03 : New test. * gfortran.dg/pdt_2.f03 : New test. * gfortran.dg/pdt_3.f03 : New test. * gfortran.dg/pdt_4.f03 : New test. * gfortran.dg/pdt_5.f03 : New test. From-SVN: r251925
Diffstat (limited to 'gcc/fortran/primary.c')
-rw-r--r--gcc/fortran/primary.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index b30afdd..883141f 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1609,10 +1609,10 @@ match_actual_arg (gfc_expr **result)
}
-/* Match a keyword argument. */
+/* Match a keyword argument or type parameter spec list.. */
static match
-match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base)
+match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base, bool pdt)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
gfc_actual_arglist *a;
@@ -1630,12 +1630,28 @@ match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base)
goto cleanup;
}
+ if (pdt)
+ {
+ if (gfc_match_char ('*') == MATCH_YES)
+ {
+ actual->spec_type = SPEC_ASSUMED;
+ goto add_name;
+ }
+ else if (gfc_match_char (':') == MATCH_YES)
+ {
+ actual->spec_type = SPEC_DEFERRED;
+ goto add_name;
+ }
+ else
+ actual->spec_type = SPEC_EXPLICIT;
+ }
+
m = match_actual_arg (&actual->expr);
if (m != MATCH_YES)
goto cleanup;
/* Make sure this name has not appeared yet. */
-
+add_name:
if (name[0] != '\0')
{
for (a = base; a; a = a->next)
@@ -1737,10 +1753,15 @@ cleanup:
list is assumed to allow keyword arguments because we don't know if
the symbol associated with the procedure has an implicit interface
or not. We make sure keywords are unique. If sub_flag is set,
- we're matching the argument list of a subroutine. */
+ we're matching the argument list of a subroutine.
+
+ NOTE: An alternative use for this function is to match type parameter
+ spec lists, which are so similar to actual argument lists that the
+ machinery can be reused. This use is flagged by the optional argument
+ 'pdt'. */
match
-gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
+gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp, bool pdt)
{
gfc_actual_arglist *head, *tail;
int seen_keyword;
@@ -1758,6 +1779,7 @@ gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
if (gfc_match_char (')') == MATCH_YES)
return MATCH_YES;
+
head = NULL;
matching_actual_arglist++;
@@ -1772,8 +1794,13 @@ gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
tail = tail->next;
}
- if (sub_flag && gfc_match_char ('*') == MATCH_YES)
+ if (sub_flag && !pdt && gfc_match_char ('*') == MATCH_YES)
{
+ if (pdt)
+ {
+ tail->spec_type = SPEC_ASSUMED;
+ goto next;
+ }
m = gfc_match_st_label (&label);
if (m == MATCH_NO)
gfc_error ("Expected alternate return label at %C");
@@ -1788,11 +1815,27 @@ gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
goto next;
}
+ if (pdt && !seen_keyword)
+ {
+ if (gfc_match_char (':') == MATCH_YES)
+ {
+ tail->spec_type = SPEC_DEFERRED;
+ goto next;
+ }
+ else if (gfc_match_char ('*') == MATCH_YES)
+ {
+ tail->spec_type = SPEC_ASSUMED;
+ goto next;
+ }
+ else
+ tail->spec_type = SPEC_EXPLICIT;
+ }
+
/* After the first keyword argument is seen, the following
arguments must also have keywords. */
if (seen_keyword)
{
- m = match_keyword_arg (tail, head);
+ m = match_keyword_arg (tail, head, pdt);
if (m == MATCH_ERROR)
goto cleanup;
@@ -1813,7 +1856,7 @@ gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp)
/* See if we have the first keyword argument. */
if (m == MATCH_NO)
{
- m = match_keyword_arg (tail, head);
+ m = match_keyword_arg (tail, head, false);
if (m == MATCH_YES)
seen_keyword = 1;
if (m == MATCH_ERROR)
@@ -2948,7 +2991,7 @@ gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
expression here. */
if (gfc_in_match_data ())
gfc_reduce_init_expr (e);
-
+
*result = e;
return MATCH_YES;
}
@@ -3662,7 +3705,7 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag)
implicit_ns = gfc_current_ns;
else
implicit_ns = sym->ns;
-
+
old_loc = gfc_current_locus;
if (gfc_match_member_sep (sym) == MATCH_YES
&& sym->ts.type == BT_UNKNOWN