aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_asm.erl2
-rw-r--r--lib/compiler/src/beam_disasm.erl7
-rw-r--r--lib/compiler/src/beam_type.erl23
-rw-r--r--lib/compiler/src/core_lint.erl2
-rw-r--r--lib/compiler/src/sys_core_fold.erl9
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl50
-rw-r--r--lib/compiler/test/unused_multiple_values_error.core11
-rw-r--r--lib/kernel/doc/src/specs.xml1
-rw-r--r--lib/kernel/src/inet6_tcp_dist.erl8
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl8
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/tools/src/cover.erl48
-rw-r--r--lib/tools/test/cover_SUITE.erl17
-rw-r--r--lib/tools/test/cover_SUITE_data/compile_beam/v.erl7
-rw-r--r--lib/tools/test/cover_SUITE_data/compile_beam/z.erl1
-rw-r--r--lib/tools/vsn.mk2
18 files changed, 168 insertions, 33 deletions
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index a7c8508321..98967e651f 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -387,7 +387,7 @@ encode_arg({list, List}, Dict0) ->
{L, Dict} = encode_list(List, Dict0, []),
{[encode(?tag_z, 1), encode(?tag_u, length(List))|L], Dict};
encode_arg({float, Float}, Dict) when is_float(Float) ->
- {[encode(?tag_z, 0),<<Float:64/float>>], Dict};
+ encode_arg({literal,Float}, Dict);
encode_arg({fr,Fr}, Dict) ->
{[encode(?tag_z, 2),encode(?tag_u, Fr)], Dict};
encode_arg({field_flags,Flags0}, Dict) ->
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 62bdc74cc8..67d756c45c 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -512,7 +512,12 @@ decode_z_tagged(Tag,B,Bs,Literals) when (B band 16#08) =:= 0 ->
decode_alloc_list(Bs, Literals);
4 -> % literal
{{u,LitIndex},RestBs} = decode_arg(Bs),
- {{literal,gb_trees:get(LitIndex, Literals)},RestBs};
+ case gb_trees:get(LitIndex, Literals) of
+ Float when is_float(Float) ->
+ {{float,Float},RestBs};
+ Literal ->
+ {{literal,Literal},RestBs}
+ end;
_ ->
?exit({decode_z_tagged,{invalid_extended_tag,N}})
end;
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 7392f99fb6..372923a5cf 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -142,9 +142,11 @@ simplify_float(Is0, Ts0) ->
throw:not_possible -> not_possible
end.
-simplify_float_1([{set,[D0],[A],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
- case tdb_find(A, Ts0) of
+simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0,
+ Ts0, Rs0, Acc0) ->
+ case tdb_find(A0, Ts0) of
float ->
+ A = coerce_to_float(A0),
{Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
{D,Rs} = find_dest(D0, Rs1),
Areg = fetch_reg(A, Rs),
@@ -156,13 +158,16 @@ simplify_float_1([{set,[D0],[A],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0, Ts0, Rs
{Rs,Acc} = flush(Rs0, Is0, Acc0),
simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)])
end;
-simplify_float_1([{set,[D0],[A,B],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
- case float_op(Op0, A, B, Ts0) of
+simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
+ Ts0, Rs0, Acc0) ->
+ case float_op(Op0, A0, B0, Ts0) of
no ->
Ts = update(I, Ts0),
{Rs,Acc} = flush(Rs0, Is0, Acc0),
simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
{yes,Op} ->
+ A = coerce_to_float(A0),
+ B = coerce_to_float(B0),
{Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
{Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
{D,Rs} = find_dest(D0, Rs2),
@@ -187,6 +192,16 @@ simplify_float_1([], Ts, Rs, Acc0) ->
Is = opt_fmoves(Is0, []),
{Is,Ts}.
+coerce_to_float({integer,I}=Int) ->
+ try float(I) of
+ F ->
+ {float,F}
+ catch _:_ ->
+ %% Let the overflow happen at run-time.
+ Int
+ end;
+coerce_to_float(Other) -> Other.
+
opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
{set,[_]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
case beam_utils:is_killed_block(R, Is) of
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 8b688df830..1e8983f594 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -309,7 +309,7 @@ expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) ->
{Vvs,St1} = variable_list(Vs, St0),
return_match(Rt, 1, body(B, union(Vvs, Def), any, St1));
expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = expr(Arg, Def, any, St0), %Ignore values
+ St1 = expr(Arg, Def, 1, St0),
body(B, Def, Rt, St1);
expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index d5fec0c869..cda3f7d81e 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -132,7 +132,12 @@ body(Body, Sub) ->
body(#c_values{anno=A,es=Es0}, Ctxt, Sub) ->
Es1 = expr_list(Es0, Ctxt, Sub),
- #c_values{anno=A,es=Es1};
+ case Ctxt of
+ value ->
+ #c_values{anno=A,es=Es1};
+ effect ->
+ make_effect_seq(Es1, Sub)
+ end;
body(E, Ctxt, Sub) ->
?ASSERT(verify_scope(E, Sub)),
expr(E, Ctxt, Sub).
@@ -1272,6 +1277,8 @@ eval_element(Call, #c_literal{val=Pos}, #c_var{name=V}, Types)
true ->
eval_failure(Call, badarg)
end;
+ {ok,_} ->
+ eval_failure(Call, badarg);
error ->
Call
end;
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index b9c5be09ce..51b3064589 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -75,6 +75,7 @@ INLINE= \
CORE_MODULES = \
bs_shadowed_size_var \
+ unused_multiple_values_error \
nested_call_in_case
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 53a65d8d17..abc9ab6a72 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -21,7 +21,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1,
- eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1]).
+ eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1,
+ unused_multiple_values_error/1,unused_multiple_values/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -36,7 +37,8 @@ all() ->
groups() ->
[{p,test_lib:parallel(),
[t_element,setelement,t_length,append,t_apply,bifs,
- eq,nested_call_in_case,guard_try_catch,coverage]}].
+ eq,nested_call_in_case,guard_try_catch,coverage,
+ unused_multiple_values_error,unused_multiple_values]}].
init_per_suite(Config) ->
@@ -69,6 +71,9 @@ t_element(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})),
?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})),
?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})),
+ {'EXIT',{badarg,_}} = (catch element(2, not_a_tuple)),
+ {'EXIT',{badarg,_}} = (catch element(2, [])),
+ {'EXIT',{badarg,_}} = (catch element(2, Tuple == 3)),
case id({a,b,c}) of
{_,_,_}=Tup ->
?line {'EXIT',{badarg,_}} = (catch element(4, Tup))
@@ -89,6 +94,9 @@ setelement(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})),
?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>),
+
+ {'EXIT',{badarg,_}} = (catch setelement(1, not_a_tuple, New)),
+
ok.
setelement_crash(Tuple) ->
@@ -283,3 +291,41 @@ cover_is_safe_bool_expr(X) ->
end.
id(I) -> I.
+
+unused_multiple_values_error(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ Dir = filename:dirname(code:which(?MODULE)),
+ Core = filename:join(Dir, "unused_multiple_values_error"),
+ Opts = [no_copt,clint,return,from_core,{outdir,PrivDir}
+ |test_lib:opt_opts(?MODULE)],
+ {error,[{unused_multiple_values_error,
+ [{core_lint,{return_mismatch,{hello,1}}}]}],
+ []} = c:c(Core, Opts),
+ ok.
+
+unused_multiple_values(Config) when is_list(Config) ->
+ put(unused_multiple_values, []),
+ [false] = test_unused_multiple_values(false),
+ [b,a,{a,b},false] = test_unused_multiple_values({a,b}),
+ ok.
+
+test_unused_multiple_values(X) ->
+ ok = do_unused_multiple_values(X),
+ get(unused_multiple_values).
+
+do_unused_multiple_values(X) ->
+ case do_something(X) of
+ false ->
+ A = false;
+ Res ->
+ {A,B} = Res,
+ do_something(A),
+ do_something(B)
+ end,
+ _ThisShouldNotFail = A,
+ ok.
+
+do_something(I) ->
+ put(unused_multiple_values,
+ [I|get(unused_multiple_values)]),
+ I.
diff --git a/lib/compiler/test/unused_multiple_values_error.core b/lib/compiler/test/unused_multiple_values_error.core
new file mode 100644
index 0000000000..e06587c936
--- /dev/null
+++ b/lib/compiler/test/unused_multiple_values_error.core
@@ -0,0 +1,11 @@
+module 'unused_multiple_values_error' ['hello'/1]
+ attributes []
+'hello'/1 =
+ fun (_cor0) ->
+ do
+ case _cor0 of
+ <_cor0> when 'true' ->
+ <'ok','ok'>
+ end
+ 'ok'
+end
diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml
index b41addaa0c..813bb06e1f 100644
--- a/lib/kernel/doc/src/specs.xml
+++ b/lib/kernel/doc/src/specs.xml
@@ -29,5 +29,4 @@
<xi:include href="../specs/specs_user.xml"/>
<xi:include href="../specs/specs_wrap_log_reader.xml"/>
<xi:include href="../specs/specs_zlib_stub.xml"/>
- <xi:include href="../specs/specs_packages.xml"/>
</specs>
diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl
index b9c4fa607c..2315a56582 100644
--- a/lib/kernel/src/inet6_tcp_dist.erl
+++ b/lib/kernel/src/inet6_tcp_dist.erl
@@ -71,8 +71,12 @@ listen(Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Socket),
{_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {ok, {Socket, TcpAddress, Creation}};
+ Error ->
+ Error
+ end;
Error ->
Error
end.
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 7f935c2b36..70f3c87723 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -67,8 +67,12 @@ listen(Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Socket),
{_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {ok, {Socket, TcpAddress, Creation}};
+ Error ->
+ Error
+ end;
Error ->
Error
end.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 46a991eb38..b6cf4407d2 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.16
+KERNEL_VSN = 2.16.1
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 33d7a57cc3..c1467697e3 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.19
+STDLIB_VSN = 1.19.1
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 468225dc13..2579711dc7 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1372,10 +1372,15 @@ do_compile_beam(Module,Beam,UserOptions) ->
Forms0 = epp:interpret_file_attribute(Code),
{Forms,Vars} = transform(Vsn, Forms0, Module, Beam),
+ %% We need to recover the source from the compilation
+ %% info otherwise the newly compiled module will have
+ %% source pointing to the current directory
+ SourceInfo = get_source_info(Module, Beam),
+
%% Compile and load the result
%% It's necessary to check the result of loading since it may
%% fail, for example if Module resides in a sticky directory
- {ok, Module, Binary} = compile:forms(Forms, UserOptions),
+ {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions),
case code:load_binary(Module, ?TAG, Binary) of
{module, Module} ->
@@ -1403,6 +1408,17 @@ get_abstract_code(Module, Beam) ->
Error -> Error
end.
+get_source_info(Module, Beam) ->
+ case beam_lib:chunks(Beam, [compile_info]) of
+ {ok, {Module, [{compile_info, Compile}]}} ->
+ case lists:keyfind(source, 1, Compile) of
+ { source, _ } = Tuple -> [Tuple];
+ false -> []
+ end;
+ _ ->
+ []
+ end.
+
transform(Vsn, Code, Module, Beam) when Vsn=:=abstract_v1; Vsn=:=abstract_v2 ->
Vars0 = #vars{module=Module, vsn=Vsn},
MainFile=find_main_filename(Code),
@@ -1783,17 +1799,11 @@ munge_expr({'catch',Line,Expr}, Vars) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
{{'catch',Line,MungedExpr}, Vars2};
munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard=:=false->
+ Vars) ->
{MungedExprM, Vars2} = munge_expr(ExprM, Vars),
{MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
{MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
{{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard=:=true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
munge_expr({call,Line,Expr,Exprs}, Vars) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
{MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
@@ -1945,7 +1955,7 @@ move_clauses([]) ->
%% Given a .beam file, find the .erl file. Look first in same directory as
%% the .beam file, then in <beamdir>/../src
-find_source(File0) ->
+find_source(Module, File0) ->
case filename:rootname(File0,".beam") of
File0 ->
File0;
@@ -1962,11 +1972,27 @@ find_source(File0) ->
true ->
InDotDotSrc;
false ->
- {beam,File0}
+ find_source_from_module(Module, File0)
end
end
end.
+%% In case we can't find the file from the given .beam,
+%% we try to get the information directly from the module source
+find_source_from_module(Module, File) ->
+ Compile = Module:module_info(compile),
+ case lists:keyfind(source, 1, Compile) of
+ {source, Path} ->
+ case filelib:is_file(Path) of
+ true ->
+ Path;
+ false ->
+ {beam, File}
+ end;
+ false ->
+ {beam, File}
+ end.
+
do_parallel_analysis(Module, Analysis, Level, Loaded, From, State) ->
analyse_info(Module,State#main_state.imported),
C = case Loaded of
@@ -2070,7 +2096,7 @@ do_parallel_analysis_to_file(Module, OutFile, Opts, Loaded, From, State) ->
{imported, File0, _} ->
File0
end,
- case find_source(File) of
+ case find_source(Module, File) of
{beam,_BeamFile} ->
reply(From, {error,no_source_code_found});
ErlFile ->
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 57260a3869..5abc5c41b1 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -149,7 +149,9 @@ compile(Config) when is_list(Config) ->
ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
{ok,crypt} = cover:compile_beam("crypt.beam")
end,
+ Path = filename:join([?config(data_dir, Config), "compile_beam", "v.erl"]),
?line {ok,v} = cover:compile_beam(v),
+ {source,Path} = lists:keyfind(source, 1, v:module_info(compile)),
?line {ok,w} = cover:compile_beam("w.beam"),
?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x),
?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a),
@@ -277,12 +279,23 @@ analyse(Config) when is_list(Config) ->
?line f:f2(),
?line {ok, "f.COVER.out"} = cover:analyse_to_file(f),
- %% Source code cannot be found by analyse_to_file
+ %% Source code can be found via source
?line {ok,v} = compile:file("compile_beam/v",[debug_info]),
?line code:purge(v),
?line {module,v} = code:load_file(v),
?line {ok,v} = cover:compile_beam(v),
- ?line {error,no_source_code_found} = cover:analyse_to_file(v),
+ {ok,"v.COVER.out"} = cover:analyse_to_file(v),
+
+ %% Source code cannot be found
+ {ok,_} = file:copy("compile_beam/z.erl", "z.erl"),
+ {ok,z} = compile:file(z,[debug_info]),
+ code:purge(z),
+ {module,z} = code:load_file(z),
+ {ok,z} = cover:compile_beam(z),
+ ok = file:delete("z.erl"),
+ {error,no_source_code_found} = cover:analyse_to_file(z),
+ code:purge(z),
+ code:delete(z),
?line {error,{not_cover_compiled,b}} = cover:analyse(b),
?line {error,{not_cover_compiled,g}} = cover:analyse(g),
diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
index 007957297a..7fb0b08d40 100644
--- a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
+++ b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
@@ -1,6 +1,9 @@
-module(v).
-
--export([f/0]).
+-compile({ no_auto_import, [is_integer/1] }).
+-export([f/0,f/1]).
f() ->
ok.
+
+f(Number) when erlang:is_integer(Number) ->
+ Number.
diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/z.erl b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl
new file mode 100644
index 0000000000..7a2b143dde
--- /dev/null
+++ b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl
@@ -0,0 +1 @@
+-module(z).
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 892a425124..4fb2f30e4f 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.9
+TOOLS_VSN = 2.6.10