[m-dev.] fixing the bug reported on m-users

Zoltan Somogyi zoltan.somogyi at runbox.com
Tue Nov 2 01:56:11 AEDT 2021


I have added to tests/invalid a minimal version of the program
that Sean Charles sent me. The test has two modules. The main
module does nothing except call a predicate from the aux module.
The aux module exports a predicate, but one of the modes in its
mode declaration is "int" rather than "in". This is a bug that we
should report, since there is no mode in scope named "int".
And we do report it when compiling the aux module.
The error message is generated by the module qualification pass.

The reason the compiler crashes when the compile the main module
is the following sequence of events.

- The mmc invocation that generates the .int file for the aux module
  module qualifies the items that it intends to put into the .int file,
  and thus it discovers the error and generates a report for it,
  but by default, we ignore the report. (We report it only if
  --print-errors-warnings-when-generating-interface is set.)
  Therefore the .int file we generate has an unreported error:
  a reference to an undefined mode.

- The mmc invocation that is intended to generate code for the main
  module reads in the .int file of the aux module. The module qualification
  pass in this case gets mode definitions both from the source code of the
  module being compiled and from the .int files of all the imported modules,
  but then it module qualifies only the module being compiled.
  The rationale for this is that the contents of the .int files have already been
  through module qualification before the .int file was generated. This is true, but
  since that process ignores errors, it nevertheless may not have been *fully*
  module qualified.

- The mode declaration containing the reference to the undefined mode
  is added to the HLDS.

- The first compiler pass that looks at that mode declaration, which happens
  to be the part of post-typecheck that propagates types into modes, does
  a lookup of the mode name and crashes when it does not find it.

I can think of several ways to fix the problem, one for each of the first,
second and fourth paragraphs above.

Approach 1: always report errors when generating interface files.
If we prevent the generation of .int files containing undefined modes
(or any undefined entity detected by module qualification), the problem
cannot arise.

Approach 2: we could module qualify items we read from .int files,
as well as the .m file, when generating target code.

Approach 3: we could change the code that propagates types into modes
to do a search, not a lookup, in the mode table, and to generate an error
message it the mode name is not found.

Approach 1 is sort-of the simplest, but it is a significant change to how
the compiler works. When I added the option that now governs whether
we report errors when making interface files, I intended to make it the
default only after finishing my current series of changes.

Approach 2 can be done simply, but its performance impact is nontrivial,
given that many modules import a long list of other modules.

Approach 3 has the least performance impact, but the code needed for it
would effectively duplicate the job of module qualification. (Though it would
be possible for post-typecheck to use the same code to generate the
error message as module qualification.)

Any preferences as to which approach I should take?

Zoltan.


More information about the developers mailing list