array.c (resolve_array_list): Apply C4106.

2012-12-19  Paul Thomas  <pault@gcc.gnu.org>

	* array.c (resolve_array_list): Apply C4106.
	* check.c (gfc_check_same_type_as): Exclude polymorphic
	entities from check for extensible types. Improved error
	for disallowed argument types to name the offending type.
	* class.c : Update copyright date.
	(gfc_class_null_initializer): Add argument for initialization
	expression and deal with unlimited polymorphic typespecs.
	(get_unique_type_string): Give unlimited polymorphic
	entities a type string.
	(gfc_intrinsic_hash_value): New function.
	(gfc_build_class_symbol): Incorporate unlimited polymorphic
	entities.
	(gfc_find_derived_vtab): Deal with unlimited polymorphic
	entities.
	(gfc_find_intrinsic_vtab): New function.
	* decl.c (gfc_match_decl_type_spec): Match typespec for
	unlimited polymorphic type.
	(gfc_match_data_decl): Skip to 'ok' if unlimited polymorphic.
	expr.c (gfc_check_pointer_assign): Apply C717.  If unlimited
	polymorphic lvalue, find rvalue vtable for all typespecs,
	except unlimited polymorphic expressions.
	(gfc_check_vardef_context): Handle unlimited polymorphic
	entities.
	* gfortran.h : Add unlimited polymorphic attribute. Add
	second arg to gfc_class_null_initializer primitive and
	primitive for gfc_find_intrinsic_vtab.  Add UNLIMITED_POLY
	to detect unlimited polymorphic expressions.
	* interface.c (gfc_compare_types): If expr1 is unlimited
	polymorphic, always return 1. If expr2 is unlimited polymorphic
	enforce C717.
	(gfc_compare_interfaces): Skip past conditions that do not
	apply for unlimited polymorphic entities.
	(compare_parameter): Make sure that an unlimited polymorphic,
	allocatable or pointer, formal argument is matched by an
	unlimited polymorphic actual argument.
	(compare_actual_formal): Ensure that an intrinsic vtable exists
	to match an unlimited polymorphic formal argument.
	* match.c (gfc_match_allocate): Type kind parameter does not
	need to match an unlimited polymorphic allocate-object.
	(alloc_opt_list): An unlimited polymorphic allocate-object
	requires a typespec or a SOURCE tag.
	(select_intrinsic_set_tmp): New function.
	(select_type_set_tmp): Call new function.  If it returns NULL,
	build a derived type or class temporary instead.
	(gfc_match_type_is): Remove restriction to derived types only.
	Bind(C) or sequence derived types not permitted.
	* misc (gfc_typename):  Printed CLASS(*) for unlimited
	polymorphism.
	* module.c : Add AB_UNLIMITED_POLY to pass unlimited
	polymorphic attribute to and from modules.
	* resolve.c (resolve_common_vars): Unlimited polymorphic
	entities cannot appear in common blocks.
	(resolve_deallocate_expr): Deallocate unlimited polymorphic
	enities.
	(resolve_allocate_expr): Likewise for allocation.  Make sure
	vtable exists.
	(gfc_type_is_extensible): Unlimited polymorphic entities are
	not extensible.
	(resolve_select_type): Handle unlimited polymorphic selectors.
	Ensure that length type parameters are assumed and that names
	for intrinsic types are generated.
	(resolve_fl_var_and_proc): Exclude select type temporaries
	from test of extensibility of type.
	(resolve_fl_variable): Likewise for test that assumed character
	length must be a dummy or a parameter.
	(resolve_fl_derived0): Return SUCCESS unconditionally for
	unlimited polymorphic entities. Also, allow unlimited
	polymorphic components.
	(resolve_fl_derived): Return SUCCESS unconditionally for
	unlimited polymorphic entities.
	(resolve_symbol): Return early with unlimited polymorphic
	entities.
	* simplifiy.c : Update copyright year.
	(gfc_simplify_extends_type_of): No simplification possible
	for unlimited polymorphic arguments.
	* symbol.c (gfc_use_derived): Nothing to do for unlimited
	polymorphic "derived type".
	(gfc_type_compatible): Return unity if ts1 is unlimited
	polymorphic.
	* trans-decl.c (create_function_arglist) Formal arguments
	without a character length should be treated in the same way
	as passed lengths.
	(gfc_trans_deferred_vars): Nullify the vptr of unlimited
	polymorphic pointers. Avoid unlimited polymorphic entities
	triggering gcc_unreachable.
	* trans-expr.c (gfc_conv_intrinsic_to_class): New function.
	(gfc_trans_class_init_assign): Make indirect reference of
	src.expr.
	(gfc_trans_class_assign): Expression NULL of unknown type
	should set NULL vptr on lhs. Treat C717 cases where lhs is
	a derived type and the rhs is unlimited polymorphic.
	(gfc_conv_procedure_call): Handle the conversion of a non-class
	actual argument to match an unlimited polymorphic formal
	argument.  Suppress the passing of a character string length
	in this case.  Make sure that calls to the character __copy
	function have two character string length arguments.
	(gfc_conv_initializer): Pass the initialization expression to
	gfc_class_null_initializer.
	(gfc_trans_subcomponent_assign): Ditto.
	(gfc_conv_structure): Move handling of _size component.
	trans-intrinsic.c: (gfc_conv_same_type_as): Handle conditions
	where unlimited polymorphic arguments have null vptr.
	* trans-stmt.c (trans_associate_var): Correctly treat array
	temporaries associated with unlimited polymorphic selectors.
	Recover the overwritten dtype for the descriptor. Use the _size
	field of the vptr for character string lengths.
	(gfc_trans_allocate): Cope with unlimited polymorphic allocate
	objects; especially with character source tags.
	(reset_vptr): New function.
	(gfc_trans_deallocate): Call it.
	* trans-types.c (gfc_get_derived_type): Detect unlimited
	polymorphic types and deal with cases where the derived type of
	components is null.
	* trans.c : Update copyright year.
	(trans_code): Call gfc_trans_class_assign for C717 cases where
	the lhs is not unlimited polymorphic.

2012-12-19  Paul Thomas  <pault@gcc.gnu.org>

	* intrinsics/extends_type_of.c : Return correct results for
	null vptrs.

2012-12-19  Paul Thomas  <pault@gcc.gnu.org>

	* gfortran.dg/unlimited_polymorphic_1.f03: New test.
	* gfortran.dg/unlimited_polymorphic_2.f03: New test.
	* gfortran.dg/unlimited_polymorphic_3.f03: New test.
	* gfortran.dg/same_type_as.f03: Correct for improved message.

From-SVN: r194622
This commit is contained in:
Paul Thomas 2012-12-20 00:15:00 +00:00
parent 26c08c0323
commit 8b7043164f
26 changed files with 1665 additions and 394 deletions

View file

@ -1,3 +1,122 @@
2012-12-19 Paul Thomas <pault@gcc.gnu.org>
* array.c (resolve_array_list): Apply C4106.
* check.c (gfc_check_same_type_as): Exclude polymorphic
entities from check for extensible types. Improved error
for disallowed argument types to name the offending type.
* class.c : Update copyright date.
(gfc_class_null_initializer): Add argument for initialization
expression and deal with unlimited polymorphic typespecs.
(get_unique_type_string): Give unlimited polymorphic
entities a type string.
(gfc_intrinsic_hash_value): New function.
(gfc_build_class_symbol): Incorporate unlimited polymorphic
entities.
(gfc_find_derived_vtab): Deal with unlimited polymorphic
entities.
(gfc_find_intrinsic_vtab): New function.
* decl.c (gfc_match_decl_type_spec): Match typespec for
unlimited polymorphic type.
(gfc_match_data_decl): Skip to 'ok' if unlimited polymorphic.
expr.c (gfc_check_pointer_assign): Apply C717. If unlimited
polymorphic lvalue, find rvalue vtable for all typespecs,
except unlimited polymorphic expressions.
(gfc_check_vardef_context): Handle unlimited polymorphic
entities.
* gfortran.h : Add unlimited polymorphic attribute. Add
second arg to gfc_class_null_initializer primitive and
primitive for gfc_find_intrinsic_vtab. Add UNLIMITED_POLY
to detect unlimited polymorphic expressions.
* interface.c (gfc_compare_types): If expr1 is unlimited
polymorphic, always return 1. If expr2 is unlimited polymorphic
enforce C717.
(gfc_compare_interfaces): Skip past conditions that do not
apply for unlimited polymorphic entities.
(compare_parameter): Make sure that an unlimited polymorphic,
allocatable or pointer, formal argument is matched by an
unlimited polymorphic actual argument.
(compare_actual_formal): Ensure that an intrinsic vtable exists
to match an unlimited polymorphic formal argument.
* match.c (gfc_match_allocate): Type kind parameter does not
need to match an unlimited polymorphic allocate-object.
(alloc_opt_list): An unlimited polymorphic allocate-object
requires a typespec or a SOURCE tag.
(select_intrinsic_set_tmp): New function.
(select_type_set_tmp): Call new function. If it returns NULL,
build a derived type or class temporary instead.
(gfc_match_type_is): Remove restriction to derived types only.
Bind(C) or sequence derived types not permitted.
* misc (gfc_typename): Printed CLASS(*) for unlimited
polymorphism.
* module.c : Add AB_UNLIMITED_POLY to pass unlimited
polymorphic attribute to and from modules.
* resolve.c (resolve_common_vars): Unlimited polymorphic
entities cannot appear in common blocks.
(resolve_deallocate_expr): Deallocate unlimited polymorphic
enities.
(resolve_allocate_expr): Likewise for allocation. Make sure
vtable exists.
(gfc_type_is_extensible): Unlimited polymorphic entities are
not extensible.
(resolve_select_type): Handle unlimited polymorphic selectors.
Ensure that length type parameters are assumed and that names
for intrinsic types are generated.
(resolve_fl_var_and_proc): Exclude select type temporaries
from test of extensibility of type.
(resolve_fl_variable): Likewise for test that assumed character
length must be a dummy or a parameter.
(resolve_fl_derived0): Return SUCCESS unconditionally for
unlimited polymorphic entities. Also, allow unlimited
polymorphic components.
(resolve_fl_derived): Return SUCCESS unconditionally for
unlimited polymorphic entities.
(resolve_symbol): Return early with unlimited polymorphic
entities.
* simplifiy.c : Update copyright year.
(gfc_simplify_extends_type_of): No simplification possible
for unlimited polymorphic arguments.
* symbol.c (gfc_use_derived): Nothing to do for unlimited
polymorphic "derived type".
(gfc_type_compatible): Return unity if ts1 is unlimited
polymorphic.
* trans-decl.c (create_function_arglist) Formal arguments
without a character length should be treated in the same way
as passed lengths.
(gfc_trans_deferred_vars): Nullify the vptr of unlimited
polymorphic pointers. Avoid unlimited polymorphic entities
triggering gcc_unreachable.
* trans-expr.c (gfc_conv_intrinsic_to_class): New function.
(gfc_trans_class_init_assign): Make indirect reference of
src.expr.
(gfc_trans_class_assign): Expression NULL of unknown type
should set NULL vptr on lhs. Treat C717 cases where lhs is
a derived type and the rhs is unlimited polymorphic.
(gfc_conv_procedure_call): Handle the conversion of a non-class
actual argument to match an unlimited polymorphic formal
argument. Suppress the passing of a character string length
in this case. Make sure that calls to the character __copy
function have two character string length arguments.
(gfc_conv_initializer): Pass the initialization expression to
gfc_class_null_initializer.
(gfc_trans_subcomponent_assign): Ditto.
(gfc_conv_structure): Move handling of _size component.
trans-intrinsic.c: (gfc_conv_same_type_as): Handle conditions
where unlimited polymorphic arguments have null vptr.
* trans-stmt.c (trans_associate_var): Correctly treat array
temporaries associated with unlimited polymorphic selectors.
Recover the overwritten dtype for the descriptor. Use the _size
field of the vptr for character string lengths.
(gfc_trans_allocate): Cope with unlimited polymorphic allocate
objects; especially with character source tags.
(reset_vptr): New function.
(gfc_trans_deallocate): Call it.
* trans-types.c (gfc_get_derived_type): Detect unlimited
polymorphic types and deal with cases where the derived type of
components is null.
* trans.c : Update copyright year.
(trans_code): Call gfc_trans_class_assign for C717 cases where
the lhs is not unlimited polymorphic.
2012-12-19 Tobias Burnus <burnus@net-b.de>
PR fortran/55733
@ -51,7 +170,7 @@
PR fortran/55593
* frontend-passes.c (doloop_code): Use resolved_sym
instead of n.sym->formal for formal argument list
to get the correct version for all generic subroutines.
to get the correct version for all generic subroutines.
2012-12-05 Tobias Burnus <burnus@net-b.de>

View file

