OK, I played a bit myself to see what the "right way" would look like, and I
came up with the attached patch, which is complicated, and not even correct.
And indeed, it plays with allocatable and pointer stuff.
So your approach makes some sense now.
I do here some propositions for comment and error messages which IMO explain
better where the problem lies (Iff I have understood the problem correctly).
They are quite verbose however, and possibly not correct english (many
negations).
One could consider separating the "is LOCK_TYPE type" and "type has type
LOCK_TYPE components" cases to make the diagnostic easier to read, but that
would make the code even more complex.
Anyway comments and propositions welcome.
review, 2nd try:
> diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
> index 2910ab5..9f732e5 100644
> --- a/gcc/fortran/parse.c
> +++ b/gcc/fortran/parse.c
> @@ -2148,15 +2157,61 @@ endType:
>
> /* Looking for coarray components. */
> if (c->attr.codimension
> - || (c->attr.coarray_comp && !c->attr.pointer && !c->attr.allocatable))
> - sym->attr.coarray_comp = 1;
> + || (c->ts.type == BT_CLASS && c->attr.class_ok
> + && CLASS_DATA (c)->attr.codimension))
> + {
> + coarray = true;
> + sym->attr.coarray_comp = 1;
> + }
> +
> + if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.codimension)
- Err, is the codimension attribute on the derived type?
Or did you mean [...] && c->ts.u.derived->attr.coarray_comp (to match the code
removed)?
> + {
> + coarray = true;
> + if (!pointer && !allocatable)
> + sym->attr.coarray_comp = 1;
> + }
>
> /* Looking for lock_type components. */
> - if (c->attr.lock_comp
> - || (sym->ts.type == BT_DERIVED
> + if ((c->ts.type == BT_DERIVED
> && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
> - && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE))
> - sym->attr.lock_comp = 1;
> + && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
> + || (c->ts.type == BT_CLASS && c->attr.class_ok
> + && CLASS_DATA (c)->ts.u.derived->from_intmod
> + == INTMOD_ISO_FORTRAN_ENV
> + && CLASS_DATA (c)->ts.u.derived->intmod_sym_id
> + == ISOFORTRAN_LOCK_TYPE)
> + || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.lock_comp
> + && !allocatable && !pointer))
> + {
> + lock_type = 1;
> + lock_comp = c;
> + sym->attr.lock_comp = 1;
> + }
> +
> + /* F2008, C1302. */
> +
Additional comment:
/* 5.3.14: An entity with the pointer attribute shall not be a coarray.
2.4.7: A subobject of a coarray is a coarray if it doesn't have any pointer
component selection. */
> + if (pointer && !coarray && (lock_type
> + || (c->ts.type == BT_DERIVED
> + && c->ts.u.derived->attr.lock_comp)))
> + gfc_error ("Component %s at %L of type LOCK_TYPE or with subcomponent "
> + "of type LOCK_TYPE is a pointer but not a coarray",
> + c->name, &c->loc);
"Component %s at %L can be neither a coarray as it is a pointer, nor a non-
coarray as it would be a non-coarray of type LOCK_TYPE or would have a non-
coarray subcomponent of type LOCK_TYPE", c->name, &c->loc
> +
/* 2.4.7: A subobject of a coarray is a coarray if it doesn't have any
allocatable component selection.
Thus, an allocatable component has to be a coarray for its subcomponents to
be coarrays. */
> + if (lock_type && allocatable && !coarray)
- If lock_type && allocatable is true, then subcomponents of type LOCK_TYPE
are discarded (cf the condition above for lock_type = 1), is that right?
I don't think you have this case in the tests you proposed.
> + gfc_error ("Component %s at %L of type LOCK_TYPE or with subcomponent "
> + "of type LOCK_TYPE is allocatable but not a "
> + "coarray", c->name, &c->loc);
"Allocatable component %s at %L can't be a non-coarray as it would be a non-
coarray of type LOCK_TYPE or it would have a non-coarray sub-component of type
LOCK_TYPE"
> +
/* 5.3.6: An entity whose type has a coarray ultimate component shall not be a
coarray. */
> + if (sym->attr.coarray_comp && !coarray && lock_type)
> + gfc_error ("Component %s at %L of type LOCK_TYPE or with subcomponent "
> + "of type LOCK_TYPE is not a coarray, but other coarray "
> + "components exist", c->name, &c->loc);
"An entity of type %s at %L can be neither a coarray as it has a coarray
sub-component, nor a non-coarray as its sub-component %s would be a non-
coarray of type LOCK_TYPE or would have a non-coarray sub-component of type
LOCK_TYPE"
> +
> + if (sym->attr.lock_comp && coarray && !lock_type)
> + gfc_error ("Component %s at %L of type LOCK_TYPE or with subcomponent "
> + "of type LOCK_TYPE has to be a coarray as %s at %L has a "
> + "codimension", lock_comp->name, &lock_comp->loc, c->name,
> + &c->loc);
"An entity of type %s at %L can be neither a coarray as its component %s at %L
has a codimension, nor a non-coarray as its component %s at %L would be a
non-coarray of type LOCK_TYPE or would have a non-coarray sub-component of
type LOCK_TYPE"
>
> /* Look for private components. */
> if (sym->component_access == ACCESS_PRIVATE
The rest looks good.
Mikael
diff --git a/gfortran.h b/gfortran.h
index acfa9d4..e03f172 100644
--- a/gfortran.h
+++ b/gfortran.h
@@ -786,6 +786,8 @@ typedef struct
/* The namespace where the attribute has been set. */
struct gfc_namespace *volatile_ns, *asynchronous_ns;
+
+ const char *lock_comp_ref, *noncoarray_lock_comp_ref;
}
symbol_attribute;
diff --git a/resolve.c b/resolve.c
index b8a8ebb..fedad13 100644
--- a/resolve.c
+++ b/resolve.c
@@ -12087,6 +12087,112 @@ resolve_fl_parameter (gfc_symbol *sym)
}
+static bool
+is_type_lock_type (gfc_typespec *ts)
+{
+ return (ts->type == BT_DERIVED
+ && ts->u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+ && ts->u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE);
+}
+
+
+static const char *
+set_subref_str (const char **dest, const char *base_name,
+ const char *subref)
+{
+ const unsigned int bufflen = strlen(base_name) + strlen(subref) + 2;
+ char *str;
+
+ if (subref == NULL || !strcmp (subref, ""))
+ return NULL;
+
+ str = XCNEWVEC (char, bufflen);
+ snprintf (str, bufflen, "%s%%%s", base_name, subref);
+ *dest = str;
+ return *dest;
+}
+
+
+static const char *comp_pick_lock_comp (gfc_component *);
+
+static const char *
+type_pick_lock_comp (gfc_symbol *derived)
+{
+ gfc_component *c;
+ const char *str;
+
+ if (derived->attr.lock_comp_ref != NULL)
+ return derived->attr.lock_comp_ref;
+
+ for (c = derived->components; c; c = c->next)
+ {
+ str = set_subref_str (&c->attr.lock_comp_ref, c->name,
+ comp_pick_lock_comp (c));
+ if (str != NULL)
+ return str;
+ }
+
+ derived->attr.lock_comp_ref = "";
+ return derived->attr.lock_comp_ref;
+}
+
+
+static const char *
+type_pick_noncoarray_lock_comp (gfc_symbol *derived)
+{
+ gfc_component *c;
+ gfc_typespec *ts;
+ const char *str;
+
+ if (derived->attr.noncoarray_lock_comp_ref != NULL)
+ return derived->attr.noncoarray_lock_comp_ref;
+
+ for (c = derived->components; c; c = c->next)
+ {
+ ts = &c->ts;
+ if (ts->type != BT_DERIVED)
+ continue;
+
+ if (!c->attr.codimension && is_type_lock_type (&c->ts))
+ {
+ c->attr.noncoarray_lock_comp_ref = gfc_get_string (c->name);
+ return c->attr.noncoarray_lock_comp_ref;
+ }
+
+ if (c->attr.pointer || c->attr.allocatable)
+ {
+ str = set_subref_str (&c->attr.noncoarray_lock_comp_ref,
+ c->name, comp_pick_lock_comp (c));
+ if (str != NULL)
+ return str;
+ }
+ else
+ {
+ str = set_subref_str (&c->attr.noncoarray_lock_comp_ref, c->name,
+ type_pick_noncoarray_lock_comp (c->ts.u.derived));
+ if (str != NULL)
+ return str;
+ }
+ }
+
+ derived->attr.noncoarray_lock_comp_ref = "";
+ return derived->attr.noncoarray_lock_comp_ref;
+}
+
+
+static const char *
+comp_pick_lock_comp (gfc_component *comp)
+{
+ if (comp->ts.type != BT_DERIVED)
+ return NULL;
+
+ if (is_type_lock_type (&comp->ts))
+ return gfc_get_string (comp->name);
+
+ return type_pick_lock_comp (comp->ts.u.derived);
+}
+
+
/* Do anything necessary to resolve a symbol. Right now, we just
assume that an otherwise unknown symbol is a variable. This sort
of thing commonly happens for symbols in module. */
@@ -12403,15 +12509,28 @@ resolve_symbol (gfc_symbol *sym)
sym->ts.u.derived->name) == FAILURE)
return;
- /* F2008, C1302. */
- if (sym->ts.type == BT_DERIVED
- && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
- && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE
- && !sym->attr.codimension)
+ if (!sym->attr.codimension)
{
- gfc_error ("Variable '%s' at %L of type LOCK_TYPE must be a coarray",
- sym->name, &sym->declared_at);
- return;
+ if (is_type_lock_type (&sym->ts))
+ {
+ gfc_error ("Variable '%s' at %L must be a coarray as it is of type "
+ "LOCK_TYPE", sym->name, &sym->declared_at);
+ return;
+ }
+ else if (sym->ts.type == BT_DERIVED)
+ {
+ const char *comp_ref =
+ type_pick_noncoarray_lock_comp (sym->ts.u.derived);
+
+ if (strcmp (comp_ref, "") != 0)
+ {
+ gfc_error ("Variable '%s' at %L must be a coarray as its "
+ "sub-component '%s%%%s' is a non-coarray of type "
+ "LOCK_TYPE.", sym->name, &sym->declared_at, sym->name,
+ comp_ref);
+ return;
+ }
+ }
}
/* An assumed-size array with INTENT(OUT) shall not be of a type for which