aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/decl.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2017-09-12 18:06:52 +0000
committerPaul Thomas <pault@gcc.gnu.org>2017-09-12 18:06:52 +0000
commit18a4e7e305c1e12392ac35073b89f2ca0e7f8eda (patch)
tree35868a7bbccbfde8c2a0a0a67d0e69c9c17b1d6c /gcc/fortran/decl.c
parent29788f907095044876531d7b4df154ad8398f854 (diff)
downloadgcc-18a4e7e305c1e12392ac35073b89f2ca0e7f8eda.zip
gcc-18a4e7e305c1e12392ac35073b89f2ca0e7f8eda.tar.gz
gcc-18a4e7e305c1e12392ac35073b89f2ca0e7f8eda.tar.bz2
re PR fortran/82173 ([meta-bug] Parameterized derived type errors)
2017-09-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/82173 PR fortran/82168 * decl.c (variable_decl): Check pdt template components for appearance of KIND/LEN components in the type parameter name list, that components corresponding to type parameters have either KIND or LEN attributes and that KIND or LEN components are scalar. Copy the initializer to the parameter value. (gfc_get_pdt_instance): Add a label 'error_return' and follow it with repeated code, while replacing this code with a jump. Check if a parameter appears as a component in the template. Make sure that the parameter expressions are integer. Validate KIND expressions. (gfc_match_decl_type_spec): Search for pdt_types in the parent namespace since they are instantiated in the template ns. * expr.c (gfc_extract_int): Use a KIND parameter if it appears as a component expression. (gfc_check_init_expr): Allow expressions with the pdt_kind attribute. *primary.c (gfc_match_actual_arglist): Make sure that the first keyword argument is recognised when 'pdt' is set. 2017-09-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/82173 * gfortran.dg/pdt_4.f03 : Remove the 'is being used before it is defined' error. * gfortran.dg/pdt_6.f03 : New test. * gfortran.dg/pdt_7.f03 : New test. * gfortran.dg/pdt_8.f03 : New test. PR fortran/82168 * gfortran.dg/pdt_9.f03 : New test. From-SVN: r252039
Diffstat (limited to 'gcc/fortran/decl.c')
-rw-r--r--gcc/fortran/decl.c126
1 files changed, 107 insertions, 19 deletions
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 0609152..6e78d0d 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2537,6 +2537,39 @@ variable_decl (int elem)
goto cleanup;
}
+ if (gfc_current_state () == COMP_DERIVED
+ && gfc_current_block ()->attr.pdt_template)
+ {
+ gfc_symbol *param;
+ gfc_find_symbol (name, gfc_current_block ()->f2k_derived,
+ 0, &param);
+ if (!param && (current_attr.pdt_kind || current_attr.pdt_len))
+ {
+ gfc_error ("The component with KIND or LEN attribute at %C does not "
+ "not appear in the type parameter list at %L",
+ &gfc_current_block ()->declared_at);
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+ else if (param && !(current_attr.pdt_kind || current_attr.pdt_len))
+ {
+ gfc_error ("The component at %C that appears in the type parameter "
+ "list at %L has neither the KIND nor LEN attribute",
+ &gfc_current_block ()->declared_at);
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+ else if (as && (current_attr.pdt_kind || current_attr.pdt_len))
+ {
+ gfc_error ("The component at %C which is a type parameter must be "
+ "a scalar");
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+ else if (param && initializer)
+ param->value = gfc_copy_expr (initializer);
+ }
+
/* Add the initializer. Note that it is fine if initializer is
NULL here, because we sometimes also need to check if a
declaration *must* have an initialization expression. */
@@ -3193,8 +3226,7 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
{
gfc_error ("The type parameter spec list at %C cannot contain "
"both ASSUMED and DEFERRED parameters");
- gfc_free_actual_arglist (type_param_spec_list);
- return MATCH_ERROR;
+ goto error_return;
}
}
@@ -3202,10 +3234,27 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
name_seen = true;
param = type_param_name_list->sym;
+ c1 = gfc_find_component (pdt, param->name, false, true, NULL);
+ if (!pdt->attr.use_assoc && !c1)
+ {
+ gfc_error ("The type parameter name list at %L contains a parameter "
+ "'%qs' , which is not declared as a component of the type",
+ &pdt->declared_at, param->name);
+ goto error_return;
+ }
+
kind_expr = NULL;
if (!name_seen)
{
- if (actual_param && actual_param->spec_type == SPEC_EXPLICIT)
+ if (!actual_param && !(c1 && c1->initializer))
+ {
+ gfc_error ("The type parameter spec list at %C does not contain "
+ "enough parameter expressions");
+ goto error_return;
+ }
+ else if (!actual_param && c1 && c1->initializer)
+ kind_expr = gfc_copy_expr (c1->initializer);
+ else if (actual_param && actual_param->spec_type == SPEC_EXPLICIT)
kind_expr = gfc_copy_expr (actual_param->expr);
}
else
@@ -3225,7 +3274,7 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
{
gfc_error ("The derived parameter '%qs' at %C does not "
"have a default value", param->name);
- return MATCH_ERROR;
+ goto error_return;
}
}
}
@@ -3247,6 +3296,17 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
if (kind_expr)
{
+ /* Variable expressions seem to default to BT_PROCEDURE.
+ TODO find out why this is and fix it. */
+ if (kind_expr->ts.type != BT_INTEGER
+ && kind_expr->ts.type != BT_PROCEDURE)
+ {
+ gfc_error ("The parameter expression at %C must be of "
+ "INTEGER type and not %s type",
+ gfc_basic_typename (kind_expr->ts.type));
+ goto error_return;
+ }
+
tail->expr = gfc_copy_expr (kind_expr);
/* Try simplification even for LEN expressions. */
gfc_simplify_expr (tail->expr, 1);
@@ -3257,7 +3317,7 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
if (!param->attr.pdt_kind)
{
- if (!name_seen)
+ if (!name_seen && actual_param)
actual_param = actual_param->next;
if (kind_expr)
{
@@ -3273,16 +3333,14 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
{
gfc_error ("The KIND parameter '%qs' at %C cannot either be "
"ASSUMED or DEFERRED", param->name);
- gfc_free_actual_arglist (type_param_spec_list);
- return MATCH_ERROR;
+ goto error_return;
}
if (!kind_expr || !gfc_is_constant_expr (kind_expr))
{
gfc_error ("The value for the KIND parameter '%qs' at %C does not "
"reduce to a constant expression", param->name);
- gfc_free_actual_arglist (type_param_spec_list);
- return MATCH_ERROR;
+ goto error_return;
}
gfc_extract_int (kind_expr, &kind_value);
@@ -3293,12 +3351,19 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
gfc_free_expr (kind_expr);
}
+ if (!name_seen && actual_param)
+ {
+ gfc_error ("The type parameter spec list at %C contains too many "
+ "parameter expressions");
+ goto error_return;
+ }
+
/* Now we search for the PDT instance 'name'. If it doesn't exist, we
build it, using 'pdt' as a template. */
if (gfc_get_symbol (name, pdt->ns, &instance))
{
gfc_error ("Parameterized derived type at %C is ambiguous");
- return MATCH_ERROR;
+ goto error_return;
}
m = MATCH_YES;
@@ -3370,7 +3435,7 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
gfc_error ("Maximum extension level reached with type %qs at %L",
c2->ts.u.derived->name,
&c2->ts.u.derived->declared_at);
- return MATCH_ERROR;
+ goto error_return;
}
instance->attr.extension = c2->ts.u.derived->attr.extension + 1;
@@ -3390,6 +3455,12 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
gfc_insert_kind_parameter_exprs (e);
gfc_extract_int (e, &c2->ts.kind);
gfc_free_expr (e);
+ if (gfc_validate_kind (c2->ts.type, c2->ts.kind, true) < 0)
+ {
+ gfc_error ("Kind %d not supported for type %s at %C",
+ c2->ts.kind, gfc_basic_typename (c2->ts.type));
+ goto error_return;
+ }
}
/* Similarly, set the string length if parameterized. */
@@ -3499,6 +3570,10 @@ gfc_get_pdt_instance (gfc_actual_arglist *param_list, gfc_symbol **sym,
*ext_param_list = type_param_spec_list;
*sym = instance;
return m;
+
+error_return:
+ gfc_free_actual_arglist (type_param_spec_list);
+ return MATCH_ERROR;
}
@@ -3829,6 +3904,19 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
}
if (sym->generic && !dt_sym)
dt_sym = gfc_find_dt_in_generic (sym);
+
+ /* Host associated PDTs can get confused with their constructors
+ because they ar instantiated in the template's namespace. */
+ if (!dt_sym)
+ {
+ if (gfc_find_symbol (dt_name, NULL, 1, &dt_sym))
+ {
+ gfc_error ("Type name %qs at %C is ambiguous", name);
+ return MATCH_ERROR;
+ }
+ if (dt_sym && !dt_sym->attr.pdt_type)
+ dt_sym = NULL;
+ }
}
else if (ts->kind == -1)
{
@@ -3861,14 +3949,14 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
if (sym && sym->attr.flavor == FL_DERIVED
&& sym->attr.pdt_template
&& gfc_current_state () != COMP_DERIVED)
- {
- m = gfc_get_pdt_instance (decl_type_param_list, &sym, NULL);
- if (m != MATCH_YES)
- return m;
- gcc_assert (!sym->attr.pdt_template && sym->attr.pdt_type);
- ts->u.derived = sym;
- strcpy (name, gfc_dt_lower_string (sym->name));
- }
+ {
+ m = gfc_get_pdt_instance (decl_type_param_list, &sym, NULL);
+ if (m != MATCH_YES)
+ return m;
+ gcc_assert (!sym->attr.pdt_template && sym->attr.pdt_type);
+ ts->u.derived = sym;
+ strcpy (name, gfc_dt_lower_string (sym->name));
+ }
gfc_save_symbol_data (sym);
gfc_set_sym_referenced (sym);