[comp.lang.misc] Warning messages

adamsf@turing.cs.rpi.edu (Frank Adams) (01/12/90)

[I have cross posted this to several difference news groups, reflecting
languages where it seems to me to be most immediately applicable - mostly
due to the presence of a "pragma" construct.  Since the examples given are
for the "C" language, I have directed followups there.  Followups concerned
with other specific languages should be directed to the appropriate news
group; those dealing with the idea/problem in general probably belong in
comp.lang.misc.]

Like Mr. Smith, I have come to believe that warning messages from a
compiler are a mistake -- but for a quite different reason, and with
a quite different resolution in mind.

Warning messages are fine for small programs, where one person can
read them all and understand them.  But for a large or medium sized
program, requiring anywhere from three programmers on up, they don't work.
In such a project, one typically has a period "make" or "build", where
all source changed since the last make (sometimes all source) is compiled.
If this compilation is done with warnings enabled, typically many warnings
will be generated -- more than can reasonably be dealt with.

For conscientious software engineers, the solution is to treat warnings as
errors, so that the final program generates no warning messages.  There are
two problems with this.  The first is that the compiler doesn't help: it
returns a "success" return code for a compilation with warning messages only,
so any automated make facility will not detect the error[1].  This problem
occurs even for relatively small projects, which still use a make file.

The obvious solution is to make the compiler treat warnings as errors, and
this is indeed what I am advocating.  But this runs smack into the second
problem: sometimes, the situation being warned about is exactly what you want
to do.

To deal with this, I propose introduction of a pragma, with the syntax:

#pragma permit <keyword>

This pragma would permit the warning condition associated with <keyword> to
be found in the next line, suppressing the error message.  In implementing
this pragma, compilers should follow the following guidelines:

(1) If the keyword is unrecognized, ignore the pragma.  It may be meaningful
to some other compiler.

(2) Similarly, if the keyword is recognized, but the corresponding condition
is not found, do *not* generate any sort of message.  Not all compilers will
define a condition identically, so some other compiler might need the pragma.

(3) The pragma should be associated with the syntactic element most closely
associated with the warning.  For example, many compilers will warn about an
unreferenced local variable at the point where it goes out of scope.  The
pragma should be associated instead with the point where the variable is
declared.

(4) To deal with the automatic code generation problem, there should of course
be a compiler flag to turn off warnings globally.

A partial list of keywords for the C language might include:

assignment - permit an assignment in a conditional context

noeffect - a statement or expression has no effect (for example, "a+b;", or
"a" in "a, b=c").

ambiguous - a statement has ambiguous side effects (on the other hand, I would
be inclined to regard this as simply an error).

unused - a variable is never referenced, or assigned but never used.

uninitialized - a variable is not necessarily initialized at some reference.

unreached - a statement can never be executed.

cast - a nonportable type cast is made (for example, pointer to int).

comparison - a comparison occurs whose value can be determined at compile time.
(Examples include "u<0" and "u<=-1", where "u" is unsigned; or "a==a".)

overflow - overflow occurs in evaluation of a constant expression (including
evaluation of a simple constant).  Note that the next (bignum) condition should
also be suppressed by this keyword.

bignum - a constant occurs which is legal on this machine, but bigger than
the the guaranteed minimum size for its type.  (For example, an int greater
than 32767 on a machine where ints are 32 bits.)

noprototype - a function is called without a prototype in scope.

precedence - don't complain about the use of the default precedence in cases
where that is commonly considered to be confusing (such as "&" and "==").

I would also propose a "#pragma unreachable" which asserts that the point in
the code where it occurs cannot be reached.  This will suppress warnings such
as no return value after a call to "exit" at the end of a function.

-----------------

[1] It would of course be *possible* to build a facility which checks the
compiler output for warning messages, but this requires it to be intimate
with the compiler, and much more complex than is otherwise necessary.

sommar@enea.se (Erland Sommarskog) (01/14/90)

Frank Adams (adamsf@turing.cs.rpi.edu) writes:
>Warning messages are fine for small programs, where one person can
>read them all and understand them.  ...
>In such a project, one typically has a period "make" or "build", where
>all source changed since the last make (sometimes all source) is compiled.
>...
>For conscientious software engineers, the solution is to treat warnings as
>errors, so that the final program generates no warning messages.  There are
>two problems with this.  The first is that the compiler doesn't help: it
>returns a "success" return code for a compilation with warning messages only,
>so any automated make facility will not detect the error[1].

With the risk of starting OS war here, which is not my intention,
I would like to point out that this is sort of a Unix problem. VMS,
which is the only other operating system I know, helps you on this
one. Unix says zero is OK, the rest is not. (I think, I'm not too 
good on Unix.) VMS uses five levels which are based on the three
lowest bits in the status code. Odd status is success of some sort,
while even is warning, error or fatal error. So if you want to build
your system with warnings you say MMS/NOIGNORE. I don't remember what's
the default, I think it's /IGNORE=WARNING. (MMS is DEC's port of Make
to VMS which you can get for extra bucks.)

>The obvious solution is to make the compiler treat warnings as errors, and
>this is indeed what I am advocating.  But this runs smack into the second
>problem: sometimes, the situation being warned about is exactly what you want
>to do.

Frank Adams then goes with a proposal for C with pragmas to control
which warnings should be flagged and which should not.

I do my daily work with VAX-Pascal and its view what is a warning
and what is an error is not the same as mine. Some warnings are
really important like unitialized variables and function with assign-
ment of the return value. But do we run MMS with /NOIGNORE? Do we
even compile with /WARNING? Pas de chance. I have written modules
on 500-700 lines which generates 70 warnings all to be neglected.
Talk about low signal-to-noise ratio. A facility to kill some of the
warnings could be fine, but in this particular case there are better 
solutions. (See note below.)

For some of the cases of suspected inapproiateness the Pascal
only gives informational message and only if you ask it to. This
inclused unused variables and variables that may be uninitialized.

(What are all these warnings? All of them are for breaking the Pascal
rule that a component of a packed entity may not be passed as a VAR
parameter. This is of course perfectly OK, as long the component is
on even byte boundaries. Now, we're taking a lot of record types from
the CDD (Common Data Dictionary) since the definitions are used outside
Pascal too. Such records are included as PACKED by the %DICTIONARY
directive for some reason. To make matters worse, quadwords (64 bits)
- we have a lot of them, this is a financial system - in such records
are translated to type an empty record which has to be passed as a
VAR parameter. This gives a good deal of all our warnings.)
-- 
Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se
Unix is a virus.