https://gcc.gnu.org/g:b48823919cb0b5ed481568896c8cd9963402a681
commit r17-5735-gb48823919cb0b5ed481568896c8cd9963402a681 Author: Jose E. Marchesi <[email protected]> Date: Thu Oct 29 10:12:08 2026 +0100 a68: fix operator dispatch for standenv exponentiation In find_operator, after doing a search_table_chain_for_operator for dyadic opeators there is C.2, C.3 and C.4, which (to my understanding) are intended to implement the standard operators described in 10.2.3.5.a, 10.2.3.5.b, 10.2.3.5.c and 10.2.3.5.d without having to enumerate every real/int combination ("cross-term"): a) op P = (L real a, L int b) L real: a P L real(b); b) op P = (L int a, L real b) L real: L real(a) P b; c) op R = (L real a, L int b) bool: a R L real(b); d) op R = (L int a, L real b) bool: L real(a) R b; However, there is also: g) op <^,**,UP> = (L real a, int b) L real: ...; And that case, for pow, should _not_ be submitted to the cross-term expansion or this invalid code will be admitted: LONG 3.14 ^ LONG 2 LONG LONG 3.14 ^ LONG LONG 2 With the second operands being (incorrectly) widened, which is not allowed in a strong context. The fix is a bit ugly because it relies in the representation of the standard pow operators, but it works. Signed-off-by: Jose E. Marchesi <[email protected]> gcc/algol68/ChangeLog * a68-parser-moids-check.cc (find_operator): Do not apply shortcut for cross real/int definitions to exponentiation. gcc/testsuite/ChangeLog * algol68/execute/pow-real-1.a68: Update test. * algol68/compile/pow-long-long-real-long-long-int-1.a68: New test. * algol68/compile/pow-long-real-long-int-1.a68: Likewise. Diff: --- gcc/algol68/a68-parser-moids-check.cc | 8 ++++++++ .../algol68/compile/pow-long-long-real-long-long-int-1.a68 | 2 ++ gcc/testsuite/algol68/compile/pow-long-real-long-int-1.a68 | 3 +++ gcc/testsuite/algol68/execute/pow-real-1.a68 | 4 ++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/algol68/a68-parser-moids-check.cc b/gcc/algol68/a68-parser-moids-check.cc index 92e0e3f7c8be..7f61cec97829 100644 --- a/gcc/algol68/a68-parser-moids-check.cc +++ b/gcc/algol68/a68-parser-moids-check.cc @@ -1014,6 +1014,12 @@ find_operator (TABLE_T *s, const char *n, MOID_T *x, MOID_T *y) z = search_table_chain_for_operator (s, n, x, y); if (z != NO_TAG) return z; + + /* The checks below apply to operators covered by a) and b) in 10.2.3.5 but + not to the pow operator, which is covered by g) */ + if (strcmp (n, "**") == 0 || strcmp (n, "^") == 0) + return z; + /* (C.2) Vector and matrix "strong coercions" in standard environ. */ u = DEFLEX (a68_depref_completely (x)); v = DEFLEX (a68_depref_completely (y)); @@ -1053,6 +1059,7 @@ find_operator (TABLE_T *s, const char *n, MOID_T *x, MOID_T *y) return z; } } + /* (C.3) Look in standenv for an appropriate cross-term. */ u = a68_make_series_from_moids (x, y); u = a68_make_united_mode (u); @@ -1109,6 +1116,7 @@ find_operator (TABLE_T *s, const char *n, MOID_T *x, MOID_T *y) z = search_table_for_operator (OPERATORS (A68_STANDENV), n, v, v); if (z != NO_TAG) return z; + return NO_TAG; } diff --git a/gcc/testsuite/algol68/compile/pow-long-long-real-long-long-int-1.a68 b/gcc/testsuite/algol68/compile/pow-long-long-real-long-long-int-1.a68 new file mode 100644 index 000000000000..910dc23d9b62 --- /dev/null +++ b/gcc/testsuite/algol68/compile/pow-long-long-real-long-long-int-1.a68 @@ -0,0 +1,2 @@ +begin long long 3.14 ** long long 20 { dg-error "has not been declared" } +end diff --git a/gcc/testsuite/algol68/compile/pow-long-real-long-int-1.a68 b/gcc/testsuite/algol68/compile/pow-long-real-long-int-1.a68 new file mode 100644 index 000000000000..e6c2d46d75d3 --- /dev/null +++ b/gcc/testsuite/algol68/compile/pow-long-real-long-int-1.a68 @@ -0,0 +1,3 @@ +begin 10 * 3.14; + long 3.14 ** long 20 { dg-error "has not been declared" } +end diff --git a/gcc/testsuite/algol68/execute/pow-real-1.a68 b/gcc/testsuite/algol68/execute/pow-real-1.a68 index de8de77093f7..826d00000d32 100644 --- a/gcc/testsuite/algol68/execute/pow-real-1.a68 +++ b/gcc/testsuite/algol68/execute/pow-real-1.a68 @@ -3,7 +3,7 @@ BEGIN REAL r0 = 2.0; LONG REAL rr0 = LONG 2.0; LONG LONG REAL rrr0 = LONG LONG 2 REAL r1 = r0 ^ 2; REAL r2 = r0 ^ 3.0; WORD REAL w0 = WORD 2.0; WORD REAL w1 = w0 ^ 2; WORD REAL w2 = w0 ^ WORD 3.0; - LONG REAL rr1 = rr0 ^ LONG 2; LONG REAL rr2 = rr0 ^ LONG 3.0; - LONG LONG REAL rrr1 = rrr0 ^ LONG LONG 2; LONG LONG REAL rrr2 = rrr0 ^ LONG LONG 3.0; + LONG REAL rr1 = rr0 ^ 2; LONG REAL rr2 = rr0 ^ LONG 3.0; + LONG LONG REAL rrr1 = rrr0 ^ 2; LONG LONG REAL rrr2 = rrr0 ^ LONG LONG 3.0; SKIP END
