diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-03 10:57:46 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-03 10:57:46 +0000 |
commit | 159b58ddeefa62da79bd458d8d606509b37a7d7b (patch) | |
tree | 30c34b02b14ff9991fdc56cb67585061e9dff779 /gcc/fortran | |
parent | 578512b16c7b69545b35e7547f28d7deeaf798f5 (diff) | |
download | gcc-159b58ddeefa62da79bd458d8d606509b37a7d7b.tar.gz |
2012-01-03 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 182833 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@182834 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 66 | ||||
-rw-r--r-- | gcc/fortran/dependency.c | 39 | ||||
-rw-r--r-- | gcc/fortran/dump-parse-tree.c | 1 | ||||
-rw-r--r-- | gcc/fortran/expr.c | 19 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 6 | ||||
-rw-r--r-- | gcc/fortran/gfortranspec.c | 4 | ||||
-rw-r--r-- | gcc/fortran/interface.c | 10 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 113 | ||||
-rw-r--r-- | gcc/fortran/trans-array.c | 14 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 371 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 16 |
11 files changed, 459 insertions, 200 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index d9a9b430a42..d752513e999 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,68 @@ +2012-01-03 Hans-Peter Nilsson <hp@axis.com> + + * gfortran.h (struct gfc_expr): Add missing "struct" + qualifier for member base_expr. + +2012-01-02 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/51529 + * trans-array.c (gfc_array_allocate): Null allocated memory of + newly allocted class arrays. + + PR fortran/46262 + PR fortran/46328 + PR fortran/51052 + * interface.c(build_compcall_for_operator): Add a type to the + expression. + * trans-expr.c (conv_base_obj_fcn_val): New function. + (gfc_conv_procedure_call): Use base_expr to detect non-variable + base objects and, ensuring that there is a temporary variable, + build up the typebound call using conv_base_obj_fcn_val. + (gfc_trans_class_assign): Pick out class procedure pointer + assignments and do the assignment with no further prcessing. + (gfc_trans_class_array_init_assign, gfc_trans_class_init_assign + gfc_trans_class_assign): Move to top of file. + * gfortran.h : Add 'base_expr' field to gfc_expr. + * resolve.c (get_declared_from_expr): Add 'types' argument to + switch checking of derived types on or off. + (resolve_typebound_generic_call): Set the new argument. + (resolve_typebound_function, resolve_typebound_subroutine): + Set 'types' argument for get_declared_from_expr appropriately. + Identify base expression, if not a variable, in the argument + list of class valued calls. Assign it to the 'base_expr' field + of the final expression. Strip away all references after the + last class reference. + +2012-01-02 Tobias Burnus <burnus@net-b.de> + + PR fortran/51682 + * trans-intrinsic.c (trans_this_image, trans_image_index, + trans_num_images, conv_intrinsic_cobound): Fold_convert the + caf_num_images/caf_this_images variables to the correct int kind. + +2012-01-01 Jakub Jelinek <jakub@redhat.com> + + * gfortranspec.c (lang_specific_driver): Update copyright notice + dates. + +2011-12-31 Thomas König <tkoenig@gcc.gnu.org> + + PR fortran/51502 + * expr.c (gfc_check_vardef_context): When determining + implicit pure status, also check for variable definition + context. Walk up namespaces until a procedure is + found to reset the implict pure attribute. + * resolve.c (gfc_implicit_pure): Walk up namespaces + until a procedure is found. + +2011-12-29 Thomas Koenig <tkoenig@gcc.gnu.org> + + * dependency.c (gfc_dep_compare_functions): Document + new behavior for REALs and complex. Add comment to cases + where only INTEGERs are handled. Compare REAL and COMPLEX + constants, returning 0 and -2 only. Add assert to make + sure that only integer constants are compared. + 2011-12-19 Tobias Burnus <burnus@net-b.de> PR fortran/51605 @@ -37,6 +102,7 @@ non-compile-time-constant-shape arrays to have a default initializer. * invoke.texi: Delete the restriction on automatic arrays not + being initialized by -finit-<type>=<constant>. 2011-12-15 Tobias Burnus <burnus@net-b.de> diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c index 96c4e5fd990..a2cf21d65f1 100644 --- a/gcc/fortran/dependency.c +++ b/gcc/fortran/dependency.c @@ -245,7 +245,9 @@ gfc_dep_compare_functions (gfc_expr *e1, gfc_expr *e2, bool impure_ok) * 0 if e1 == e2 * -1 if e1 < e2 * -2 if the relationship could not be determined - * -3 if e1 /= e2, but we cannot tell which one is larger. */ + * -3 if e1 /= e2, but we cannot tell which one is larger. + REAL and COMPLEX constants are only compared for equality + or inequality; if they are unequal, -2 is returned in all cases. */ int gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) @@ -303,7 +305,7 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) if (e1->expr_type == EXPR_OP && e1->value.op.op == INTRINSIC_PLUS) { - /* Compare X+C vs. X. */ + /* Compare X+C vs. X, for INTEGER only. */ if (e1->value.op.op2->expr_type == EXPR_CONSTANT && e1->value.op.op2->ts.type == BT_INTEGER && gfc_dep_compare_expr (e1->value.op.op1, e2) == 0) @@ -342,7 +344,7 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) } } - /* Compare X vs. X+C. */ + /* Compare X vs. X+C, for INTEGER only. */ if (e2->expr_type == EXPR_OP && e2->value.op.op == INTRINSIC_PLUS) { if (e2->value.op.op2->expr_type == EXPR_CONSTANT @@ -351,7 +353,7 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) return -mpz_sgn (e2->value.op.op2->value.integer); } - /* Compare X-C vs. X. */ + /* Compare X-C vs. X, for INTEGER only. */ if (e1->expr_type == EXPR_OP && e1->value.op.op == INTRINSIC_MINUS) { if (e1->value.op.op2->expr_type == EXPR_CONSTANT @@ -415,7 +417,7 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) } } - /* Compare X vs. X-C. */ + /* Compare X vs. X-C, for INTEGER only. */ if (e2->expr_type == EXPR_OP && e2->value.op.op == INTRINSIC_MINUS) { if (e2->value.op.op2->expr_type == EXPR_CONSTANT @@ -434,9 +436,34 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) if (e1->ts.type == BT_CHARACTER && e2->ts.type == BT_CHARACTER) return gfc_compare_string (e1, e2); + /* Compare REAL and COMPLEX constants. Because of the + traps and pitfalls associated with comparing + a + 1.0 with a + 0.5, check for equality only. */ + if (e2->expr_type == EXPR_CONSTANT) + { + if (e1->ts.type == BT_REAL && e2->ts.type == BT_REAL) + { + if (mpfr_cmp (e1->value.real, e2->value.real) == 0) + return 0; + else + return -2; + } + else if (e1->ts.type == BT_COMPLEX && e2->ts.type == BT_COMPLEX) + { + if (mpc_cmp (e1->value.complex, e2->value.complex) == 0) + return 0; + else + return -2; + } + } + if (e1->ts.type != BT_INTEGER || e2->ts.type != BT_INTEGER) return -2; + /* For INTEGER, all cases where e2 is not constant should have + been filtered out above. */ + gcc_assert (e2->expr_type == EXPR_CONSTANT); + i = mpz_cmp (e1->value.integer, e2->value.integer); if (i == 0) return 0; @@ -465,7 +492,7 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) else if (e1->value.op.op == INTRINSIC_TIMES && gfc_dep_compare_expr (e1->value.op.op1, e2->value.op.op2) == 0 && gfc_dep_compare_expr (e1->value.op.op2, e2->value.op.op1) == 0) - /* Commutativity of multiplication. */ + /* Commutativity of multiplication; addition is handled above. */ return 0; return -2; diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index af2cd85a561..c715b30d397 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -2330,3 +2330,4 @@ gfc_dump_parse_tree (gfc_namespace *ns, FILE *file) dumpfile = file; show_namespace (ns); } + diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index d8ae04f0494..182738cbf3d 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -4690,9 +4690,24 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj, return FAILURE; } - if (!pointer && gfc_implicit_pure (NULL) && gfc_impure_variable (sym)) - gfc_current_ns->proc_name->attr.implicit_pure = 0; + if (!pointer && context && gfc_implicit_pure (NULL) + && gfc_impure_variable (sym)) + { + gfc_namespace *ns; + gfc_symbol *sym; + for (ns = gfc_current_ns; ns; ns = ns->parent) + { + sym = ns->proc_name; + if (sym == NULL) + break; + if (sym->attr.flavor == FL_PROCEDURE) + { + sym->attr.implicit_pure = 0; + break; + } + } + } /* Check variable definition context for associate-names. */ if (!pointer && sym->assoc) { diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index daa28965189..e8a3de05011 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1,6 +1,6 @@ /* gfortran header file Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 + 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Andy Vaught @@ -1697,6 +1697,10 @@ typedef struct gfc_expr locus where; + /* Used to store the base expression in component calls, when the expression + is not a variable. */ + struct gfc_expr *base_expr; + /* is_boz is true if the integer is regarded as BOZ bitpatten and is_snan denotes a signalling not-a-number. */ unsigned int is_boz : 1, is_snan : 1; diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c index 75ce05fca1c..2240bfb9985 100644 --- a/gcc/fortran/gfortranspec.c +++ b/gcc/fortran/gfortranspec.c @@ -1,6 +1,6 @@ /* Specific flags and argument handling of the Fortran front-end. Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009, 2010, 2011 + 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -301,7 +301,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, case OPT__version: printf ("GNU Fortran %s%s\n", pkgversion_string, version_string); - printf ("Copyright %s 2011 Free Software Foundation, Inc.\n\n", + printf ("Copyright %s 2012 Free Software Foundation, Inc.\n\n", _("(C)")); printf (_("GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\ You may redistribute copies of GNU Fortran\n\ diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index e914c6c7910..773749d5ebc 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -1,6 +1,6 @@ /* Deal with interfaces. Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 + 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Andy Vaught @@ -3256,6 +3256,14 @@ build_compcall_for_operator (gfc_expr* e, gfc_actual_arglist* actual, e->value.compcall.base_object = base; e->value.compcall.ignore_pass = 1; e->value.compcall.assign = 0; + if (e->ts.type == BT_UNKNOWN + && target->function) + { + if (target->is_generic) + e->ts = target->u.generic->specific->u.specific->n.sym->ts; + else + e->ts = target->u.specific->n.sym->ts; + } } diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 4bfdb7987bf..82045f8ea23 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -1,6 +1,6 @@ /* Perform type resolution on the various structures. Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011 + 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Andy Vaught @@ -5620,10 +5620,11 @@ resolve_typebound_static (gfc_expr* e, gfc_symtree** target, /* Get the ultimate declared type from an expression. In addition, return the last class/derived type reference and the copy of the - reference list. */ + reference list. If check_types is set true, derived types are + identified as well as class references. */ static gfc_symbol* get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref, - gfc_expr *e) + gfc_expr *e, bool check_types) { gfc_symbol *declared; gfc_ref *ref; @@ -5639,8 +5640,9 @@ get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref, if (ref->type != REF_COMPONENT) continue; - if (ref->u.c.component->ts.type == BT_CLASS - || ref->u.c.component->ts.type == BT_DERIVED) + if ((ref->u.c.component->ts.type == BT_CLASS + || (check_types && ref->u.c.component->ts.type == BT_DERIVED)) + && ref->u.c.component->attr.flavor != FL_PROCEDURE) { declared = ref->u.c.component->ts.u.derived; if (class_ref) @@ -5735,7 +5737,7 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name) success: /* Make sure that we have the right specific instance for the name. */ - derived = get_declared_from_expr (NULL, NULL, e); + derived = get_declared_from_expr (NULL, NULL, e, true); st = gfc_find_typebound_proc (derived, NULL, genname, true, &e->where); if (st) @@ -5852,7 +5854,7 @@ resolve_compcall (gfc_expr* e, const char **name) /* Resolve a typebound function, or 'method'. First separate all the non-CLASS references by calling resolve_compcall directly. */ -static gfc_try +gfc_try resolve_typebound_function (gfc_expr* e) { gfc_symbol *declared; @@ -5872,6 +5874,21 @@ resolve_typebound_function (gfc_expr* e) overridable = !e->value.compcall.tbp->non_overridable; if (expr && expr->ts.type == BT_CLASS && e->value.compcall.name) { + /* If the base_object is not a variable, the corresponding actual + argument expression must be stored in e->base_expression so + that the corresponding tree temporary can be used as the base + object in gfc_conv_procedure_call. */ + if (expr->expr_type != EXPR_VARIABLE) + { + gfc_actual_arglist *args; + + for (args= e->value.function.actual; args; args = args->next) + { + if (expr == args->expr) + expr = args->expr; + } + } + /* Since the typebound operators are generic, we have to ensure that any delays in resolution are corrected and that the vtab is present. */ @@ -5888,9 +5905,26 @@ resolve_typebound_function (gfc_expr* e) name = name ? name : e->value.function.esym->name; e->symtree = expr->symtree; e->ref = gfc_copy_ref (expr->ref); + get_declared_from_expr (&class_ref, NULL, e, false); + + /* Trim away the extraneous references that emerge from nested + use of interface.c (extend_expr). */ + if (class_ref && class_ref->next) + { + gfc_free_ref_list (class_ref->next); + class_ref->next = NULL; + } + else if (e->ref && !class_ref) + { + gfc_free_ref_list (e->ref); + e->ref = NULL; + } + gfc_add_vptr_component (e); gfc_add_component_ref (e, name); e->value.function.esym = NULL; + if (expr->expr_type != EXPR_VARIABLE) + e->base_expr = expr; return SUCCESS; } @@ -5901,7 +5935,7 @@ resolve_typebound_function (gfc_expr* e) return FAILURE; /* Get the CLASS declared type. */ - declared = get_declared_from_expr (&class_ref, &new_ref, e); + declared = get_declared_from_expr (&class_ref, &new_ref, e, true); /* Weed out cases of the ultimate component being a derived type. */ if ((class_ref && class_ref->u.c.component->ts.type == BT_DERIVED) @@ -5967,6 +6001,20 @@ resolve_typebound_subroutine (gfc_code *code) overridable = !code->expr1->value.compcall.tbp->non_overridable; if (expr && expr->ts.type == BT_CLASS && code->expr1->value.compcall.name) { + /* If the base_object is not a variable, the corresponding actual + argument expression must be stored in e->base_expression so + that the corresponding tree temporary can be used as the base + object in gfc_conv_procedure_call. */ + if (expr->expr_type != EXPR_VARIABLE) + { + gfc_actual_arglist *args; + + args= code->expr1->value.function.actual; + for (; args; args = args->next) + if (expr == args->expr) + expr = args->expr; + } + /* Since the typebound operators are generic, we have to ensure that any delays in resolution are corrected and that the vtab is present. */ @@ -5982,9 +6030,27 @@ resolve_typebound_subroutine (gfc_code *code) name = name ? name : code->expr1->value.function.esym->name; code->expr1->symtree = expr->symtree; code->expr1->ref = gfc_copy_ref (expr->ref); + + /* Trim away the extraneous references that emerge from nested + use of interface.c (extend_expr). */ + get_declared_from_expr (&class_ref, NULL, code->expr1, false); + if (class_ref && class_ref->next) + { + gfc_free_ref_list (class_ref->next); + class_ref->next = NULL; + } + else if (code->expr1->ref && !class_ref) + { + gfc_free_ref_list (code->expr1->ref); + code->expr1->ref = NULL; + } + + /* Now use the procedure in the vtable. */ gfc_add_vptr_component (code->expr1); gfc_add_component_ref (code->expr1, name); code->expr1->value.function.esym = NULL; + if (expr->expr_type != EXPR_VARIABLE) + code->expr1->base_expr = expr; return SUCCESS; } @@ -5995,7 +6061,7 @@ resolve_typebound_subroutine (gfc_code *code) return FAILURE; /* Get the CLASS declared type. */ - get_declared_from_expr (&class_ref, &new_ref, code->expr1); + get_declared_from_expr (&class_ref, &new_ref, code->expr1, true); /* Weed out cases of the ultimate component being a derived type. */ if ((class_ref && class_ref->u.c.component->ts.type == BT_DERIVED) @@ -13103,24 +13169,25 @@ gfc_pure (gfc_symbol *sym) int gfc_implicit_pure (gfc_symbol *sym) { - symbol_attribute attr; + gfc_namespace *ns; if (sym == NULL) { - /* Check if the current namespace is implicit_pure. */ - sym = gfc_current_ns->proc_name; - if (sym == NULL) - return 0; - attr = sym->attr; - if (attr.flavor == FL_PROCEDURE - && attr.implicit_pure && !attr.pure) - return 1; - return 0; + /* Check if the current procedure is implicit_pure. Walk up + the procedure list until we find a procedure. */ + for (ns = gfc_current_ns; ns; ns = ns->parent) + { + sym = ns->proc_name; + if (sym == NULL) + return 0; + + if (sym->attr.flavor == FL_PROCEDURE) + break; + } } - - attr = sym->attr; - - return attr.flavor == FL_PROCEDURE && attr.implicit_pure && !attr.pure; + + return sym->attr.flavor == FL_PROCEDURE && sym->attr.implicit_pure + && !sym->attr.pure; } diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index a6443129156..50e1ee422f9 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -1,6 +1,6 @@ /* Array translation routines Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 + 2011, 2012 Free Software Foundation, Inc. Contributed by Paul Brook <paul@nowt.org> and Steven Bosscher <s.bosscher@student.tudelft.nl> @@ -5069,6 +5069,18 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, gfc_add_expr_to_block (&se->pre, tmp); + if (expr->ts.type == BT_CLASS && expr3) + { + tmp = build_int_cst (unsigned_char_type_node, 0); + /* For class objects we need to nullify the memory in case they have + allocatable components; the reason is that _copy, which is used for + initialization, first frees the destination. */ + tmp = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_MEMSET), + 3, pointer, tmp, size); + gfc_add_expr_to_block (&se->pre, tmp); + } + /* Update the array descriptors. */ if (dimension) gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset); diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 83d8087fd50..2ffa9fc2af7 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -1,6 +1,6 @@ /* Expression translation Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 + 2011, 2012 Free Software Foundation, Inc. Contributed by Paul Brook <paul@nowt.org> and Steven Bosscher <s.bosscher@student.tudelft.nl> @@ -302,6 +302,179 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, parmse->expr = gfc_build_addr_expr (NULL_TREE, var); } + +static tree +gfc_trans_class_array_init_assign (gfc_expr *rhs, gfc_expr *lhs, gfc_expr *obj) +{ + gfc_actual_arglist *actual; + gfc_expr *ppc; + gfc_code *ppc_code; + tree res; + + actual = gfc_get_actual_arglist (); + actual->expr = gfc_copy_expr (rhs); + actual->next = gfc_get_actual_arglist (); + actual->next->expr = gfc_copy_expr (lhs); + ppc = gfc_copy_expr (obj); + gfc_add_vptr_component (ppc); + gfc_add_component_ref (ppc, "_copy"); + ppc_code = gfc_get_code (); + ppc_code->resolved_sym = ppc->symtree->n.sym; + /* Although '_copy' is set to be elemental in class.c, it is + not staying that way. Find out why, sometime.... */ + ppc_code->resolved_sym->attr.elemental = 1; + ppc_code->ext.actual = actual; + ppc_code->expr1 = ppc; + ppc_code->op = EXEC_CALL; + /* Since '_copy' is elemental, the scalarizer will take care + of arrays in gfc_trans_call. */ + res = gfc_trans_call (ppc_code, false, NULL, NULL, false); + gfc_free_statements (ppc_code); + return res; +} + +/* Special case for initializing a polymorphic dummy with INTENT(OUT). + A MEMCPY is needed to copy the full data from the default initializer + of the dynamic type. */ + +tree +gfc_trans_class_init_assign (gfc_code *code) +{ + stmtblock_t block; + tree tmp; + gfc_se dst,src,memsz; + gfc_expr *lhs, *rhs, *sz; + + gfc_start_block (&block); + + lhs = gfc_copy_expr (code->expr1); + gfc_add_data_component (lhs); + + rhs = gfc_copy_expr (code->expr1); + gfc_add_vptr_component (rhs); + + /* Make sure that the component backend_decls have been built, which + will not have happened if the derived types concerned have not + been referenced. */ + gfc_get_derived_type (rhs->ts.u.derived); + gfc_add_def_init_component (rhs); + + if (code->expr1->ts.type == BT_CLASS + && CLASS_DATA (code->expr1)->attr.dimension) + tmp = gfc_trans_class_array_init_assign (rhs, lhs, code->expr1); + else + { + sz = gfc_copy_expr (code->expr1); + gfc_add_vptr_component (sz); + gfc_add_size_component (sz); + + gfc_init_se (&dst, NULL); + gfc_init_se (&src, NULL); + gfc_init_se (&memsz, NULL); + gfc_conv_expr (&dst, lhs); + gfc_conv_expr (&src, rhs); + gfc_conv_expr (&memsz, sz); + gfc_add_block_to_block (&block, &src.pre); + tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr); + } + gfc_add_expr_to_block (&block, tmp); + + return gfc_finish_block (&block); +} + + +/* Translate an assignment to a CLASS object + (pointer or ordinary assignment). */ + +tree +gfc_trans_class_assign (gfc_expr *expr1, gfc_expr *expr2, gfc_exec_op op) +{ + stmtblock_t block; + tree tmp; + gfc_expr *lhs; + gfc_expr *rhs; + gfc_ref *ref; + + gfc_start_block (&block); + + ref = expr1->ref; + while (ref && ref->next) + ref = ref->next; + + /* Class valued proc_pointer assignments do not need any further + preparation. */ + if (ref && ref->type == REF_COMPONENT + && ref->u.c.component->attr.proc_pointer + && expr2->expr_type == EXPR_VARIABLE + && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE + && op == EXEC_POINTER_ASSIGN) + goto assign; + + if (expr2->ts.type != BT_CLASS) + { + /* Insert an additional assignment which sets the '_vptr' field. */ + gfc_symbol *vtab = NULL; + gfc_symtree *st; + + lhs = gfc_copy_expr (expr1); + gfc_add_vptr_component (lhs); + + if (expr2->ts.type == BT_DERIVED) + vtab = gfc_find_derived_vtab (expr2->ts.u.derived); + else if (expr2->expr_type == EXPR_NULL) + vtab = gfc_find_derived_vtab (expr1->ts.u.derived); + gcc_assert (vtab); + + rhs = gfc_get_expr (); + rhs->expr_type = EXPR_VARIABLE; + gfc_find_sym_tree (vtab->name, vtab->ns, 1, &st); + rhs->symtree = st; + rhs->ts = vtab->ts; + + tmp = gfc_trans_pointer_assignment (lhs, rhs); + gfc_add_expr_to_block (&block, tmp); + + gfc_free_expr (lhs); + gfc_free_expr (rhs); + } + else if (CLASS_DATA (expr2)->attr.dimension) + { + /* Insert an additional assignment which sets the '_vptr' field. */ + lhs = gfc_copy_expr (expr1); + gfc_add_vptr_component (lhs); + + rhs = gfc_copy_expr (expr2); + gfc_add_vptr_component (rhs); + + tmp = gfc_trans_pointer_assignment (lhs, rhs); + gfc_add_expr_to_block (&block, tmp); + + gfc_free_expr (lhs); + gfc_free_expr (rhs); + } + + /* Do the actual CLASS assignment. */ + if (expr2->ts.type == BT_CLASS + && !CLASS_DATA (expr2)->attr.dimension) + op = EXEC_ASSIGN; + else + gfc_add_data_component (expr1); + +assign: + + if (op == EXEC_ASSIGN) + tmp = gfc_trans_assignment (expr1, expr2, false, true); + else if (op == EXEC_POINTER_ASSIGN) + tmp = gfc_trans_pointer_assignment (expr1, expr2); + else + gcc_unreachable(); + + gfc_add_expr_to_block (&block, tmp); + + return gfc_finish_block (&block); +} + + /* End of prototype trans-class.c */ @@ -1976,6 +2149,31 @@ get_proc_ptr_comp (gfc_expr *e) } +/* Convert a typebound function reference from a class object. */ +static void +conv_base_obj_fcn_val (gfc_se * se, tree base_object, gfc_expr * expr) +{ + gfc_ref *ref; + tree var; + + if (TREE_CODE (base_object) != VAR_DECL) + { + var = gfc_create_var (TREE_TYPE (base_object), NULL); + gfc_add_modify (&se->pre, var, base_object); + } + se->expr = gfc_class_vptr_get (base_object); + se->expr = build_fold_indirect_ref_loc (input_location, se->expr); + ref = expr->ref; + while (ref && ref->next) + ref = ref->next; + gcc_assert (ref && ref->type == REF_COMPONENT); + if (ref->u.c.sym->attr.extension) + conv_parent_component_references (se, ref); + gfc_conv_component_ref (se, ref); + se->expr = build_fold_addr_expr_loc (input_location, se->expr); +} + + static void conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr) { @@ -3084,6 +3282,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, tree type; tree var; tree len; + tree base_object; VEC(tree,gc) *stringargs; tree result = NULL; gfc_formal_arglist *formal; @@ -3156,6 +3355,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, != EXPR_CONSTANT); } + base_object = NULL_TREE; + /* Evaluate the arguments. */ for (arg = args; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL) @@ -3301,6 +3502,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, { gfc_conv_expr_reference (&parmse, e); + /* Catch base objects that are not variables. */ + if (e->ts.type == BT_CLASS + && e->expr_type != EXPR_VARIABLE + && expr && e == expr->base_expr) + base_object = build_fold_indirect_ref_loc (input_location, + parmse.expr); + /* A class array element needs converting back to be a class object, if the formal argument is a class object. */ if (fsym && fsym->ts.type == BT_CLASS @@ -4000,7 +4208,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, arglist = retargs; /* Generate the actual call. */ - conv_function_val (se, sym, expr); + if (base_object == NULL_TREE) + conv_function_val (se, sym, expr); + else + conv_base_obj_fcn_val (se, base_object, expr); /* If there are alternate return labels, function type should be integer. Can't modify the type in place though, since it can be shared @@ -5294,7 +5505,6 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr) return; } - gfc_conv_expr (se, expr); /* Create a temporary var to hold the value. */ @@ -6730,158 +6940,3 @@ gfc_trans_assign (gfc_code * code) { return gfc_trans_assignment (code->expr1, code->expr2, false, true); } - - -static tree -gfc_trans_class_array_init_assign (gfc_expr *rhs, gfc_expr *lhs, gfc_expr *obj) -{ - gfc_actual_arglist *actual; - gfc_expr *ppc; - gfc_code *ppc_code; - tree res; - - actual = gfc_get_actual_arglist (); - actual->expr = gfc_copy_expr (rhs); - actual->next = gfc_get_actual_arglist (); - actual->next->expr = gfc_copy_expr (lhs); - ppc = gfc_copy_expr (obj); - gfc_add_vptr_component (ppc); - gfc_add_component_ref (ppc, "_copy"); - ppc_code = gfc_get_code (); - ppc_code->resolved_sym = ppc->symtree->n.sym; - /* Although '_copy' is set to be elemental in class.c, it is - not staying that way. Find out why, sometime.... */ - ppc_code->resolved_sym->attr.elemental = 1; - ppc_code->ext.actual = actual; - ppc_code->expr1 = ppc; - ppc_code->op = EXEC_CALL; - /* Since '_copy' is elemental, the scalarizer will take care - of arrays in gfc_trans_call. */ - res = gfc_trans_call (ppc_code, false, NULL, NULL, false); - gfc_free_statements (ppc_code); - return res; -} - -/* Special case for initializing a polymorphic dummy with INTENT(OUT). - A MEMCPY is needed to copy the full data from the default initializer - of the dynamic type. */ - -tree -gfc_trans_class_init_assign (gfc_code *code) -{ - stmtblock_t block; - tree tmp; - gfc_se dst,src,memsz; - gfc_expr *lhs,*rhs,*sz; - - gfc_start_block (&block); - - lhs = gfc_copy_expr (code->expr1); - gfc_add_data_component (lhs); - - rhs = gfc_copy_expr (code->expr1); - gfc_add_vptr_component (rhs); - - /* Make sure that the component backend_decls have been built, which - will not have happened if the derived types concerned have not - been referenced. */ - gfc_get_derived_type (rhs->ts.u.derived); - gfc_add_def_init_component (rhs); - - if (code->expr1->ts.type == BT_CLASS - && CLASS_DATA (code->expr1)->attr.dimension) - tmp = gfc_trans_class_array_init_assign (rhs, lhs, code->expr1); - else - { - sz = gfc_copy_expr (code->expr1); - gfc_add_vptr_component (sz); - gfc_add_size_component (sz); - - gfc_init_se (&dst, NULL); - gfc_init_se (&src, NULL); - gfc_init_se (&memsz, NULL); - gfc_conv_expr (&dst, lhs); - gfc_conv_expr (&src, rhs); - gfc_conv_expr (&memsz, sz); - gfc_add_block_to_block (&block, &src.pre); - tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr); - } - gfc_add_expr_to_block (&block, tmp); - - return gfc_finish_block (&block); -} - - -/* Translate an assignment to a CLASS object - (pointer or ordinary assignment). */ - -tree -gfc_trans_class_assign (gfc_expr *expr1, gfc_expr *expr2, gfc_exec_op op) -{ - stmtblock_t block; - tree tmp; - gfc_expr *lhs; - gfc_expr *rhs; - - gfc_start_block (&block); - - if (expr2->ts.type != BT_CLASS) - { - /* Insert an additional assignment which sets the '_vptr' field. */ - gfc_symbol *vtab = NULL; - gfc_symtree *st; - - lhs = gfc_copy_expr (expr1); - gfc_add_vptr_component (lhs); - - if (expr2->ts.type == BT_DERIVED) - vtab = gfc_find_derived_vtab (expr2->ts.u.derived); - else if (expr2->expr_type == EXPR_NULL) - vtab = gfc_find_derived_vtab (expr1->ts.u.derived); - gcc_assert (vtab); - - rhs = gfc_get_expr (); - rhs->expr_type = EXPR_VARIABLE; - gfc_find_sym_tree (vtab->name, vtab->ns, 1, &st); - rhs->symtree = st; - rhs->ts = vtab->ts; - - tmp = gfc_trans_pointer_assignment (lhs, rhs); - gfc_add_expr_to_block (&block, tmp); - - gfc_free_expr (lhs); - gfc_free_expr (rhs); - } - else if (CLASS_DATA (expr2)->attr.dimension) - { - /* Insert an additional assignment which sets the '_vptr' field. */ - lhs = gfc_copy_expr (expr1); - gfc_add_vptr_component (lhs); - - rhs = gfc_copy_expr (expr2); - gfc_add_vptr_component (rhs); - - tmp = gfc_trans_pointer_assignment (lhs, rhs); - gfc_add_expr_to_block (&block, tmp); - - gfc_free_expr (lhs); - gfc_free_expr (rhs); - } - - /* Do the actual CLASS assignment. */ - if (expr2->ts.type == BT_CLASS && !CLASS_DATA (expr2)->attr.dimension) - op = EXEC_ASSIGN; - else - gfc_add_data_component (expr1); - - if (op == EXEC_ASSIGN) - tmp = gfc_trans_assignment (expr1, expr2, false, true); - else if (op == EXEC_POINTER_ASSIGN) - tmp = gfc_trans_pointer_assignment (expr1, expr2); - else - gcc_unreachable(); - - gfc_add_expr_to_block (&block, tmp); - - return gfc_finish_block (&block); -} diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 5c964c1229f..2bc628d40f2 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -978,7 +978,8 @@ trans_this_image (gfc_se * se, gfc_expr *expr) /* Argument-free version: THIS_IMAGE(). */ if (expr->value.function.actual->expr == NULL) { - se->expr = gfort_gvar_caf_this_image; + se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), + gfort_gvar_caf_this_image); return; } @@ -1053,7 +1054,7 @@ trans_this_image (gfc_se * se, gfc_expr *expr) /* Used algorithm; cf. Fortran 2008, C.10. Note, due to the scalarizer, one always has a dim_arg argument. - m = this_images() - 1 + m = this_image() - 1 if (corank == 1) { sub(1) = m + lcobound(corank) @@ -1289,7 +1290,7 @@ trans_image_index (gfc_se * se, gfc_expr *expr) else { gfc_init_coarray_decl (false); - num_images = gfort_gvar_caf_num_images; + num_images = fold_convert (type, gfort_gvar_caf_num_images); } tmp = gfc_create_var (type, NULL); @@ -1309,7 +1310,8 @@ static void trans_num_images (gfc_se * se) { gfc_init_coarray_decl (false); - se->expr = gfort_gvar_caf_num_images; + se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), + gfort_gvar_caf_num_images); } @@ -1614,7 +1616,8 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr) tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - gfort_gvar_caf_num_images, + fold_convert (gfc_array_index_type, + gfort_gvar_caf_num_images), build_int_cst (gfc_array_index_type, 1)); tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, gfc_array_index_type, tmp, @@ -1628,7 +1631,8 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr) gfc_init_coarray_decl (false); tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - gfort_gvar_caf_num_images, + fold_convert (gfc_array_index_type, + gfort_gvar_caf_num_images), build_int_cst (gfc_array_index_type, 1)); resbound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, resbound, tmp); |