@ -557,7 +557,7 @@ gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
goto cleanup;
case AS_ASSUMED_RANK:
gcc_unreachable ();
gcc_unreachable ();
}
if (gfc_match_char (')') == MATCH_YES)
@ -666,7 +666,7 @@ coarray:
goto cleanup;
case AS_ASSUMED_RANK:
gcc_unreachable ();
gcc_unreachable ();
}
if (gfc_match_char (']') == MATCH_YES)
@ -1414,7 +1414,7 @@ extract_element (gfc_expr *e)
gfc_free_expr (e);
current_expand.extract_count++;
return SUCCESS;
}
@ -1815,7 +1815,7 @@ resolve_array_list (gfc_constructor_base base)
{
gfc_symbol *iter_var;
locus iter_var_loc;
if (gfc_resolve_iterator (iter, false, true) == FAILURE)
t = FAILURE;
@ -1847,6 +1847,13 @@ resolve_array_list (gfc_constructor_base base)
if (gfc_resolve_expr (c->expr) == FAILURE)
t = FAILURE;
if (UNLIMITED_POLY (c->expr))
{
gfc_error ("Array constructor value at %L shall not be unlimited "
"polymorphic [F2008: C4106]", &c->expr->where);
t = FAILURE;
}
}
return t;
@ -1941,7 +1948,7 @@ got_charlen:
expr->ts.u.cl->length = gfc_get_int_expr (gfc_default_integer_kind,
NULL, found_length);
}
else
else
{
/* We've got a character length specified. It should be an integer,
otherwise an error is signalled elsewhere. */

View file

@ -225,7 +225,7 @@ coarray_check (gfc_expr *e, int n)
}
return SUCCESS;
}
}
/* Make sure the expression is a logical array. */
@ -304,7 +304,7 @@ less_than_bitsize1 (const char *arg1, gfc_expr *expr1, const char *arg2,
{
gfc_extract_int (expr2, &i2);
i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false);
/* For ISHFT[C], check that |shift| <= bit_size(i). */
if (arg2 == NULL)
{
@ -355,7 +355,7 @@ less_than_bitsizekind (const char *arg, gfc_expr *expr, int k)
if (expr->expr_type != EXPR_CONSTANT)
return SUCCESS;
i = gfc_validate_kind (BT_INTEGER, k, false);
gfc_extract_int (expr, &val);
@ -510,7 +510,7 @@ variable_check (gfc_expr *e, int n, bool allow_proc)
|| (ref->u.c.component->ts.type != BT_CLASS
&& ref->u.c.component->attr.pointer)))
break;
}
}
if (!ref)
{
@ -575,7 +575,7 @@ dim_corank_check (gfc_expr *dim, gfc_expr *array)
if (dim->expr_type != EXPR_CONSTANT)
return SUCCESS;
if (array->ts.type == BT_CLASS)
return SUCCESS;
@ -668,7 +668,7 @@ identical_dimen_shape (gfc_expr *a, int ai, gfc_expr *b, int bi)
{
if (mpz_cmp (a_size, b_size) != 0)
ret = 0;
mpz_clear (b_size);
}
mpz_clear (a_size);
@ -841,7 +841,7 @@ gfc_check_allocated (gfc_expr *array)
return FAILURE;
if (allocatable_check (array, 0) == FAILURE)
return FAILURE;
return SUCCESS;
}
@ -1881,7 +1881,7 @@ gfc_check_ichar_iachar (gfc_expr *c, gfc_expr *kind)
return SUCCESS;
i = mpz_get_si (c->ts.u.cl->length->value.integer);
}
else
else
return SUCCESS;
}
else
@ -1903,7 +1903,7 @@ gfc_check_ichar_iachar (gfc_expr *c, gfc_expr *kind)
if (i != 1)
{
gfc_error ("Argument of %s at %L must be of length one",
gfc_error ("Argument of %s at %L must be of length one",
gfc_current_intrinsic, &c->where);
return FAILURE;
}
@ -2037,7 +2037,7 @@ gfc_check_ishftc (gfc_expr *i, gfc_expr *shift, gfc_expr *size)
|| type_check (shift, 1, BT_INTEGER) == FAILURE)
return FAILURE;
if (size != NULL)
if (size != NULL)
{
int i2, i3;
@ -3081,7 +3081,7 @@ gfc_check_rank (gfc_expr *a ATTRIBUTE_UNUSED)
bool is_variable = true;
/* Functions returning pointers are regarded as variable, cf. F2008, R602. */
if (a->expr_type == EXPR_FUNCTION)
if (a->expr_type == EXPR_FUNCTION)
is_variable = a->value.function.esym
? a->value.function.esym->result->attr.pointer
: a->symtree->n.sym->result->attr.pointer;
@ -3269,7 +3269,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
if (order_size != shape_size)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"has wrong number of elements (%d/%d)",
"has wrong number of elements (%d/%d)",
gfc_current_intrinsic_arg[3]->name,
gfc_current_intrinsic, &order->where,
order_size, shape_size);
@ -3287,7 +3287,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
if (dim < 1 || dim > order_size)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"has out-of-range dimension (%d)",
"has out-of-range dimension (%d)",
gfc_current_intrinsic_arg[3]->name,
gfc_current_intrinsic, &e->where, dim);
return FAILURE;
@ -3319,7 +3319,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
gfc_constructor *c;
bool test;
mpz_init_set_ui (size, 1);
for (c = gfc_constructor_first (shape->value.constructor);
c; c = gfc_constructor_next (c))
@ -3346,17 +3346,17 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
gfc_try
gfc_check_same_type_as (gfc_expr *a, gfc_expr *b)
{
if (a->ts.type != BT_DERIVED && a->ts.type != BT_CLASS)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"must be of a derived type",
gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
&a->where);
return FAILURE;
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"cannot be of type %s",
gfc_current_intrinsic_arg[0]->name,
gfc_current_intrinsic,
&a->where, gfc_typename (&a->ts));
return FAILURE;
}
if (!gfc_type_is_extensible (a->ts.u.derived))
if (!(gfc_type_is_extensible (a->ts.u.derived) || UNLIMITED_POLY (a)))
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"must be of an extensible type",
@ -3367,14 +3367,15 @@ gfc_check_same_type_as (gfc_expr *a, gfc_expr *b)
if (b->ts.type != BT_DERIVED && b->ts.type != BT_CLASS)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"must be of a derived type",
gfc_current_intrinsic_arg[1]->name, gfc_current_intrinsic,
&b->where);
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"cannot be of type %s",
gfc_current_intrinsic_arg[0]->name,
gfc_current_intrinsic,
&b->where, gfc_typename (&b->ts));
return FAILURE;
}
if (!gfc_type_is_extensible (b->ts.u.derived))
if (!(gfc_type_is_extensible (b->ts.u.derived) || UNLIMITED_POLY (b)))
{
gfc_error ("'%s' argument of '%s' intrinsic at %L "
"must be of an extensible type",
@ -3688,7 +3689,7 @@ gfc_check_spread (gfc_expr *source, gfc_expr *dim, gfc_expr *ncopies)
return FAILURE;
/* dim_rank_check() does not apply here. */
if (dim
if (dim
&& dim->expr_type == EXPR_CONSTANT
&& (mpz_cmp_ui (dim->value.integer, 1) < 0
|| mpz_cmp_ui (dim->value.integer, source->rank + 1) > 0))
@ -4233,7 +4234,7 @@ gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field)
if (mask->rank != field->rank && field->rank != 0)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must have "
"the same rank as '%s' or be a scalar",
"the same rank as '%s' or be a scalar",
gfc_current_intrinsic_arg[2]->name, gfc_current_intrinsic,
&field->where, gfc_current_intrinsic_arg[1]->name);
return FAILURE;
@ -4246,7 +4247,7 @@ gfc_check_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field)
if (! identical_dimen_shape (mask, i, field, i))
{
gfc_error ("'%s' and '%s' arguments of '%s' intrinsic at %L "
"must have identical shape.",
"must have identical shape.",
gfc_current_intrinsic_arg[2]->name,
gfc_current_intrinsic_arg[1]->name, gfc_current_intrinsic,
&field->where);

View file

@ -1,5 +1,5 @@
/* Implementation of Fortran 2003 Polymorphism.
Copyright (C) 2009, 2010
Copyright (C) 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Paul Richard Thomas <pault@gcc.gnu.org>
and Janus Weil <janus@gcc.gnu.org>
@ -55,7 +55,6 @@ along with GCC; see the file COPYING3. If not see
#include "gfortran.h"
#include "constructor.h"
/* Inserts a derived type component reference in a data reference chain.
TS: base type of the ref chain so far, in which we will pick the component
REF: the address of the GFC_REF pointer to update
@ -237,7 +236,7 @@ gfc_add_class_array_ref (gfc_expr *e)
ref = ref->next;
ref->type = REF_ARRAY;
ref->u.ar.type = AR_FULL;
ref->u.ar.as = as;
ref->u.ar.as = as;
}
}
@ -389,7 +388,7 @@ gfc_is_class_container_ref (gfc_expr *e)
if (ref->type != REF_COMPONENT)
result = false;
else if (ref->u.c.component->ts.type == BT_CLASS)
result = true;
result = true;
else
result = false;
}
@ -403,20 +402,31 @@ gfc_is_class_container_ref (gfc_expr *e)
the _vptr component to the declared type. */
gfc_expr *
gfc_class_null_initializer (gfc_typespec *ts)
gfc_class_null_initializer (gfc_typespec *ts, gfc_expr *init_expr)
{
gfc_expr *init;
gfc_component *comp;
gfc_symbol *vtab = NULL;
bool is_unlimited_polymorphic;
is_unlimited_polymorphic = ts->u.derived
&& ts->u.derived->components->ts.u.derived
&& ts->u.derived->components->ts.u.derived->attr.unlimited_polymorphic;
if (is_unlimited_polymorphic && init_expr)
vtab = gfc_find_intrinsic_vtab (&(init_expr->ts));
else
vtab = gfc_find_derived_vtab (ts->u.derived);
init = gfc_get_structure_constructor_expr (ts->type, ts->kind,
&ts->u.derived->declared_at);
init->ts = *ts;
for (comp = ts->u.derived->components; comp; comp = comp->next)
{
gfc_constructor *ctor = gfc_constructor_get();
if (strcmp (comp->name, "_vptr") == 0)
ctor->expr = gfc_lval_expr_from_sym (gfc_find_derived_vtab (ts->u.derived));
if (strcmp (comp->name, "_vptr") == 0 && vtab)
ctor->expr = gfc_lval_expr_from_sym (vtab);
else
ctor->expr = gfc_get_null_expr (NULL);
gfc_constructor_append (&init->value.constructor, ctor);
@ -434,9 +444,14 @@ static void
get_unique_type_string (char *string, gfc_symbol *derived)
{
char dt_name[GFC_MAX_SYMBOL_LEN+1];
if (derived->attr.unlimited_polymorphic)
sprintf (dt_name, "%s", "$tar");
else
sprintf (dt_name, "%s", derived->name);
dt_name[0] = TOUPPER (dt_name[0]);
if (derived->module)
if (derived->attr.unlimited_polymorphic)
sprintf (string, "_%s", dt_name);
else if (derived->module)
sprintf (string, "%s_%s", derived->module, dt_name);
else if (derived->ns->proc_name)
sprintf (string, "%s_%s", derived->ns->proc_name->name, dt_name);
@ -475,10 +490,30 @@ gfc_hash_value (gfc_symbol *sym)
unsigned int hash = 0;
char c[2*(GFC_MAX_SYMBOL_LEN+1)];
int i, len;
get_unique_type_string (&c[0], sym);
len = strlen (c);
for (i = 0; i < len; i++)
hash = (hash << 6) + (hash << 16) - hash + c[i];
/* Return the hash but take the modulus for the sake of module read,
even though this slightly increases the chance of collision. */
return (hash % 100000000);
}
/* Assign a hash value for an intrinsic type. The algorithm is that of SDBM. */
unsigned int
gfc_intrinsic_hash_value (gfc_typespec *ts)
{
unsigned int hash = 0;
const char *c = gfc_typename (ts);
int i, len;
len = strlen (c);
for (i = 0; i < len; i++)
hash = (hash << 6) + (hash << 16) - hash + c[i];
@ -501,6 +536,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
gfc_symbol *fclass;
gfc_symbol *vtab;
gfc_component *c;
gfc_namespace *ns;
int rank;
gcc_assert (as);
@ -518,7 +554,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
attr->class_ok = attr->dummy || attr->pointer || attr->allocatable
|| attr->select_type_temporary;
if (!attr->class_ok)
/* We can not build the class container yet. */
return SUCCESS;
@ -539,17 +575,28 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
else
sprintf (name, "__class_%s", tname);
gfc_find_symbol (name, ts->u.derived->ns, 0, &fclass);
if (ts->u.derived->attr.unlimited_polymorphic)
{
/* Find the top-level namespace. */
for (ns = gfc_current_ns; ns; ns = ns->parent)
if (!ns->parent)
break;
}
else
ns = ts->u.derived->ns;
gfc_find_symbol (name, ns, 0, &fclass);
if (fclass == NULL)
{
gfc_symtree *st;
/* If not there, create a new symbol. */
fclass = gfc_new_symbol (name, ts->u.derived->ns);
st = gfc_new_symtree (&ts->u.derived->ns->sym_root, name);
fclass = gfc_new_symbol (name, ns);
st = gfc_new_symtree (&ns->sym_root, name);
st->n.sym = fclass;
gfc_set_sym_referenced (fclass);
fclass->refs++;
fclass->ts.type = BT_UNKNOWN;
if (!ts->u.derived->attr.unlimited_polymorphic)
fclass->attr.abstract = ts->u.derived->attr.abstract;
fclass->f2k_derived = gfc_get_namespace (NULL, 0);
if (gfc_add_flavor (&fclass->attr, FL_DERIVED,
@ -569,7 +616,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
c->attr.allocatable = attr->allocatable;
c->attr.dimension = attr->dimension;
c->attr.codimension = attr->codimension;
c->attr.abstract = ts->u.derived->attr.abstract;
c->attr.abstract = fclass->attr.abstract;
c->as = (*as);
c->initializer = NULL;
@ -591,17 +638,21 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
c->attr.pointer = 1;
}
/* Since the extension field is 8 bit wide, we can only have
up to 255 extension levels. */
if (ts->u.derived->attr.extension == 255)
if (!ts->u.derived->attr.unlimited_polymorphic)
{
gfc_error ("Maximum extension level reached with type '%s' at %L",
ts->u.derived->name, &ts->u.derived->declared_at);
return FAILURE;
/* Since the extension field is 8 bit wide, we can only have
up to 255 extension levels. */
if (ts->u.derived->attr.extension == 255)
{
gfc_error ("Maximum extension level reached with type '%s' at %L",
ts->u.derived->name, &ts->u.derived->declared_at);
return FAILURE;
}
fclass->attr.extension = ts->u.derived->attr.extension + 1;
fclass->attr.alloc_comp = ts->u.derived->attr.alloc_comp;
}
fclass->attr.extension = ts->u.derived->attr.extension + 1;
fclass->attr.alloc_comp = ts->u.derived->attr.alloc_comp;
fclass->attr.is_class = 1;
ts->u.derived = fclass;
attr->allocatable = attr->pointer = attr->dimension = attr->codimension = 0;
@ -620,7 +671,7 @@ add_proc_comp (gfc_symbol *vtype, const char *name, gfc_typebound_proc *tb)
if (tb->non_overridable)
return;
c = gfc_find_component (vtype, name, true, true);
if (c == NULL)
@ -670,7 +721,7 @@ add_procs_to_declared_vtab1 (gfc_symtree *st, gfc_symbol *vtype)
if (st->right)
add_procs_to_declared_vtab1 (st->right, vtype);
if (st->n.tb && !st->n.tb->error
if (st->n.tb && !st->n.tb->error
&& !st->n.tb->is_generic && st->n.tb->u.specific)
add_proc_comp (vtype, st->name, st->n.tb);
}
@ -1766,15 +1817,15 @@ gfc_find_derived_vtab (gfc_symbol *derived)
gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL, *def_init = NULL;
gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
/* Find the top-level namespace (MODULE or PROGRAM). */
/* Find the top-level namespace. */
for (ns = gfc_current_ns; ns; ns = ns->parent)
if (!ns->parent)
break;
/* If the type is a class container, use the underlying derived type. */
if (derived->attr.is_class)
if (!derived->attr.unlimited_polymorphic && derived->attr.is_class)
derived = gfc_get_derived_super_type (derived);
if (ns)
{
char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
@ -1844,7 +1895,11 @@ gfc_find_derived_vtab (gfc_symbol *derived)
goto cleanup;
c->attr.pointer = 1;
c->attr.access = ACCESS_PRIVATE;
parent = gfc_get_derived_super_type (derived);
if (!derived->attr.unlimited_polymorphic)
parent = gfc_get_derived_super_type (derived);
else
parent = NULL;
if (parent)
{
parent_vtab = gfc_find_derived_vtab (parent);
@ -1862,7 +1917,9 @@ gfc_find_derived_vtab (gfc_symbol *derived)
c->initializer = gfc_get_null_expr (NULL);
}
if (derived->components == NULL && !derived->attr.zero_comp)
if (!derived->attr.unlimited_polymorphic
&& derived->components == NULL
&& !derived->attr.zero_comp)
{
/* At this point an error must have occurred.
Prevent further errors on the vtype components. */
@ -1878,7 +1935,8 @@ gfc_find_derived_vtab (gfc_symbol *derived)
c->attr.access = ACCESS_PRIVATE;
c->ts.type = BT_DERIVED;
c->ts.u.derived = derived;
if (derived->attr.abstract)
if (derived->attr.unlimited_polymorphic
|| derived->attr.abstract)
c->initializer = gfc_get_null_expr (NULL);
else
{
@ -1905,7 +1963,8 @@ gfc_find_derived_vtab (gfc_symbol *derived)
c->attr.access = ACCESS_PRIVATE;
c->tb = XCNEW (gfc_typebound_proc);
c->tb->ppc = 1;
if (derived->attr.abstract)
if (derived->attr.unlimited_polymorphic
|| derived->attr.abstract)
c->initializer = gfc_get_null_expr (NULL);
else
{
@ -1966,7 +2025,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
Note: The actual wrapper function can only be generated
at resolution time. */
/* FIXME: Enable ABI-breaking "_final" generation. */
if (0)
if (0)
{
if (gfc_add_component (vtype, "_final", &c) == FAILURE)
goto cleanup;
@ -1978,7 +2037,8 @@ gfc_find_derived_vtab (gfc_symbol *derived)
}
/* Add procedure pointers for type-bound procedures. */
add_procs_to_declared_vtab (derived, vtype);
if (!derived->attr.unlimited_polymorphic)
add_procs_to_declared_vtab (derived, vtype);
}
have_vtype:
@ -2055,6 +2115,233 @@ yes:
}
/* Find (or generate) the symbol for an intrinsic type's vtab. This is
need to support unlimited polymorphism. */
gfc_symbol *
gfc_find_intrinsic_vtab (gfc_typespec *ts)
{
gfc_namespace *ns;
gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL, *def_init = NULL;
gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
int charlen = 0;
if (ts->type == BT_CHARACTER && ts->deferred)
{
gfc_error ("TODO: Deferred character length variable at %C cannot "
"yet be associated with unlimited polymorphic entities");
return NULL;
}
if (ts->type == BT_UNKNOWN)
return NULL;
/* Sometimes the typespec is passed from a single call. */
if (ts->type == BT_DERIVED)
return gfc_find_derived_vtab (ts->u.derived);
/* Find the top-level namespace. */
for (ns = gfc_current_ns; ns; ns = ns->parent)
if (!ns->parent)
break;
if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length
&& ts->u.cl->length->expr_type == EXPR_CONSTANT)
charlen = mpz_get_si (ts->u.cl->length->value.integer);
if (ns)
{
char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
if (ts->type == BT_CHARACTER)
sprintf (tname, "%s_%d_%d", gfc_basic_typename (ts->type),
charlen, ts->kind);
else
sprintf (tname, "%s_%d_", gfc_basic_typename (ts->type), ts->kind);
sprintf (name, "__vtab_%s", tname);
/* Look for the vtab symbol in various namespaces. */
gfc_find_symbol (name, gfc_current_ns, 0, &vtab);
if (vtab == NULL)
gfc_find_symbol (name, ns, 0, &vtab);
if (vtab == NULL)
{
gfc_get_symbol (name, ns, &vtab);
vtab->ts.type = BT_DERIVED;
if (gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
&gfc_current_locus) == FAILURE)
goto cleanup;
vtab->attr.target = 1;
vtab->attr.save = SAVE_IMPLICIT;
vtab->attr.vtab = 1;
vtab->attr.access = ACCESS_PUBLIC;
gfc_set_sym_referenced (vtab);
sprintf (name, "__vtype_%s", tname);
gfc_find_symbol (name, ns, 0, &vtype);
if (vtype == NULL)
{
gfc_component *c;
int hash;
gfc_namespace *sub_ns;
gfc_namespace *contained;
gfc_get_symbol (name, ns, &vtype);
if (gfc_add_flavor (&vtype->attr, FL_DERIVED,
NULL, &gfc_current_locus) == FAILURE)
goto cleanup;
vtype->attr.access = ACCESS_PUBLIC;
vtype->attr.vtype = 1;
gfc_set_sym_referenced (vtype);
/* Add component '_hash'. */
if (gfc_add_component (vtype, "_hash", &c) == FAILURE)
goto cleanup;
c->ts.type = BT_INTEGER;
c->ts.kind = 4;
c->attr.access = ACCESS_PRIVATE;
hash = gfc_intrinsic_hash_value (ts);
c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
NULL, hash);
/* Add component '_size'. */
if (gfc_add_component (vtype, "_size", &c) == FAILURE)
goto cleanup;
c->ts.type = BT_INTEGER;
c->ts.kind = 4;
c->attr.access = ACCESS_PRIVATE;
if (ts->type == BT_CHARACTER)
c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
NULL, charlen*ts->kind);
else
c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
NULL, ts->kind);
/* Add component _extends. */
if (gfc_add_component (vtype, "_extends", &c) == FAILURE)
goto cleanup;
c->attr.pointer = 1;
c->attr.access = ACCESS_PRIVATE;
/* Avoid segfaults because due to character length. */
c->ts.type = ts->type == BT_CHARACTER ? BT_VOID : ts->type;
c->ts.kind = ts->kind;
c->initializer = gfc_get_null_expr (NULL);
/* Add component _def_init. */
if (gfc_add_component (vtype, "_def_init", &c) == FAILURE)
goto cleanup;
c->attr.pointer = 1;
c->attr.access = ACCESS_PRIVATE;
/* Avoid segfaults due to missing character length. */
c->ts.type = ts->type == BT_CHARACTER ? BT_VOID : ts->type;
c->ts.kind = ts->kind;
c->initializer = gfc_get_null_expr (NULL);
/* Add component _copy. */
if (gfc_add_component (vtype, "_copy", &c) == FAILURE)
goto cleanup;
c->attr.proc_pointer = 1;
c->attr.access = ACCESS_PRIVATE;
c->tb = XCNEW (gfc_typebound_proc);
c->tb->ppc = 1;
/* Check to see if copy function already exists. Note
that this is only used for characters of different
lengths. */
contained = ns->contained;
for (; contained; contained = contained->sibling)
if (contained->proc_name
&& strcmp (name, contained->proc_name->name) == 0)
{
copy = contained->proc_name;
goto got_char_copy;
}
/* Set up namespace. */
sub_ns = gfc_get_namespace (ns, 0);
sub_ns->sibling = ns->contained;
ns->contained = sub_ns;
sub_ns->resolved = 1;
/* Set up procedure symbol. */
if (ts->type != BT_CHARACTER)
sprintf (name, "__copy_%s", tname);
else
/* __copy is always the same for characters. */
sprintf (name, "__copy_character_%d", ts->kind);
gfc_get_symbol (name, sub_ns, &copy);
sub_ns->proc_name = copy;
copy->attr.flavor = FL_PROCEDURE;
copy->attr.subroutine = 1;
copy->attr.pure = 1;
copy->attr.if_source = IFSRC_DECL;
/* This is elemental so that arrays are automatically
treated correctly by the scalarizer. */
copy->attr.elemental = 1;
if (ns->proc_name->attr.flavor == FL_MODULE)
copy->module = ns->proc_name->name;
gfc_set_sym_referenced (copy);
/* Set up formal arguments. */
gfc_get_symbol ("src", sub_ns, &src);
src->ts.type = ts->type;
src->ts.kind = ts->kind;
src->attr.flavor = FL_VARIABLE;
src->attr.dummy = 1;
src->attr.intent = INTENT_IN;
gfc_set_sym_referenced (src);
copy->formal = gfc_get_formal_arglist ();
copy->formal->sym = src;
gfc_get_symbol ("dst", sub_ns, &dst);
dst->ts.type = ts->type;
dst->ts.kind = ts->kind;
dst->attr.flavor = FL_VARIABLE;
dst->attr.dummy = 1;
dst->attr.intent = INTENT_OUT;
gfc_set_sym_referenced (dst);
copy->formal->next = gfc_get_formal_arglist ();
copy->formal->next->sym = dst;
/* Set up code. */
sub_ns->code = gfc_get_code ();
sub_ns->code->op = EXEC_INIT_ASSIGN;
sub_ns->code->expr1 = gfc_lval_expr_from_sym (dst);
sub_ns->code->expr2 = gfc_lval_expr_from_sym (src);
got_char_copy:
/* Set initializer. */
c->initializer = gfc_lval_expr_from_sym (copy);
c->ts.interface = copy;
}
vtab->ts.u.derived = vtype;
vtab->value = gfc_default_initializer (&vtab->ts);
}
}
found_sym = vtab;
cleanup:
/* It is unexpected to have some symbols added at resolution or code
generation time. We commit the changes in order to keep a clean state. */
if (found_sym)
{
gfc_commit_symbol (vtab);
if (vtype)
gfc_commit_symbol (vtype);
if (def_init)
gfc_commit_symbol (def_init);
if (copy)
gfc_commit_symbol (copy);
if (src)
gfc_commit_symbol (src);
if (dst)
gfc_commit_symbol (dst);
}
else
gfc_undo_symbols ();
return found_sym;
}
/* General worker function to find either a type-bound procedure or a
type-bound user operator. */
@ -2147,7 +2434,7 @@ gfc_find_typebound_intrinsic_op (gfc_symbol* derived, gfc_try* t,
/* Try to find it in the current type's namespace. */
if (derived->f2k_derived)
res = derived->f2k_derived->tb_op[op];
else
else
res = NULL;
/* Check access. */

View file

@ -2735,9 +2735,37 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
return MATCH_ERROR;
else if (m == MATCH_YES)
{
gfc_fatal_error ("Unlimited polymorphism at %C not yet supported");
gfc_symbol *upe;
gfc_symtree *st;
ts->type = BT_CLASS;
gfc_find_symbol ("$tar", gfc_current_ns, 1, &upe);
if (upe == NULL)
{
upe = gfc_new_symbol ("$tar", gfc_current_ns);
st = gfc_new_symtree (&gfc_current_ns->sym_root, "$tar");
st->n.sym = upe;
gfc_set_sym_referenced (upe);
upe->refs++;
upe->ts.type = BT_VOID;
upe->attr.unlimited_polymorphic = 1;
/* This is essential to force the construction of
unlimited polymorphic component class containers. */
upe->attr.zero_comp = 1;
if (gfc_add_flavor (&upe->attr, FL_DERIVED,
NULL, &gfc_current_locus) == FAILURE)
return MATCH_ERROR;
}
else
{
st = gfc_find_symtree (gfc_current_ns->sym_root, "$tar");
if (st == NULL)
st = gfc_new_symtree (&gfc_current_ns->sym_root, "$tar");
st->n.sym = upe;
upe->refs++;
}
ts->u.derived = upe;
return m;
}
m = gfc_match (" class ( %n )", name);
if (m != MATCH_YES)
@ -4248,6 +4276,10 @@ gfc_match_data_decl (void)
goto cleanup;
}
if (current_ts.type == BT_CLASS
&& current_ts.u.derived->attr.unlimited_polymorphic)
goto ok;
if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
&& current_ts.u.derived->components == NULL
&& !current_ts.u.derived->attr.zero_comp)

View file

@ -729,10 +729,10 @@ gfc_copy_shape_excluding (mpz_t *shape, int rank, gfc_expr *dim)
mpz_t *new_shape, *s;
int i, n;
if (shape == NULL
if (shape == NULL
|| rank <= 1
|| dim == NULL
|| dim->expr_type != EXPR_CONSTANT
|| dim->expr_type != EXPR_CONSTANT
|| dim->ts.type != BT_INTEGER)
return NULL;
@ -1389,7 +1389,7 @@ find_array_section (gfc_expr *expr, gfc_ref *ref)
gcc_assert (begin->rank == 1);
/* Zero-sized arrays have no shape and no elements, stop early. */
if (!begin->shape)
if (!begin->shape)
{
mpz_init_set_ui (nelts, 0);
break;
@ -1473,7 +1473,7 @@ find_array_section (gfc_expr *expr, gfc_ref *ref)
/* An element reference reduces the rank of the expression; don't
add anything to the shape array. */
if (ref->u.ar.dimen_type[d] != DIMEN_ELEMENT)
if (ref->u.ar.dimen_type[d] != DIMEN_ELEMENT)
mpz_set (expr->shape[shape_i++], tmp_mpz);
}
@ -1520,7 +1520,7 @@ find_array_section (gfc_expr *expr, gfc_ref *ref)
}
else
{
mpz_add (ctr[d], ctr[d], stride[d]);
mpz_add (ctr[d], ctr[d], stride[d]);
if (mpz_cmp_ui (stride[d], 0) > 0
? mpz_cmp (ctr[d], end[d]) > 0
@ -1952,7 +1952,7 @@ scalarize_intrinsic_call (gfc_expr *e)
gfc_constructor *ci, *new_ctor;
gfc_expr *expr, *old;
int n, i, rank[5], array_arg;
/* Find which, if any, arguments are arrays. Assume that the old
expression carries the type information and that the first arg
that is an array expression carries all the shape information.*/
@ -2105,7 +2105,7 @@ check_intrinsic_op (gfc_expr *e, gfc_try (*check_function) (gfc_expr *))
case INTRINSIC_LE_OS:
if ((*check_function) (op2) == FAILURE)
return FAILURE;
if (!(et0 (op1) == BT_CHARACTER && et0 (op2) == BT_CHARACTER)
&& !(numeric_type (et0 (op1)) && numeric_type (et0 (op2))))
{
@ -2271,7 +2271,7 @@ check_inquiry (gfc_expr *e, int not_restricted)
name = e->symtree->n.sym->name;
functions = (gfc_option.warn_std & GFC_STD_F2003)
functions = (gfc_option.warn_std & GFC_STD_F2003)
? inquiry_func_f2003 : inquiry_func_f95;
for (i = 0; functions[i]; i++)
@ -2360,7 +2360,7 @@ check_transformational (gfc_expr *e)
name = e->symtree->n.sym->name;
functions = (gfc_option.allow_std & GFC_STD_F2003)
functions = (gfc_option.allow_std & GFC_STD_F2003)
? trans_func_f2003 : trans_func_f95;
/* NULL() is dealt with below. */
@ -3097,7 +3097,7 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
|| gfc_current_ns->parent->proc_name->attr.subroutine)
|| gfc_current_ns->parent->proc_name->attr.is_main_program))
{
/* ... that is not a function... */
/* ... that is not a function... */
if (!gfc_current_ns->proc_name->attr.function)
bad_proc = true;
@ -3137,7 +3137,7 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
}
if (rvalue->expr_type == EXPR_NULL)
{
{
if (has_pointer && (ref == NULL || ref->next == NULL)
&& lvalue->symtree->n.sym->attr.data)
return SUCCESS;
@ -3150,7 +3150,7 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
}
/* This is possibly a typo: x = f() instead of x => f(). */
if (gfc_option.warn_surprising
if (gfc_option.warn_surprising
&& rvalue->expr_type == EXPR_FUNCTION
&& rvalue->symtree->n.sym->attr.pointer)
gfc_warning ("POINTER valued function appears on right-hand side of "
@ -3222,15 +3222,15 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
mpfr_init (rv);
gfc_set_model_kind (rvalue->ts.kind);
mpfr_init (diff);
mpfr_set (rv, rvalue->value.real, GFC_RND_MODE);
mpfr_sub (diff, rv, rvalue->value.real, GFC_RND_MODE);
if (!mpfr_zero_p (diff))
gfc_warning ("Change of value in conversion from "
" %s to %s at %L", gfc_typename (&rvalue->ts),
gfc_typename (&lvalue->ts), &rvalue->where);
mpfr_clear (rv);
mpfr_clear (diff);
}
@ -3550,9 +3550,22 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
if (!gfc_compare_types (&lvalue->ts, &rvalue->ts))
{
gfc_error ("Different types in pointer assignment at %L; attempted "
"assignment of %s to %s", &lvalue->where,
gfc_typename (&rvalue->ts), gfc_typename (&lvalue->ts));
/* Check for F03:C717. */
if (UNLIMITED_POLY (rvalue)
&& !(UNLIMITED_POLY (lvalue)
|| (lvalue->ts.type == BT_DERIVED
&& (lvalue->ts.u.derived->attr.is_bind_c
|| lvalue->ts.u.derived->attr.sequence))))
gfc_error ("Data-pointer-object &L must be unlimited "
"polymorphic, a sequence derived type or of a "
"type with the BIND attribute assignment at %L "
"to be compatible with an unlimited polymorphic "
"target", &lvalue->where);
else
gfc_error ("Different types in pointer assignment at %L; "
"attempted assignment of %s to %s", &lvalue->where,
gfc_typename (&rvalue->ts),
gfc_typename (&lvalue->ts));
return FAILURE;
}
@ -3569,9 +3582,11 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
return FAILURE;
}
if (lvalue->ts.type == BT_CLASS && rvalue->ts.type == BT_DERIVED)
/* Make sure the vtab is present. */
if (lvalue->ts.type == BT_CLASS && rvalue->ts.type == BT_DERIVED)
gfc_find_derived_vtab (rvalue->ts.u.derived);
else if (UNLIMITED_POLY (lvalue) && !UNLIMITED_POLY (rvalue))
gfc_find_intrinsic_vtab (&rvalue->ts);
/* Check rank remapping. */
if (rank_remap)
@ -3647,7 +3662,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
if (is_implicit_pure && gfc_impure_variable (rvalue->symtree->n.sym))
gfc_current_ns->proc_name->attr.implicit_pure = 0;
if (gfc_has_vector_index (rvalue))
{
@ -3747,7 +3762,7 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_expr *rvalue)
if (r == FAILURE)
return r;
if (sym->attr.pointer && rvalue->expr_type != EXPR_NULL)
{
/* F08:C461. Additional checks for pointer initialization. */
@ -3772,7 +3787,7 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_expr *rvalue)
return FAILURE;
}
}
if (sym->attr.proc_pointer && rvalue->expr_type != EXPR_NULL)
{
/* F08:C1220. Additional checks for procedure pointer initialization. */
@ -4251,7 +4266,7 @@ gfc_expr_check_typed (gfc_expr* e, gfc_namespace* ns, bool strict)
static bool
replace_symbol (gfc_expr *expr, gfc_symbol *sym, int *i ATTRIBUTE_UNUSED)
{
if ((expr->expr_type == EXPR_VARIABLE
if ((expr->expr_type == EXPR_VARIABLE
|| (expr->expr_type == EXPR_FUNCTION
&& !gfc_is_intrinsic (expr->symtree->n.sym, 0, expr->where)))
&& expr->symtree->n.sym->ns == sym->ts.interface->formal_ns
@ -4285,7 +4300,7 @@ replace_comp (gfc_expr *expr, gfc_symbol *sym, int *i ATTRIBUTE_UNUSED)
{
gfc_component *comp;
comp = (gfc_component *)sym;
if ((expr->expr_type == EXPR_VARIABLE
if ((expr->expr_type == EXPR_VARIABLE
|| (expr->expr_type == EXPR_FUNCTION
&& !gfc_is_intrinsic (expr->symtree->n.sym, 0, expr->where)))
&& expr->symtree->n.sym->ns == comp->ts.interface->formal_ns)
@ -4421,7 +4436,7 @@ gfc_get_corank (gfc_expr *e)
if (e->ts.type == BT_CLASS && e->ts.u.derived->components)
corank = e->ts.u.derived->components->as
? e->ts.u.derived->components->as->corank : 0;
else
else
corank = e->symtree->n.sym->as ? e->symtree->n.sym->as->corank : 0;
for (ref = e->ref; ref; ref = ref->next)
@ -4478,7 +4493,7 @@ gfc_has_ultimate_pointer (gfc_expr *e)
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_COMPONENT)
last = ref;
if (last && last->u.c.component->ts.type == BT_CLASS)
return CLASS_DATA (last->u.c.component)->attr.pointer_comp;
else if (last && last->u.c.component->ts.type == BT_DERIVED)
@ -4598,7 +4613,7 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict)
ar->as->upper[i]->value.integer) != 0))
colon = false;
}
return true;
}
@ -4618,7 +4633,7 @@ gfc_build_intrinsic_call (const char* name, locus where, unsigned numarg, ...)
isym = gfc_find_function (name);
gcc_assert (isym);
result = gfc_get_expr ();
result->expr_type = EXPR_FUNCTION;
result->ts = isym->ts;
@ -4669,6 +4684,7 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
bool is_pointer;
bool check_intentin;
bool ptr_component;
bool unlimited;
symbol_attribute attr;
gfc_ref* ref;
@ -4683,6 +4699,8 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
sym = e->value.function.esym ? e->value.function.esym : e->symtree->n.sym;
}
unlimited = e->ts.type == BT_CLASS && UNLIMITED_POLY (sym);
attr = gfc_expr_attr (e);
if (!pointer && e->expr_type == EXPR_FUNCTION && attr.pointer)
{
@ -4722,7 +4740,7 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
/* Find out whether the expr is a pointer; this also means following
component references to the last one. */
is_pointer = (attr.pointer || attr.proc_pointer);
if (pointer && !is_pointer)
if (pointer && !is_pointer && !unlimited)
{
if (context)
gfc_error ("Non-POINTER in pointer association context (%s)"

View file

@ -796,10 +796,12 @@ typedef struct
components or private components, procedure pointer components,
possibly nested. zero_comp is true if the derived type has no
component at all. defined_assign_comp is true if the derived
type or a (sub-)component has a typebound defined assignment. */
type or a (sub-)component has a typebound defined assignment.
unlimited_polymorphic flags the type of the container for these
entities. */
unsigned alloc_comp:1, pointer_comp:1, proc_pointer_comp:1,
private_comp:1, zero_comp:1, coarray_comp:1, lock_comp:1,
defined_assign_comp:1;
defined_assign_comp:1, unlimited_polymorphic:1;
/* This is a temporary selector for SELECT TYPE. */
unsigned select_type_temporary:1;
@ -1271,7 +1273,6 @@ typedef struct gfc_symbol
}
gfc_symbol;
/* This structure is used to keep track of symbols in common blocks. */
typedef struct gfc_common_head
{
@ -2964,11 +2965,12 @@ void gfc_add_class_array_ref (gfc_expr *);
bool gfc_is_class_array_ref (gfc_expr *, bool *);
bool gfc_is_class_scalar_expr (gfc_expr *);
bool gfc_is_class_container_ref (gfc_expr *e);
gfc_expr *gfc_class_null_initializer (gfc_typespec *);
gfc_expr *gfc_class_null_initializer (gfc_typespec *, gfc_expr *);
unsigned int gfc_hash_value (gfc_symbol *);
gfc_try gfc_build_class_symbol (gfc_typespec *, symbol_attribute *,
gfc_array_spec **, bool);
gfc_symbol *gfc_find_derived_vtab (gfc_symbol *);
gfc_symbol *gfc_find_intrinsic_vtab (gfc_typespec *);
gfc_symtree* gfc_find_typebound_proc (gfc_symbol*, gfc_try*,
const char*, bool, locus*);
gfc_symtree* gfc_find_typebound_user_op (gfc_symbol*, gfc_try*,
@ -2980,6 +2982,11 @@ gfc_symtree* gfc_get_tbp_symtree (gfc_symtree**, const char*);
bool gfc_is_finalizable (gfc_symbol *, gfc_expr **);
#define CLASS_DATA(sym) sym->ts.u.derived->components
#define UNLIMITED_POLY(sym) \
(sym != NULL && sym->ts.type == BT_CLASS \
&& CLASS_DATA (sym) \
&& CLASS_DATA (sym)->ts.u.derived \
&& CLASS_DATA (sym)->ts.u.derived->attr.unlimited_polymorphic)
/* frontend-passes.c */

View file

@ -214,7 +214,7 @@ gfc_match_interface (void)
if (gfc_get_symbol (name, NULL, &sym))
return MATCH_ERROR;
if (!sym->attr.generic
if (!sym->attr.generic
&& gfc_add_generic (&sym->attr, sym->name, NULL) == FAILURE)
return MATCH_ERROR;
@ -351,7 +351,7 @@ gfc_match_end_interface (void)
gfc_error ("Expecting 'END INTERFACE OPERATOR (%s)' at %C, "
"but got %s", s1, s2);
}
}
break;
@ -446,7 +446,7 @@ gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
if (dt1->attr.dimension && gfc_compare_array_spec (dt1->as, dt2->as) == 0)
return 0;
/* Make sure that link lists do not put this function into an
/* Make sure that link lists do not put this function into an
endless recursive loop! */
if (!(dt1->ts.type == BT_DERIVED && derived1 == dt1->ts.u.derived)
&& !(dt2->ts.type == BT_DERIVED && derived2 == dt2->ts.u.derived)
@ -485,7 +485,17 @@ gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
that is for the formal arg, but oh well. */
if (ts1->type == BT_VOID || ts2->type == BT_VOID)
return 1;
if (ts1->type == BT_CLASS
&& ts1->u.derived->components->ts.u.derived->attr.unlimited_polymorphic)
return 1;
/* F2003: C717 */
if (ts2->type == BT_CLASS && ts1->type == BT_DERIVED
&& ts2->u.derived->components->ts.u.derived->attr.unlimited_polymorphic
&& (ts1->u.derived->attr.sequence || ts1->u.derived->attr.is_bind_c))
return 1;
if (ts1->type != ts2->type
&& ((ts1->type != BT_DERIVED && ts1->type != BT_CLASS)
|| (ts2->type != BT_DERIVED && ts2->type != BT_CLASS)))
@ -523,7 +533,7 @@ compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
return 0; /* Ranks differ. */
return gfc_compare_types (&s1->ts, &s2->ts)
|| s1->ts.type == BT_ASSUMED || s2->ts.type == BT_ASSUMED;
|| s1->ts.type == BT_ASSUMED || s2->ts.type == BT_ASSUMED;
}
@ -1157,7 +1167,7 @@ check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
}
}
}
return SUCCESS;
}
@ -1403,6 +1413,9 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
return 0;
}
if (UNLIMITED_POLY (f1->sym))
goto next;
if (strict_flag)
{
/* Check all characteristics. */
@ -1418,7 +1431,7 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
f1->sym->name);
return 0;
}
next:
f1 = f1->next;
f2 = f2->next;
}
@ -1712,7 +1725,7 @@ gfc_check_interfaces (gfc_namespace *ns)
for (ns2 = ns; ns2; ns2 = ns2->parent)
{
gfc_intrinsic_op other_op;
if (check_interface1 (ns->op[i], ns2->op[i], 0,
interface_name, true))
goto done;
@ -1814,7 +1827,7 @@ argument_rank_mismatch (const char *name, locus *where,
"(rank-%d and scalar)", name, where, rank1);
}
else
{
{
gfc_error ("Rank mismatch in argument '%s' at %L "
"(rank-%d and rank-%d)", name, where, rank1, rank2);
}
@ -1900,7 +1913,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
&& formal->ts.type != BT_ASSUMED
&& !gfc_compare_types (&formal->ts, &actual->ts)
&& !(formal->ts.type == BT_DERIVED && actual->ts.type == BT_CLASS
&& gfc_compare_derived_types (formal->ts.u.derived,
&& gfc_compare_derived_types (formal->ts.u.derived,
CLASS_DATA (actual)->ts.u.derived)))
{
if (where)
@ -1933,6 +1946,23 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
}
}
/* F08: 12.5.2.5 Allocatable and pointer dummy variables. However, this
is necessary also for F03, so retain error for both.
NOTE: Other type/kind errors pre-empt this error. Since they are F03
compatible, no attempt has been made to channel to this one. */
if (UNLIMITED_POLY (formal) && !UNLIMITED_POLY (actual)
&& (CLASS_DATA (formal)->attr.allocatable
||CLASS_DATA (formal)->attr.class_pointer))
{
if (where)
gfc_error ("Actual argument to '%s' at %L must be unlimited "
"polymorphic since the formal argument is a "
"pointer or allocatable unlimited polymorphic "
"entity [F2008: 12.5.2.5]", formal->name,
&actual->where);
return 0;
}
if (formal->attr.codimension && !gfc_is_coarray (actual))
{
if (where)
@ -2078,7 +2108,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
is_pointer = ref->u.c.component->attr.pointer;
else if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT
&& ref->u.ar.dimen > 0
&& (!ref->next
&& (!ref->next
|| (ref->next->type == REF_SUBSTRING && !ref->next->next)))
break;
}
@ -2156,7 +2186,7 @@ get_sym_storage_size (gfc_symbol *sym)
return 0;
}
else
strlen = 1;
strlen = 1;
if (symbol_rank (sym) == 0)
return strlen;
@ -2194,7 +2224,7 @@ get_expr_storage_size (gfc_expr *e)
if (e == NULL)
return 0;
if (e->ts.type == BT_CHARACTER)
{
if (e->ts.u.cl && e->ts.u.cl->length
@ -2455,6 +2485,13 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
return 0;
}
/* Make sure that intrinsic vtables exist for calls to unlimited
polymorphic formal arguments. */
if (UNLIMITED_POLY(f->sym)
&& a->expr->ts.type != BT_DERIVED
&& a->expr->ts.type != BT_CLASS)
gfc_find_intrinsic_vtab (&a->expr->ts);
if (a->expr->expr_type == EXPR_NULL
&& ((f->sym->ts.type != BT_CLASS && !f->sym->attr.pointer
&& (f->sym->attr.allocatable || !f->sym->attr.optional
@ -2478,7 +2515,7 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
return 0;
}
if (!compare_parameter (f->sym, a->expr, ranks_must_agree,
is_elemental, where))
return 0;
@ -2628,7 +2665,7 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
"pointer dummy '%s'", &a->expr->where,f->sym->name);
return 0;
}
/* Fortran 2008, C1242. */
if (f->sym->attr.pointer && gfc_is_coindexed (a->expr))
@ -3283,7 +3320,7 @@ gfc_search_interface (gfc_interface *intr, int sub_flag,
has_null_arg = true;
null_expr_loc = a->expr->where;
break;
}
}
for (; intr; intr = intr->next)
{
@ -3310,7 +3347,7 @@ gfc_search_interface (gfc_interface *intr, int sub_flag,
}
/* Satisfy 12.4.4.1 such that an elemental match has lower
weight than a non-elemental match. */
weight than a non-elemental match. */
if (intr->sym->attr.elemental)
{
elem_sym = intr->sym;
@ -3613,7 +3650,7 @@ gfc_extend_expr (gfc_expr *e)
tbo = matching_typebound_op (&tb_base, actual, i, NULL, &gname);
break;
}
/* If there is a matching typebound-operator, replace the expression with
a call to it and succeed. */
if (tbo)
@ -3703,7 +3740,7 @@ gfc_extend_assign (gfc_code *c, gfc_namespace *ns)
/* See if we find a matching type-bound assignment. */
tbo = matching_typebound_op (&tb_base, actual,
INTRINSIC_ASSIGN, NULL, &gname);
/* If there is one, replace the expression with a call to it and
succeed. */
if (tbo)
@ -4028,7 +4065,7 @@ gfc_check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
" FUNCTION", proc->name, &where);
return FAILURE;
}
if (check_result_characteristics (proc_target, old_target,
err, sizeof(err)) == FAILURE)
{

View file

@ -588,7 +588,7 @@ gfc_match_name_C (const char **buffer)
size_t i = 0;
gfc_char_t c;
char* buf;
size_t cursz = 16;
size_t cursz = 16;
old_loc = gfc_current_locus;
gfc_gobble_whitespace ();
@ -605,7 +605,7 @@ gfc_match_name_C (const char **buffer)
gfc_current_locus = old_loc;
return MATCH_YES;
}
if (!ISALPHA (c) && c != '_')
{
gfc_error ("Invalid C name in NAME= specifier at %C");
@ -625,9 +625,9 @@ gfc_match_name_C (const char **buffer)
cursz *= 2;
buf = XRESIZEVEC (char, buf, cursz);
}
old_loc = gfc_current_locus;
/* Get next char; param means we're in a string. */
c = gfc_next_char_literal (INSTRING_WARN);
} while (ISALNUM (c) || c == '_');
@ -650,7 +650,7 @@ gfc_match_name_C (const char **buffer)
return MATCH_ERROR;
}
}
/* If we stopped because we had an invalid character for a C name, report
that to the user by returning MATCH_NO. */
if (c != '"' && c != '\'')
@ -708,8 +708,8 @@ gfc_match_symbol (gfc_symbol **matched_symbol, int host_assoc)
}
/* Match an intrinsic operator. Returns an INTRINSIC enum. While matching,
we always find INTRINSIC_PLUS before INTRINSIC_UPLUS. We work around this
/* Match an intrinsic operator. Returns an INTRINSIC enum. While matching,
we always find INTRINSIC_PLUS before INTRINSIC_UPLUS. We work around this
in matchexp.c. */
match
@ -1441,7 +1441,7 @@ gfc_match_if (gfc_statement *if_type)
old_loc2 = gfc_current_locus;
gfc_current_locus = old_loc;
if (gfc_match_parens () == MATCH_ERROR)
return MATCH_ERROR;
@ -1473,7 +1473,7 @@ gfc_match_if (gfc_statement *if_type)
gfc_free_expr (expr);
return MATCH_ERROR;
}
if (gfc_notify_std (GFC_STD_F95_OBS, "Arithmetic IF "
"statement at %C") == FAILURE)
return MATCH_ERROR;
@ -1579,7 +1579,7 @@ gfc_match_if (gfc_statement *if_type)
match ("write", gfc_match_write, ST_WRITE)
/* The gfc_match_assignment() above may have returned a MATCH_NO
where the assignment was to a named constant. Check that
where the assignment was to a named constant. Check that
special case here. */
m = gfc_match_assignment ();
if (m == MATCH_NO)
@ -1907,7 +1907,7 @@ static match
match_derived_type_spec (gfc_typespec *ts)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
locus old_locus;
locus old_locus;
gfc_symbol *derived;
old_locus = gfc_current_locus;
@ -1930,7 +1930,7 @@ match_derived_type_spec (gfc_typespec *ts)
return MATCH_YES;
}
gfc_current_locus = old_locus;
gfc_current_locus = old_locus;
return MATCH_NO;
}
@ -2194,7 +2194,7 @@ cleanup:
return MATCH_ERROR;
}
/* Match the rest of a simple FORALL statement that follows an
/* Match the rest of a simple FORALL statement that follows an
IF statement. */
static match
@ -2373,7 +2373,7 @@ gfc_match_do (void)
return MATCH_NO;
/* Check for balanced parens. */
if (gfc_match_parens () == MATCH_ERROR)
return MATCH_ERROR;
@ -2585,7 +2585,7 @@ match_exit_cycle (gfc_statement st, gfc_exec_op op)
" do-construct-name at %C") == FAILURE)
return MATCH_ERROR;
break;
default:
gfc_error ("%s statement at %C is not applicable to construct '%s'",
gfc_ascii_statement (st), sym->name);
@ -3265,7 +3265,7 @@ gfc_match_goto (void)
return MATCH_YES;
}
/* The assigned GO TO statement. */
/* The assigned GO TO statement. */
if (gfc_match_variable (&expr, 0) == MATCH_YES)
{
@ -3432,6 +3432,7 @@ gfc_match_allocate (void)
match m;
locus old_locus, deferred_locus;
bool saw_stat, saw_errmsg, saw_source, saw_mold, saw_deferred, b1, b2, b3;
bool saw_unlimited = false;
head = tail = NULL;
stat = errmsg = source = mold = tmp = NULL;
@ -3573,7 +3574,7 @@ gfc_match_allocate (void)
}
/* Enforce F03:C627. */
if (ts.kind != tail->expr->ts.kind)
if (ts.kind != tail->expr->ts.kind && !UNLIMITED_POLY (tail->expr))
{
gfc_error ("Kind type parameter for entity at %L differs from "
"the kind type parameter of the typespec",
@ -3585,6 +3586,8 @@ gfc_match_allocate (void)
if (tail->expr->ts.type == BT_DERIVED)
tail->expr->ts.u.derived = gfc_use_derived (tail->expr->ts.u.derived);
saw_unlimited = saw_unlimited | UNLIMITED_POLY (tail->expr);
if (gfc_peek_ascii_char () == '(' && !sym->attr.dimension)
{
gfc_error ("Shape specification for allocatable scalar at %C");
@ -3696,7 +3699,7 @@ alloc_opt_list:
gfc_error ("Redundant MOLD tag found at %L ", &tmp->where);
goto cleanup;
}
/* Check F08:C637. */
if (ts.type != BT_UNKNOWN)
{
@ -3739,7 +3742,20 @@ alloc_opt_list:
&deferred_locus);
goto cleanup;
}
/* Check F03:C625, */
if (saw_unlimited && ts.type == BT_UNKNOWN && !source && !mold)
{
for (tail = head; tail; tail = tail->next)
{
if (UNLIMITED_POLY (tail->expr))
gfc_error ("Unlimited polymorphic allocate-object at %L "
"requires either a type-spec or SOURCE tag "
"or a MOLD tag", &tail->expr->where);
}
goto cleanup;
}
new_st.op = EXEC_ALLOCATE;
new_st.expr1 = stat;
new_st.expr2 = errmsg;
@ -4067,7 +4083,7 @@ done:
}
/* Match the call of a type-bound procedure, if CALL%var has already been
/* Match the call of a type-bound procedure, if CALL%var has already been
matched and var found to be a derived-type variable. */
static match
@ -4081,7 +4097,7 @@ match_typebound_call (gfc_symtree* varst)
base->symtree = varst;
base->where = gfc_current_locus;
gfc_set_sym_referenced (varst->n.sym);
m = gfc_match_varspec (base, 0, true, true);
if (m == MATCH_NO)
gfc_error ("Expected component reference at %C");
@ -4258,7 +4274,7 @@ cleanup:
/* Given a name, return a pointer to the common head structure,
creating it if it does not exist. If FROM_MODULE is nonzero, we
mangle the name so that it doesn't interfere with commons defined
mangle the name so that it doesn't interfere with commons defined
in the using namespace.
TODO: Add to global symbol tree. */
@ -4403,7 +4419,7 @@ gfc_match_common (void)
/* Store a ref to the common block for error checking. */
sym->common_block = t;
sym->common_block->refs++;
/* See if we know the current common block is bind(c), and if
so, then see if we can check if the symbol is (which it'll
need to be). This can happen if the bind(c) attr stmt was
@ -4423,13 +4439,13 @@ gfc_match_common (void)
sym->name, &(sym->declared_at), t->name,
t->name);
}
if (sym->attr.is_bind_c == 1)
gfc_error_now ("Variable '%s' in common block "
"'%s' at %C can not be bind(c) since "
"it is not global", sym->name, t->name);
}
if (sym->attr.in_common)
{
gfc_error ("Symbol '%s' at %C is already in a COMMON block",
@ -4872,7 +4888,7 @@ cleanup:
/* Check that a statement function is not recursive. This is done by looking
for the statement function symbol(sym) by looking recursively through its
expression(e). If a reference to sym is found, true is returned.
expression(e). If a reference to sym is found, true is returned.
12.5.4 requires that any variable of function that is implicitly typed
shall have that type confirmed by any subsequent type declaration. The
implicit typing is conveniently done here. */
@ -5207,47 +5223,100 @@ select_type_push (gfc_symbol *sel)
}
/* Set the temporary for the current intrinsic SELECT TYPE selector. */
static gfc_symtree *
select_intrinsic_set_tmp (gfc_typespec *ts)
{
char name[GFC_MAX_SYMBOL_LEN];
gfc_symtree *tmp;
int charlen = 0;
if (ts->type == BT_CLASS || ts->type == BT_DERIVED)
return NULL;
if (select_type_stack->selector->ts.type == BT_CLASS
&& !select_type_stack->selector->attr.class_ok)
return NULL;
if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length
&& ts->u.cl->length->expr_type == EXPR_CONSTANT)
charlen = mpz_get_si (ts->u.cl->length->value.integer);
if (ts->type != BT_CHARACTER)
sprintf (name, "__tmp_%s_%d", gfc_basic_typename (ts->type),
ts->kind);
else
sprintf (name, "__tmp_%s_%d_%d", gfc_basic_typename (ts->type),
charlen, ts->kind);
gfc_get_sym_tree (name, gfc_current_ns, &tmp, false);
gfc_add_type (tmp->n.sym, ts, NULL);
/* Copy across the array spec to the selector. */
if (select_type_stack->selector->ts.type == BT_CLASS
&& (CLASS_DATA (select_type_stack->selector)->attr.dimension
|| CLASS_DATA (select_type_stack->selector)->attr.codimension))
{
tmp->n.sym->attr.pointer = 1;
tmp->n.sym->attr.dimension
= CLASS_DATA (select_type_stack->selector)->attr.dimension;
tmp->n.sym->attr.codimension
= CLASS_DATA (select_type_stack->selector)->attr.codimension;
tmp->n.sym->as
= gfc_copy_array_spec (CLASS_DATA (select_type_stack->selector)->as);
}
gfc_set_sym_referenced (tmp->n.sym);
gfc_add_flavor (&tmp->n.sym->attr, FL_VARIABLE, name, NULL);
tmp->n.sym->attr.select_type_temporary = 1;
return tmp;
}
/* Set up a temporary for the current TYPE IS / CLASS IS branch . */
static void
select_type_set_tmp (gfc_typespec *ts)
{
char name[GFC_MAX_SYMBOL_LEN];
gfc_symtree *tmp;
gfc_symtree *tmp = NULL;
if (!ts)
{
select_type_stack->tmp = NULL;
return;
}
if (!gfc_type_is_extensible (ts->u.derived))
return;
if (ts->type == BT_CLASS)
sprintf (name, "__tmp_class_%s", ts->u.derived->name);
else
sprintf (name, "__tmp_type_%s", ts->u.derived->name);
gfc_get_sym_tree (name, gfc_current_ns, &tmp, false);
gfc_add_type (tmp->n.sym, ts, NULL);
tmp = select_intrinsic_set_tmp (ts);
if (select_type_stack->selector->ts.type == BT_CLASS
&& select_type_stack->selector->attr.class_ok)
if (tmp == NULL)
{
tmp->n.sym->attr.pointer
if (ts->type == BT_CLASS)
sprintf (name, "__tmp_class_%s", ts->u.derived->name);
else
sprintf (name, "__tmp_type_%s", ts->u.derived->name);
gfc_get_sym_tree (name, gfc_current_ns, &tmp, false);
gfc_add_type (tmp->n.sym, ts, NULL);
if (select_type_stack->selector->ts.type == BT_CLASS
&& select_type_stack->selector->attr.class_ok)
{
tmp->n.sym->attr.pointer
= CLASS_DATA (select_type_stack->selector)->attr.class_pointer;
/* Copy across the array spec to the selector. */
if ((CLASS_DATA (select_type_stack->selector)->attr.dimension
|| CLASS_DATA (select_type_stack->selector)->attr.codimension))
{
tmp->n.sym->attr.dimension
/* Copy across the array spec to the selector. */
if (CLASS_DATA (select_type_stack->selector)->attr.dimension
|| CLASS_DATA (select_type_stack->selector)->attr.codimension)
{
tmp->n.sym->attr.dimension
= CLASS_DATA (select_type_stack->selector)->attr.dimension;
tmp->n.sym->attr.codimension
tmp->n.sym->attr.codimension
= CLASS_DATA (select_type_stack->selector)->attr.codimension;
tmp->n.sym->as
tmp->n.sym->as
= gfc_copy_array_spec (CLASS_DATA (select_type_stack->selector)->as);
}
}
}
gfc_set_sym_referenced (tmp->n.sym);
@ -5257,6 +5326,7 @@ select_type_set_tmp (gfc_typespec *ts)
if (ts->type == BT_CLASS)
gfc_build_class_symbol (&tmp->n.sym->ts, &tmp->n.sym->attr,
&tmp->n.sym->as, false);
}
/* Add an association for it, so the rest of the parser knows it is
an associate-name. The target will be set during resolution. */
@ -5267,7 +5337,7 @@ select_type_set_tmp (gfc_typespec *ts)
select_type_stack->tmp = tmp;
}
/* Match a SELECT TYPE statement. */
match
@ -5356,7 +5426,7 @@ gfc_match_select_type (void)
select_type_push (expr1->symtree->n.sym);
return MATCH_YES;
cleanup:
parent_ns = gfc_current_ns->parent;
gfc_free_namespace (gfc_current_ns);
@ -5457,9 +5527,7 @@ gfc_match_type_is (void)
c = gfc_get_case ();
c->where = gfc_current_locus;
/* TODO: Once unlimited polymorphism is implemented, we will need to call
match_type_spec here. */
if (match_derived_type_spec (&c->ts) == MATCH_ERROR)
if (match_type_spec (&c->ts) == MATCH_ERROR)
goto cleanup;
if (gfc_match_char (')') != MATCH_YES)
@ -5474,6 +5542,16 @@ gfc_match_type_is (void)
new_st.op = EXEC_SELECT_TYPE;
new_st.ext.block.case_list = c;
if (c->ts.type == BT_DERIVED && c->ts.u.derived
&& (c->ts.u.derived->attr.sequence
|| c->ts.u.derived->attr.is_bind_c))
{
gfc_error ("The type-spec shall not specify a sequence derived "
"type or a type with the BIND attribute in SELECT "
"TYPE at %C [F2003:C815]");
return MATCH_ERROR;
}
/* Create temporary variable. */
select_type_set_tmp (&c->ts);
@ -5546,7 +5624,7 @@ gfc_match_class_is (void)
new_st.op = EXEC_SELECT_TYPE;
new_st.ext.block.case_list = c;
/* Create temporary variable. */
select_type_set_tmp (&c->ts);
@ -5564,7 +5642,7 @@ cleanup:
/********************* WHERE subroutines ********************/
/* Match the rest of a simple WHERE statement that follows an IF statement.
/* Match the rest of a simple WHERE statement that follows an IF statement.
*/
static match

