https://gcc.gnu.org/g:eb5da48dd4f854f8607dfa95e20467529a15c606
commit r16-6420-geb5da48dd4f854f8607dfa95e20467529a15c606 Author: Jose E. Marchesi <[email protected]> Date: Sun Dec 28 01:35:35 2025 +0100 a68: fix deduplication of imported modes The internal global list of modes maintained by the compiler should not contain two modes that are equivalent. When importing module interfaces, the modes in these interfaces should get deduplicated before being "interned" in the compiler's modes list. This commit fixes the deduplication to accommodate the fact that more than one module interface may be read from a given packet (compilation unit) and also that multiple interfaces may be imported indirectly via publicized modules. Signed-off-by: Jose E. Marchesi <[email protected]> gcc/algol68/ChangeLog * a68-imports.cc (a68_decode_modes): Do not deduplicate imported modes here. (a68_open_packet): Do it here. * a68-parser-extract.cc (extract_revelation): Recurse into publicized modules after interning modes in the current module, not before. gcc/testsuite/ChangeLog * algol68/execute/modules/module23bar.a68: New test. * algol68/execute/modules/module23foo.a68: Likewise. * algol68/execute/modules/program-23.a68: Likewise. Diff: --- gcc/algol68/a68-imports.cc | 56 ++++++++++++++-------- gcc/algol68/a68-parser-extract.cc | 21 +++++--- .../algol68/execute/modules/module23bar.a68 | 7 +++ .../algol68/execute/modules/module23foo.a68 | 5 ++ .../algol68/execute/modules/program-23.a68 | 6 +++ 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/gcc/algol68/a68-imports.cc b/gcc/algol68/a68-imports.cc index ff117163e155..a13e05940e0f 100644 --- a/gcc/algol68/a68-imports.cc +++ b/gcc/algol68/a68-imports.cc @@ -1110,26 +1110,6 @@ a68_decode_modes (MOIF_T *moif, encoded_modes_map_t &encoded_modes, vec_safe_push (MODES (moif), em->moid); } - /* Next step is to see if equivalent modes the any of the modes in the moif - DIM already exist in the compiler's mode list. In that case, replace the - DIM moif's mode with the existing mode anywhere in the moif. */ - for (MOID_T *m : MODES (moif)) - { - MOID_T *r = a68_search_equivalent_mode (m); - if (r != NO_MOID) - { - a68_replace_equivalent_mode (MODES (moif), m, r); - - /* Update encoded_modes to reflect the replacement. */ - for (auto entry : encoded_modes) - { - struct encoded_mode *em = entry.second; - if (em->moid == m) - em->moid = r; - } - } - } - *errstr = NULL; *ppos = pos; return true; @@ -1419,5 +1399,41 @@ a68_open_packet (const char *module) MOIF_T *moif = TOP_MOIF (&A68_JOB); while (moif != NO_MOIF && strcmp (NAME (moif), module) != 0) FORWARD (moif); + + /* If we got a moif, we need to make sure that it doesn't introduce new modes + that are equivalent to any mode in the compiler's mode list. If it does, + we replace the mode everywhere in the moif. */ + + if (moif != NO_MOIF) + { + for (MOID_T *m : MODES (moif)) + { + MOID_T *r = a68_search_equivalent_mode (m); + if (r != NO_MOID) + { + a68_replace_equivalent_mode (MODES (moif), m, r); + + /* Update extracts to reflect the replacement. */ + for (EXTRACT_T *e : INDICANTS (moif)) + { + if (EXTRACT_MODE (e) == m) + EXTRACT_MODE (e) = r; + } + + for (EXTRACT_T *e : IDENTIFIERS (moif)) + { + if (EXTRACT_MODE (e) == m) + EXTRACT_MODE (e) = r; + } + + for (EXTRACT_T *e : OPERATORS (moif)) + { + if (EXTRACT_MODE (e) == m) + EXTRACT_MODE (e) = r; + } + } + } + } + return moif; } diff --git a/gcc/algol68/a68-parser-extract.cc b/gcc/algol68/a68-parser-extract.cc index f02ae6db322c..70c0dd74cac8 100644 --- a/gcc/algol68/a68-parser-extract.cc +++ b/gcc/algol68/a68-parser-extract.cc @@ -204,12 +204,6 @@ extract_revelation (NODE_T *q, const char *module, TAG_T *tag) if (tag != NO_TAG) MOIF (tag) = moif; - /* First thing to do is to extract the revelations of publicized modules in - this moif. This leads to recursive calls of this function. */ - - for (EXTRACT_T *e : MODULES (moif)) - extract_revelation (q, EXTRACT_SYMBOL (e), NO_TAG); - /* Store all the modes from the MOIF in the moid list. The front-end depends on being able to compare any two modes by pointer @@ -225,10 +219,23 @@ extract_revelation (NODE_T *q, const char *module, TAG_T *tag) { MOID_T *r = a68_register_extra_mode (&TOP_MOID (&A68_JOB), m); if (r != m) - gcc_unreachable (); + { + printf ("r: %s\n", a68_moid_to_string (r, 80, NO_NODE, false)); + printf ("m: %s\n", a68_moid_to_string (m, 80, NO_NODE, false)); + gcc_unreachable (); + } } } + /* Second thing to do is to extract the revelations of publicized modules in + this moif. This leads to recursive calls of this function. Note that + this should be done _after_ the modes get added to the global list of + modes so mode deduplication in a68_open_packet in the recursive + extract_revelation calls is properly done. */ + + for (EXTRACT_T *e : MODULES (moif)) + extract_revelation (q, EXTRACT_SYMBOL (e), NO_TAG); + /* Store mode indicants from the MOIF in the symbol table, and also in the moid list. */ for (EXTRACT_T *e : INDICANTS (moif)) diff --git a/gcc/testsuite/algol68/execute/modules/module23bar.a68 b/gcc/testsuite/algol68/execute/modules/module23bar.a68 new file mode 100644 index 000000000000..bc7933004df9 --- /dev/null +++ b/gcc/testsuite/algol68/execute/modules/module23bar.a68 @@ -0,0 +1,7 @@ +module Module23Bar = access pub Module23Foo +def + pub mode BarMode = ref FooMode; + pub int bar = foo + 10; + skip +fed + diff --git a/gcc/testsuite/algol68/execute/modules/module23foo.a68 b/gcc/testsuite/algol68/execute/modules/module23foo.a68 new file mode 100644 index 000000000000..574c92cb5be8 --- /dev/null +++ b/gcc/testsuite/algol68/execute/modules/module23foo.a68 @@ -0,0 +1,5 @@ +module Module23Foo = +def pub mode FooMode = struct (string name, doc); + pub int foo = 10; + skip +fed diff --git a/gcc/testsuite/algol68/execute/modules/program-23.a68 b/gcc/testsuite/algol68/execute/modules/program-23.a68 new file mode 100644 index 000000000000..d1b6fc4c5979 --- /dev/null +++ b/gcc/testsuite/algol68/execute/modules/program-23.a68 @@ -0,0 +1,6 @@ +{ dg-modules "module23foo module23bar" } + +access Module23Bar +begin assert (foo = 10); + assert (bar = 20) +end
