This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[accaf, fortran, 1/4] Allocatable components support in derived typed coarrays
- From: Andre Vehreschild <vehre at gmx dot de>
- To: GCC-Fortran-ML <fortran at gcc dot gnu dot org>
- Cc: Damian Rouson <damian at sourceryinstitute dot org>, Tobias Burnus <burnus at net-b dot de>
- Date: Tue, 30 Aug 2016 17:50:17 +0200
- Subject: [accaf, fortran, 1/4] Allocatable components support in derived typed coarrays
- Authentication-results: sourceware.org; auth=none
Hi all,
this patch adds propagation of an in_coarray flag to the gfortran
routines that handle the creation of derived type objects and its
containing arrays. The flag is responsible for causing the add of
caf_tokens for all allocatable objects.
Furthermore adds this patch a gfc_caf_attr (gfc_expr *) routine that
works similar to the gfc_expr_attr (), but treats the codimension flag
as infectious, i.e., when there is an object with a codimension in the
expression, than this is reflected in the resulting attr. The routine
gfc_is_coarray () only returned true, when the object addressed by the
expression (after traversing all refs) was a coarray and therefore could
not be used. gfc_caf_attr() furthermore reports whether the expression
passes any allocatable component while traversing the chain of refs.
This patch is the base for part 2 of this patch set and the new
routines are only used in part 2.
Regards,
Andre
--
Andre Vehreschild * Email: vehre ad gmx dot de
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 8e2b892..b3acf1d 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -3128,10 +3128,14 @@ gfc_check_conformance (gfc_expr *op1, gfc_expr *op2, const char *optype_msgid, .
/* Given an assignable expression and an arbitrary expression, make
- sure that the assignment can take place. */
+ sure that the assignment can take place. Only add a call to the intrinsic
+ conversion routines, when allow_convert is set. When this assign is a
+ coarray call, then the convert is done by the coarray routine implictly and
+ adding the intrinsic conversion would do harm in most cases. */
bool
-gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
+gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform,
+ bool allow_convert)
{
gfc_symbol *sym;
gfc_ref *ref;
@@ -3309,12 +3313,15 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
kind values can be converted into one another. */
if (lvalue->ts.type == BT_CHARACTER && rvalue->ts.type == BT_CHARACTER)
{
- if (lvalue->ts.kind != rvalue->ts.kind)
+ if (lvalue->ts.kind != rvalue->ts.kind && allow_convert)
gfc_convert_chartype (rvalue, &lvalue->ts);
return true;
}
+ if (!allow_convert)
+ return true;
+
return gfc_convert_type (rvalue, &lvalue->ts, 1);
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 813f7d9..5ae2964 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1033,6 +1033,8 @@ typedef struct gfc_component
/* Needed for procedure pointer components. */
struct gfc_typebound_proc *tb;
+ /* When allocatable/pointer and in a coarray the associated token. */
+ tree caf_token;
}
gfc_component;
@@ -2758,7 +2760,7 @@ int gfc_validate_kind (bt, int, bool);
int gfc_get_int_kind_from_width_isofortranenv (int size);
int gfc_get_real_kind_from_width_isofortranenv (int size);
tree gfc_get_union_type (gfc_symbol *);
-tree gfc_get_derived_type (gfc_symbol * derived);
+tree gfc_get_derived_type (gfc_symbol * derived, bool in_coarray = false);
extern int gfc_index_integer_kind;
extern int gfc_default_integer_kind;
extern int gfc_max_integer_kind;
@@ -3037,7 +3039,7 @@ int gfc_numeric_ts (gfc_typespec *);
int gfc_kind_max (gfc_expr *, gfc_expr *);
bool gfc_check_conformance (gfc_expr *, gfc_expr *, const char *, ...) ATTRIBUTE_PRINTF_3;
-bool gfc_check_assign (gfc_expr *, gfc_expr *, int);
+bool gfc_check_assign (gfc_expr *, gfc_expr *, int, bool c = true);
bool gfc_check_pointer_assign (gfc_expr *, gfc_expr *);
bool gfc_check_assign_symbol (gfc_symbol *, gfc_component *, gfc_expr *);
@@ -3199,6 +3201,7 @@ const char *gfc_dt_upper_string (const char *);
/* primary.c */
symbol_attribute gfc_variable_attr (gfc_expr *, gfc_typespec *);
symbol_attribute gfc_expr_attr (gfc_expr *);
+symbol_attribute gfc_caf_attr (gfc_expr *, bool in_allocate = false);
match gfc_match_rvalue (gfc_expr **);
match gfc_match_varspec (gfc_expr*, int, bool, bool);
int gfc_check_digit (char, int);
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 396edf2..b486b4e 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2376,6 +2376,163 @@ gfc_expr_attr (gfc_expr *e)
}
+/* Given an expression, figure out what the ultimate expression
+ attribute is. This routine is similar to gfc_variable_attr with
+ parts of gfc_expr_attr, but focuses more on the needs of
+ coarrays. For coarrays a codimension attribute is kind of
+ "infectious" being propagated once set and never cleared. */
+
+static symbol_attribute
+caf_variable_attr (gfc_expr *expr, bool in_allocate)
+{
+ int dimension, codimension, pointer, allocatable, target, coarray_comp,
+ alloc_comp;
+ symbol_attribute attr;
+ gfc_ref *ref;
+ gfc_symbol *sym;
+ gfc_component *comp;
+
+ if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
+ gfc_internal_error ("gfc_caf_attr(): Expression isn't a variable");
+
+ sym = expr->symtree->n.sym;
+ gfc_clear_attr (&attr);
+
+ if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
+ {
+ dimension = CLASS_DATA (sym)->attr.dimension;
+ codimension = CLASS_DATA (sym)->attr.codimension;
+ pointer = CLASS_DATA (sym)->attr.class_pointer;
+ allocatable = CLASS_DATA (sym)->attr.allocatable;
+ coarray_comp = CLASS_DATA (sym)->attr.coarray_comp;
+ alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
+ }
+ else
+ {
+ dimension = sym->attr.dimension;
+ codimension = sym->attr.codimension;
+ pointer = sym->attr.pointer;
+ allocatable = sym->attr.allocatable;
+ coarray_comp = sym->attr.coarray_comp;
+ alloc_comp = sym->ts.type == BT_DERIVED ?
+ sym->ts.u.derived->attr.alloc_comp : 0;
+ }
+
+ target = attr.target;
+ if (pointer || attr.proc_pointer)
+ target = 1;
+
+ for (ref = expr->ref; ref; ref = ref->next)
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+
+ switch (ref->u.ar.type)
+ {
+ case AR_FULL:
+ case AR_SECTION:
+ dimension = 1;
+ break;
+
+ case AR_ELEMENT:
+ /* Handle coarrays. */
+ if (ref->u.ar.dimen > 0 && !in_allocate)
+ allocatable = pointer = 0;
+ break;
+
+ case AR_UNKNOWN:
+ /* If any of start, end or stride is not integer, there will
+ already have been an error issued. */
+ int errors;
+ gfc_get_errors (NULL, &errors);
+ if (errors == 0)
+ gfc_internal_error ("gfc_caf_attr(): Bad array reference");
+ }
+
+ break;
+
+ case REF_COMPONENT:
+ comp = ref->u.c.component;
+
+ if (comp->ts.type == BT_CLASS)
+ {
+ codimension |= CLASS_DATA (comp)->attr.codimension;
+ pointer = CLASS_DATA (comp)->attr.class_pointer;
+ allocatable = CLASS_DATA (comp)->attr.allocatable;
+ coarray_comp |= CLASS_DATA (comp)->attr.coarray_comp;
+ }
+ else
+ {
+ codimension |= comp->attr.codimension;
+ pointer = comp->attr.pointer;
+ allocatable = comp->attr.allocatable;
+ coarray_comp |= comp->attr.coarray_comp;
+ }
+
+ if (pointer || attr.proc_pointer)
+ target = 1;
+
+ break;
+
+ case REF_SUBSTRING:
+ allocatable = pointer = 0;
+ break;
+ }
+
+ attr.dimension = dimension;
+ attr.codimension = codimension;
+ attr.pointer = pointer;
+ attr.allocatable = allocatable;
+ attr.target = target;
+ attr.save = sym->attr.save;
+ attr.coarray_comp = coarray_comp;
+ attr.alloc_comp = alloc_comp;
+
+ return attr;
+}
+
+
+symbol_attribute
+gfc_caf_attr (gfc_expr *e, bool in_allocate)
+{
+ symbol_attribute attr;
+
+ switch (e->expr_type)
+ {
+ case EXPR_VARIABLE:
+ attr = caf_variable_attr (e, in_allocate);
+ break;
+
+ case EXPR_FUNCTION:
+ gfc_clear_attr (&attr);
+
+ if (e->value.function.esym && e->value.function.esym->result)
+ {
+ gfc_symbol *sym = e->value.function.esym->result;
+ attr = sym->attr;
+ if (sym->ts.type == BT_CLASS)
+ {
+ attr.dimension = CLASS_DATA (sym)->attr.dimension;
+ attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
+ attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
+ attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
+ }
+ }
+ else if (e->symtree)
+ attr = caf_variable_attr (e, in_allocate);
+ else
+ gfc_clear_attr (&attr);
+ break;
+
+ default:
+ gfc_clear_attr (&attr);
+ break;
+ }
+
+ return attr;
+}
+
+
/* Match a structure constructor. The initial symbol has already been
seen. */
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 0a92efe..7e213af 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -9746,27 +9746,29 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
return false;
}
- gfc_check_assign (lhs, rhs, 1);
-
/* Assign the 'data' of a class object to a derived type. */
if (lhs->ts.type == BT_DERIVED
&& rhs->ts.type == BT_CLASS)
gfc_add_data_component (rhs);
- /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable.
- Additionally, insert this code when the RHS is a CAF as we then use the
- GFC_ISYM_CAF_SEND intrinsic just to avoid a temporary; but do not do so if
- the LHS is (re)allocatable or has a vector subscript. If the LHS is a
- noncoindexed array and the RHS is a coindexed scalar, use the normal code
- path. */
- if (flag_coarray == GFC_FCOARRAY_LIB
+ bool caf_convert_to_send = flag_coarray == GFC_FCOARRAY_LIB
&& (lhs_coindexed
|| (code->expr2->expr_type == EXPR_FUNCTION
&& code->expr2->value.function.isym
&& code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET
&& (code->expr1->rank == 0 || code->expr2->rank != 0)
&& !gfc_expr_attr (rhs).allocatable
- && !gfc_has_vector_subscript (rhs))))
+ && !gfc_has_vector_subscript (rhs)));
+
+ gfc_check_assign (lhs, rhs, 1, !caf_convert_to_send);
+
+ /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable.
+ Additionally, insert this code when the RHS is a CAF as we then use the
+ GFC_ISYM_CAF_SEND intrinsic just to avoid a temporary; but do not do so if
+ the LHS is (re)allocatable or has a vector subscript. If the LHS is a
+ noncoindexed array and the RHS is a coindexed scalar, use the normal code
+ path. */
+ if (caf_convert_to_send)
{
if (code->expr2->expr_type == EXPR_FUNCTION
&& code->expr2->value.function.isym