View file

@ -1,5 +1,6 @@
/* Miscellaneous stuff that doesn't fit anywhere else.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Andy Vaught
@ -158,8 +159,11 @@ gfc_typename (gfc_typespec *ts)
sprintf (buffer, "TYPE(%s)", ts->u.derived->name);
break;
case BT_CLASS:
sprintf (buffer, "CLASS(%s)",
ts->u.derived->components->ts.u.derived->name);
ts = &ts->u.derived->components->ts;
if (ts->u.derived->attr.unlimited_polymorphic)
sprintf (buffer, "CLASS(*)");
else
sprintf (buffer, "CLASS(%s)", ts->u.derived->name);
break;
case BT_ASSUMED:
sprintf (buffer, "TYPE(*)");

View file

@ -1844,7 +1844,7 @@ typedef enum
AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
AB_IMPLICIT_PURE, AB_ARTIFICIAL
AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY
}
ab_attribute;
@ -1898,6 +1898,7 @@ static const mstring attr_bits[] =
minit ("VTAB", AB_VTAB),
minit ("CLASS_POINTER", AB_CLASS_POINTER),
minit ("IMPLICIT_PURE", AB_IMPLICIT_PURE),
minit ("UNLIMITED_POLY", AB_UNLIMITED_POLY),
minit (NULL, -1)
};
@ -2036,6 +2037,8 @@ mio_symbol_attribute (symbol_attribute *attr)
MIO_NAME (ab_attribute) (AB_PURE, attr_bits);
if (attr->implicit_pure)
MIO_NAME (ab_attribute) (AB_IMPLICIT_PURE, attr_bits);
if (attr->unlimited_polymorphic)
MIO_NAME (ab_attribute) (AB_UNLIMITED_POLY, attr_bits);
if (attr->recursive)
MIO_NAME (ab_attribute) (AB_RECURSIVE, attr_bits);
if (attr->always_explicit)
@ -2177,6 +2180,9 @@ mio_symbol_attribute (symbol_attribute *attr)
case AB_IMPLICIT_PURE:
attr->implicit_pure = 1;
break;
case AB_UNLIMITED_POLY:
attr->unlimited_polymorphic = 1;
break;
case AB_RECURSIVE:
attr->recursive = 1;
break;

View file

@ -929,6 +929,10 @@ resolve_common_vars (gfc_symbol *sym, bool named_common)
&csym->declared_at);
}
if (UNLIMITED_POLY (csym))
gfc_error_now ("'%s' in cannot appear in COMMON at %L "
"[F2008:C5100]", csym->name, &csym->declared_at);
if (csym->ts.type != BT_DERIVED)
continue;
@ -6898,6 +6902,7 @@ resolve_deallocate_expr (gfc_expr *e)
gfc_ref *ref;
gfc_symbol *sym;
gfc_component *c;
bool unlimited;
if (gfc_resolve_expr (e) == FAILURE)
return FAILURE;
@ -6906,6 +6911,7 @@ resolve_deallocate_expr (gfc_expr *e)
goto bad;
sym = e->symtree->n.sym;
unlimited = UNLIMITED_POLY(sym);
if (sym->ts.type == BT_CLASS)
{
@ -6950,7 +6956,7 @@ resolve_deallocate_expr (gfc_expr *e)
attr = gfc_expr_attr (e);
if (allocatable == 0 && attr.pointer == 0)
if (allocatable == 0 && attr.pointer == 0 && !unlimited)
{
bad:
gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
@ -7118,6 +7124,7 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
int i, pointer, allocatable, dimension, is_abstract;
int codimension;
bool coindexed;
bool unlimited;
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_expr *e2;
@ -7149,6 +7156,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
/* Check whether ultimate component is abstract and CLASS. */
is_abstract = 0;
/* Is the allocate-object unlimited polymorphic? */
unlimited = UNLIMITED_POLY(e);
if (e->expr_type != EXPR_VARIABLE)
{
allocatable = 0;
@ -7235,7 +7245,7 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
}
/* Check for F08:C628. */
if (allocatable == 0 && pointer == 0)
if (allocatable == 0 && pointer == 0 && !unlimited)
{
gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
&e->where);
@ -7254,12 +7264,12 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
}
/* Check F03:C632 and restriction following Note 6.18. */
if (code->expr3->rank > 0
if (code->expr3->rank > 0 && !unlimited
&& conformable_arrays (code->expr3, e) == FAILURE)
goto failure;
/* Check F03:C633. */
if (code->expr3->ts.kind != e->ts.kind)
if (code->expr3->ts.kind != e->ts.kind && !unlimited)
{
gfc_error ("The allocate-object at %L and the source-expr at %L "
"shall have the same kind type parameter",
@ -7362,7 +7372,7 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
code->expr3 = rhs;
}
if (e->ts.type == BT_CLASS)
if (e->ts.type == BT_CLASS && !unlimited && !UNLIMITED_POLY (code->expr3))
{
/* Make sure the vtab symbol is present when
the module variables are generated. */
@ -7371,7 +7381,29 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
ts = code->expr3->ts;
else if (code->ext.alloc.ts.type == BT_DERIVED)
ts = code->ext.alloc.ts;
gfc_find_derived_vtab (ts.u.derived);
if (dimension)
e = gfc_expr_to_initialize (e);
}
else if (unlimited && !UNLIMITED_POLY (code->expr3))
{
/* Again, make sure the vtab symbol is present when
the module variables are generated. */
gfc_typespec *ts = NULL;
if (code->expr3)
ts = &code->expr3->ts;
else
ts = &code->ext.alloc.ts;
gcc_assert (ts);
if (ts->type == BT_CLASS || ts->type == BT_DERIVED)
gfc_find_derived_vtab (ts->u.derived);
else
gfc_find_intrinsic_vtab (ts);
if (dimension)
e = gfc_expr_to_initialize (e);
}
@ -8206,7 +8238,9 @@ resolve_select (gfc_code *code)
bool
gfc_type_is_extensible (gfc_symbol *sym)
{
return !(sym->attr.is_bind_c || sym->attr.sequence);
return !(sym->attr.is_bind_c || sym->attr.sequence
|| (sym->attr.is_class
&& sym->components->ts.u.derived->attr.unlimited_polymorphic));
}
@ -8312,6 +8346,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
char name[GFC_MAX_SYMBOL_LEN];
gfc_namespace *ns;
int error = 0;
int charlen = 0;
ns = code->ext.block.ns;
gfc_resolve (ns);
@ -8344,6 +8379,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
/* Check F03:C815. */
if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
&& !selector_type->attr.unlimited_polymorphic
&& !gfc_type_is_extensible (c->ts.u.derived))
{
gfc_error ("Derived type '%s' at %L must be extensible",
@ -8354,6 +8390,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
/* Check F03:C816. */
if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
&& !selector_type->attr.unlimited_polymorphic
&& !gfc_type_is_extension_of (selector_type, c->ts.u.derived))
{
gfc_error ("Derived type '%s' at %L must be an extension of '%s'",
@ -8362,6 +8399,15 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
continue;
}
/* Check F03:C814. */
if (c->ts.type == BT_CHARACTER && c->ts.u.cl->length != NULL)
{
gfc_error ("The type-spec at %L shall specify that each length "
"type parameter is assumed", &c->where);
error++;
continue;
}
/* Intercept the DEFAULT case. */
if (c->ts.type == BT_UNKNOWN)
{
@ -8420,6 +8466,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
ns->code->next = new_st;
code = new_st;
code->op = EXEC_SELECT;
gfc_add_vptr_component (code->expr1);
gfc_add_hash_component (code->expr1);
@ -8431,6 +8478,16 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
if (c->ts.type == BT_DERIVED)
c->low = c->high = gfc_get_int_expr (gfc_default_integer_kind, NULL,
c->ts.u.derived->hash_value);
else if (c->ts.type != BT_CLASS && c->ts.type != BT_UNKNOWN)
{
gfc_symbol *ivtab;
gfc_expr *e;
ivtab = gfc_find_intrinsic_vtab (&c->ts);
gcc_assert (ivtab);
e = CLASS_DATA (ivtab)->initializer;
c->low = c->high = gfc_copy_expr (e);
}
else if (c->ts.type == BT_UNKNOWN)
continue;
@ -8442,13 +8499,25 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
if (c->ts.type == BT_CLASS)
sprintf (name, "__tmp_class_%s", c->ts.u.derived->name);
else
else if (c->ts.type == BT_DERIVED)
sprintf (name, "__tmp_type_%s", c->ts.u.derived->name);
else if (c->ts.type == BT_CHARACTER)
{
if (c->ts.u.cl && c->ts.u.cl->length
&& c->ts.u.cl->length->expr_type == EXPR_CONSTANT)
charlen = mpz_get_si (c->ts.u.cl->length->value.integer);
sprintf (name, "__tmp_%s_%d_%d", gfc_basic_typename (c->ts.type),
charlen, c->ts.kind);
}
else
sprintf (name, "__tmp_%s_%d", gfc_basic_typename (c->ts.type),
c->ts.kind);
st = gfc_find_symtree (ns->sym_root, name);
gcc_assert (st->n.sym->assoc);
st->n.sym->assoc->target = gfc_get_variable_expr (code->expr1->symtree);
st->n.sym->assoc->target->where = code->expr1->where;
if (c->ts.type == BT_DERIVED)
if (c->ts.type != BT_CLASS && c->ts.type != BT_UNKNOWN)
gfc_add_data_component (st->n.sym->assoc->target);
new_st = gfc_get_code ();
@ -11029,6 +11098,8 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag)
{
/* F03:C502. */
if (sym->attr.class_ok
&& !sym->attr.select_type_temporary
&& !UNLIMITED_POLY(sym)
&& !gfc_type_is_extensible (CLASS_DATA (sym)->ts.u.derived))
{
gfc_error ("Type '%s' of CLASS variable '%s' at %L is not extensible",
@ -11167,7 +11238,7 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
dummy arguments. */
e = sym->ts.u.cl->length;
if (e == NULL && !sym->attr.dummy && !sym->attr.result
&& !sym->ts.deferred)
&& !sym->ts.deferred && !sym->attr.select_type_temporary)
{
gfc_error ("Entity with assumed character length at %L must be a "
"dummy argument or a PARAMETER", &sym->declared_at);
@ -12412,6 +12483,9 @@ resolve_fl_derived0 (gfc_symbol *sym)
gfc_symbol* super_type;
gfc_component *c;
if (sym->attr.unlimited_polymorphic)
return SUCCESS;
super_type = gfc_get_derived_super_type (sym);
/* F2008, C432. */
@ -12764,7 +12838,8 @@ resolve_fl_derived0 (gfc_symbol *sym)
if (c->ts.type == BT_CLASS && c->attr.class_ok
&& CLASS_DATA (c)->attr.class_pointer
&& CLASS_DATA (c)->ts.u.derived->components == NULL
&& !CLASS_DATA (c)->ts.u.derived->attr.zero_comp)
&& !CLASS_DATA (c)->ts.u.derived->attr.zero_comp
&& !UNLIMITED_POLY (c))
{
gfc_error ("The pointer component '%s' of '%s' at %L is a type "
"that has not been declared", c->name, sym->name,
@ -12833,6 +12908,9 @@ resolve_fl_derived (gfc_symbol *sym)
{
gfc_symbol *gen_dt = NULL;
if (sym->attr.unlimited_polymorphic)
return SUCCESS;
if (!sym->attr.is_class)
gfc_find_symbol (sym->name, sym->ns, 0, &gen_dt);
if (gen_dt && gen_dt->generic && gen_dt->generic->next
@ -12859,7 +12937,11 @@ resolve_fl_derived (gfc_symbol *sym)
/* Fix up incomplete CLASS symbols. */
gfc_component *data = gfc_find_component (sym, "_data", true, true);
gfc_component *vptr = gfc_find_component (sym, "_vptr", true, true);
if (vptr->ts.u.derived == NULL)
/* Nothing more to do for unlimited polymorphic entities. */
if (data->ts.u.derived->attr.unlimited_polymorphic)
return SUCCESS;
else if (vptr->ts.u.derived == NULL)
{
gfc_symbol *vtab = gfc_find_derived_vtab (data->ts.u.derived);
gcc_assert (vtab);
@ -13074,6 +13156,9 @@ resolve_symbol (gfc_symbol *sym)
if (sym->attr.artificial)
return;
if (sym->attr.unlimited_polymorphic)
return;
if (sym->attr.flavor == FL_UNKNOWN
|| (sym->attr.flavor == FL_PROCEDURE && !sym->attr.intrinsic
&& !sym->attr.generic && !sym->attr.external

View file

@ -1,6 +1,6 @@
/* Simplify intrinsic functions at compile-time.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011 Free Software Foundation, Inc.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Contributed by Andy Vaught & Katherine Holcomb
This file is part of GCC.
@ -82,7 +82,7 @@ range_check (gfc_expr *result, const char *name)
{
case ARITH_OK:
return result;
case ARITH_OVERFLOW:
gfc_error ("Result of %s overflows its kind at %L", name,
&result->where);
@ -380,7 +380,7 @@ compute_dot_product (gfc_expr *matrix_a, int stride_a, int offset_a,
}
/* Build a result expression for transformational intrinsics,
/* Build a result expression for transformational intrinsics,
depending on DIM. */
static gfc_expr *
@ -491,7 +491,7 @@ simplify_transformation_to_scalar (gfc_expr *result, gfc_expr *array, gfc_expr *
REAL, PARAMETER :: array(n, m) = ...
REAL, PARAMETER :: s(n) = PROD(array, DIM=1)
where OP == gfc_multiply(). The result might be post processed using post_op. */
where OP == gfc_multiply(). The result might be post processed using post_op. */
static gfc_expr *
simplify_transformation_to_array (gfc_expr *result, gfc_expr *array, gfc_expr *dim,
@ -1314,7 +1314,7 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x,
mpfr_clear (last1);
return result;
}
/* Get second recursion anchor. */
mpfr_init (last2);
@ -1335,7 +1335,7 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x,
}
if (jn)
gfc_constructor_insert_expr (&result->value.constructor, e, &x->where, -2);
else
else
gfc_constructor_append_expr (&result->value.constructor, e, &x->where);
if (n1 + 1 == n2)
@ -1349,7 +1349,7 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x,
mpfr_init (x2rev);
mpfr_ui_div (x2rev, 2, x->value.real, GFC_RND_MODE);
for (i = 2; i <= n2-n1; i++)
{
e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where);
@ -1743,7 +1743,7 @@ gfc_simplify_cosh (gfc_expr *x)
case BT_COMPLEX:
mpc_cosh (result->value.complex, x->value.complex, GFC_MPC_RND_MODE);
break;
default:
gcc_unreachable ();
}
@ -2251,6 +2251,10 @@ gfc_simplify_extends_type_of (gfc_expr *a, gfc_expr *mold)
return gfc_get_logical_expr (gfc_default_logical_kind, &a->where,
gfc_type_is_extension_of (mold->ts.u.derived,
a->ts.u.derived));
if (UNLIMITED_POLY (a) || UNLIMITED_POLY (mold))
return NULL;
/* Return .false. if the dynamic type can never be the same. */
if ((a->ts.type == BT_CLASS && mold->ts.type == BT_CLASS
&& !gfc_type_is_extension_of
@ -2676,7 +2680,7 @@ gfc_simplify_index (gfc_expr *x, gfc_expr *y, gfc_expr *b, gfc_expr *kind)
int back, len, lensub;
int i, j, k, count, index = 0, start;
if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT
if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT
|| ( b != NULL && b->expr_type != EXPR_CONSTANT))
return NULL;
@ -2685,7 +2689,7 @@ gfc_simplify_index (gfc_expr *x, gfc_expr *y, gfc_expr *b, gfc_expr *kind)
else
back = 0;
k = get_kind (BT_INTEGER, kind, "INDEX", gfc_default_integer_kind);
k = get_kind (BT_INTEGER, kind, "INDEX", gfc_default_integer_kind);
if (k == -1)
return &gfc_bad_expr;
@ -3229,7 +3233,7 @@ simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper,
int k;
k = get_kind (BT_INTEGER, kind, upper ? "UBOUND" : "LBOUND",
gfc_default_integer_kind);
gfc_default_integer_kind);
if (k == -1)
return &gfc_bad_expr;
@ -3558,7 +3562,7 @@ simplify_cobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
e->expr_type = EXPR_ARRAY;
e->ts.type = BT_INTEGER;
k = get_kind (BT_INTEGER, kind, upper ? "UCOBOUND" : "LCOBOUND",
gfc_default_integer_kind);
gfc_default_integer_kind);
if (k == -1)
{
gfc_free_expr (e);
@ -3912,7 +3916,7 @@ gfc_simplify_maskr (gfc_expr *i, gfc_expr *kind_arg)
if (i->expr_type != EXPR_CONSTANT)
return NULL;
kind = get_kind (BT_INTEGER, kind_arg, "MASKR", gfc_default_integer_kind);
if (kind == -1)
return &gfc_bad_expr;
@ -3944,7 +3948,7 @@ gfc_simplify_maskl (gfc_expr *i, gfc_expr *kind_arg)
if (i->expr_type != EXPR_CONSTANT)
return NULL;
kind = get_kind (BT_INTEGER, kind_arg, "MASKL", gfc_default_integer_kind);
if (kind == -1)
return &gfc_bad_expr;
@ -4066,7 +4070,7 @@ min_max_choose (gfc_expr *arg, gfc_expr *extremum, int sign)
#undef LENGTH
#undef STRING
break;
default:
gfc_internal_error ("simplify_min_max(): Bad type in arglist");
}
@ -4119,14 +4123,14 @@ simplify_min_max (gfc_expr *expr, int sign)
return NULL;
/* Convert to the correct type and kind. */
if (expr->ts.type != BT_UNKNOWN)
if (expr->ts.type != BT_UNKNOWN)
return gfc_convert_constant (expr->value.function.actual->expr,
expr->ts.type, expr->ts.kind);
if (specific->ts.type != BT_UNKNOWN)
if (specific->ts.type != BT_UNKNOWN)
return gfc_convert_constant (expr->value.function.actual->expr,
specific->ts.type, specific->ts.kind);
specific->ts.type, specific->ts.kind);
return gfc_copy_expr (expr->value.function.actual->expr);
}
@ -4176,14 +4180,14 @@ simplify_minval_maxval (gfc_expr *expr, int sign)
return NULL;
/* Convert to the correct type and kind. */
if (expr->ts.type != BT_UNKNOWN)
if (expr->ts.type != BT_UNKNOWN)
return gfc_convert_constant (extremum->expr,
expr->ts.type, expr->ts.kind);
if (specific->ts.type != BT_UNKNOWN)
if (specific->ts.type != BT_UNKNOWN)
return gfc_convert_constant (extremum->expr,
specific->ts.type, specific->ts.kind);
specific->ts.type, specific->ts.kind);
return gfc_copy_expr (extremum->expr);
}
@ -4261,7 +4265,7 @@ gfc_simplify_mod (gfc_expr *a, gfc_expr *p)
}
gfc_set_model_kind (kind);
mpfr_fmod (result->value.real, a->value.real, p->value.real,
mpfr_fmod (result->value.real, a->value.real, p->value.real,
GFC_RND_MODE);
break;
@ -4310,7 +4314,7 @@ gfc_simplify_modulo (gfc_expr *a, gfc_expr *p)
}
gfc_set_model_kind (kind);
mpfr_fmod (result->value.real, a->value.real, p->value.real,
mpfr_fmod (result->value.real, a->value.real, p->value.real,
GFC_RND_MODE);
if (mpfr_cmp_ui (result->value.real, 0) != 0)
{
@ -4319,7 +4323,7 @@ gfc_simplify_modulo (gfc_expr *a, gfc_expr *p)
GFC_RND_MODE);
}
else
mpfr_copysign (result->value.real, result->value.real,
mpfr_copysign (result->value.real, result->value.real,
p->value.real, GFC_RND_MODE);
break;
@ -4621,7 +4625,7 @@ gfc_simplify_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector)
}
else if (mask->expr_type == EXPR_ARRAY)
{
/* Copy only those elements of ARRAY to RESULT whose
/* Copy only those elements of ARRAY to RESULT whose
MASK equals .TRUE.. */
mask_ctor = gfc_constructor_first (mask->value.constructor);
while (mask_ctor)
@ -4921,8 +4925,8 @@ gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
if (e->expr_type != EXPR_CONSTANT)
return NULL;
if (len ||
(e->ts.u.cl->length &&
if (len ||
(e->ts.u.cl->length &&
mpz_sgn (e->ts.u.cl->length->value.integer)) != 0)
{
const char *res = gfc_extract_int (n, &ncop);
@ -5740,7 +5744,7 @@ gfc_simplify_spacing (gfc_expr *x)
}
/* In the Fortran 95 standard, the result is b**(e - p) where b, e, and p
are the radix, exponent of x, and precision. This excludes the
are the radix, exponent of x, and precision. This excludes the
possibility of subnormal numbers. Fortran 2003 states the result is
b**max(e - p, emin - 1). */
@ -6025,11 +6029,11 @@ gfc_simplify_transfer (gfc_expr *source, gfc_expr *mold, gfc_expr *size)
: mold;
/* Set result character length, if needed. Note that this needs to be
set even for array expressions, in order to pass this information into
set even for array expressions, in order to pass this information into
gfc_target_interpret_expr. */
if (result->ts.type == BT_CHARACTER && gfc_is_constant_expr (mold_element))
result->value.character.length = mold_element->value.character.length;
/* Set the number of elements in the result, and determine its size. */
if (mold->expr_type == EXPR_ARRAY || mold->rank || size)
@ -6087,7 +6091,7 @@ gfc_simplify_transpose (gfc_expr *matrix)
{
gfc_expr *e = gfc_constructor_lookup_expr (matrix->value.constructor,
col * matrix_rows + row);
gfc_constructor_insert_expr (&result->value.constructor,
gfc_constructor_insert_expr (&result->value.constructor,
gfc_copy_expr (e), &matrix->where,
row * matrix_cols + col);
}

View file

@ -1955,6 +1955,9 @@ gfc_use_derived (gfc_symbol *sym)
if (!sym)
return NULL;
if (sym->attr.unlimited_polymorphic)
return sym;
if (sym->attr.generic)
sym = gfc_find_dt_in_generic (sym);
@ -4905,6 +4908,11 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2)
bool is_derived1 = (ts1->type == BT_DERIVED);
bool is_derived2 = (ts2->type == BT_DERIVED);
if (is_class1
&& ts1->u.derived->components
&& ts1->u.derived->components->ts.u.derived->attr.unlimited_polymorphic)
return 1;
if (!is_derived1 && !is_derived2 && !is_class1 && !is_class2)
return (ts1->type == ts2->type);

View file

@ -327,7 +327,7 @@ gfc_sym_mangled_identifier (gfc_symbol * sym)
binding label (mainly those that are bind(c)). */
if (sym->attr.is_bind_c == 1 && sym->binding_label)
return get_identifier (sym->binding_label);
if (sym->module == NULL)
return gfc_sym_identifier (sym);
else
@ -433,14 +433,14 @@ gfc_finish_cray_pointee (tree decl, gfc_symbol *sym)
tree value;
/* Parameters need to be dereferenced. */
if (sym->cp_pointer->attr.dummy)
if (sym->cp_pointer->attr.dummy)
ptr_decl = build_fold_indirect_ref_loc (input_location,
ptr_decl);
/* Check to see if we're dealing with a variable-sized array. */
if (sym->attr.dimension
&& TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
{
&& TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
{
/* These decls will be dereferenced later, so we don't dereference
them here. */
value = convert (TREE_TYPE (decl), ptr_decl);
@ -483,7 +483,7 @@ gfc_finish_decl (tree decl)
/* We should know the storage size. */
gcc_assert (DECL_SIZE (decl) != NULL_TREE
|| (TREE_STATIC (decl)
|| (TREE_STATIC (decl)
? (!DECL_INITIAL (decl) || !DECL_CONTEXT (decl))
: DECL_EXTERNAL (decl)));
@ -550,7 +550,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
TREE_PUBLIC(decl) = 1;
DECL_COMMON(decl) = 1;
}
/* If a variable is USE associated, it's always external. */
if (sym->attr.use_assoc)
{
@ -592,7 +592,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
TREE_SIDE_EFFECTS (decl) = 1;
new_type = build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_VOLATILE);
TREE_TYPE (decl) = new_type;
}
}
/* Keep variables larger than max-stack-var-size off stack. */
if (!sym->ns->proc_name->attr.recursive
@ -948,7 +948,7 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
/* Do we know the element size? */
known_size = sym->ts.type != BT_CHARACTER
|| INTEGER_CST_P (sym->ts.u.cl->backend_decl);
if (known_size && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
{
/* For descriptorless arrays with known element size the actual
@ -1558,7 +1558,7 @@ get_proc_pointer_decl (gfc_symbol *sym)
if (sym->attr.use_assoc)
DECL_IGNORED_P (decl) = 1;
}
if ((sym->ns->proc_name
&& sym->ns->proc_name->backend_decl == current_function_decl)
|| sym->attr.contained)
@ -1984,7 +1984,7 @@ create_function_arglist (gfc_symbol * sym)
type = TREE_VALUE (typelist);
parm = build_decl (input_location,
PARM_DECL, get_identifier ("__entry"), type);
DECL_CONTEXT (parm) = fndecl;
DECL_ARG_TYPE (parm) = type;
TREE_READONLY (parm) = 1;
@ -2106,7 +2106,7 @@ create_function_arglist (gfc_symbol * sym)
gfc_finish_decl (length);
/* Remember the passed value. */
if (f->sym->ts.u.cl->passed_length != NULL)
if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length)
{
/* This can happen if the same type is used for multiple
arguments. We need to copy cl as otherwise
@ -2215,7 +2215,7 @@ create_function_arglist (gfc_symbol * sym)
gcc_assert (GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) == NULL_TREE);
GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) = token;
}
DECL_CONTEXT (token) = fndecl;
DECL_ARTIFICIAL (token) = 1;
DECL_ARG_TYPE (token) = TREE_VALUE (typelist);
@ -2314,7 +2314,7 @@ build_entry_thunks (gfc_namespace * ns, bool global)
vec<tree, va_gc> *string_args = NULL;
thunk_sym = el->sym;
build_function_decl (thunk_sym, global);
create_function_arglist (thunk_sym);
@ -2411,7 +2411,7 @@ build_entry_thunks (gfc_namespace * ns, bool global)
tmp = fold_build3_loc (input_location, COMPONENT_REF,
TREE_TYPE (field), union_decl, field,
NULL_TREE);
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
TREE_TYPE (DECL_RESULT (current_function_decl)),
DECL_RESULT (current_function_decl), tmp);
tmp = build1_v (RETURN_EXPR, tmp);
@ -2985,7 +2985,7 @@ gfc_build_intrinsic_function_decls (void)
gfc_int4_type_node);
TREE_READONLY (gfor_fndecl_math_ishftc4) = 1;
TREE_NOTHROW (gfor_fndecl_math_ishftc4) = 1;
gfor_fndecl_math_ishftc8 = gfc_build_library_function_decl (
get_identifier (PREFIX("ishftc8")),
gfc_int8_type_node, 3, gfc_int8_type_node, gfc_int4_type_node,
@ -3121,7 +3121,7 @@ gfc_build_builtin_function_decls (void)
void_type_node, -2, pchar_type_node, pchar_type_node);
/* The runtime_error_at function does not return. */
TREE_THIS_VOLATILE (gfor_fndecl_runtime_error_at) = 1;
gfor_fndecl_runtime_warning_at = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("runtime_warning_at")), ".RR",
void_type_node, -2, pchar_type_node, pchar_type_node);
@ -3816,7 +3816,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
if (sym->ts.type == BT_CLASS)
{
/* Initialize _vptr to declared type. */
gfc_symbol *vtab = gfc_find_derived_vtab (sym->ts.u.derived);
gfc_symbol *vtab;
tree rhs;
gfc_save_backend_locus (&loc);
@ -3827,8 +3827,14 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
se.want_pointer = 1;
gfc_conv_expr (&se, e);
gfc_free_expr (e);
rhs = gfc_build_addr_expr (TREE_TYPE (se.expr),
gfc_get_symbol_decl (vtab));
if (UNLIMITED_POLY (sym))
rhs = build_int_cst (TREE_TYPE (se.expr), 0);
else
{
vtab = gfc_find_derived_vtab (sym->ts.u.derived);
rhs = gfc_build_addr_expr (TREE_TYPE (se.expr),
gfc_get_symbol_decl (vtab));
}
gfc_add_modify (&init, se.expr, rhs);
gfc_restore_backend_locus (&loc);
}
@ -3894,7 +3900,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock),
NULL_TREE);
}
else
else if (!(UNLIMITED_POLY(sym)))
gcc_unreachable ();
}
@ -4347,7 +4353,7 @@ generate_coarray_sym_init (gfc_symbol *sym)
tree tmp, size, decl, token;
if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension
|| sym->attr.use_assoc || !sym->attr.referenced)
|| sym->attr.use_assoc || !sym->attr.referenced)
return;
decl = sym->backend_decl;
@ -4360,7 +4366,7 @@ generate_coarray_sym_init (gfc_symbol *sym)
size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (decl)));
/* Ensure that we do not have size=0 for zero-sized arrays. */
/* Ensure that we do not have size=0 for zero-sized arrays. */
size = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
fold_convert (size_type_node, size),
build_int_cst (size_type_node, 1));
@ -4382,7 +4388,7 @@ generate_coarray_sym_init (gfc_symbol *sym)
token, null_pointer_node, /* token, stat. */
null_pointer_node, /* errgmsg, errmsg_len. */
build_int_cst (integer_type_node, 0));
gfc_add_modify (&caf_init_block, decl, fold_convert (TREE_TYPE (decl), tmp));
@ -4724,7 +4730,7 @@ generate_local_decl (gfc_symbol * sym)
{
if (gfc_option.warn_unused_dummy_argument)
gfc_warning ("Unused dummy argument '%s' at %L", sym->name,
&sym->declared_at);
&sym->declared_at);
}
/* Silence bogus "unused parameter" warnings from the
@ -5151,9 +5157,9 @@ create_main_function (tree fndecl)
/* Coarray: Call _gfortran_caf_finalize(void). */
if (gfc_option.coarray == GFC_FCOARRAY_LIB)
{
{
/* Per F2008, 8.5.1 END of the main program implies a
SYNC MEMORY. */
SYNC MEMORY. */
tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
tmp = build_call_expr_loc (input_location, tmp, 0);
gfc_add_expr_to_block (&body, tmp);

View file

@ -64,7 +64,7 @@ get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr)
static tree
conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
{
tree desc, type;
tree desc, type;
type = get_scalar_to_descriptor_type (scalar, attr);
desc = gfc_create_var (type, "desc");
@ -456,9 +456,68 @@ class_scalar_coarray_to_class (gfc_se *parmse, gfc_expr *e,
}
/* Takes an intrinsic type expression and returns the address of a temporary
class object of the 'declared' type. */
void
gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
gfc_typespec class_ts)
{
gfc_symbol *vtab;
gfc_ss *ss;
tree ctree;
tree var;
tree tmp;
/* The intrinsic type needs to be converted to a temporary
CLASS object. */
tmp = gfc_typenode_for_spec (&class_ts);
var = gfc_create_var (tmp, "class");
/* Set the vptr. */
ctree = gfc_class_vptr_get (var);
vtab = gfc_find_intrinsic_vtab (&e->ts);
gcc_assert (vtab);
tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
gfc_add_modify (&parmse->pre, ctree,
fold_convert (TREE_TYPE (ctree), tmp));
/* Now set the data field. */
ctree = gfc_class_data_get (var);
if (parmse->ss && parmse->ss->info->useflags)
{
/* For an array reference in an elemental procedure call we need
to retain the ss to provide the scalarized array reference. */
gfc_conv_expr_reference (parmse, e);
tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
gfc_add_modify (&parmse->pre, ctree, tmp);
}
else
{
ss = gfc_walk_expr (e);
if (ss == gfc_ss_terminator)
{
parmse->ss = NULL;
gfc_conv_expr_reference (parmse, e);
tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
gfc_add_modify (&parmse->pre, ctree, tmp);
}
else
{
parmse->ss = ss;
gfc_conv_expr_descriptor (parmse, e);
gfc_add_modify (&parmse->pre, ctree, parmse->expr);
}
}
/* Pass the address of the class object. */
parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
}
/* Takes a scalarized class array expression and returns the
address of a temporary scalar class object of the 'declared'
type.
type.
OOP-TODO: This could be improved by adding code that branched on
the dynamic type being the same as the declared type. In this case
the original class expression can be passed directly.
@ -567,7 +626,7 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
tmp = NULL_TREE;
if (class_ref == NULL
&& e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
&& e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
tmp = e->symtree->n.sym->backend_decl;
else
{
@ -813,6 +872,8 @@ gfc_trans_class_init_assign (gfc_code *code)
gfc_conv_expr (&src, rhs);
gfc_conv_expr (&memsz, sz);
gfc_add_block_to_block (&block, &src.pre);
src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr);
}
@ -826,7 +887,7 @@ gfc_trans_class_init_assign (gfc_code *code)
}
gfc_add_expr_to_block (&block, tmp);
return gfc_finish_block (&block);
}
@ -867,10 +928,19 @@ gfc_trans_class_assign (gfc_expr *expr1, gfc_expr *expr2, gfc_exec_op op)
lhs = gfc_copy_expr (expr1);
gfc_add_vptr_component (lhs);
if (UNLIMITED_POLY (expr1)
&& expr2->expr_type == EXPR_NULL && expr2->ts.type == BT_UNKNOWN)
{
rhs = gfc_get_null_expr (&expr2->where);
goto assign_vptr;
}
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);
else
vtab = gfc_find_intrinsic_vtab (&expr2->ts);
gcc_assert (vtab);
rhs = gfc_get_expr ();
@ -878,13 +948,21 @@ gfc_trans_class_assign (gfc_expr *expr1, gfc_expr *expr2, gfc_exec_op op)
gfc_find_sym_tree (vtab->name, vtab->ns, 1, &st);
rhs->symtree = st;
rhs->ts = vtab->ts;
assign_vptr:
tmp = gfc_trans_pointer_assignment (lhs, rhs);
gfc_add_expr_to_block (&block, tmp);
gfc_free_expr (lhs);
gfc_free_expr (rhs);
}
else if (expr1->ts.type == BT_DERIVED && UNLIMITED_POLY (expr2))
{
/* F2003:C717 only sequence and bind-C types can come here. */
gcc_assert (expr1->ts.u.derived->attr.sequence
|| expr1->ts.u.derived->attr.is_bind_c);
gfc_add_data_component (expr2);
goto assign;
}
else if (CLASS_DATA (expr2)->attr.dimension)
{
/* Insert an additional assignment which sets the '_vptr' field. */
@ -1110,7 +1188,7 @@ gfc_conv_missing_dummy (gfc_se * se, gfc_expr * arg, gfc_typespec ts, int kind)
tmp = gfc_get_int_type (kind);
tmp = fold_convert (tmp, build_fold_indirect_ref_loc (input_location,
se->expr));
/* Test for a NULL value. */
tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), present,
tmp, fold_convert (TREE_TYPE (tmp), integer_one_node));
@ -1147,9 +1225,9 @@ gfc_get_expr_charlen (gfc_expr *e)
gfc_ref *r;
tree length;
gcc_assert (e->expr_type == EXPR_VARIABLE
gcc_assert (e->expr_type == EXPR_VARIABLE
&& e->ts.type == BT_CHARACTER);
length = NULL; /* To silence compiler warning. */
if (is_subref_array (e) && e->ts.u.cl->length)
@ -1238,8 +1316,8 @@ flatten_array_ctors_without_strlen (gfc_expr* e)
{
case EXPR_OP:
flatten_array_ctors_without_strlen (e->value.op.op1);
flatten_array_ctors_without_strlen (e->value.op.op2);
flatten_array_ctors_without_strlen (e->value.op.op1);
flatten_array_ctors_without_strlen (e->value.op.op2);
break;
case EXPR_COMPCALL:
@ -1604,7 +1682,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
se_expr = gfc_get_fake_result_decl (sym, parent_flag);
/* Similarly for alternate entry points. */
else if (alternate_entry
else if (alternate_entry
&& (sym->ns->proc_name->backend_decl == current_function_decl
|| parent_flag))
{
@ -1640,7 +1718,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
/* Dereference the expression, where needed. Since characters
are entirely different from other types, they are treated
are entirely different from other types, they are treated
separately. */
if (sym->ts.type == BT_CHARACTER)
{
@ -1670,7 +1748,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
se->expr = build_fold_indirect_ref_loc (input_location,
se->expr);
/* Dereference non-character pointer variables.
/* Dereference non-character pointer variables.
These must be dummies, results, or scalars. */
if ((sym->attr.pointer || sym->attr.allocatable
|| gfc_is_associate_pointer (sym)
@ -1828,11 +1906,11 @@ static const unsigned char powi_table[POWI_TABLE_SIZE] =
124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
};
/* If n is larger than lookup table's max index, we use the "window
/* If n is larger than lookup table's max index, we use the "window
method". */
#define POWI_WINDOW_SIZE 3
/* Recursive function to expand the power operator. The temporary
/* Recursive function to expand the power operator. The temporary
values are put in tmpvar. The function returns tmpvar[1] ** n. */
static tree
gfc_conv_powi (gfc_se * se, unsigned HOST_WIDE_INT n, tree * tmpvar)
@ -1895,7 +1973,7 @@ gfc_conv_cst_int_power (gfc_se * se, tree lhs, tree rhs)
/* There's no ABS for HOST_WIDE_INT, so here we go. It also takes care
of the asymmetric range of the integer type. */
n = (unsigned HOST_WIDE_INT) (m < 0 ? -m : m);
type = TREE_TYPE (lhs);
sgn = tree_int_cst_sgn (rhs);
@ -2006,7 +2084,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
case 4:
ikind = 0;
break;
case 8:
ikind = 1;
break;
@ -2034,7 +2112,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
case 4:
kind = 0;
break;
case 8:
kind = 1;
break;
@ -2050,7 +2128,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
default:
gcc_unreachable ();
}
switch (expr->value.op.op1->ts.type)
{
case BT_INTEGER:
@ -2068,7 +2146,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
case 0:
fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
break;
case 1:
fndecl = builtin_decl_explicit (BUILT_IN_POWI);
break;
@ -2078,7 +2156,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
break;
case 3:
/* Use the __builtin_powil() only if real(kind=16) is
/* Use the __builtin_powil() only if real(kind=16) is
actually the C long double type. */
if (!gfc_real16_is_float128)
fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
@ -2089,7 +2167,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
}
}
/* If we don't have a good builtin for this, go for the
/* If we don't have a good builtin for this, go for the
library function. */
if (!fndecl)
fndecl = gfor_fndecl_math_powi[kind][ikind].real;
@ -2497,7 +2575,7 @@ gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr)
(int)(*expr)->value.character.string[0]);
if ((*expr)->ts.kind != gfc_c_int_kind)
{
/* The expr needs to be compatible with a C int. If the
/* The expr needs to be compatible with a C int. If the
conversion fails, then the 2 causes an ICE. */
ts.type = BT_INTEGER;
ts.kind = gfc_c_int_kind;
@ -2937,8 +3015,8 @@ gfc_add_interface_mapping (gfc_interface_mapping * mapping,
else if (!sym->attr.dimension || sym->attr.pointer || sym->attr.allocatable)
value = build_fold_indirect_ref_loc (input_location,
se->expr);
/* For character(*), use the actual argument's descriptor. */
/* For character(*), use the actual argument's descriptor. */
else if (sym->ts.type == BT_CHARACTER && !new_sym->ts.u.cl->length)
value = build_fold_indirect_ref_loc (input_location,
se->expr);
@ -3347,7 +3425,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
rss = gfc_walk_expr (expr);
gcc_assert (rss != gfc_ss_terminator);
/* Initialize the scalarizer. */
gfc_init_loopinfo (&loop);
gfc_add_ss_to_loop (&loop, rss);
@ -3507,7 +3585,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false, true);
gfc_add_expr_to_block (&body, tmp);
/* Generate the copying loops. */
gfc_trans_scalarizing_loops (&loop2, &body);
@ -3534,7 +3612,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
if (formal_ptr)
{
size = gfc_index_one_node;
offset = gfc_index_zero_node;
offset = gfc_index_zero_node;
for (n = 0; n < dimen; n++)
{
tmp = gfc_conv_descriptor_ubound_get (parmse->expr,
@ -3635,7 +3713,7 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym,
&& !(fsym->attr.pointer || fsym->attr.allocatable)
&& fsym->as->type != AS_ASSUMED_SHAPE;
f = f || !sym->attr.always_explicit;
gfc_conv_array_parameter (se, arg->expr, f, NULL, NULL, NULL);
}
@ -3654,7 +3732,7 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym,
arg->expr->ts.f90_type = sym->ts.u.derived->ts.f90_type;
arg->expr->ts.kind = sym->ts.u.derived->ts.kind;
gfc_conv_expr_reference (se, arg->expr);
return 1;
}
else if (sym->intmod_sym_id == ISOCBINDING_F_POINTER
@ -3756,14 +3834,14 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym,
gfc_array_index_type, stride,
fold_convert (gfc_array_index_type,
shapese.expr)));
/* Finish scalarization loop. */
/* Finish scalarization loop. */
gfc_trans_scalarizing_loops (&loop, &body);
gfc_add_block_to_block (&block, &loop.pre);
gfc_add_block_to_block (&block, &loop.post);
gfc_add_block_to_block (&block, &fptrse.post);
gfc_cleanup_loop (&loop);
gfc_add_modify (&block, offset,
gfc_add_modify (&block, offset,
fold_build1_loc (input_location, NEGATE_EXPR,
gfc_array_index_type, offset));
gfc_conv_descriptor_offset_set (&block, desc, offset);
@ -3796,7 +3874,7 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym,
{
tree eq_expr;
tree not_null_expr;
/* Given two arguments so build the arg2se from second arg. */
gfc_init_se (&arg2se, NULL);
gfc_conv_expr (&arg2se, arg->next->expr);
@ -3820,7 +3898,7 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym,
return 1;
}
/* Nothing was done. */
return 0;
}
@ -3994,6 +4072,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable);
}
else if (UNLIMITED_POLY (fsym) && e->ts.type != BT_CLASS)
{
/* The intrinsic type needs to be converted to a temporary
CLASS object for the unlimited polymorphic formal. */
gfc_init_se (&parmse, se);
gfc_conv_intrinsic_to_class (&parmse, e, fsym->ts);
}
else if (se->ss && se->ss->info->useflags)
{
gfc_ss *ss;
@ -4051,7 +4136,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
= fold_build3_loc (input_location, COND_EXPR,
TREE_TYPE (parmse.expr),
gfc_unlikely (tmp),
fold_convert (TREE_TYPE (parmse.expr),
fold_convert (TREE_TYPE (parmse.expr),
null_pointer_node),
parmse.expr);
}
@ -4192,7 +4277,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
CLASS_DATA (fsym)->attr.class_pointer
|| CLASS_DATA (fsym)->attr.allocatable);
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
allocated on entry, it must be deallocated. */
if (fsym && fsym->attr.intent == INTENT_OUT
&& (fsym->attr.allocatable
@ -4205,7 +4290,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_init_block (&block);
ptr = parmse.expr;
if (e->ts.type == BT_CLASS)
ptr = gfc_class_data_get (ptr);
ptr = gfc_class_data_get (ptr);
tmp = gfc_deallocate_with_status (ptr, NULL_TREE,
NULL_TREE, NULL_TREE,
@ -4327,7 +4412,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* If the argument is a function call that may not create
a temporary for the result, we have to check that we
can do it, i.e. that there is no alias between this
can do it, i.e. that there is no alias between this
argument and another one. */
if (gfc_get_noncopying_intrinsic_argument (e) != NULL)
{
@ -4387,7 +4472,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
else
gfc_conv_array_parameter (&parmse, e, f, fsym, sym->name, NULL);
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
/* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
allocated on entry, it must be deallocated. */
if (fsym && fsym->attr.allocatable
&& fsym->attr.intent == INTENT_OUT)
@ -4404,7 +4489,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
tmp, build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->pre, tmp);
}
}
}
}
/* The case with fsym->attr.optional is that of a user subroutine
@ -4430,7 +4515,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& ((e->rank != 0 && sym->attr.elemental)
|| e->representation.length || e->ts.type == BT_CHARACTER
|| (e->rank != 0
&& (fsym == NULL
&& (fsym == NULL
|| (fsym-> as
&& (fsym->as->type == AS_ASSUMED_SHAPE
|| fsym->as->type == AS_ASSUMED_RANK
@ -4600,7 +4685,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
fold_convert (TREE_TYPE (tmp),
null_pointer_node));
}
gfc_trans_runtime_check (true, false, cond, &se->pre, &e->where,
msg);
free (msg);
@ -4618,8 +4703,21 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
}
/* Character strings are passed as two parameters, a length and a
pointer - except for Bind(c) which only passes the pointer. */
if (parmse.string_length != NULL_TREE && !sym->attr.is_bind_c)
pointer - except for Bind(c) which only passes the pointer.
An unlimited polymorphic formal argument likewise does not
need the length. */
if (parmse.string_length != NULL_TREE
&& !sym->attr.is_bind_c
&& !(fsym && UNLIMITED_POLY (fsym)))
vec_safe_push (stringargs, parmse.string_length);
/* When calling __copy for character expressions to unlimited
polymorphic entities, the dst argument needs a string length. */
if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
&& strncmp (sym->name, "__vtab_CHARACTER", 16) == 0
&& arg->next && arg->next->expr
&& arg->next->expr->ts.type == BT_DERIVED
&& arg->next->expr->ts.u.derived->attr.unlimited_polymorphic)
vec_safe_push (stringargs, parmse.string_length);
/* For descriptorless coarrays and assumed-shape coarray dummies, we
@ -4656,7 +4754,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) != NULL_TREE);
tmp = GFC_TYPE_ARRAY_CAF_TOKEN (caf_type);
}
vec_safe_push (stringargs, tmp);
if (GFC_DESCRIPTOR_TYPE_P (caf_type)
@ -4752,7 +4850,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_expr (&parmse, ts.u.cl->length);
gfc_add_block_to_block (&se->pre, &parmse.pre);
gfc_add_block_to_block (&se->post, &parmse.post);
tmp = fold_convert (gfc_charlen_type_node, parmse.expr);
tmp = fold_build2_loc (input_location, MAX_EXPR,
gfc_charlen_type_node, tmp,
@ -5490,7 +5588,7 @@ gfc_conv_array_constructor_expr (gfc_se * se, gfc_expr * expr)
/* Build a static initializer. EXPR is the expression for the initial value.
The other parameters describe the variable of the component being
The other parameters describe the variable of the component being
initialized. EXPR may be null. */
tree
@ -5521,7 +5619,7 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR);
return se.expr;
}
if (array && !procptr)
{
tree ctor;
@ -5557,7 +5655,7 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
case BT_CLASS:
gfc_init_se (&se, NULL);
if (ts->type == BT_CLASS && expr->expr_type == EXPR_NULL)
gfc_conv_structure (&se, gfc_class_null_initializer(ts), 1);
gfc_conv_structure (&se, gfc_class_null_initializer(ts, expr), 1);
else
gfc_conv_structure (&se, expr, 1);
gcc_assert (TREE_CODE (se.expr) == CONSTRUCTOR);
@ -5579,7 +5677,7 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
}
}
}
static tree
gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
{
@ -5626,7 +5724,7 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
cm->as->lower[n]->value.integer);
mpz_add_ui (lss_array->shape[n], lss_array->shape[n], 1);
}
/* Associate the SS with the loop. */
gfc_add_ss_to_loop (&loop, lss);
gfc_add_ss_to_loop (&loop, rss);
@ -5691,7 +5789,7 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm,
gfc_start_block (&block);
gfc_init_se (&se, NULL);
/* Get the descriptor for the expressions. */
/* Get the descriptor for the expressions. */
se.want_pointer = 0;
gfc_conv_expr_descriptor (&se, expr);
gfc_add_block_to_block (&block, &se.pre);
@ -5867,7 +5965,7 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr)
{
/* NULL initialization for CLASS components. */
tmp = gfc_trans_structure_assign (dest,
gfc_class_null_initializer (&cm->ts));
gfc_class_null_initializer (&cm->ts, expr));
gfc_add_expr_to_block (&block, tmp);
}
else if (cm->attr.dimension && !cm->attr.proc_pointer)
@ -5948,7 +6046,7 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr)
fold_convert (TREE_TYPE (lse.expr), se.expr));
return gfc_finish_block (&block);
}
}
for (c = gfc_constructor_first (expr->value.constructor);
c; c = gfc_constructor_next (c), cm = cm->next)
@ -6004,13 +6102,9 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
if (!c->expr || (cm->attr.allocatable && cm->attr.flavor != FL_PROCEDURE))
continue;
if (strcmp (cm->name, "_size") == 0)
{
val = TYPE_SIZE_UNIT (gfc_get_derived_type (cm->ts.u.derived));
CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val);
}
else if (cm->initializer && cm->initializer->expr_type != EXPR_NULL
&& strcmp (cm->name, "_extends") == 0)
if (cm->initializer && cm->initializer->expr_type != EXPR_NULL
&& strcmp (cm->name, "_extends") == 0
&& cm->initializer->symtree)
{
tree vtab;
gfc_symbol *vtabs;
@ -6018,6 +6112,11 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
vtab = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtabs));
CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, vtab);
}
else if (cm->ts.u.derived && strcmp (cm->name, "_size") == 0)
{
val = TYPE_SIZE_UNIT (gfc_get_derived_type (cm->ts.u.derived));
CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val);
}
else
{
val = gfc_conv_initializer (c->expr, &cm->ts,
@ -6030,7 +6129,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
}
}
se->expr = build_constructor (type, v);
if (init)
if (init)
TREE_CONSTANT (se->expr) = 1;
}
@ -6309,7 +6408,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
scalar = ss == gfc_ss_terminator;
if (!scalar)
gfc_free_ss_chain (ss);
if (scalar)
{
/* Scalar pointers. */
@ -6794,7 +6893,7 @@ arrayfunc_assign_needs_temporary (gfc_expr * expr1, gfc_expr * expr2)
/* Functions returning pointers or allocatables need temporaries. */
c = expr2->value.function.esym
? (expr2->value.function.esym->attr.pointer
? (expr2->value.function.esym->attr.pointer
|| expr2->value.function.esym->attr.allocatable)
: (expr2->symtree->n.sym->attr.pointer
|| expr2->symtree->n.sym->attr.allocatable);
@ -7085,7 +7184,7 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
correctly take care of the reallocation internally. For intrinsic
calls, the array data is freed and the library takes care of allocation.
TODO: Add logic of trans-array.c: gfc_alloc_allocatable_for_assignment
to the library. */
to the library. */
if (gfc_option.flag_realloc_lhs
&& gfc_is_reallocatable_lhs (expr1)
&& !gfc_expr_attr (expr1).codimension
@ -7417,7 +7516,7 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
gfc_init_se (&lse, NULL);
lse.want_pointer = 1;
gfc_conv_expr (&lse, expr1);
jump_label1 = gfc_build_label_decl (NULL_TREE);
jump_label2 = gfc_build_label_decl (NULL_TREE);

View file

@ -5911,6 +5911,7 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
gfc_expr *a, *b;
gfc_se se1, se2;
tree tmp;
tree conda = NULL_TREE, condb = NULL_TREE;
gfc_init_se (&se1, NULL);
gfc_init_se (&se2, NULL);
@ -5918,6 +5919,20 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
a = expr->value.function.actual->expr;
b = expr->value.function.actual->next->expr;
if (UNLIMITED_POLY (a))
{
tmp = gfc_class_vptr_get (a->symtree->n.sym->backend_decl);
conda = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
tmp, build_int_cst (TREE_TYPE (tmp), 0));
}
if (UNLIMITED_POLY (b))
{
tmp = gfc_class_vptr_get (b->symtree->n.sym->backend_decl);
condb = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
tmp, build_int_cst (TREE_TYPE (tmp), 0));
}
if (a->ts.type == BT_CLASS)
{
gfc_add_vptr_component (a);
@ -5939,8 +5954,18 @@ gfc_conv_same_type_as (gfc_se *se, gfc_expr *expr)
gfc_conv_expr (&se1, a);
gfc_conv_expr (&se2, b);
tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
se1.expr, fold_convert (TREE_TYPE (se1.expr), se2.expr));
tmp = fold_build2_loc (input_location, EQ_EXPR,
boolean_type_node, se1.expr,
fold_convert (TREE_TYPE (se1.expr), se2.expr));
if (conda)
tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
boolean_type_node, conda, tmp);
if (condb)
tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
boolean_type_node, condb, tmp);
se->expr = convert (gfc_typenode_for_spec (&expr->ts), tmp);
}

