#include "intrinsic.h"
+/* Make sure an expression is a scalar. */
+
+static try
+scalar_check (gfc_expr *e, int n)
+{
+ if (e->rank == 0)
+ return SUCCESS;
+
+ gfc_error ("'%s' argument of '%s' intrinsic at %L must be a scalar",
+ gfc_current_intrinsic_arg[n], gfc_current_intrinsic, &e->where);
+
+ return FAILURE;
+}
+
+
/* Check the type of an expression. */
static try
if (type_check (k, n, BT_INTEGER) == FAILURE)
return FAILURE;
+ if (scalar_check (k, n) == FAILURE)
+ return FAILURE;
+
if (k->expr_type != EXPR_CONSTANT)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be a constant",
}
-/* Make sure an expression is a scalar. */
-
-static try
-scalar_check (gfc_expr *e, int n)
-{
- if (e->rank == 0)
- return SUCCESS;
-
- gfc_error ("'%s' argument of '%s' intrinsic at %L must be a scalar",
- gfc_current_intrinsic_arg[n], gfc_current_intrinsic, &e->where);
-
- return FAILURE;
-}
-
-
/* Make sure two expressions have the same type. */
static try
/* Check the common DIM parameter for correctness. */
static try
-dim_check (gfc_expr *dim, int n, int optional)
+dim_check (gfc_expr *dim, int n, bool optional)
{
- if (optional && dim == NULL)
+ if (dim == NULL)
return SUCCESS;
if (dim == NULL)
if (scalar_check (dim, n) == FAILURE)
return FAILURE;
- if (nonoptional_check (dim, n) == FAILURE)
+ if (!optional && nonoptional_check (dim, n) == FAILURE)
return FAILURE;
return SUCCESS;
}
+/* Check whether two character expressions have the same length;
+ returns SUCCESS if they have or if the length cannot be determined. */
+
+static try
+check_same_strlen (const gfc_expr *a, const gfc_expr *b, const char *name)
+{
+ long len_a, len_b;
+ len_a = len_b = -1;
+
+ if (a->ts.cl && a->ts.cl->length
+ && a->ts.cl->length->expr_type == EXPR_CONSTANT)
+ len_a = mpz_get_si (a->ts.cl->length->value.integer);
+ else if (a->expr_type == EXPR_CONSTANT
+ && (a->ts.cl == NULL || a->ts.cl->length == NULL))
+ len_a = a->value.character.length;
+ else
+ return SUCCESS;
+
+ if (b->ts.cl && b->ts.cl->length
+ && b->ts.cl->length->expr_type == EXPR_CONSTANT)
+ len_b = mpz_get_si (b->ts.cl->length->value.integer);
+ else if (b->expr_type == EXPR_CONSTANT
+ && (b->ts.cl == NULL || b->ts.cl->length == NULL))
+ len_b = b->value.character.length;
+ else
+ return SUCCESS;
+
+ if (len_a == len_b)
+ return SUCCESS;
+
+ gfc_error ("Unequal character lengths (%ld and %ld) in %s intrinsic "
+ "at %L", len_a, len_b, name, &a->where);
+ return FAILURE;
+}
+
+
/***** Check functions *****/
/* Check subroutine suitable for intrinsics taking a real argument and
try
-gfc_check_achar (gfc_expr *a)
+gfc_check_achar (gfc_expr *a, gfc_expr *kind)
{
if (type_check (a, 0, BT_INTEGER) == FAILURE)
return FAILURE;
+ if (kind_check (kind, 1, BT_CHARACTER) == FAILURE)
+ return FAILURE;
return SUCCESS;
}
if (logical_array_check (mask, 0) == FAILURE)
return FAILURE;
- if (dim_check (dim, 1, 1) == FAILURE)
+ if (dim_check (dim, 1, false) == FAILURE)
return FAILURE;
return SUCCESS;
{
if (logical_array_check (mask, 0) == FAILURE)
return FAILURE;
- if (dim_check (dim, 1, 1) == FAILURE)
+ if (dim_check (dim, 1, false) == FAILURE)
return FAILURE;
if (kind_check (kind, 2, BT_INTEGER) == FAILURE)
return FAILURE;
/* TODO: more requirements on shift parameter. */
}
- if (dim_check (dim, 2, 1) == FAILURE)
+ /* FIXME (PR33317): Allow optional DIM=. */
+ if (dim_check (dim, 2, false) == FAILURE)
return FAILURE;
return SUCCESS;
if (! identical_dimen_shape (vector_a, 0, vector_b, 0))
{
- gfc_error ("different shape for arguments '%s' and '%s' at %L for "
+ gfc_error ("Different shape for arguments '%s' and '%s' at %L for "
"intrinsic 'dot_product'", gfc_current_intrinsic_arg[0],
gfc_current_intrinsic_arg[1], &vector_a->where);
return FAILURE;
/* TODO: more restrictions on boundary. */
}
- if (dim_check (dim, 1, 1) == FAILURE)
+ /* FIXME (PR33317): Allow optional DIM=. */
+ if (dim_check (dim, 4, false) == FAILURE)
return FAILURE;
return SUCCESS;
if (numeric_check (x, 0) == FAILURE)
return FAILURE;
- if (kind != NULL)
- {
- if (type_check (kind, 1, BT_INTEGER) == FAILURE)
- return FAILURE;
-
- if (scalar_check (kind, 1) == FAILURE)
- return FAILURE;
- }
+ if (kind_check (kind, 1, BT_INTEGER) == FAILURE)
+ return FAILURE;
return SUCCESS;
}
if (dim != NULL)
{
- if (dim_check (dim, 1, 1) == FAILURE)
+ if (dim_check (dim, 1, false) == FAILURE)
return FAILURE;
if (dim_rank_check (dim, array, 1) == FAILURE)
/* Check for case matrix_a has shape(m), matrix_b has shape (m, k). */
if (!identical_dimen_shape (matrix_a, 0, matrix_b, 0))
{
- gfc_error ("different shape on dimension 1 for arguments '%s' "
+ gfc_error ("Different shape on dimension 1 for arguments '%s' "
"and '%s' at %L for intrinsic matmul",
gfc_current_intrinsic_arg[0],
gfc_current_intrinsic_arg[1], &matrix_a->where);
- matrix_a has shape (n,m) and matrix_b has shape (m). */
if (!identical_dimen_shape (matrix_a, 1, matrix_b, 0))
{
- gfc_error ("different shape on dimension 2 for argument '%s' and "
+ gfc_error ("Different shape on dimension 2 for argument '%s' and "
"dimension 1 for argument '%s' at %L for intrinsic "
"matmul", gfc_current_intrinsic_arg[0],
gfc_current_intrinsic_arg[1], &matrix_a->where);
ap->next->next->expr = m;
}
- if (dim_check (d, 1, 1) == FAILURE)
+ if (d && dim_check (d, 1, false) == FAILURE)
return FAILURE;
if (d && dim_rank_check (d, a, 0) == FAILURE)
ap->next->next->expr = m;
}
- if (dim_check (d, 1, 1) == FAILURE)
+ if (d && dim_check (d, 1, false) == FAILURE)
return FAILURE;
if (d && dim_rank_check (d, a, 0) == FAILURE)
if (type_check (mask, 2, BT_LOGICAL) == FAILURE)
return FAILURE;
+ if (tsource->ts.type == BT_CHARACTER)
+ return check_same_strlen (tsource, fsource, "MERGE");
+
return SUCCESS;
}
+
try
gfc_check_move_alloc (gfc_expr *from, gfc_expr *to)
{
if (dim != NULL)
{
- if (type_check (dim, 1, BT_INTEGER) == FAILURE)
- return FAILURE;
-
- if (kind_value_check (dim, 1, gfc_default_integer_kind) == FAILURE)
+ if (dim_check (dim, 1, true) == FAILURE)
return FAILURE;
if (dim_rank_check (dim, array, 0) == FAILURE)
return FAILURE;
}
- if (dim_check (dim, 1, 0) == FAILURE)
+ if (dim == NULL)
+ return FAILURE;
+
+ if (dim_check (dim, 1, false) == FAILURE)
return FAILURE;
if (type_check (ncopies, 2, BT_INTEGER) == FAILURE)
if (dim != NULL)
{
- if (dim_check (dim, 1, 1) == FAILURE)
+ if (dim_check (dim, 1, false) == FAILURE)
return FAILURE;
if (dim_rank_check (dim, array, 0) == FAILURE)
try
+gfc_check_getarg (gfc_expr *pos, gfc_expr *value)
+{
+ if (type_check (pos, 0, BT_INTEGER) == FAILURE)
+ return FAILURE;
+
+ if (pos->ts.kind > gfc_default_integer_kind)
+ {
+ gfc_error ("'%s' argument of '%s' intrinsic at %L must be of a kind "
+ "not wider than the default kind (%d)",
+ gfc_current_intrinsic_arg[0], gfc_current_intrinsic,
+ &pos->where, gfc_default_integer_kind);
+ return FAILURE;
+ }
+
+ if (type_check (value, 1, BT_CHARACTER) == FAILURE)
+ return FAILURE;
+
+ return SUCCESS;
+}
+
+
+try
gfc_check_getlog (gfc_expr *msg)
{
if (type_check (msg, 0, BT_CHARACTER) == FAILURE)