Age | Commit message (Collapse) | Author |
|
The compiler would silently accept and Dialyzer would crash on
code like:
<<X:(2.5)>>
It is never acceptable for Dialyzer to crash. The compiler should
at least generate a warning for such code. It is tempting to let
the compiler generate an error, but that would mean that code like:
Sz = 42.0,
<<X:Sz>>.
would be possible to compile with optimizations disabled, but not
with optimizations enabled.
Dialyzer crashes because it calls cerl:bitstr_bitsize/1, which
crashes if the type of size for the segment is invalid. The easiest
way to avoid that crash is to extend the sanity checks in v3_core
to also include the size field of binary segments. That will cause
the compiler to issue a warning and to replace the bad binary
construction with a call to erlang:error/1. (It also means that
Dialyzer will not issue a warning for bad size fields.)
|
|
|
|
In Core Erlang and later passes, compiler-generated code can be
indicated in two different ways: by negative line numbers and by
a 'compiler_generated' annotation.
Simplify the code and improve coverage by turning negative line
numbers positive and adding a 'compiler_generated' annotation in
the v3_core pass. That means that Core Erlang and latter passes
do not have deal with negative line numbers.
|
|
Currently, the external fun syntax "fun M:F/A" only supports
literals. That is, "fun lists:reverse/1" is allowed but not
"fun M:F/A".
In many real-life situations, some or all of M, F, A are
not known until run-time, and one is forced to either use
the undocumented erlang:make_fun/3 BIF or to use a
"tuple fun" (which is deprecated).
EEP-23 suggests that the parser (erl_parse) should immediately
transform "fun M:F/A" to "erlang:make_fun(M, F, A)". We have
not followed that approach in this implementation, because we
want the abstract code to mirror the source code as closely
as possible, and we also consider erlang:make_fun/3 to
be an implementation detail that we might want to remove in
the future.
Instead, we will change the abstract format for "fun M:F/A" (in a way
that is not backwards compatible), and while we are at it, we will
move the translation from "fun M:F/A" to "erlang:make_fun(M, F, A)"
from sys_pre_expand down to the v3_core pass. We will also update
the debugger and xref to use the new format.
We did consider making the abstract format backward compatible if
no variables were used in the fun, but decided against it. Keeping
it backward compatible would mean that there would be different
abstract formats for the no-variable and variable case, and tools
would have to handle both formats, probably forever.
Reference: http://www.erlang.org/eeps/eep-0023.html
|
|
|
|
|
|
In the following code:
m(<<Sz:8,_:Sz/binary>>) ->
Sz = wrong.
the Sz variable is supposed to be bound in the function header and the
matching "Sz = wrong" should cause a badarg exception. But what
happens is that the Sz variables seems to be unbound and the matching
succeds and the m/1 function returns 'wrong'.
If the Sz variable is used directly (not matched), it will have
the expected value. Thus the following code:
m(<<Sz:8,_:Sz/binary>>) ->
Sz.
will correctly return the value of Sz that was matched out from
the binary.
Reported-by: Bernard Duggan
|
|
|
|
In binary matching, there must only be one "tail segment" (i.e.
a size-less segment of type binary) and it must be last. Thus,
the compiler will reject the following function definition:
foo(<<A/bits,B/bits>>) -> ok.
But code such as the following:
[42 || <<_:8/integer, _/bits>> <= Bits]
will internally (in the Core Erlang format) be translated to a
binary matching pattern containing two tail segments. The compiler
happens to generate correct code anyway (later passes will get
rid of the redundant tail segment), but it is ugly and will
confuse tools such as Dialyzer.
Change the transformation of binary generators (in both list and
binary comprehensions) not to generate add a tail segment if there
already is one.
|
|
In the code for handling binary generators (in list and binary
comprehensions), factor out the code for appending a match-all tail
segment onto a pattern into a separate function. That will only
make the code somewhat simpler, but will facilitate fixing a
bug/misfeture in the next commit.
|
|
Commit 329f737c03db51918361e127560a6f700e99028e removed
some unused code, but also introduced the need for
further clean-ups.
Fix a spec so that its return corresponds to reality.
Take out code that will never match from a function.
|
|
The is_simple/1 function does not need to handle #c_binary{},
since it will never be called with a #c_binary{} argument.
|
|
The state record #core{} has a "es" field that can be used for
causing a compilation error. Since incorrect programs have been
rejected much earlier by erl_lint, no errors were actually stored
in the "es" fields. Therefore, get rid of the "es" field and
the support for generating a compilation error in the v3_core
module.
|
|
There is currently no zero-cost way to silence the warning
"the result of the expression is ignored", which is issued
for code such as:
list_to_integer(S),
ok
Such code can be useful for assertions or input validation.
Teach the compiler to silence the warning for expressions
that are explicitly assigned to to the "_" variable,
such as:
_ = list_to_integer(S),
ok
Implement it by having the v3_core pass annotate calls in
Core Erlang like this:
let <_> = ( call 'erlang':'list_to_integer'(S) -| ['result_not_wanted'] )
in 'ok'
and modifiy sys_core_fold to suppress the warning for any call
having the annotation.
We deliberately do not make it possible to silence the warnings
for expressions like:
{build,an,unnecessary,term}, ok
or
is_list(L), ok
because we don't know of any real-world scenarios in which that would
be useful.
|
|
A function_clause exception is generated by jumping to a func_info/3
instruction at the beginning of the function. The x registers are
assumed to contain the arguments for the function. That means
that a func_info/3 instruction copied from another function
(or even from the same function if not at the top level) will
not work, so it must be replaced with an instruction that
generates a case_clause exception.
In Core Erlang, a func_info/3 instruction is represented as
a the primop match_fail({function_clause,Arg1,...ArgN}).
The current mechanism that is supposed to replace the
primop match_fail(function_clause) with match_fail(case_clause)
will fail to do that in the following circumstances:
1. If the inliner has inlined a function into itself.
Fix that by having the inliner clear the function_name annotations
on all match_fail primops in functions that are inlined. (To simplify
doing that, the annotation is now on the primop node itself and not on
the 'function_clause' atom inside it.)
2. If the inliner has rewritten the tuple node in the primop node
to a literal (when inlining a function call with literal arguments),
v3_kernel would not recognize the match_fail(function_clause) primop
and would not rewrite it. Fix it by making v3_kernel smarter.
Also simplify the "old" inliner (sys_core_inline) to only clear
the function_name annotations instead of rewriting function_clause
execptions to case_clause execptions itself.
|
|
The no_binaries option terminates the compiler with an error
if any bit syntax is used in the module being compiled.
(It used to be implied by the removed r11 option.)
|
|
* ks/compiler:
compiler: keep line numbers for attributes
compiler Makefile: alphabetize module names
compile.erl: eliminate compiler warning
|
|
In the future, we might want to generate warnings
for attributes, referring to them with line numbers.
sys_pre_expand used to replace line number for attributes
with 0. Change sys_pre_expand to retain the real line
number.
v3_core used to throw away the line numbers. Change
v3_core so that it retains the line numbers in annotations.
While at it, do some tidying as suggested by tidier.
|
|
|