diff options
author | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-07-21 11:46:43 +0000 |
---|---|---|
committer | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-07-21 11:46:43 +0000 |
commit | 9e8bea80804e1fbff4a86996d5b99564c357c8e8 (patch) | |
tree | 5a6818c2c68cdfff542a803eb6343f5fc8df1b24 /gcc/fortran/check.c | |
parent | ffb840b4125e9678af756f1a902ca0fe7f04bbd0 (diff) | |
download | gcc-9e8bea80804e1fbff4a86996d5b99564c357c8e8.tar.gz |
2013-07-21 Tobias Burnus <burnus@net-b.de>
PR fortran/57894
* check.c (min_max_args): Add keyword= check.
2013-07-21 Tobias Burnus <burnus@net-b.de>
PR fortran/57894
* gfortran.dg/min_max_conformance_2.f90: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@201092 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/check.c')
-rw-r--r-- | gcc/fortran/check.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index 4024cd45652..884dc43b125 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -2328,16 +2328,85 @@ gfc_check_logical (gfc_expr *a, gfc_expr *kind) /* Min/max family. */ static bool -min_max_args (gfc_actual_arglist *arg) +min_max_args (gfc_actual_arglist *args) { - if (arg == NULL || arg->next == NULL) + gfc_actual_arglist *arg; + int i, j, nargs, *nlabels, nlabelless; + bool a1 = false, a2 = false; + + if (args == NULL || args->next == NULL) { gfc_error ("Intrinsic '%s' at %L must have at least two arguments", gfc_current_intrinsic, gfc_current_intrinsic_where); return false; } + if (!args->name) + a1 = true; + + if (!args->next->name) + a2 = true; + + nargs = 0; + for (arg = args; arg; arg = arg->next) + if (arg->name) + nargs++; + + if (nargs == 0) + return true; + + /* Note: Having a keywordless argument after an "arg=" is checked before. */ + nlabelless = 0; + nlabels = XALLOCAVEC (int, nargs); + for (arg = args, i = 0; arg; arg = arg->next, i++) + if (arg->name) + { + int n; + char *endp; + + if (arg->name[0] != 'a' || arg->name[1] < '1' || arg->name[1] > '9') + goto unknown; + n = strtol (&arg->name[1], &endp, 10); + if (endp[0] != '\0') + goto unknown; + if (n <= 0) + goto unknown; + if (n <= nlabelless) + goto duplicate; + nlabels[i] = n; + if (n == 1) + a1 = true; + if (n == 2) + a2 = true; + } + else + nlabelless++; + + if (!a1 || !a2) + { + gfc_error ("Missing '%s' argument to the %s intrinsic at %L", + !a1 ? "a1" : "a2", gfc_current_intrinsic, + gfc_current_intrinsic_where); + return false; + } + + /* Check for duplicates. */ + for (i = 0; i < nargs; i++) + for (j = i + 1; j < nargs; j++) + if (nlabels[i] == nlabels[j]) + goto duplicate; + return true; + +duplicate: + gfc_error ("Duplicate argument '%s' at %L to intrinsic %s", arg->name, + &arg->expr->where, gfc_current_intrinsic); + return false; + +unknown: + gfc_error ("Unknown argument '%s' at %L to intrinsic %s", arg->name, + &arg->expr->where, gfc_current_intrinsic); + return false; } @@ -2345,7 +2414,6 @@ static bool check_rest (bt type, int kind, gfc_actual_arglist *arglist) { gfc_actual_arglist *arg, *tmp; - gfc_expr *x; int m, n; |