Avoiding Crying Wolf With Warnings
May 19, 2017
by Randy Brukardt
Janus/Ada has always been a "noisy" compiler. It prints strings of progress
symbols while it works, information about memory usage, program size, and the
like when it is done, and even has a friendly sign-off message. This policy
spills over into warnings, where the compiler will warn you about almost
anything that might matter to you.
Janus/Ada is noisy in part because of our experience with other compilers when
we were starting out. Computers were a lot slower in 1981 (the 4 MHZ Z-80 running
CP/M that was one of the original targets was more than 2500 times slower than
the Windows box on which I write this); compilation times for each file were
measured in minutes rather than seconds. Early compilers that followed a
minimalist philosophy (like the early Unix compilers) could leave a programmer
staring at a blinking cursor for 5 minutes or more before any result occurred.
Since early computers (not to mention software) were nowhere near as reliable as
today's machines, that made it impossible to tell if the compiler was even working.
At times, I'd wait 30 minutes only to find out that something had gone wrong and
the compile hadn't finished at all.
Therefore, when we started building our own compiler, we wanted it to print
something at least every second or so in order that we could tell it was in fact
working rather than having died because of a memory fault.
The same philosophy extended to compiler error reporting. We'd used some
compilers with very minimalist error handling, the Unix C compiler being the
worst. It seemed that it had only two error messages: "lvalue expected" at
compile time and "bus error, core dumped" at runtime. From those you had to
figure out what the problem was and how to fix it. We'd also used the UW Pascal
compiler, which had been designed for introductory programmers to use. It had
very detailed error messages both at compile-time and runtime (it even dumped
all of the local variables in the error walkbacks). It was clear which of these
we wanted our compiler to be like!
Thus we've included warnings about a wide variety of things, from cases where
exceptions are always going to be raised to ranges that are null (contain no
values). Some of them usually need action, some never need action, and others
are in between.
This wide spread of warnings has periodically confused Janus/Ada users,
causing them to think they need to change the type of a component, or causing
them to suppress all warnings, thus missing messages about likely bugs in their
code.
Thus, future versions of Janus/Ada (starting with the forthcoming Preview)
now have both Informational Messages and Warnings. The basic idea is that a
warning describes a condition that probably should be eliminated, while an
informational message describes performance or stylistic conditions that do not
necessarily require action.
Informational messages can be suppressed separately with their own option
(/YI) and all are suppressed if all warnings are suppressed with the /W option.
(If only some of the warnings are suppressed, informational messages are not
suppressed.) We've also added a Treat Warnings as Errors option (/YW) which
allows a project to ensure that no warnings remain in a fielded system (as no
code will be generated if any errors exist).
This split leaves some old warnings in a grey area. For instance, consider
Some or all of the code on this line is unreachable. This can indicate a
problem if the indicated code is an important part of the program. But it is
just as likely to indicate some code that is unused by Ada conditional
compilation (that is, an if statement controlled by a Boolean constant),
and in a few cases might indicate some compiler-generated data structure is
unused (such as the table used to implement Subtype'Image). As such, we eventually
decided to treat this as an informational message.
Similarly, new messages have to be placed in one category or the other, and
that poses the same problems. Consider, for instance, the new message Ada 2007
feature treated as implementation-defined. You'll see this if you compile
in Ada 95 mode (/Y5) and you with package Ada.Directories, for instance.
There's no real problem with doing so; the package will work as expected. That
argues for it to be an informational message. However, the main use of the /Y5
flag is to ensure that code is portable to other compilers, and one cannot
expect an Ada 95 compiler to have package Ada.Directories. That suggests that
the use of Ada.Directories ought to be replaced by something else, and that's
what warnings are for. Thus we settled on making this a warning with a large
level (so it is easy to suppress, in this case with the /W8 option). [On the
third hand, if you're compiling for maximum portability, you're also using /IX
(to set No_Implementation_Extensions) along with /Y5, and that will make uses
of Ada.Directories an error with a different message. So what to do is never
completely clear!]
Having informational messages also allows Janus/Ada to report additional issues
that would be confusing to report as warnings. For instance, a new informational
message in Janus/Ada is Feature is obsolescent, consider replacing.
Obsolescent features can continue to be used as they're still a required part of
the Ada Standard, so this is more advice than a demand. As such, it is
inappropriate as a warning, but it is fine as an informational message.
We hope these changes will reduce or even eliminate the need to suppress
warnings in normal usage. That way, one won't have to have a testing failure to
find out about potential bugs identified by the compiler. On the other hand,
suppressing informational messages may be valuable if there are too many of them;
doing so will not eliminate anything really critical.
Undoubtedly these changes won't work for everyone. If you have thoughts
on this topic, please sent them to me at
randy@rrsoftware.com.
|