summaryrefslogtreecommitdiff
path: root/gcc/fortran/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/expr.c')
-rw-r--r--gcc/fortran/expr.c79
1 files changed, 59 insertions, 20 deletions
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 73f2c40a36c..ea766537a50 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2378,21 +2378,15 @@ check_init_expr (gfc_expr *e)
return t;
}
+/* Reduces a general expression to an initialization expression (a constant).
+ This used to be part of gfc_match_init_expr.
+ Note that this function doesn't free the given expression on FAILURE. */
-/* Match an initialization expression. We work by first matching an
- expression, then reducing it to a constant. */
-
-match
-gfc_match_init_expr (gfc_expr **result)
+gfc_try
+gfc_reduce_init_expr (gfc_expr *expr)
{
- gfc_expr *expr;
- match m;
gfc_try t;
- m = gfc_match_expr (&expr);
- if (m != MATCH_YES)
- return m;
-
gfc_init_expr = 1;
t = gfc_resolve_expr (expr);
if (t == SUCCESS)
@@ -2400,18 +2394,12 @@ gfc_match_init_expr (gfc_expr **result)
gfc_init_expr = 0;
if (t == FAILURE)
- {
- gfc_free_expr (expr);
- return MATCH_ERROR;
- }
+ return FAILURE;
if (expr->expr_type == EXPR_ARRAY
&& (gfc_check_constructor_type (expr) == FAILURE
- || gfc_expand_constructor (expr) == FAILURE))
- {
- gfc_free_expr (expr);
- return MATCH_ERROR;
- }
+ || gfc_expand_constructor (expr) == FAILURE))
+ return FAILURE;
/* Not all inquiry functions are simplified to constant expressions
so it is necessary to call check_inquiry again. */
@@ -2419,6 +2407,33 @@ gfc_match_init_expr (gfc_expr **result)
&& !gfc_in_match_data ())
{
gfc_error ("Initialization expression didn't reduce %C");
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+
+/* Match an initialization expression. We work by first matching an
+ expression, then reducing it to a constant. */
+
+match
+gfc_match_init_expr (gfc_expr **result)
+{
+ gfc_expr *expr;
+ match m;
+ gfc_try t;
+
+ expr = NULL;
+
+ m = gfc_match_expr (&expr);
+ if (m != MATCH_YES)
+ return m;
+
+ t = gfc_reduce_init_expr (expr);
+ if (t != SUCCESS)
+ {
+ gfc_free_expr (expr);
return MATCH_ERROR;
}
@@ -3487,3 +3502,27 @@ gfc_expr_check_typed (gfc_expr* e, gfc_namespace* ns, bool strict)
return error_found ? FAILURE : SUCCESS;
}
+
+/* Walk an expression tree and replace all symbols with a corresponding symbol
+ in the formal_ns of "sym". Needed for copying interfaces in PROCEDURE
+ statements. The boolean return value is required by gfc_traverse_expr. */
+
+static bool
+replace_symbol (gfc_expr *expr, gfc_symbol *sym, int *i ATTRIBUTE_UNUSED)
+{
+ if ((expr->expr_type == EXPR_VARIABLE || expr->expr_type == EXPR_FUNCTION)
+ && expr->symtree->n.sym->ns == sym->ts.interface->formal_ns)
+ {
+ gfc_symtree *stree;
+ gfc_get_sym_tree (expr->symtree->name, sym->formal_ns, &stree);
+ stree->n.sym->attr = expr->symtree->n.sym->attr;
+ expr->symtree = stree;
+ }
+ return false;
+}
+
+void
+gfc_expr_replace_symbols (gfc_expr *expr, gfc_symbol *dest)
+{
+ gfc_traverse_expr (expr, dest, &replace_symbol, 0);
+}