diff options
author | Andre Vehreschild <vehre@gcc.gnu.org> | 2023-07-12 12:51:30 +0200 |
---|---|---|
committer | Andre Vehreschild <vehre@gcc.gnu.org> | 2023-07-12 13:27:43 +0200 |
commit | f9182da3213aa57c16dd0b52862126de4a259f6a (patch) | |
tree | 5e2f22ae80cb2197ffbd46171ec21c8dae8b5592 /gcc/fortran/expr.cc | |
parent | 25f831eab368d1bbec4dc67bf058cb7cf6b721ee (diff) | |
download | gcc-f9182da3213aa57c16dd0b52862126de4a259f6a.zip gcc-f9182da3213aa57c16dd0b52862126de4a259f6a.tar.gz gcc-f9182da3213aa57c16dd0b52862126de4a259f6a.tar.bz2 |
gfortran: Allow ref'ing PDT's len() in parameter-initializer.
Fix declaring a parameter initialized using a pdt_len reference
not simplifying the reference to a constant.
2023-07-12 Andre Vehreschild <vehre@gcc.gnu.org>
gcc/fortran/ChangeLog:
PR fortran/102003
* expr.cc (find_inquiry_ref): Replace len of pdt_string by
constant.
(simplify_ref_chain): Ensure input to find_inquiry_ref is
NULL.
(gfc_match_init_expr): Prevent PDT analysis for function calls.
(gfc_pdt_find_component_copy_initializer): Get the initializer
value for given component.
* gfortran.h (gfc_pdt_find_component_copy_initializer): New
function.
* simplify.cc (gfc_simplify_len): Replace len() of PDT with pdt
component ref or constant.
gcc/testsuite/ChangeLog:
* gfortran.dg/pdt_33.f03: New test.
Diffstat (limited to 'gcc/fortran/expr.cc')
-rw-r--r-- | gcc/fortran/expr.cc | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index e418f1f..663fe63 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -1862,6 +1862,13 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp) else if (tmp->expr_type == EXPR_CONSTANT) *newp = gfc_get_int_expr (gfc_default_integer_kind, NULL, tmp->value.character.length); + else if (gfc_init_expr_flag + && tmp->ts.u.cl->length->symtree->n.sym->attr.pdt_len) + *newp = gfc_pdt_find_component_copy_initializer (tmp->symtree->n + .sym, + tmp->ts.u.cl + ->length->symtree + ->n.sym->name); else goto cleanup; @@ -1902,7 +1909,9 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp) mpc_imagref (tmp->value.complex), GFC_RND_MODE); break; } - tmp = gfc_copy_expr (*newp); + // TODO: Fix leaking expr tmp, when simplify is done twice. + if (inquiry->next) + gfc_replace_expr (tmp, *newp); } if (!(*newp)) @@ -2067,7 +2076,7 @@ static bool simplify_ref_chain (gfc_ref *ref, int type, gfc_expr **p) { int n; - gfc_expr *newp; + gfc_expr *newp = NULL; for (; ref; ref = ref->next) { @@ -3229,7 +3238,7 @@ gfc_match_init_expr (gfc_expr **result) return m; } - if (gfc_derived_parameter_expr (expr)) + if (expr->expr_type != EXPR_FUNCTION && gfc_derived_parameter_expr (expr)) { *result = expr; gfc_init_expr_flag = false; @@ -6556,3 +6565,19 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj, return true; } + +gfc_expr* +gfc_pdt_find_component_copy_initializer (gfc_symbol *sym, const char *name) +{ + /* The actual length of a pdt is in its components. In the + initializer of the current ref is only the default value. + Therefore traverse the chain of components and pick the correct + one's initializer expressions. */ + for (gfc_component *comp = sym->ts.u.derived->components; comp != NULL; + comp = comp->next) + { + if (!strcmp (comp->name, name)) + return gfc_copy_expr (comp->initializer); + } + return NULL; +} |