View file

@ -247,7 +247,7 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
if (e == NULL)
continue;
/* Obtain the info structure for the current argument. */
/* Obtain the info structure for the current argument. */
for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
if (ss->info->expr == e)
break;
@ -449,9 +449,9 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
gfc_add_ss_to_loop (&loop, ss);
gfc_conv_ss_startstride (&loop);
/* TODO: gfc_conv_loop_setup generates a temporary for vector
subscripts. This could be prevented in the elemental case
as temporaries are handled separatedly
/* TODO: gfc_conv_loop_setup generates a temporary for vector
subscripts. This could be prevented in the elemental case
as temporaries are handled separatedly
(below in gfc_conv_elemental_dependencies). */
gfc_conv_loop_setup (&loop, &code->expr1->where);
gfc_mark_ss_chain_used (ss, 1);
@ -657,7 +657,7 @@ gfc_trans_stop (gfc_code *code, bool error_stop)
? (gfc_option.coarray == GFC_FCOARRAY_LIB
? gfor_fndecl_caf_error_stop
: gfor_fndecl_error_stop_numeric)
: gfor_fndecl_stop_numeric_f08, 1,
: gfor_fndecl_stop_numeric_f08, 1,
fold_convert (gfc_int4_type_node, se.expr));
}
else
@ -689,7 +689,7 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
/* Short cut: For single images without STAT= or LOCK_ACQUIRED
return early. (ERRMSG= is always untouched for -fcoarray=single.) */
if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
return NULL_TREE;
return NULL_TREE;
gfc_init_se (&se, NULL);
gfc_start_block (&se.pre);
@ -734,7 +734,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
return early. (ERRMSG= is always untouched for -fcoarray=single.) */
if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
&& gfc_option.coarray != GFC_FCOARRAY_LIB)
return NULL_TREE;
return NULL_TREE;
gfc_init_se (&se, NULL);
gfc_start_block (&se.pre);
@ -824,7 +824,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
{
if (TREE_TYPE (stat) == integer_type_node)
stat = gfc_build_addr_expr (NULL, stat);
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
3, stat, errmsg, errmsglen);
gfc_add_expr_to_block (&se.pre, tmp);
@ -837,7 +837,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
3, gfc_build_addr_expr (NULL, tmp_stat),
errmsg, errmsglen);
gfc_add_expr_to_block (&se.pre, tmp);
gfc_add_modify (&se.pre, stat,
fold_convert (TREE_TYPE (stat), tmp_stat));
}
@ -890,7 +890,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
if (TREE_TYPE (stat) == integer_type_node)
stat = gfc_build_addr_expr (NULL, stat);
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
5, fold_convert (integer_type_node, len),
images, stat, errmsg, errmsglen);
gfc_add_expr_to_block (&se.pre, tmp);
@ -899,13 +899,13 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
{
tree tmp_stat = gfc_create_var (integer_type_node, "stat");
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
5, fold_convert (integer_type_node, len),
images, gfc_build_addr_expr (NULL, tmp_stat),
errmsg, errmsglen);
gfc_add_expr_to_block (&se.pre, tmp);
gfc_add_modify (&se.pre, stat,
gfc_add_modify (&se.pre, stat,
fold_convert (TREE_TYPE (stat), tmp_stat));
}
}
@ -995,7 +995,7 @@ gfc_trans_if_1 (gfc_code * code)
loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
elsestmt);
gfc_add_expr_to_block (&if_se.pre, stmt);
/* Finish off this statement. */
@ -1141,6 +1141,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
gfc_expr *e;
tree tmp;
bool class_target;
bool unlimited;
tree desc;
tree offset;
tree dim;
@ -1153,6 +1154,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
&& (gfc_is_class_scalar_expr (e)
|| gfc_is_class_array_ref (e, NULL));
unlimited = UNLIMITED_POLY (e);
/* Do a `pointer assignment' with updated descriptor (or assign descriptor
to array temporary) for arrays with either unknown shape or if associating
to a variable. */
@ -1194,9 +1197,10 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
gfc_finish_block (&se.post));
}
/* Derived type temporaries, arising from TYPE IS, just need the
descriptor of class arrays to be assigned directly. */
else if (class_target && sym->ts.type == BT_DERIVED && sym->attr.dimension)
/* Temporaries, arising from TYPE IS, just need the descriptor of class
arrays to be assigned directly. */
else if (class_target && sym->attr.dimension
&& (sym->ts.type == BT_DERIVED || unlimited))
{
gfc_se se;
@ -1208,7 +1212,16 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
if (unlimited)
{
/* Recover the dtype, which has been overwritten by the
assignment from an unlimited polymorphic object. */
tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
gfc_add_modify (&se.pre, tmp,
gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
}
gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
gfc_finish_block (&se.post));
}
@ -1229,7 +1242,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
/* For a class array we need a descriptor for the selector. */
gfc_conv_expr_descriptor (&se, e);
/* Obtain a temporary class container for the result. */
/* Obtain a temporary class container for the result. */
gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
@ -1254,7 +1267,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
{
/* This is bound to be a class array element. */
gfc_conv_expr_reference (&se, e);
/* Get the _vptr component of the class object. */
/* Get the _vptr component of the class object. */
tmp = gfc_get_vptr_from_expr (se.expr);
/* Obtain a temporary class container for the result. */
gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
@ -1266,7 +1279,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
tmp = TREE_TYPE (sym->backend_decl);
tmp = gfc_build_addr_expr (tmp, se.expr);
gfc_add_modify (&se.pre, sym->backend_decl, tmp);
gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
gfc_finish_block (&se.post));
}
@ -1281,6 +1294,23 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
tmp = gfc_trans_assignment (lhs, e, false, true);
gfc_add_init_cleanup (block, tmp, NULL_TREE);
}
/* Set the stringlength from the vtable size. */
if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
{
tree charlen;
gfc_se se;
gfc_init_se (&se, NULL);
gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
tmp = gfc_get_symbol_decl (e->symtree->n.sym);
tmp = gfc_vtable_size_get (tmp);
gfc_get_symbol_decl (sym);
charlen = sym->ts.u.cl->backend_decl;
gfc_add_modify (&se.pre, charlen,
fold_convert (TREE_TYPE (charlen), tmp));
gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
gfc_finish_block (&se.post));
}
}
@ -1319,7 +1349,7 @@ gfc_trans_block_construct (gfc_code* code)
gfc_trans_deferred_vars (sym, &block);
for (ass = code->ext.block.assoc; ass; ass = ass->next)
trans_associate_var (ass->st->n.sym, &block);
return gfc_finish_wrapped_block (&block);
}
@ -1366,7 +1396,7 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
tree cycle_label;
tree exit_label;
location_t loc;
type = TREE_TYPE (dovar);
loc = code->ext.iterator->start->where.lb->location;
@ -1374,7 +1404,7 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
/* Initialize the DO variable: dovar = from. */
gfc_add_modify_loc (loc, pblock, dovar,
fold_convert (TREE_TYPE(dovar), from));
/* Save value for do-tinkering checking. */
if (gfc_option.rtcheck & GFC_RTCHECK_DO)
{
@ -1612,8 +1642,8 @@ gfc_trans_do (gfc_code * code, tree exit_cond)
tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
build_int_cst (TREE_TYPE (step), 0));
step_sign = fold_build3_loc (loc, COND_EXPR, type, tmp,
build_int_cst (type, -1),
step_sign = fold_build3_loc (loc, COND_EXPR, type, tmp,
build_int_cst (type, -1),
build_int_cst (type, 1));
tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
@ -3183,7 +3213,7 @@ compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
if (INTEGER_CST_P (inner_size))
{
while (forall_tmp
&& !forall_tmp->mask
&& !forall_tmp->mask
&& INTEGER_CST_P (forall_tmp->size))
{
inner_size = fold_build2_loc (input_location, MULT_EXPR,
@ -3707,7 +3737,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
for (n = 0; n < nvar; n++)
{
/* size = (end + step - start) / step. */
tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
step[n], start[n]);
tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
end[n], tmp);
@ -4108,7 +4138,7 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
stmtblock_t body;
tree index, maskexpr;
/* A defined assignment. */
/* A defined assignment. */
if (cnext && cnext->resolved_sym)
return gfc_trans_call (cnext, true, mask, count1, invert);
@ -4893,10 +4923,19 @@ gfc_trans_allocate (gfc_code * code)
if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
memsz, &nelems, code->expr3))
{
bool unlimited_char;
unlimited_char = UNLIMITED_POLY (al->expr)
&& ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
|| (code->ext.alloc.ts.type == BT_CHARACTER
&& code->ext.alloc.ts.u.cl
&& code->ext.alloc.ts.u.cl->length));
/* A scalar or derived type. */
/* Determine allocate size. */
if (al->expr->ts.type == BT_CLASS
&& !unlimited_char
&& code->expr3
&& memsz == NULL_TREE)
{
@ -4913,8 +4952,8 @@ gfc_trans_allocate (gfc_code * code)
else
memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
}
else if (al->expr->ts.type == BT_CHARACTER
&& al->expr->ts.deferred && code->expr3)
else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
|| unlimited_char) && code->expr3)
{
if (!code->expr3->ts.u.cl->backend_decl)
{
@ -4968,13 +5007,17 @@ gfc_trans_allocate (gfc_code * code)
memsz));
/* Convert to size in bytes, using the character KIND. */
if (unlimited_char)
tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
else
tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
tmp = TYPE_SIZE_UNIT (tmp);
memsz = fold_build2_loc (input_location, MULT_EXPR,
TREE_TYPE (tmp), tmp,
fold_convert (TREE_TYPE (tmp), memsz));
}
else if (al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
|| unlimited_char)
{
gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
gfc_init_se (&se_sz, NULL);
@ -5026,7 +5069,7 @@ gfc_trans_allocate (gfc_code * code)
}
else if (al->expr->ts.type == BT_CLASS)
{
/* With class objects, it is best to play safe and null the
/* With class objects, it is best to play safe and null the
memory because we cannot know if dynamic types have allocatable
components or not. */
tmp = build_call_expr_loc (input_location,
@ -5050,8 +5093,8 @@ gfc_trans_allocate (gfc_code * code)
build_empty_stmt (input_location));
gfc_add_expr_to_block (&block, tmp);
}
/* We need the vptr of CLASS objects to be initialized. */
/* We need the vptr of CLASS objects to be initialized. */
e = gfc_copy_expr (al->expr);
if (e->ts.type == BT_CLASS)
{
@ -5090,16 +5133,19 @@ gfc_trans_allocate (gfc_code * code)
ts = &code->expr3->ts;
else if (e->ts.type == BT_DERIVED)
ts = &e->ts;
else if (code->ext.alloc.ts.type == BT_DERIVED)
else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
ts = &code->ext.alloc.ts;
else if (e->ts.type == BT_CLASS)
ts = &CLASS_DATA (e)->ts;
else
ts = &e->ts;
if (ts->type == BT_DERIVED)
if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
{
if (ts->type == BT_DERIVED)
vtab = gfc_find_derived_vtab (ts->u.derived);
else
vtab = gfc_find_intrinsic_vtab (ts);
gcc_assert (vtab);
gfc_init_se (&lse, NULL);
lse.want_pointer = 1;
@ -5184,9 +5230,12 @@ gfc_trans_allocate (gfc_code * code)
ppc = gfc_copy_expr (rhs);
gfc_add_vptr_component (ppc);
}
else
else if (rhs->ts.type == BT_DERIVED)
ppc = gfc_lval_expr_from_sym
(gfc_find_derived_vtab (rhs->ts.u.derived));
else
ppc = gfc_lval_expr_from_sym
(gfc_find_intrinsic_vtab (&rhs->ts));
gfc_add_component_ref (ppc, "_copy");
ppc_code = gfc_get_code ();
@ -5296,6 +5345,30 @@ gfc_trans_allocate (gfc_code * code)
}
/* Reset the vptr after deallocation. */
static void
reset_vptr (stmtblock_t *block, gfc_expr *e)
{
gfc_expr *rhs, *lhs = gfc_copy_expr (e);
gfc_symbol *vtab;
tree tmp;
if (UNLIMITED_POLY (e))
rhs = gfc_get_null_expr (NULL);
else
{
vtab = gfc_find_derived_vtab (e->ts.u.derived);
rhs = gfc_lval_expr_from_sym (vtab);
}
gfc_add_vptr_component (lhs);
tmp = gfc_trans_pointer_assignment (lhs, rhs);
gfc_add_expr_to_block (block, tmp);
gfc_free_expr (lhs);
gfc_free_expr (rhs);
}
/* Translate a DEALLOCATE statement. */
tree
@ -5376,6 +5449,8 @@ gfc_trans_deallocate (gfc_code *code)
tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
label_finish, expr);
gfc_add_expr_to_block (&se.pre, tmp);
if (UNLIMITED_POLY (al->expr))
reset_vptr (&se.pre, al->expr);
}
else
{
@ -5388,19 +5463,9 @@ gfc_trans_deallocate (gfc_code *code)
se.expr,
build_int_cst (TREE_TYPE (se.expr), 0));
gfc_add_expr_to_block (&se.pre, tmp);
if (al->expr->ts.type == BT_CLASS)
{
/* Reset _vptr component to declared type. */
gfc_expr *rhs, *lhs = gfc_copy_expr (al->expr);
gfc_symbol *vtab = gfc_find_derived_vtab (al->expr->ts.u.derived);
gfc_add_vptr_component (lhs);
rhs = gfc_lval_expr_from_sym (vtab);
tmp = gfc_trans_pointer_assignment (lhs, rhs);
gfc_add_expr_to_block (&se.pre, tmp);
gfc_free_expr (lhs);
gfc_free_expr (rhs);
}
reset_vptr (&se.pre, al->expr);
}
if (code->expr1)

