summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-03 10:57:46 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-03 10:57:46 +0000
commit159b58ddeefa62da79bd458d8d606509b37a7d7b (patch)
tree30c34b02b14ff9991fdc56cb67585061e9dff779 /gcc/fortran
parent578512b16c7b69545b35e7547f28d7deeaf798f5 (diff)
downloadgcc-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/ChangeLog66
-rw-r--r--gcc/fortran/dependency.c39
-rw-r--r--gcc/fortran/dump-parse-tree.c1
-rw-r--r--gcc/fortran/expr.c19
-rw-r--r--gcc/fortran/gfortran.h6
-rw-r--r--gcc/fortran/gfortranspec.c4
-rw-r--r--gcc/fortran/interface.c10
-rw-r--r--gcc/fortran/resolve.c113
-rw-r--r--gcc/fortran/trans-array.c14
-rw-r--r--gcc/fortran/trans-expr.c371
-rw-r--r--gcc/fortran/trans-intrinsic.c16
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);