/* Intrinsic function resolution.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Andy Vaught & Katherine Holcomb
source->rank = 0;
}
else if (source->expr_type == EXPR_ARRAY)
- {
- source->ts.cl->length =
+ source->ts.cl->length =
gfc_int_expr (source->value.constructor->expr->value.character.length);
- source->rank = 1;
- }
}
/* Helper function for resolving the "mask" argument. */
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
if (mask->rank == 0)
{
/* In the library, we access the mask with a GFC_LOGICAL_1
argument. No need to waste memory if we are about to create
a temporary array. */
- if (mask->expr_type == EXPR_OP)
+ if (mask->expr_type == EXPR_OP && mask->ts.kind != 1)
{
ts.type = BT_LOGICAL;
ts.kind = 1;
}
+void
+gfc_resolve_adjustl (gfc_expr *f, gfc_expr *string)
+{
+ f->ts.type = BT_CHARACTER;
+ f->ts.kind = string->ts.kind;
+ f->value.function.name = gfc_get_string ("__adjustl_s%d", f->ts.kind);
+}
+
+
+void
+gfc_resolve_adjustr (gfc_expr *f, gfc_expr *string)
+{
+ f->ts.type = BT_CHARACTER;
+ f->ts.kind = string->ts.kind;
+ f->value.function.name = gfc_get_string ("__adjustr_s%d", f->ts.kind);
+}
+
+
static void
gfc_resolve_char_achar (gfc_expr *f, gfc_expr *x, gfc_expr *kind,
const char *name)
gfc_resolve_aint (gfc_expr *f, gfc_expr *a, gfc_expr *kind)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = a->ts.type;
f->ts.kind = (kind == NULL) ? a->ts.kind : mpz_get_si (kind->value.integer);
gfc_resolve_anint (gfc_expr *f, gfc_expr *a, gfc_expr *kind)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = a->ts.type;
f->ts.kind = (kind == NULL) ? a->ts.kind : mpz_get_si (kind->value.integer);
gfc_resolve_besn (gfc_expr *f, gfc_expr *n, gfc_expr *x)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts = x->ts;
if (n->ts.kind != gfc_c_int_kind)
f->shape = gfc_copy_shape_excluding (mask->shape, mask->rank, dim);
}
+ resolve_mask_arg (mask);
+
f->value.function.name
- = gfc_get_string (PREFIX ("count_%d_%c%d"), f->ts.kind,
- gfc_type_letter (mask->ts.type), mask->ts.kind);
+ = gfc_get_string (PREFIX ("count_%d_%c"), f->ts.kind,
+ gfc_type_letter (mask->ts.type));
}
if (shift->ts.kind < m)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = m;
gfc_convert_type_warn (shift, &ts, 2, 0);
if (dim != NULL)
{
- if (dim->expr_type != EXPR_CONSTANT && dim->symtree->n.sym->attr.optional)
+ if (dim->expr_type != EXPR_CONSTANT && dim->symtree != NULL
+ && dim->symtree->n.sym->attr.optional)
{
/* Mark this for later setting the type in gfc_conv_missing_dummy. */
dim->representation.length = shift->ts.kind;
}
}
- f->value.function.name
- = gfc_get_string (PREFIX ("cshift%d_%d%s"), n, shift->ts.kind,
- array->ts.type == BT_CHARACTER ? "_char" : "");
+ if (array->ts.type == BT_CHARACTER)
+ {
+ if (array->ts.kind == gfc_default_character_kind)
+ f->value.function.name
+ = gfc_get_string (PREFIX ("cshift%d_%d_char"), n, shift->ts.kind);
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("cshift%d_%d_char%d"), n, shift->ts.kind,
+ array->ts.kind);
+ }
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("cshift%d_%d"), n, shift->ts.kind);
}
gfc_resolve_ctime (gfc_expr *f, gfc_expr *time)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_CHARACTER;
f->ts.kind = gfc_default_character_kind;
temp.expr_type = EXPR_OP;
gfc_clear_ts (&temp.ts);
- temp.value.op.operator = INTRINSIC_NONE;
+ temp.value.op.op = INTRINSIC_NONE;
temp.value.op.op1 = a;
temp.value.op.op2 = b;
gfc_type_convert_binary (&temp);
if (shift->ts.kind < m)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = m;
gfc_convert_type_warn (shift, &ts, 2, 0);
if (dim != NULL)
{
- if (dim->expr_type != EXPR_CONSTANT && dim->symtree->n.sym->attr.optional)
+ if (dim->expr_type != EXPR_CONSTANT && dim->symtree != NULL
+ && dim->symtree->n.sym->attr.optional)
{
/* Mark this for later setting the type in gfc_conv_missing_dummy. */
dim->representation.length = shift->ts.kind;
}
}
- f->value.function.name
- = gfc_get_string (PREFIX ("eoshift%d_%d%s"), n, shift->ts.kind,
- array->ts.type == BT_CHARACTER ? "_char" : "");
+ if (array->ts.type == BT_CHARACTER)
+ {
+ if (array->ts.kind == gfc_default_character_kind)
+ f->value.function.name
+ = gfc_get_string (PREFIX ("eoshift%d_%d_char"), n, shift->ts.kind);
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("eoshift%d_%d_char%d"), n, shift->ts.kind,
+ array->ts.kind);
+ }
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("eoshift%d_%d"), n, shift->ts.kind);
}
void
+gfc_resolve_hypot (gfc_expr *f, gfc_expr *x, gfc_expr *y ATTRIBUTE_UNUSED)
+{
+ f->ts = x->ts;
+ f->value.function.name = gfc_get_string ("__hypot_r%d", x->ts.kind);
+}
+
+
+void
gfc_resolve_iand (gfc_expr *f, gfc_expr *i, gfc_expr *j)
{
/* If the kind of i and j are different, then g77 cross-promoted the
gfc_expr *kind)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_INTEGER;
if (kind)
gfc_resolve_isatty (gfc_expr *f, gfc_expr *u)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_LOGICAL;
f->ts.kind = gfc_default_integer_kind;
if (size->ts.kind < gfc_index_integer_kind)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = gfc_index_integer_kind;
{
temp.expr_type = EXPR_OP;
gfc_clear_ts (&temp.ts);
- temp.value.op.operator = INTRINSIC_NONE;
+ temp.value.op.op = INTRINSIC_NONE;
temp.value.op.op1 = a;
temp.value.op.op2 = b;
gfc_type_convert_binary (&temp);
f->rank = (a->rank == 2 && b->rank == 2) ? 2 : 1;
+ if (a->rank == 2 && b->rank == 2)
+ {
+ if (a->shape && b->shape)
+ {
+ f->shape = gfc_get_shape (f->rank);
+ mpz_init_set (f->shape[0], a->shape[0]);
+ mpz_init_set (f->shape[1], b->shape[1]);
+ }
+ }
+ else if (a->rank == 1)
+ {
+ if (b->shape)
+ {
+ f->shape = gfc_get_shape (f->rank);
+ mpz_init_set (f->shape[0], b->shape[1]);
+ }
+ }
+ else
+ {
+ /* b->rank == 1 and a->rank == 2 here, all other cases have
+ been caught in check.c. */
+ if (a->shape)
+ {
+ f->shape = gfc_get_shape (f->rank);
+ mpz_init_set (f->shape[0], a->shape[0]);
+ }
+ }
+
f->value.function.name
= gfc_get_string (PREFIX ("matmul_%c%d"), gfc_type_letter (f->ts.type),
f->ts.kind);
resolve_mask_arg (mask);
if (mask->rank != 0)
- f->value.function.name = (array->ts.type == BT_CHARACTER
- ? PREFIX ("pack_char") : PREFIX ("pack"));
+ {
+ if (array->ts.type == BT_CHARACTER)
+ f->value.function.name
+ = array->ts.kind == 1 ? PREFIX ("pack_char")
+ : gfc_get_string
+ (PREFIX ("pack_char%d"),
+ array->ts.kind);
+ else
+ f->value.function.name = PREFIX ("pack");
+ }
else
- f->value.function.name = (array->ts.type == BT_CHARACTER
- ? PREFIX ("pack_s_char") : PREFIX ("pack_s"));
+ {
+ if (array->ts.type == BT_CHARACTER)
+ f->value.function.name
+ = array->ts.kind == 1 ? PREFIX ("pack_s_char")
+ : gfc_get_string
+ (PREFIX ("pack_s_char%d"),
+ array->ts.kind);
+ else
+ f->value.function.name = PREFIX ("pack_s");
+ }
}
if (dim != NULL)
{
f->rank = array->rank - 1;
+ f->shape = gfc_copy_shape_excluding (array->shape, array->rank, dim);
gfc_resolve_dim_arg (dim);
}
case BT_REAL:
case BT_INTEGER:
case BT_LOGICAL:
+ case BT_CHARACTER:
kind = source->ts.kind;
break;
= gfc_get_string (PREFIX ("reshape_%c%d"),
gfc_type_letter (source->ts.type),
source->ts.kind);
+ else if (source->ts.type == BT_CHARACTER)
+ f->value.function.name = gfc_get_string (PREFIX ("reshape_char%d"),
+ kind);
else
f->value.function.name
= gfc_get_string (PREFIX ("reshape_%d"), source->ts.kind);
-
break;
default:
f->value.function.name = (source->ts.type == BT_CHARACTER
- ? PREFIX ("reshape_char") : PREFIX ("reshape"));
+ ? PREFIX ("reshape_char") : PREFIX ("reshape"));
break;
}
void
gfc_resolve_rrspacing (gfc_expr *f, gfc_expr *x)
{
- int k;
- gfc_actual_arglist *prec;
-
f->ts = x->ts;
f->value.function.name = gfc_get_string ("__rrspacing_%d", x->ts.kind);
-
- /* Create a hidden argument to the library routines for rrspacing. This
- hidden argument is the precision of x. */
- k = gfc_validate_kind (BT_REAL, x->ts.kind, false);
- prec = gfc_get_actual_arglist ();
- prec->name = "p";
- prec->expr = gfc_int_expr (gfc_real_kinds[k].digits);
- /* The library routine expects INTEGER(4). */
- if (prec->expr->ts.kind != gfc_c_int_kind)
- {
- gfc_typespec ts;
- ts.type = BT_INTEGER;
- ts.kind = gfc_c_int_kind;
- gfc_convert_type (prec->expr, &ts, 2);
- }
- f->value.function.actual->next = prec;
}
void
-gfc_resolve_scale (gfc_expr *f, gfc_expr *x, gfc_expr *i)
+gfc_resolve_scale (gfc_expr *f, gfc_expr *x, gfc_expr *i ATTRIBUTE_UNUSED)
{
f->ts = x->ts;
-
- /* The implementation calls scalbn which takes an int as the
- second argument. */
- if (i->ts.kind != gfc_c_int_kind)
- {
- gfc_typespec ts;
- ts.type = BT_INTEGER;
- ts.kind = gfc_c_int_kind;
- gfc_convert_type_warn (i, &ts, 2, 0);
- }
-
f->value.function.name = gfc_get_string ("__scale_%d", x->ts.kind);
}
void
-gfc_resolve_set_exponent (gfc_expr *f, gfc_expr *x, gfc_expr *i)
+gfc_resolve_set_exponent (gfc_expr *f, gfc_expr *x,
+ gfc_expr *i ATTRIBUTE_UNUSED)
{
f->ts = x->ts;
-
- /* The library implementation uses GFC_INTEGER_4 unconditionally,
- convert type so we don't have to implement all possible
- permutations. */
- if (i->ts.kind != gfc_c_int_kind)
- {
- gfc_typespec ts;
- ts.type = BT_INTEGER;
- ts.kind = gfc_c_int_kind;
- gfc_convert_type_warn (i, &ts, 2, 0);
- }
-
f->value.function.name = gfc_get_string ("__set_exponent_%d", x->ts.kind);
}
void
gfc_resolve_spacing (gfc_expr *f, gfc_expr *x)
{
- int k;
- gfc_actual_arglist *prec, *tiny, *emin_1;
-
f->ts = x->ts;
f->value.function.name = gfc_get_string ("__spacing_%d", x->ts.kind);
-
- /* Create hidden arguments to the library routine for spacing. These
- hidden arguments are tiny(x), min_exponent - 1, and the precision
- of x. */
-
- k = gfc_validate_kind (BT_REAL, x->ts.kind, false);
-
- tiny = gfc_get_actual_arglist ();
- tiny->name = "tiny";
- tiny->expr = gfc_get_expr ();
- tiny->expr->expr_type = EXPR_CONSTANT;
- tiny->expr->where = gfc_current_locus;
- tiny->expr->ts.type = x->ts.type;
- tiny->expr->ts.kind = x->ts.kind;
- mpfr_init (tiny->expr->value.real);
- mpfr_set (tiny->expr->value.real, gfc_real_kinds[k].tiny, GFC_RND_MODE);
-
- emin_1 = gfc_get_actual_arglist ();
- emin_1->name = "emin";
- emin_1->expr = gfc_int_expr (gfc_real_kinds[k].min_exponent - 1);
-
- /* The library routine expects INTEGER(4). */
- if (emin_1->expr->ts.kind != gfc_c_int_kind)
- {
- gfc_typespec ts;
- ts.type = BT_INTEGER;
- ts.kind = gfc_c_int_kind;
- gfc_convert_type (emin_1->expr, &ts, 2);
- }
- emin_1->next = tiny;
-
- prec = gfc_get_actual_arglist ();
- prec->name = "prec";
- prec->expr = gfc_int_expr (gfc_real_kinds[k].digits);
-
- /* The library routine expects INTEGER(4). */
- if (prec->expr->ts.kind != gfc_c_int_kind)
- {
- gfc_typespec ts;
- ts.type = BT_INTEGER;
- ts.kind = gfc_c_int_kind;
- gfc_convert_type (prec->expr, &ts, 2);
- }
- prec->next = emin_1;
-
- f->value.function.actual->next = prec;
}
f->ts = source->ts;
f->rank = source->rank + 1;
if (source->rank == 0)
- f->value.function.name = (source->ts.type == BT_CHARACTER
- ? PREFIX ("spread_char_scalar")
- : PREFIX ("spread_scalar"));
+ {
+ if (source->ts.type == BT_CHARACTER)
+ f->value.function.name
+ = source->ts.kind == 1 ? PREFIX ("spread_char_scalar")
+ : gfc_get_string
+ (PREFIX ("spread_char%d_scalar"),
+ source->ts.kind);
+ else
+ f->value.function.name = PREFIX ("spread_scalar");
+ }
else
- f->value.function.name = (source->ts.type == BT_CHARACTER
- ? PREFIX ("spread_char")
- : PREFIX ("spread"));
+ {
+ if (source->ts.type == BT_CHARACTER)
+ f->value.function.name
+ = source->ts.kind == 1 ? PREFIX ("spread_char")
+ : gfc_get_string
+ (PREFIX ("spread_char%d"),
+ source->ts.kind);
+ else
+ f->value.function.name = PREFIX ("spread");
+ }
if (dim && gfc_is_constant_expr (dim)
&& ncopies && gfc_is_constant_expr (ncopies) && source->shape[0])
gfc_resolve_fgetc (gfc_expr *f, gfc_expr *u, gfc_expr *c ATTRIBUTE_UNUSED)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_INTEGER;
f->ts.kind = gfc_c_int_kind;
gfc_resolve_fputc (gfc_expr *f, gfc_expr *u, gfc_expr *c ATTRIBUTE_UNUSED)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_INTEGER;
f->ts.kind = gfc_c_int_kind;
gfc_resolve_ftell (gfc_expr *f, gfc_expr *u)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_INTEGER;
f->ts.kind = gfc_index_integer_kind;
if (dim != NULL)
{
f->rank = array->rank - 1;
+ f->shape = gfc_copy_shape_excluding (array->shape, array->rank, dim);
gfc_resolve_dim_arg (dim);
}
break;
default:
- f->value.function.name = PREFIX ("transpose");
+ if (matrix->ts.type == BT_CHARACTER && matrix->ts.kind == 4)
+ f->value.function.name = PREFIX ("transpose_char4");
+ else
+ f->value.function.name = PREFIX ("transpose");
break;
}
break;
gfc_resolve_ttynam (gfc_expr *f, gfc_expr *unit)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
f->ts.type = BT_CHARACTER;
f->ts.kind = gfc_default_character_kind;
f->rank = mask->rank;
resolve_mask_arg (mask);
- f->value.function.name
- = gfc_get_string (PREFIX ("unpack%d%s"), field->rank > 0 ? 1 : 0,
- vector->ts.type == BT_CHARACTER ? "_char" : "");
+ if (vector->ts.type == BT_CHARACTER)
+ {
+ if (vector->ts.kind == 1)
+ f->value.function.name
+ = gfc_get_string (PREFIX ("unpack%d_char"), field->rank > 0 ? 1 : 0);
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("unpack%d_char%d"),
+ field->rank > 0 ? 1 : 0, vector->ts.kind);
+ }
+ else
+ f->value.function.name
+ = gfc_get_string (PREFIX ("unpack%d"), field->rank > 0 ? 1 : 0);
}
const char *name;
gfc_expr *seconds, *handler, *status;
gfc_typespec ts;
+ gfc_clear_ts (&ts);
seconds = c->ext.actual->expr;
handler = c->ext.actual->next->expr;
}
+/* Create a formal arglist based on an actual one and set the INTENTs given. */
+
+static gfc_formal_arglist*
+create_formal_for_intents (gfc_actual_arglist* actual, const sym_intent* ints)
+{
+ gfc_formal_arglist* head;
+ gfc_formal_arglist* tail;
+ int i;
+
+ if (!actual)
+ return NULL;
+
+ head = tail = gfc_get_formal_arglist ();
+ for (i = 0; actual; actual = actual->next, tail = tail->next, ++i)
+ {
+ gfc_symbol* sym;
+
+ sym = gfc_new_symbol ("dummyarg", NULL);
+ sym->ts = actual->expr->ts;
+
+ sym->attr.intent = ints[i];
+ tail->sym = sym;
+
+ if (actual->next)
+ tail->next = gfc_get_formal_arglist ();
+ }
+
+ return head;
+}
+
+
void
gfc_resolve_mvbits (gfc_code *c)
{
+ static const sym_intent INTENTS[] = {INTENT_IN, INTENT_IN, INTENT_IN,
+ INTENT_INOUT, INTENT_IN};
+
const char *name;
gfc_typespec ts;
+ gfc_clear_ts (&ts);
/* FROMPOS, LEN and TOPOS are restricted to small values. As such,
they will be converted so that they fit into a C int. */
c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
/* Mark as elemental subroutine as this does not happen automatically. */
c->resolved_sym->attr.elemental = 1;
+
+ /* Create a dummy formal arglist so the INTENTs are known later for purpose
+ of creating temporaries. */
+ c->resolved_sym->formal = create_formal_for_intents (c->ext.actual, INTENTS);
}
if (c->ext.actual->expr->ts.kind != gfc_default_integer_kind)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = gfc_default_integer_kind;
const char *name;
gfc_expr *number, *handler, *status;
gfc_typespec ts;
+ gfc_clear_ts (&ts);
number = c->ext.actual->expr;
handler = c->ext.actual->next->expr;
const char *name;
gfc_typespec ts;
gfc_expr *n;
+ gfc_clear_ts (&ts);
/* The STATUS argument has to be of default kind. If it is not,
we convert it. */
const char *name;
gfc_typespec ts;
gfc_expr *n;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = gfc_default_integer_kind;
{
gfc_typespec ts;
gfc_expr *n;
+ gfc_clear_ts (&ts);
ts.type = BT_INTEGER;
ts.kind = gfc_index_integer_kind;
gfc_resolve_ctime_sub (gfc_code *c)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
/* ctime TIME argument is a INTEGER(KIND=8), says the doc */
if (c->ext.actual->expr->ts.kind != 8)
const char *name;
gfc_typespec ts;
gfc_expr *u, *st;
+ gfc_clear_ts (&ts);
u = c->ext.actual->expr;
st = c->ext.actual->next->next->expr;
const char *name;
gfc_typespec ts;
gfc_expr *u, *st;
+ gfc_clear_ts (&ts);
u = c->ext.actual->expr;
st = c->ext.actual->next->next->expr;
gfc_expr *whence;
gfc_expr *status;
gfc_typespec ts;
+ gfc_clear_ts (&ts);
unit = c->ext.actual->expr;
offset = c->ext.actual->next->expr;
gfc_expr *unit;
gfc_expr *offset;
gfc_typespec ts;
+ gfc_clear_ts (&ts);
unit = c->ext.actual->expr;
offset = c->ext.actual->next->expr;
gfc_resolve_ttynam_sub (gfc_code *c)
{
gfc_typespec ts;
+ gfc_clear_ts (&ts);
if (c->ext.actual->expr->ts.kind != gfc_c_int_kind)
{