View file

@ -2338,16 +2338,18 @@ gfc_get_derived_type (gfc_symbol * derived)
tree canonical = NULL_TREE;
tree *chain = NULL;
bool got_canonical = false;
bool unlimited_entity = false;
gfc_component *c;
gfc_dt_list *dt;
gfc_namespace *ns;
if (derived->attr.unlimited_polymorphic)
return ptr_type_node;
if (derived && derived->attr.flavor == FL_PROCEDURE
&& derived->attr.generic)
derived = gfc_find_dt_in_generic (derived);
gcc_assert (derived && derived->attr.flavor == FL_DERIVED);
/* See if it's one of the iso_c_binding derived types. */
if (derived->attr.is_iso_c == 1)
{
@ -2431,6 +2433,12 @@ gfc_get_derived_type (gfc_symbol * derived)
derived->backend_decl = typenode;
}
if (derived->components
&& derived->components->ts.type == BT_DERIVED
&& strcmp (derived->components->name, "_data") == 0
&& derived->components->ts.u.derived->attr.unlimited_polymorphic)
unlimited_entity = true;
/* Go through the derived type components, building them as
necessary. The reason for doing this now is that it is
possible to recurse back to this derived type through a
@ -2511,14 +2519,16 @@ gfc_get_derived_type (gfc_symbol * derived)
!c->attr.target);
}
else if ((c->attr.pointer || c->attr.allocatable)
&& !c->attr.proc_pointer)
&& !c->attr.proc_pointer
&& !(unlimited_entity && c == derived->components))
field_type = build_pointer_type (field_type);
if (c->attr.pointer)
field_type = gfc_nonrestricted_type (field_type);
/* vtype fields can point to different types to the base type. */
if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.vtype)
if (c->ts.type == BT_DERIVED
&& c->ts.u.derived && c->ts.u.derived->attr.vtype)
field_type = build_pointer_type_for_mode (TREE_TYPE (field_type),
ptr_mode, true);

