New compiler warnings in R10B

Bjorn Gustavsson bjorn@REDACTED
Thu Dec 18 10:00:03 CET 2003


Inspired by the discussion in the "Small Poll" thread,
I decided to start implementing new compiler warnings
right away. (It was planned to be done in R10B anyway.)

This is still a work in progress, but the warnings produced
so far has been useful.

What I've done is to change the optimization and code-generation
passes to emit warnings if they discover something funny.
That is not hard to do. The only reason we haven't done it
before is that the line number of the offending line in the
source code wasn't available. Now it is.

Now to some examples!

1. CLAUSES THAT CANNOT BE REACHED
=================================

Here is your typical factorial calculation module:

-module(fact).
-export([fact/1]).

fact(N) ->
    fact(N, 1).

fact(N, Acc0) ->
    Acc = Acc0 * N,
    fact(N-1, Acc);
fact(0, Acc) -> Acc.

Compiling it, we get the following warning:

$ erlc fact.erl
/home/bjorn/test/fact.erl:10: Warning: this clause cannot match because the previous clause always matches

Line 10 is the last line in the module. It will not be reached because the
first clause is always chosen.

We found many warnings of this type in the OTP. Most of them are
probably not bugs, but just redundant code. For instance, in inet.erl:

  .
  .
  .
getaddrs_tm(Address, Family, Timer) ->
  .
  .
  .
getaddrs_tm(_,_,_) -> {error, einval}.

The last clause will actually never get executed.


2. BAD EXPRESSIONS
==================

There are also warnings for expression that cannot be evaluated
without causing an exception. Here is an example module:

01 -module(buggy).
02 
03 -compile(export_all).
04 
05 a() ->
06    42+an_atom.
07
08 b() ->
09    A = 'I am just an atom',
10    foo(),
11    42+A.
12
13 c() ->
14    42+an_integer().
15
16 an_integer() ->
17    he_he_i_am_not_a_real_integer.
18
19 foo() ->
20    'I am just pretending to do some work'.

There will be different warnings depending on how much optimization
is turned off. I you turn off optimization, you will get no warnings.

$ erlc +no_copt buggy.erl
$

(Note: In general, there is never any need to turn off optimizations.
It will buy you very little time and the default optimizations are
in general "safe" - they don't change the meaning of your program
in any way.)

With the default settings, we'll get two warnings.

$ erlc buggy.erl
/home/bjorn/test/buggy.erl:6: Warning: this expression would cause a 'badarith' exception at run-time
/home/bjorn/test/buggy.erl:11: Warning: this expression would cause a 'badarith' exception at run-time
$

If we turn on inlining, we'll get one more warning.

$ erlc +inline buggy.erl
/home/bjorn/test/buggy.erl:6: Warning: this expression would cause a 'badarith' exception at run-time
/home/bjorn/test/buggy.erl:11: Warning: this expression would cause a 'badarith' exception at run-time
/home/bjorn/test/buggy.erl:14: Warning: this expression would cause a 'badarith' exception at run-time
$ 

After inlining, the expression at line 14 is now

  42+ he_he_i_am_not_a_real_integer


/Bjorn
-- 
Björn Gustavsson, Erlang/OTP, Ericsson AB



More information about the erlang-questions mailing list