* [Patch, Fortran] PR57894 - MIN/MAX arg= check
@ 2013-07-16 15:26 Tobias Burnus
2013-07-16 15:42 ` Tobias Burnus
2013-07-20 21:21 ` Mikael Morin
0 siblings, 2 replies; 3+ messages in thread
From: Tobias Burnus @ 2013-07-16 15:26 UTC (permalink / raw)
To: gcc patches, gfortran
[-- Attachment #1: Type: text/plain, Size: 444 bytes --]
As reported in the PR, gfortran was lacking a check for the args= for
MIN/MAX. Those are special as they accept 'infinitely' many arguments -
while others have a finite set.
Added checks:
- Ensure that only a1=, a2=, a3= etc. is used.
- Ensure that every argument occurs only once
- ensure that the first two arguments (a1=, a2= when keywords are used)
are always present
Build and regtested on x86-64-gnu-linux.
OK for the trunk?
Tobias
[-- Attachment #2: minmax-check.diff --]
[-- Type: text/x-patch, Size: 4220 bytes --]
2013-07-16 Tobias Burnus <burnus@net-b.de>
PR fortran/57894
* check.c (min_max_args): Add keyword= check.
2013-07-16 Tobias Burnus <burnus@net-b.de>
PR fortran/57894
* gfortran.dg/min_max_conformance_2.f90: New.
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 4024cd4..492c8ec 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;
diff --git a/gcc/testsuite/gfortran.dg/min_max_conformance_2.f90 b/gcc/testsuite/gfortran.dg/min_max_conformance_2.f90
new file mode 100644
index 0000000..085206c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/min_max_conformance_2.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+!
+! PR fortran/57894
+!
+! Contributed by Vittorio Zecca
+!
+print *, max(a2=2,a65=45,a2=5) ! { dg-error "has already appeared in the current argument list" }
+print *, min(a1=2.0,a65=45.0,a2=5.0e0) ! OK
+print *, max(a2=2,a65=45,a3=5) ! { dg-error "Missing 'a1' argument to the max intrinsic" }
+print *, min(a1=2.0,a65=45.0,a3=5.0e0) ! { dg-error "Missing 'a2' argument to the min intrinsic" }
+print *, min1(2.0,a1=45.0,a2=5.0e0) ! { dg-error "Duplicate argument 'a1'" }
+
+print *, max0(a1=2,a65a=45,a2=5) ! { dg-error "Unknown argument 'a65a'" }
+print *, amax0(a1=2,as65=45,a2=5) ! { dg-error "Unknown argument 'as65'" }
+print *, max1(a1=2,a2=45,5) ! { dg-error "Missing keyword name in actual argument list" }
+print *, amax1(a1=2,a3=45,a4=5) ! { dg-error "Missing 'a2' argument" }
+print *, dmax1(a1=2,a2=45,a4z=5) ! { dg-error "Unknown argument 'a4z'" }
+
+print *, min0(a1=2,a65a=45,a2=5) ! { dg-error "Unknown argument 'a65a'" }
+print *, amin0(a1=2,as65=45,a2=5) ! { dg-error "Unknown argument 'as65'" }
+print *, min1(a1=2,a2=45,5) ! { dg-error "Missing keyword name in actual argument list" }
+print *, amin1(a1=2,a3=45,a4=5) ! { dg-error "Missing 'a2' argument" }
+print *, dmin1(a1=2,a2=45,a4z=5) ! { dg-error "Unknown argument 'a4z'" }
+end
[-- Attachment #3: fiif.f90 --]
[-- Type: text/x-fortran, Size: 793 bytes --]
! { dg-do compile }
! Test the fix for PR20896 in which the ambiguous use
! of p was not detected.
!
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
!
INTERFACE g
SUBROUTINE s1(p) ! { dg-error "is already being used" }
INTERFACE
SUBROUTINE p
END
END INTERFACE
END
SUBROUTINE s2(p) ! { dg-error "Global name" }
INTERFACE
REAL FUNCTION p()
END
END INTERFACE
END
END INTERFACE
INTERFACE
REAL FUNCTION x()
END
END INTERFACE
INTERFACE
SUBROUTINE y
END
END INTERFACE
! call g (x)
! call g (y)
END
REAL FUNCTION x()
x = 0.1
END
SUBROUTINE y()
print *, 1.5
END
SUBROUTINE s1(p)
call p()
END
SUBROUTINE s2(p)
print *, p()
END
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Patch, Fortran] PR57894 - MIN/MAX arg= check
2013-07-16 15:26 [Patch, Fortran] PR57894 - MIN/MAX arg= check Tobias Burnus
@ 2013-07-16 15:42 ` Tobias Burnus
2013-07-20 21:21 ` Mikael Morin
1 sibling, 0 replies; 3+ messages in thread
From: Tobias Burnus @ 2013-07-16 15:42 UTC (permalink / raw)
To: gcc patches, gfortran
Tobias Burnus wrote:
> Build and regtested on x86-64-gnu-linux.
> OK for the trunk?
Scratch the second test case / second attachment ("fiif.f90"), which
wasn't supposed to get attached.
(If you wonder, it's Joost's/Dominique's test case, reated to
PR39290/PR40276, cf.
http://gcc.gnu.org/ml/fortran/2013-07/msg00017.html. The test is now
rejected by my PR40276/PR57711 patch - but I fear for the wrong reasons:
While the interface is ambiguous, the current patch only rejects the
use. I have to check whether the check could also reject valid use - or
only gives the slightly puzzling error for invalid use. In any case, the
ambiguity check has to be corrected [long standing issue].)
Tobias
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Patch, Fortran] PR57894 - MIN/MAX arg= check
2013-07-16 15:26 [Patch, Fortran] PR57894 - MIN/MAX arg= check Tobias Burnus
2013-07-16 15:42 ` Tobias Burnus
@ 2013-07-20 21:21 ` Mikael Morin
1 sibling, 0 replies; 3+ messages in thread
From: Mikael Morin @ 2013-07-20 21:21 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc patches, gfortran
Le 16/07/2013 17:16, Tobias Burnus a écrit :
> As reported in the PR, gfortran was lacking a check for the args= for
> MIN/MAX. Those are special as they accept 'infinitely' many arguments -
> while others have a finite set.
>
> Added checks:
> - Ensure that only a1=, a2=, a3= etc. is used.
> - Ensure that every argument occurs only once
> - ensure that the first two arguments (a1=, a2= when keywords are used)
> are always present
>
> Build and regtested on x86-64-gnu-linux.
> OK for the trunk?
>
Yes, with a few indenting problems (8+ spaces) fixed.
Thanks
Mikael
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-07-20 21:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-16 15:26 [Patch, Fortran] PR57894 - MIN/MAX arg= check Tobias Burnus
2013-07-16 15:42 ` Tobias Burnus
2013-07-20 21:21 ` Mikael Morin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).