View file

@ -1,6 +1,6 @@
/* Code translation -- generate GCC trees from gfc_code.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2012 Free Software Foundation, Inc.
Contributed by Paul Brook
This file is part of GCC.
@ -87,7 +87,7 @@ tree
gfc_create_var_np (tree type, const char *prefix)
{
tree t;
t = create_tmp_var_raw (type, prefix);
/* No warnings for anonymous variables. */
@ -139,7 +139,7 @@ gfc_evaluate_now (tree expr, stmtblock_t * pblock)
}
/* Build a MODIFY_EXPR node and add it to a given statement block PBLOCK.
/* Build a MODIFY_EXPR node and add it to a given statement block PBLOCK.
A MODIFY_EXPR is an assignment:
LHS <- RHS. */
@ -428,7 +428,7 @@ trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
arg = gfc_build_addr_expr (pchar_type_node,
gfc_build_localized_cstring_const (message));
free (message);
asprintf (&message, "%s", _(msgid));
arg2 = gfc_build_addr_expr (pchar_type_node,
gfc_build_localized_cstring_const (message));
@ -440,7 +440,7 @@ trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
argarray[1] = arg2;
for (i = 0; i < nargs; i++)
argarray[2 + i] = va_arg (ap, tree);
/* Build the function call to runtime_(warning,error)_at; because of the
variable number of arguments, we can't use build_call_expr_loc dinput_location,
irectly. */
@ -591,14 +591,14 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size)
/* Allocate memory, using an optional status argument.
This function follows the following pseudo-code:
void *
allocate (size_t size, integer_type stat)
{
void *newmem;
if (stat requested)
stat = 0;
@ -661,7 +661,7 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
/* Allocate memory, using an optional status argument.
This function follows the following pseudo-code:
void *
@ -717,9 +717,9 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
/* Generate code for an ALLOCATE statement when the argument is an
allocatable variable. If the variable is currently allocated, it is an
error to allocate it again.
This function follows the following pseudo-code:
void *
allocate_allocatable (void *mem, size_t size, integer_type stat)
{
@ -733,7 +733,7 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
runtime_error ("Attempting to allocate already allocated variable");
}
}
expr must be set to the original expression being allocated for its locus
and variable name in case a runtime error has to be printed. */
void
@ -866,7 +866,7 @@ gfc_call_free (tree var)
even when no status variable is passed to us (this is used for
unconditional deallocation generated by the front-end at end of
each procedure).
If a runtime-message is possible, `expr' must point to the original
expression being deallocated for its locus and variable name.
@ -1075,7 +1075,7 @@ gfc_deallocate_scalar_with_status (tree pointer, tree status, bool can_fail,
/* When POINTER is not NULL, we free it. */
gfc_start_block (&non_null);
/* Free allocatable components. */
if (ts.type == BT_DERIVED && ts.u.derived->attr.alloc_comp)
{
@ -1091,7 +1091,7 @@ gfc_deallocate_scalar_with_status (tree pointer, tree status, bool can_fail,
tmp, 0);
gfc_add_expr_to_block (&non_null, tmp);
}
tmp = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_FREE), 1,
fold_convert (pvoid_type_node, pointer));
@ -1320,6 +1320,12 @@ trans_code (gfc_code * code, tree cond)
case EXEC_POINTER_ASSIGN:
if (code->expr1->ts.type == BT_CLASS)
res = gfc_trans_class_assign (code->expr1, code->expr2, code->op);
else if (UNLIMITED_POLY (code->expr2)
&& code->expr1->ts.type == BT_DERIVED
&& (code->expr1->ts.u.derived->attr.sequence
|| code->expr1->ts.u.derived->attr.is_bind_c))
/* F2003: C717 */
res = gfc_trans_class_assign (code->expr1, code->expr2, code->op);
else
res = gfc_trans_pointer_assign (code);
break;
@ -1544,7 +1550,7 @@ trans_code (gfc_code * code, tree cond)
{
if (TREE_CODE (res) != STATEMENT_LIST)
SET_EXPR_LOCATION (res, input_location);
/* Add the new statement to the block. */
gfc_add_expr_to_block (&block, res);
}
@ -1686,7 +1692,7 @@ gfc_finish_wrapped_block (gfc_wrapped_block* block)
if (block->cleanup)
result = build2_loc (input_location, TRY_FINALLY_EXPR, void_type_node,
result, block->cleanup);
/* Clear the block. */
block->init = NULL_TREE;
block->code = NULL_TREE;

View file

@ -1,3 +1,10 @@
2012-12-19 Paul Thomas <pault@gcc.gnu.org>
* gfortran.dg/unlimited_polymorphic_1.f03: New test.
* gfortran.dg/unlimited_polymorphic_2.f03: New test.
* gfortran.dg/unlimited_polymorphic_3.f03: New test.
* gfortran.dg/same_type_as.f03: Correct for improved message.
2012-12-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/arm/vmaxnmdf.c: New test.

View file

@ -0,0 +1,211 @@
! { dg-do run }
!
! Basic tests of functionality of unlimited polymorphism
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
!
MODULE m
TYPE :: a
integer :: i
END TYPE
contains
subroutine bar (arg, res)
class(*) :: arg
character(100) :: res
select type (w => arg)
type is (a)
write (res, '(a, I4)') "type(a)", w%i
type is (integer)
write (res, '(a, I4)') "integer", w
type is (real(4))
write (res, '(a, F4.1)') "real4", w
type is (real(8))
write (res, '(a, F4.1)') "real8", w
type is (character(*, kind = 4))
call abort
type is (character(*))
write (res, '(a, I2, a, a)') "char(", LEN(w), ")", trim(w)
end select
end subroutine
subroutine foo (arg, res)
class(*) :: arg (:)
character(100) :: res
select type (w => arg)
type is (a)
write (res,'(a, 10I4)') "type(a) array", w%i
type is (integer)
write (res,'(a, 10I4)') "integer array", w
type is (real)
write (res,'(a, 10F4.1)') "real array", w
type is (character(*))
write (res, '(a5, I2, a, I2, a1, 2(a))') &
"char(",len(w),",", size(w,1),") array ", w
end select
end subroutine
END MODULE
USE m
TYPE(a), target :: obj1 = a(99)
TYPE(a), target :: obj2(3) = a(999)
integer, target :: obj3 = 999
real(4), target :: obj4(4) = [(real(i), i = 1, 4)]
integer, target :: obj5(3) = [(i*99, i = 1, 3)]
class(*), pointer :: u1
class(*), pointer :: u2(:)
class(*), allocatable :: u3
class(*), allocatable :: u4(:)
type(a), pointer :: aptr(:)
character(8) :: sun = "sunshine"
character(100) :: res
! NULL without MOLD used to cause segfault
u2 => NULL()
u2 => NULL(aptr)
! Test pointing to derived types.
u1 => obj1
if (SAME_TYPE_AS (obj1, u1) .neqv. .TRUE.) call abort
u2 => obj2
call bar (u1, res)
if (trim (res) .ne. "type(a) 99") call abort
call foo (u2, res)
if (trim (res) .ne. "type(a) array 999 999 999") call abort
if (SAME_TYPE_AS (obj1, u1) .neqv. .TRUE.) call abort
! Check allocate with an array SOURCE.
allocate (u2(5), source = [(a(i), i = 1,5)])
if (SAME_TYPE_AS (u1, a(2)) .neqv. .TRUE.) call abort
call foo (u2, res)
if (trim (res) .ne. "type(a) array 1 2 3 4 5") call abort
deallocate (u2)
! Point to intrinsic targets.
u1 => obj3
call bar (u1, res)
if (trim (res) .ne. "integer 999") call abort
u2 => obj4
call foo (u2, res)
if (trim (res) .ne. "real array 1.0 2.0 3.0 4.0") call abort
u2 => obj5
call foo (u2, res)
if (trim (res) .ne. "integer array 99 198 297") call abort
! Test allocate with source.
allocate (u1, source = sun)
call bar (u1, res)
if (trim (res) .ne. "char( 8)sunshine") call abort
deallocate (u1)
allocate (u2(3), source = [7,8,9])
call foo (u2, res)
if (trim (res) .ne. "integer array 7 8 9") call abort
deallocate (u2)
if (EXTENDS_TYPE_OF (obj1, u2) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u2, obj1) .neqv. .FALSE.) call abort
allocate (u2(3), source = [5.0,6.0,7.0])
call foo (u2, res)
if (trim (res) .ne. "real array 5.0 6.0 7.0") call abort
if (EXTENDS_TYPE_OF (obj1, u2) .neqv. .FALSE.) call abort
if (EXTENDS_TYPE_OF (u2, obj1) .neqv. .FALSE.) call abort
deallocate (u2)
! Check allocate with a MOLD tag.
allocate (u2(3), mold = 8.0)
call foo (u2, res)
if (res(1:10) .ne. "real array") call abort
deallocate (u2)
! Test passing an intrinsic type to a CLASS(*) formal.
call bar(1, res)
if (trim (res) .ne. "integer 1") call abort
call bar(2.0, res)
if (trim (res) .ne. "real4 2.0") call abort
call bar(2d0, res)
if (trim (res) .ne. "real8 2.0") call abort
call bar(a(3), res)
if (trim (res) .ne. "type(a) 3") call abort
call bar(sun, res)
if (trim (res) .ne. "char( 8)sunshine") call abort
call bar (obj3, res)
if (trim (res) .ne. "integer 999") call abort
call foo([4,5], res)
if (trim (res) .ne. "integer array 4 5") call abort
call foo([6.0,7.0], res)
if (trim (res) .ne. "real array 6.0 7.0") call abort
call foo([a(8),a(9)], res)
if (trim (res) .ne. "type(a) array 8 9") call abort
call foo([sun, " & rain"], res)
if (trim (res) .ne. "char( 8, 2)sunshine & rain") call abort
call foo([sun//" never happens", " & rain always happens"], res)
if (trim (res) .ne. "char(22, 2)sunshine never happens & rain always happens") call abort
call foo (obj4, res)
if (trim (res) .ne. "real array 1.0 2.0 3.0 4.0") call abort
call foo (obj5, res)
if (trim (res) .ne. "integer array 99 198 297") call abort
! Allocatable entities
if (EXTENDS_TYPE_OF (obj1, u3) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u3, obj1) .neqv. .FALSE.) call abort
if (EXTENDS_TYPE_OF (obj1, u4) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u4, obj1) .neqv. .FALSE.) call abort
allocate (u3, source = 2.4)
call bar (u3, res)
if (trim (res) .ne. "real4 2.4") call abort
allocate (u4(2), source = [a(88), a(99)])
call foo (u4, res)
if (trim (res) .ne. "type(a) array 88 99") call abort
if (EXTENDS_TYPE_OF (obj1, u3) .neqv. .FALSE.) call abort
if (EXTENDS_TYPE_OF (u3, obj1) .neqv. .FALSE.) call abort
deallocate (u3)
if (EXTENDS_TYPE_OF (obj1, u3) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u3, obj1) .neqv. .FALSE.) call abort
if (EXTENDS_TYPE_OF (obj1, u4) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u4, obj1) .neqv. .TRUE.) call abort
deallocate (u4)
if (EXTENDS_TYPE_OF (obj1, u4) .neqv. .TRUE.) call abort
if (EXTENDS_TYPE_OF (u4, obj1) .neqv. .FALSE.) call abort
! Check assumed rank calls
call foobar (u3, 0)
call foobar (u4, 1)
contains
subroutine foobar (arg, ranki)
class(*) :: arg (..)
integer :: ranki
integer i
i = rank (arg)
if (i .ne. ranki) call abort
end subroutine
END

View file

@ -0,0 +1,81 @@
! { dg-do compile }
!
! Test the most important constraints unlimited polymorphic entities
!
! Contributed by Paul Thomas <pault@gcc.gnu.org>
! and Tobias Burnus <burnus@gcc.gnu.org>
!
CHARACTER(:), allocatable, target :: chr ! { dg-error "TODO: Deferred character length variable" }
! F2008: C5100
integer :: i(2)
logical :: flag
class(*), pointer :: u1, u2(:) ! { dg-error "cannot appear in COMMON" }
common u1
u1 => chr
! F2003: C625
allocate (u1) ! { dg-error "requires either a type-spec or SOURCE tag" }
allocate (u1, mold = 1.0) ! { dg-error "requires either a type-spec or SOURCE tag" }
allocate (real :: u1)
Allocate (u1, source = 1.0)
! F2008: C4106
u2 = [u1] ! { dg-error "shall not be unlimited polymorphic" }
i = u2 ! { dg-error "Can\\'t convert CLASS\\(\\*\\)" }
! Repeats same_type_as_1.f03 for unlimited polymorphic u2
flag = same_type_as (i, u2) ! { dg-error "cannot be of type INTEGER" }
flag = extends_type_of (i, u2) ! { dg-error "cannot be of type INTEGER" }
contains
! C717 (R735) If data-target is unlimited polymorphic,
! data-pointer-object shall be unlimited polymorphic, of a sequence
! derived type, or of a type with the BIND attribute.
!
subroutine bar
type sq
sequence
integer :: i
end type sq
type(sq), target :: x
class(*), pointer :: y
integer, pointer :: tgt
x%i = 42
y => x
call foo (y)
y => tgt ! This is OK, of course.
tgt => y ! { dg-error "must be unlimited polymorphic" }
select type (y) ! This is the correct way to accomplish the previous
type is (integer)
tgt => y
end select
end subroutine bar
subroutine foo(tgt)
class(*), pointer, intent(in) :: tgt
type t
sequence
integer :: k
end type t
type(t), pointer :: ptr
ptr => tgt ! C717 allows this.
select type (tgt)
! F03:C815 or F08:C839
type is (t) ! { dg-error "shall not specify a sequence derived type" }
ptr => tgt ! { dg-error "Expected TYPE IS" }
end select
print *, ptr%k
end subroutine foo
END

View file

@ -0,0 +1,55 @@
! { dg-do run }
!
! Check that pointer assignments allowed by F2003:C717
! work and check null initialization of CLASS(*) pointers.
!
! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
!
program main
interface
subroutine foo(z)
class(*), pointer, intent(in) :: z
end subroutine foo
end interface
type sq
sequence
integer :: i
end type sq
type(sq), target :: x
class(*), pointer :: y, z
x%i = 42
y => x
z => y ! unlimited => unlimited allowed
call foo (z)
call bar
contains
subroutine bar
type t
end type t
type(t), pointer :: x
class(*), pointer :: ptr1 => null() ! pointer initialization
class(*), pointer :: ptr2 => null(x) ! pointer initialization
if (same_type_as (ptr1, x) .neqv. .FALSE.) call abort
if (same_type_as (ptr2, x) .neqv. .TRUE.) call abort
end subroutine bar
end program main
subroutine foo(tgt)
use iso_c_binding
class(*), pointer, intent(in) :: tgt
type, bind(c) :: s
integer (c_int) :: k
end type s
type t
sequence
integer :: k
end type t
type(s), pointer :: ptr1
type(t), pointer :: ptr2
ptr1 => tgt ! bind(c) => unlimited allowed
if (ptr1%k .ne. 42) call abort
ptr2 => tgt ! sequence type => unlimited allowed
if (ptr2%k .ne. 42) call abort
end subroutine foo

View file

@ -1,3 +1,8 @@
2012-12-19 Paul Thomas <pault@gcc.gnu.org>
* intrinsics/extends_type_of.c : Return correct results for
null vptrs.
2012-12-03 Janus Weil <janus@gcc.gnu.org>
PR fortran/55548

View file

@ -49,6 +49,14 @@ export_proto(is_extension_of);
GFC_LOGICAL_4
is_extension_of (struct vtype *v1, struct vtype *v2)
{
/* Assume that only unlimited polymorphic entities will pass NULL v1 or v2
if they are unallocated or disassociated. */
if (!v2)
return 1;
if (!v1)
return 0;
while (v1)
{
if (v1->hash == v2->hash) return 1;