summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorfxcoudert <fxcoudert@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-12 20:45:29 +0000
committerfxcoudert <fxcoudert@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-12 20:45:29 +0000
commit3d3b790db32448aed311a1df5c182f639ee7ec97 (patch)
tree1aa675f2be8264295523bb56ade85d71e6c31e8c /gcc/fortran
parent6a78072d36ae9f17efded1ff6f8f85f610ffe715 (diff)
downloadgcc-3d3b790db32448aed311a1df5c182f639ee7ec97.tar.gz
PR fortran/30964
PR fortran/33054 * trans-expr.c (gfc_conv_function_call): When no formal argument list is available, we still substitute missing optional arguments. * check.c (gfc_check_random_seed): Correct the check on the number of arguments to RANDOM_SEED. * intrinsic.c (add_subroutines): Add a resolution function to RANDOM_SEED. * iresolve.c (gfc_resolve_random_seed): New function. * intrinsic.h (gfc_resolve_random_seed): New prototype. * intrinsics/random.c (random_seed): Rename into random_seed_i4. (random_seed_i8): New function. * gfortran.map (GFORTRAN_1.0): Remove _gfortran_random_seed, add _gfortran_random_seed_i4 and _gfortran_random_seed_i8. * libgfortran.h (iexport_proto): Replace random_seed by random_seed_i4 and random_seed_i8. * runtime/main.c (init): Call the new random_seed_i4. * gfortran.dg/random_4.f90: New test. * gfortran.dg/random_5.f90: New test. * gfortran.dg/random_6.f90: New test. * gfortran.dg/random_7.f90: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127383 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog13
-rw-r--r--gcc/fortran/check.c31
-rw-r--r--gcc/fortran/intrinsic.c5
-rw-r--r--gcc/fortran/intrinsic.h1
-rw-r--r--gcc/fortran/iresolve.c10
-rw-r--r--gcc/fortran/trans-expr.c52
6 files changed, 77 insertions, 35 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index a6e5c9edc1a..acbe9a7cf77 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,5 +1,18 @@
2007-08-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+ PR fortran/30964
+ PR fortran/33054
+ * trans-expr.c (gfc_conv_function_call): When no formal argument
+ list is available, we still substitute missing optional arguments.
+ * check.c (gfc_check_random_seed): Correct the check on the
+ number of arguments to RANDOM_SEED.
+ * intrinsic.c (add_subroutines): Add a resolution function to
+ RANDOM_SEED.
+ * iresolve.c (gfc_resolve_random_seed): New function.
+ * intrinsic.h (gfc_resolve_random_seed): New prototype.
+
+2007-08-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
PR fortran/32860
* error.c (error_uinteger): New function.
(error_integer): Call error_uinteger.
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index f0de08f3a21..23955deab9d 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -2880,8 +2880,15 @@ gfc_check_random_number (gfc_expr *harvest)
try
gfc_check_random_seed (gfc_expr *size, gfc_expr *put, gfc_expr *get)
{
+ unsigned int nargs = 0;
+ locus *where = NULL;
+
if (size != NULL)
{
+ if (size->expr_type != EXPR_VARIABLE
+ || !size->symtree->n.sym->attr.optional)
+ nargs++;
+
if (scalar_check (size, 0) == FAILURE)
return FAILURE;
@@ -2897,10 +2904,12 @@ gfc_check_random_seed (gfc_expr *size, gfc_expr *put, gfc_expr *get)
if (put != NULL)
{
-
- if (size != NULL)
- gfc_error ("Too many arguments to %s at %L", gfc_current_intrinsic,
- &put->where);
+ if (put->expr_type != EXPR_VARIABLE
+ || !put->symtree->n.sym->attr.optional)
+ {
+ nargs++;
+ where = &put->where;
+ }
if (array_check (put, 1) == FAILURE)
return FAILURE;
@@ -2917,10 +2926,12 @@ gfc_check_random_seed (gfc_expr *size, gfc_expr *put, gfc_expr *get)
if (get != NULL)
{
-
- if (size != NULL || put != NULL)
- gfc_error ("Too many arguments to %s at %L", gfc_current_intrinsic,
- &get->where);
+ if (get->expr_type != EXPR_VARIABLE
+ || !get->symtree->n.sym->attr.optional)
+ {
+ nargs++;
+ where = &get->where;
+ }
if (array_check (get, 2) == FAILURE)
return FAILURE;
@@ -2938,6 +2949,10 @@ gfc_check_random_seed (gfc_expr *size, gfc_expr *put, gfc_expr *get)
return FAILURE;
}
+ /* RANDOM_SEED may not have more than one non-optional argument. */
+ if (nargs > 1)
+ gfc_error ("Too many arguments to %s at %L", gfc_current_intrinsic, where);
+
return SUCCESS;
}
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 59006b2ee24..7f02245c7fb 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -2467,8 +2467,9 @@ add_subroutines (void)
gfc_check_random_number, NULL, gfc_resolve_random_number,
h, BT_REAL, dr, REQUIRED);
- add_sym_3s ("random_seed", GFC_ISYM_RANDOM_SEED, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_random_seed, NULL, NULL,
+ add_sym_3s ("random_seed", GFC_ISYM_RANDOM_SEED, NO_CLASS,
+ BT_UNKNOWN, 0, GFC_STD_F95,
+ gfc_check_random_seed, NULL, gfc_resolve_random_seed,
sz, BT_INTEGER, di, OPTIONAL, pt, BT_INTEGER, di, OPTIONAL,
gt, BT_INTEGER, di, OPTIONAL);
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 79cf3e52951..1e03e0cdd30 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -487,6 +487,7 @@ void gfc_resolve_ltime (gfc_code *);
void gfc_resolve_mvbits (gfc_code *);
void gfc_resolve_perror (gfc_code *);
void gfc_resolve_random_number (gfc_code *);
+void gfc_resolve_random_seed (gfc_code *);
void gfc_resolve_rename_sub (gfc_code *);
void gfc_resolve_link_sub (gfc_code *);
void gfc_resolve_symlnk_sub (gfc_code *);
diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c
index e3186155f27..6232374161e 100644
--- a/gcc/fortran/iresolve.c
+++ b/gcc/fortran/iresolve.c
@@ -2507,6 +2507,16 @@ gfc_resolve_random_number (gfc_code *c)
void
+gfc_resolve_random_seed (gfc_code *c)
+{
+ const char *name;
+
+ name = gfc_get_string (PREFIX ("random_seed_i%d"), gfc_default_integer_kind);
+ c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
+}
+
+
+void
gfc_resolve_rename_sub (gfc_code *c)
{
const char *name;
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 1ae601ff17a..d421a7347e2 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2303,36 +2303,38 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
}
}
- if (fsym)
+ /* The case with fsym->attr.optional is that of a user subroutine
+ with an interface indicating an optional argument. When we call
+ an intrinsic subroutine, however, fsym is NULL, but we might still
+ have an optional argument, so we proceed to the substitution
+ just in case. */
+ if (e && (fsym == NULL || fsym->attr.optional))
{
- if (e)
+ /* If an optional argument is itself an optional dummy argument,
+ check its presence and substitute a null if absent. */
+ if (e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ gfc_conv_missing_dummy (&parmse, e, fsym ? fsym->ts : e->ts);
+ }
+
+ if (fsym && e)
+ {
+ /* Obtain the character length of an assumed character length
+ length procedure from the typespec. */
+ if (fsym->ts.type == BT_CHARACTER
+ && parmse.string_length == NULL_TREE
+ && e->ts.type == BT_PROCEDURE
+ && e->symtree->n.sym->ts.type == BT_CHARACTER
+ && e->symtree->n.sym->ts.cl->length != NULL)
{
- /* If an optional argument is itself an optional dummy
- argument, check its presence and substitute a null
- if absent. */
- if (e->expr_type == EXPR_VARIABLE
- && e->symtree->n.sym->attr.optional
- && fsym->attr.optional)
- gfc_conv_missing_dummy (&parmse, e, fsym->ts);
-
- /* Obtain the character length of an assumed character
- length procedure from the typespec. */
- if (fsym->ts.type == BT_CHARACTER
- && parmse.string_length == NULL_TREE
- && e->ts.type == BT_PROCEDURE
- && e->symtree->n.sym->ts.type == BT_CHARACTER
- && e->symtree->n.sym->ts.cl->length != NULL)
- {
- gfc_conv_const_charlen (e->symtree->n.sym->ts.cl);
- parmse.string_length
- = e->symtree->n.sym->ts.cl->backend_decl;
- }
+ gfc_conv_const_charlen (e->symtree->n.sym->ts.cl);
+ parmse.string_length = e->symtree->n.sym->ts.cl->backend_decl;
}
-
- if (need_interface_mapping)
- gfc_add_interface_mapping (&mapping, fsym, &parmse);
}
+ if (fsym && need_interface_mapping)
+ gfc_add_interface_mapping (&mapping, fsym, &parmse);
+
gfc_add_block_to_block (&se->pre, &parmse.pre);
gfc_add_block_to_block (&post, &parmse.post);