aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/src/test_server_node.erl18
-rw-r--r--lib/compiler/src/compile.erl7
-rw-r--r--lib/compiler/src/v3_kernel.erl4
-rw-r--r--lib/debugger/src/dbg_icmd.erl6
-rw-r--r--lib/debugger/src/dbg_ieval.erl6
-rw-r--r--lib/debugger/src/dbg_ieval.hrl4
-rw-r--r--lib/debugger/src/dbg_wx_trace.erl4
-rw-r--r--lib/eunit/src/eunit_data.erl1
-rw-r--r--lib/eunit/src/eunit_lib.erl6
-rw-r--r--lib/eunit/src/eunit_listener.erl37
-rw-r--r--lib/eunit/src/eunit_proc.erl2
-rw-r--r--lib/eunit/src/eunit_serial.erl18
-rw-r--r--lib/eunit/src/eunit_test.erl3
-rw-r--r--lib/eunit/src/eunit_tests.erl2
-rw-r--r--lib/kernel/src/disk_log_1.erl6
-rw-r--r--lib/kernel/src/error_logger.erl81
-rw-r--r--lib/kernel/src/heart.erl3
-rw-r--r--lib/kernel/src/inet.erl4
-rw-r--r--lib/kernel/src/user_drv.erl3
-rw-r--r--lib/mnesia/src/mnesia_schema.erl3
-rw-r--r--lib/observer/src/observer_tv_table.erl3
-rw-r--r--lib/public_key/doc/src/public_key.xml10
-rw-r--r--lib/public_key/doc/src/public_key_records.xml6
-rw-r--r--lib/runtime_tools/src/dbg.erl6
-rw-r--r--lib/ssl/doc/src/ssl.xml22
-rw-r--r--lib/ssl/src/ssl_certificate.erl22
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl65
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl151
-rw-r--r--lib/stdlib/src/dets_utils.erl4
-rw-r--r--lib/stdlib/src/dets_v8.erl4
-rw-r--r--lib/stdlib/src/dets_v9.erl4
-rw-r--r--lib/stdlib/src/dict.erl4
-rw-r--r--lib/stdlib/src/digraph.erl6
-rw-r--r--lib/stdlib/src/epp.erl15
-rw-r--r--lib/stdlib/src/erl_expand_records.erl36
-rw-r--r--lib/stdlib/src/erl_lint.erl32
-rw-r--r--lib/stdlib/src/file_sorter.erl4
-rw-r--r--lib/stdlib/src/lists.erl4
-rw-r--r--lib/stdlib/src/ms_transform.erl13
-rw-r--r--lib/stdlib/src/otp_internal.erl14
-rw-r--r--lib/stdlib/src/qlc.erl4
-rw-r--r--lib/stdlib/src/qlc_pt.erl6
-rw-r--r--lib/stdlib/src/rand.erl6
-rw-r--r--lib/stdlib/src/shell.erl8
-rw-r--r--lib/stdlib/src/unicode.erl4
-rw-r--r--lib/stdlib/src/zip.erl4
-rw-r--r--lib/stdlib/test/epp_SUITE.erl21
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl17
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl6
-rw-r--r--lib/stdlib/test/shell_SUITE.erl4
-rw-r--r--lib/tools/src/cprof.erl3
-rw-r--r--lib/tools/src/fprof.erl8
-rw-r--r--lib/tools/src/xref_utils.erl23
-rw-r--r--lib/tools/test/cover_SUITE_data/d.erl2
-rw-r--r--lib/xmerl/src/xmerl_sax_parser_base.erlsrc3
-rw-r--r--lib/xmerl/src/xmerl_scan.erl113
56 files changed, 605 insertions, 270 deletions
diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl
index 3419f3f5d0..db8d3cde01 100644
--- a/lib/common_test/src/test_server_node.erl
+++ b/lib/common_test/src/test_server_node.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -121,7 +121,7 @@ start_tracer_node(TraceFile,TI) ->
%%%
trace_nodes(Sock,Nodes) ->
Bin = term_to_binary({add_nodes,Nodes}),
- ok = gen_tcp:send(Sock, [1|Bin]),
+ ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
receive_ack(Sock).
@@ -142,7 +142,7 @@ receive_ack(Sock) ->
%%%
stop_tracer_node(Sock) ->
Bin = term_to_binary(id(stop)),
- ok = gen_tcp:send(Sock, [1|Bin]),
+ ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
receive {tcp_closed,Sock} -> gen_tcp:close(Sock) end,
ok.
@@ -171,7 +171,7 @@ trc([TraceFile, PortAtom, Type]) ->
{packet,2}]) of
{ok,Sock} ->
BinResult = term_to_binary(Result),
- ok = gen_tcp:send(Sock,[1|BinResult]),
+ ok = gen_tcp:send(Sock,tag_trace_message(BinResult)),
trc_loop(Sock,Patterns,Type);
_else ->
ok
@@ -187,7 +187,7 @@ trc_loop(Sock,Patterns,Type) ->
{ok,{add_nodes,Nodes}} ->
add_nodes(Nodes,Patterns,Type),
Bin = term_to_binary(id(ok)),
- ok = gen_tcp:send(Sock, [1|Bin]),
+ ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
trc_loop(Sock,Patterns,Type);
{ok,stop} ->
ttb:stop(),
@@ -482,7 +482,7 @@ node_started(Host,PortAtom) ->
{ok,Sock} ->
Started = term_to_binary({started, node(), Version, VsnStr}),
- ok = gen_tcp:send(Sock, [1|Started]),
+ ok = gen_tcp:send(Sock, tag_trace_message(Started)),
receive _Anyting ->
gen_tcp:close(Sock),
erlang:halt()
@@ -492,8 +492,10 @@ node_started(Host,PortAtom) ->
end.
-
-
+-compile({inline, [tag_trace_message/1]}).
+-dialyzer({no_improper_lists, tag_trace_message/1}).
+tag_trace_message(M) ->
+ [1|M].
% start_which_node(Optlist) -> hostname
start_which_node(Optlist) ->
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 72f1a767ed..46917905de 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1620,11 +1620,8 @@ output_encoding(F, #compile{encoding = Encoding}) ->
ok = io:setopts(F, [{encoding, Encoding}]),
ok = io:fwrite(F, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
-restore_expanded_types("P", Fs) ->
- epp:restore_typed_record_fields(Fs);
restore_expanded_types("E", {M,I,Fs0}) ->
- Fs1 = restore_expand_module(Fs0),
- Fs = epp:restore_typed_record_fields(Fs1),
+ Fs = restore_expand_module(Fs0),
{M,I,Fs};
restore_expanded_types(_Ext, Code) -> Code.
@@ -1636,6 +1633,8 @@ restore_expand_module([{attribute,Line,spec,[Arg]}|Fs]) ->
[{attribute,Line,spec,Arg}|restore_expand_module(Fs)];
restore_expand_module([{attribute,Line,callback,[Arg]}|Fs]) ->
[{attribute,Line,callback,Arg}|restore_expand_module(Fs)];
+restore_expand_module([{attribute,Line,record,[R]}|Fs]) ->
+ [{attribute,Line,record,R}|restore_expand_module(Fs)];
restore_expand_module([F|Fs]) ->
[F|restore_expand_module(Fs)];
restore_expand_module([]) -> [].
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 011748df3a..4446d5ff1d 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -143,8 +143,10 @@ attributes([]) -> [].
include_attribute(type) -> false;
include_attribute(spec) -> false;
+include_attribute(callback) -> false;
include_attribute(opaque) -> false;
include_attribute(export_type) -> false;
+include_attribute(record) -> false;
include_attribute(_) -> true.
function({#c_var{name={F,Arity}=FA},Body}, St0) ->
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index 4c34f253c6..1b274e20ae 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -267,7 +267,7 @@ handle_int_msg({old_code,Mod}, Status, Bs,
#ieval{level=Le,module=M}=Ieval) ->
if
Status =:= idle, Le =:= 1 ->
- erase([Mod|db]),
+ erase(?DB_REF_KEY(Mod)),
put(cache, []);
true ->
case dbg_istk:in_use_p(Mod, M) of
@@ -277,7 +277,7 @@ handle_int_msg({old_code,Mod}, Status, Bs,
exit(get(self), kill),
dbg_ieval:exception(exit, old_code, Bs, Ieval);
false ->
- erase([Mod|db]),
+ erase(?DB_REF_KEY(Mod)),
put(cache, [])
end
end;
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 7ed371a653..f5e079ef7e 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -560,7 +560,7 @@ get_function(Mod, Name, Args, extern) ->
end.
db_ref(Mod) ->
- case get([Mod|db]) of
+ case get(?DB_REF_KEY(Mod)) of
undefined ->
case dbg_iserver:call(get(int),
{get_module_db, Mod, get(self)}) of
@@ -572,7 +572,7 @@ db_ref(Mod) ->
Node =/= node() -> {Node,ModDb};
true -> ModDb
end,
- put([Mod|db], DbRef),
+ put(?DB_REF_KEY(Mod), DbRef),
DbRef
end;
DbRef ->
diff --git a/lib/debugger/src/dbg_ieval.hrl b/lib/debugger/src/dbg_ieval.hrl
index 95d0842b19..ad422a9e4a 100644
--- a/lib/debugger/src/dbg_ieval.hrl
+++ b/lib/debugger/src/dbg_ieval.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,3 +27,5 @@
%% (i.e. the next call will leave interpreted code).
top = false
}).
+
+-define(DB_REF_KEY(Mod), {Mod,db}).
diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl
index 5fd1519ba0..f9c60f9b72 100644
--- a/lib/debugger/src/dbg_wx_trace.erl
+++ b/lib/debugger/src/dbg_wx_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -811,7 +811,7 @@ gui_show_module(Win, Mod, Line, Mod, _Pid, How) ->
dbg_wx_trace_win:mark_line(Win, Line, How);
gui_show_module(Win, Mod, Line, _Cm, Pid, How) ->
Win2 = case dbg_wx_trace_win:is_shown(Win, Mod) of
- {true, Win3} -> Win3;
+ %% {true, Win3} -> Win3;
false -> gui_load_module(Win, Mod, Pid)
end,
dbg_wx_trace_win:mark_line(Win2, Line, How).
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index 8b53a3681d..cc002cb449 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -761,6 +761,7 @@ lazy_test_() ->
lazy_gen(7),
?_assertMatch(7, get(count))]}.
+-dialyzer({no_improper_lists, lazy_gen/1}).
lazy_gen(N) ->
{generator,
fun () ->
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index d8f98cffa5..4dbe023257 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -192,6 +192,7 @@ error_msg(Title, Fmt, Args) ->
io_lib:fwrite("*** ~ts ***\n~ts\n\n", [Title, Msg]).
-ifdef(TEST).
+-dialyzer({no_match, format_exception_test_/0}).
format_exception_test_() ->
[?_assertMatch(
"\nymmud:rorre"++_,
@@ -273,6 +274,7 @@ dlist_next([], Xs) ->
-ifdef(TEST).
+-dialyzer({no_match, dlist_test_/0}).
dlist_test_() ->
{"deep list traversal",
[{"non-list term -> singleton list",
@@ -338,6 +340,7 @@ is_nonempty_string([]) -> false;
is_nonempty_string(Cs) -> is_string(Cs).
-ifdef(TEST).
+-dialyzer({no_match, is_string_test_/0}).
is_string_test_() ->
{"is_string",
[{"no non-lists", ?_assert(not is_string($A))},
@@ -399,6 +402,7 @@ uniq([X | Xs]) -> [X | uniq(Xs)];
uniq([]) -> [].
-ifdef(TEST).
+-dialyzer({[no_match, no_fail_call, no_improper_lists], uniq_test_/0}).
uniq_test_() ->
{"uniq",
[?_assertError(function_clause, uniq(ok)),
@@ -459,6 +463,7 @@ normalize([]) ->
-ifdef(TEST).
+-dialyzer({no_match, cmd_test_/0}).
cmd_test_() ->
([?_test({0, "hello\n"} = ?_cmd_("echo hello"))]
++ case os:type() of
@@ -576,6 +581,7 @@ trie_match([], _T) ->
-ifdef(TEST).
+-dialyzer({no_match, trie_test_/0}).
trie_test_() ->
[{"basic representation",
[?_assert(trie_new() =:= gb_trees:empty()),
diff --git a/lib/eunit/src/eunit_listener.erl b/lib/eunit/src/eunit_listener.erl
index ecaac424a2..d9b836863b 100644
--- a/lib/eunit/src/eunit_listener.erl
+++ b/lib/eunit/src/eunit_listener.erl
@@ -27,14 +27,11 @@
-export([start/1, start/2]).
--export([behaviour_info/1]).
-
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_begin,3},{handle_end,3},{handle_cancel,3},
- {terminate,2}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(_) -> _.
+-callback handle_begin(_, _, _) -> _.
+-callback handle_end(_, _, _) -> _.
+-callback handle_cancel(_, _, _) -> _.
+-callback terminate(_, _) -> _.
-record(state, {callback, % callback module
@@ -50,18 +47,22 @@ start(Callback) ->
start(Callback, Options) ->
St = #state{callback = Callback},
- spawn_opt(fun () -> init(St, Options) end,
+ spawn_opt(init_fun(St, Options),
proplists:get_all_values(spawn, Options)).
-init(St0, Options) ->
- St1 = call(init, [Options], St0),
- St2 = expect([], undefined, St1),
- Data = [{pass, St2#state.pass},
- {fail, St2#state.fail},
- {skip, St2#state.skip},
- {cancel, St2#state.cancel}],
- call(terminate, [{ok, Data}, St2#state.state], St2),
- exit(normal).
+-spec init_fun(_, _) -> no_return().
+
+init_fun(St0, Options) ->
+ fun () ->
+ St1 = call(init, [Options], St0),
+ St2 = expect([], undefined, St1),
+ Data = [{pass, St2#state.pass},
+ {fail, St2#state.fail},
+ {skip, St2#state.skip},
+ {cancel, St2#state.cancel}],
+ call(terminate, [{ok, Data}, St2#state.state], St2),
+ exit(normal)
+ end.
expect(Id, ParentId, St) ->
case wait_for(Id, 'begin', ParentId) of
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index 98ae31d54b..8bdf94c877 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -268,6 +268,8 @@ insulator_wait(Child, Parent, Buf, St) ->
kill_task(Child, St)
end.
+-spec kill_task(_, _) -> no_return().
+
kill_task(Child, St) ->
exit(Child, kill),
terminate_insulator(St).
diff --git a/lib/eunit/src/eunit_serial.erl b/lib/eunit/src/eunit_serial.erl
index 1a0179a5df..da76064a53 100644
--- a/lib/eunit/src/eunit_serial.erl
+++ b/lib/eunit/src/eunit_serial.erl
@@ -61,14 +61,16 @@
messages = dict:new() :: dict:dict()}).
start(Pids) ->
- spawn(fun () -> serializer(Pids) end).
-
-serializer(Pids) ->
- St = #state{listeners = sets:from_list(Pids),
- cancelled = eunit_lib:trie_new(),
- messages = dict:new()},
- expect([], undefined, 0, St),
- exit(normal).
+ spawn(serializer_fun(Pids)).
+
+serializer_fun(Pids) ->
+ fun () ->
+ St = #state{listeners = sets:from_list(Pids),
+ cancelled = eunit_lib:trie_new(),
+ messages = dict:new()},
+ expect([], undefined, 0, St),
+ exit(normal)
+ end.
%% collect beginning and end of an expected item; return {Done, NewSt}
%% where Done is true if there are no more items of this group
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index 9cf40a738d..62d30b1930 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -40,6 +40,7 @@ get_stacktrace() ->
get_stacktrace(Ts) ->
eunit_lib:uniq(prune_trace(erlang:get_stacktrace(), Ts)).
+-dialyzer({no_match, prune_trace/2}).
prune_trace([{eunit_data, _, _} | Rest], Tail) ->
prune_trace(Rest, Tail);
prune_trace([{eunit_data, _, _, _} | Rest], Tail) ->
@@ -75,6 +76,7 @@ run_testfun(F) ->
-ifdef(TEST).
+-dialyzer({[no_match, no_fail_call, no_return], macro_test_/0}).
macro_test_() ->
{"macro definitions",
[{?LINE, fun () ->
@@ -301,6 +303,7 @@ wrapper_test_() ->
]}.
%% this must be exported (done automatically by the autoexport transform)
+-dialyzer({no_missing_calls, wrapper_test_exported_/0}).
wrapper_test_exported_() ->
{ok, ?MODULE:nonexisting_function()}.
-endif.
diff --git a/lib/eunit/src/eunit_tests.erl b/lib/eunit/src/eunit_tests.erl
index 47ea0aaf46..5dee1cb49e 100644
--- a/lib/eunit/src/eunit_tests.erl
+++ b/lib/eunit/src/eunit_tests.erl
@@ -23,6 +23,8 @@
-include("eunit.hrl").
+-dialyzer(no_match).
+
-ifdef(TEST).
id(X) -> X. % for suppressing compiler warnings
-endif.
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index 9b9fd086f1..2e61363aa6 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,6 +79,7 @@ log(FdC, FileName, X) ->
logl(X) ->
logl(X, [], 0).
+-dialyzer({no_improper_lists, logl/3}).
logl([X | T], Bs, Size) ->
Sz = byte_size(X),
BSz = <<Sz:?SIZESZ/unit:8>>,
@@ -1142,6 +1143,7 @@ write_index_file(read_write, FName, NewFile, OldFile, OldCnt) ->
file_error(FileName, E)
end.
+-dialyzer({no_improper_lists, to_8_bytes/4}).
to_8_bytes(<<N:32,T/binary>>, NT, FileName, Fd) ->
to_8_bytes(T, [NT | <<N:64>>], FileName, Fd);
to_8_bytes(B, NT, _FileName, _Fd) when byte_size(B) =:= 0 ->
@@ -1276,6 +1278,7 @@ ext_split_bins(CurB, MaxB, FirstPos, Bins) ->
MaxBs = MaxB - CurB, IsFirst = CurB =:= FirstPos,
ext_split_bins(MaxBs, IsFirst, [], Bins, 0, 0).
+-dialyzer({no_improper_lists, ext_split_bins/6}).
ext_split_bins(MaxBs, IsFirst, First, [X | Last], Bs, N) ->
NBs = Bs + byte_size(X),
if
@@ -1296,6 +1299,7 @@ int_split_bins(CurB, MaxB, FirstPos, Bins) ->
MaxBs = MaxB - CurB, IsFirst = CurB =:= FirstPos,
int_split_bins(MaxBs, IsFirst, [], Bins, 0, 0).
+-dialyzer({no_improper_lists, int_split_bins/6}).
int_split_bins(MaxBs, IsFirst, First, [X | Last], Bs, N) ->
Sz = byte_size(X),
NBs = Bs + Sz + ?HEADERSZ,
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index eb231fd155..30a9457bb3 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -435,5 +435,82 @@ add_node(X, Pid) ->
%% Can't do io_lib:format
-display2(Tag,F,A) ->
- erlang:display({error_logger,Tag,F,A}).
+display2({{_Y,_Mo,_D},{_H,_Mi,_S}} = Date, F, A) ->
+ display_date(Date),
+ display3(string_p(F), F, A).
+
+display_date({{Y,Mo,D},{H,Mi,S}}) ->
+ erlang:display_string(
+ integer_to_list(Y) ++ "-" ++
+ two_digits(Mo) ++ "-" ++
+ two_digits(D) ++ " " ++
+ two_digits(H) ++ ":" ++
+ two_digits(Mi) ++ ":" ++
+ two_digits(S) ++ " ").
+
+two_digits(N) when 0 =< N, N =< 9 ->
+ [$0, $0 + N];
+two_digits(N) ->
+ integer_to_list(N).
+
+display3(true, F, A) ->
+ %% Format string with arguments
+ erlang:display_string(F ++ "\n"),
+ [begin
+ erlang:display_string("\t"),
+ erlang:display(Arg)
+ end || Arg <- A],
+ ok;
+display3(false, Atom, A) when is_atom(Atom) ->
+ %% The widest atom seems to be 'supervisor_report' at 17.
+ ColumnWidth = 20,
+ AtomString = atom_to_list(Atom),
+ AtomLength = length(AtomString),
+ Padding = lists:duplicate(ColumnWidth - AtomLength, $\s),
+ erlang:display_string(AtomString ++ Padding),
+ display4(A);
+display3(_, F, A) ->
+ erlang:display({F, A}).
+
+display4([A, []]) ->
+ %% Not sure why crash reports look like this.
+ display4(A);
+display4(A = [_|_]) ->
+ case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of
+ true ->
+ erlang:display_string("\n"),
+ lists:foreach(
+ fun({Key, Value}) ->
+ erlang:display_string(
+ " " ++
+ atom_to_list(Key) ++
+ ": "),
+ erlang:display(Value)
+ end, A);
+ false ->
+ erlang:display(A)
+ end;
+display4(A) ->
+ erlang:display(A).
+
+string_p([]) ->
+ false;
+string_p(Term) ->
+ string_p1(Term).
+
+string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 ->
+ string_p1(T);
+string_p1([$\n|T]) -> string_p1(T);
+string_p1([$\r|T]) -> string_p1(T);
+string_p1([$\t|T]) -> string_p1(T);
+string_p1([$\v|T]) -> string_p1(T);
+string_p1([$\b|T]) -> string_p1(T);
+string_p1([$\f|T]) -> string_p1(T);
+string_p1([$\e|T]) -> string_p1(T);
+string_p1([H|T]) when is_list(H) ->
+ case string_p1(H) of
+ true -> string_p1(T);
+ _ -> false
+ end;
+string_p1([]) -> true;
+string_p1(_) -> false.
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index 464b6919f1..137fad706f 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -265,6 +265,7 @@ do_cycle_port_program(Caller, Parent, Port, Cmd) ->
send_heart_beat(Port) -> Port ! {self(), {command, [?HEART_BEAT]}}.
%% Set a new HEART_COMMAND.
+-dialyzer({no_improper_lists, send_heart_cmd/2}).
send_heart_cmd(Port, []) ->
Port ! {self(), {command, [?CLEAR_CMD]}};
send_heart_cmd(Port, Cmd) ->
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index b573112445..c1ae99ea24 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -289,7 +289,7 @@ getifaddrs(Socket) ->
-spec getifaddrs() -> {ok, Iflist} | {error, posix()} when
Iflist :: [{Ifname,[Ifopt]}],
Ifname :: string(),
- Ifopt :: {flag,[Flag]} | {addr,Addr} | {netmask,Netmask}
+ Ifopt :: {flags,[Flag]} | {addr,Addr} | {netmask,Netmask}
| {broadaddr,Broadaddr} | {dstaddr,Dstaddr}
| {hwaddr,Hwaddr},
Flag :: up | broadcast | loopback | pointtopoint
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index ca3c53ff93..b794d4f45e 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -559,6 +559,7 @@ put_int16(N, Tail) ->
%% is sent back to the process sending the request. This command was added in
%% OTP 18 to make sure that data sent from io:format is actually printed
%% to the console before the vm stops when calling erlang:halt(integer()).
+-dialyzer({no_improper_lists, io_command/1}).
io_command({put_chars_sync, unicode,Cs,Reply}) ->
{{command,[?OP_PUTC_SYNC|unicode:characters_to_binary(Cs,utf8)]},Reply};
io_command({put_chars, unicode,Cs}) ->
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index 1bd8703e1d..782493fb4f 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1095,6 +1095,7 @@ do_delete_table(Tab) ->
ensure_writable(schema),
insert_schema_ops(TidTs, make_delete_table(Tab, whole_table)).
+-dialyzer({no_improper_lists, make_delete_table/2}).
make_delete_table(Tab, Mode) ->
case existed_before(Tab) of
false ->
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 88f606b3e4..75e6919642 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -669,6 +669,7 @@ merge([], New, _Key) ->
merge(Old, New, Key) ->
merge2(keysort(Key, Old), keysort(Key, New), Key).
+-dialyzer({no_improper_lists, merge2/3}).
merge2([[Obj|_]|Old], [Obj|New], Key) ->
[[Obj]|merge2(Old, New, Key)];
merge2([[A|Op]|Old], [B|New], Key)
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 258e7cd1b9..16a7497a22 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -114,8 +114,8 @@
</item>
<tag><c>pem_entry () =</c></tag>
- <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER not_encrypted</c></p>
- <p><c>| cipher_info()}</c></p></item>
+ <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
+ <p><c> not_encrypted | cipher_info()}</c></p></item>
<tag><c>cipher_info() = </c></tag>
<item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)</c></p>
@@ -786,13 +786,13 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<fsummary>Decodes an SSH file-binary.</fsummary>
<type>
<v>SshBin = binary()</v>
- <d>Example {ok, SshBin} = file:read_file("known_hosts").</d>
+ <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
<v>Type = public_key | ssh_file()</v>
<d>If <c>Type</c> is <c>public_key</c> the binary can be either
an RFC4716 public key or an OpenSSH public key.</d>
</type>
<desc>
- <p>Decodes an SSH file-binary. In the case of <c>know_hosts</c> or
+ <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
<c>auth_keys</c>, the binary can include one or more lines of the
file. Returns a list of public keys and their attributes, possible
attribute values depends on the file type represented by the
@@ -842,7 +842,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
</type>
<desc>
- <p>Veryfies a digital signature.</p>
+ <p>Verifies a digital signature.</p>
</desc>
</func>
diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml
index fb03da3150..d34f3ed9a3 100644
--- a/lib/public_key/doc/src/public_key_records.xml
+++ b/lib/public_key/doc/src/public_key_records.xml
@@ -57,9 +57,9 @@
<taglist>
<tag><c>time() =</c></tag>
- <item><p><c>uct_time() | general_time()</c></p></item>
+ <item><p><c>utc_time() | general_time()</c></p></item>
- <tag><c>uct_time() =</c></tag>
+ <tag><c>utc_time() =</c></tag>
<item><p><c>{utcTime, "YYMMDDHHMMSSZ"}</c></p></item>
<tag><c>general_time() =</c></tag>
@@ -144,7 +144,7 @@
<section>
<title>DSA</title>
- <p>Erlang representation of <url href="http://www.ietf.org/rfc/rfc6979.txt">Digigital Signature Algorithm (DSA)</url> keys</p>
+ <p>Erlang representation of <url href="http://www.ietf.org/rfc/rfc6979.txt">Digital Signature Algorithm (DSA)</url> keys</p>
<code>
#'DSAPrivateKey',{
version, % integer()
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 22b531e6ee..6eea1a0917 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1276,6 +1276,8 @@ gen_reader_file(ReadFun, Filename) ->
exit({client_cannot_open, Error})
end.
+-dialyzer({no_improper_lists, mk_reader/2}).
+
%% Creates and returns a reader (lazy list).
mk_reader(ReadFun, Source) ->
fun() ->
@@ -1301,6 +1303,8 @@ mk_reader_wrap([Hd | _] = WrapFiles) ->
exit({client_cannot_open, Error})
end.
+-dialyzer({no_improper_lists, mk_reader_wrap/2}).
+
mk_reader_wrap([_Hd | Tail] = WrapFiles, File) ->
fun() ->
case read_term(fun file_read/2, File) of
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index bf87644116..aaf03d1cd8 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -221,7 +221,7 @@
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.
By default <c>secure_renegotiate</c> is set to <c>false</c>,
that is, secure renegotiation is used if possible,
- but it fallback to unsecure renegotiation if the peer
+ but it falls back to insecure renegotiation if the peer
does not support
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.</p>
</item>
@@ -307,7 +307,7 @@ atom()}} |
<tag><c>unknown_ca</c></tag>
<item><p>No trusted CA was found in the trusted store. The trusted CA is
normally a so called ROOT CA, which is a self-signed certificate. Trust can
- be claimed for an intermediat CA (trusted anchor does not have to be
+ be claimed for an intermediate CA (trusted anchor does not have to be
self-signed according to X-509) by using option <c>partial_chain</c>.</p>
</item>
@@ -352,7 +352,7 @@ marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_valid
<tag><c>{http, timeout()}</c></tag>
<item><p>
Enables fetching of CRLs specified as http URIs in<seealso
- marker="public_key:public_key_records"> X509 cerificate extensions.</seealso>
+ marker="public_key:public_key_records"> X509 certificate extensions.</seealso>
Requires the OTP inets application.</p>
</item>
</taglist>
@@ -611,14 +611,14 @@ fun(srp, Username :: string(), UserState :: term()) ->
<tag><c>{sni_hosts, [{hostname(), ssloptions()}]}</c></tag>
<item><p>If the server receives a SNI (Server Name Indication) from the client
- matching a host listed in the <c>sni_hosts</c> option, the speicific options for
+ matching a host listed in the <c>sni_hosts</c> option, the specific options for
that host will override previously specified options.
The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p></item>
<tag><c>{sni_fun, SNIfun::fun()}</c></tag>
<item><p>If the server receives a SNI (Server Name Indication) from the client,
- the given function will be called to retrive <c>ssloptions()</c> for indicated server.
+ the given function will be called to retrieve <c>ssloptions()</c> for the indicated server.
These options will be merged into predefined <c>ssloptions()</c>.
The function should be defined as:
@@ -632,7 +632,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
of resources of such an operation is higher for the server than the
client. This can act as a vector for denial of service attacks. The SSL
application already takes measures to counter-act such attempts,
- but client-initiated renegotiation can be stricly disabled by setting
+ but client-initiated renegotiation can be strictly disabled by setting
this option to <c>false</c>. The default value is <c>true</c>.
Note that disabling renegotiation can result in long-lived connections
becoming unusable due to limits on the number of messages the underlying
@@ -748,10 +748,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
<v>How = timeout() | {NewController::pid(), timeout()} </v>
<v>Reason = term()</v>
</type>
- <desc><p>Closes or downgrades an SSL connection, in the later case the transport
- connection will be handed over to the <c>NewController</c> process after reciving
- the TLS close alert from the peer. The retuned transport socket will have
- the following options set [{active, false}, {packet, 0}, {mode, binary}].</p>
+ <desc><p>Closes or downgrades an SSL connection. In the latter case the transport
+ connection will be handed over to the <c>NewController</c> process after receiving
+ the TLS close alert from the peer. The returned transport socket will have
+ the following options set: <c>[{active, false}, {packet, 0}, {mode, binary}]</c></p>
</desc>
</func>
@@ -818,7 +818,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<v>Reason = term()</v>
</type>
<desc><p>Returns the connection information you requested. The connection information you can request contains protocol, cipher_suite, and sni_hostname.
- <c>{ok, Info}</c> will be returned if it executes sucessfully. The Info is a proplists containing the information you requested.
+ <c>{ok, Info}</c> will be returned if it executes successfully. <c>Info</c> is a proplist containing the information you requested.
Otherwise, <c>{error, Reason}</c> will be returned.</p>
</desc>
</func>
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 4658e76ab1..e9dc5764a3 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -56,15 +56,15 @@
%% errors. Returns {RootCert, Path, VerifyErrors}
%%--------------------------------------------------------------------
trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) ->
- Path = [Cert | _] = lists:reverse(CertChain),
- OtpCert = public_key:pkix_decode_cert(Cert, otp),
+ Path = [BinCert | _] = lists:reverse(CertChain),
+ OtpCert = public_key:pkix_decode_cert(BinCert, otp),
SignedAndIssuerID =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
{ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self),
{self, IssuerId};
false ->
- other_issuer(OtpCert, CertDbHandle)
+ other_issuer(OtpCert, BinCert, CertDbHandle)
end,
case SignedAndIssuerID of
@@ -187,7 +187,7 @@ public_key_type(?'id-ecPublicKey') ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, _Cert, CertDbHandle, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -200,7 +200,7 @@ certificate_chain(OtpCert, _Cert, CertDbHandle, CertsDbRef, Chain) ->
{_, true = SelfSigned} ->
certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, CertDbHandle) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle) of
{ok, {SerialNr, Issuer}} ->
certificate_chain(CertDbHandle, CertsDbRef, Chain,
SerialNr, Issuer, SelfSigned);
@@ -232,12 +232,12 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, undefined, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, CertDbHandle) ->
+find_issuer(OtpCert, BinCert, CertDbHandle) ->
IsIssuerFun =
fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
true ->
- case verify_cert_signer(OtpCert, ErlCertCandidate#'OTPCertificate'.tbsCertificate) of
+ case verify_cert_signer(BinCert, ErlCertCandidate#'OTPCertificate'.tbsCertificate) of
true ->
throw(public_key:pkix_issuer_id(ErlCertCandidate, self));
false ->
@@ -265,9 +265,9 @@ is_valid_extkey_usage(KeyUse, server) ->
%% Server wants to verify client
is_valid_key_usage(KeyUse, ?'id-kp-clientAuth').
-verify_cert_signer(OtpCert, SignerTBSCert) ->
+verify_cert_signer(BinCert, SignerTBSCert) ->
PublicKey = public_key(SignerTBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo),
- public_key:pkix_verify(public_key:pkix_encode('OTPCertificate', OtpCert, otp), PublicKey).
+ public_key:pkix_verify(BinCert, PublicKey).
public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorithm = ?'id-ecPublicKey',
parameters = Params},
@@ -281,12 +281,12 @@ public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorith
subjectPublicKey = Key}) ->
{Key, Params}.
-other_issuer(OtpCert, CertDbHandle) ->
+other_issuer(OtpCert, BinCert, CertDbHandle) ->
case public_key:pkix_issuer_id(OtpCert, other) of
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, CertDbHandle) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 5940a86a7f..968ef30791 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -75,7 +75,8 @@ error_handling_tests()->
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
unknown_server_ca_accept_backwardscompatibility,
- no_authority_key_identifier].
+ no_authority_key_identifier,
+ no_authority_key_identifier_and_nonstandard_encoding].
init_per_suite(Config0) ->
catch crypto:stop(),
@@ -850,6 +851,68 @@ delete_authority_key_extension([Head | Rest], Acc) ->
%%--------------------------------------------------------------------
+no_authority_key_identifier_and_nonstandard_encoding() ->
+ [{doc, "Test cert with nonstandard encoding that does not have"
+ " authorityKeyIdentifier extension but are present in trusted certs db."}].
+
+no_authority_key_identifier_and_nonstandard_encoding(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
+
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
+ [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile),
+ ServerCert = public_key:pkix_decode_cert(DerCert, plain),
+ ServerTbsCert = ServerCert#'Certificate'.tbsCertificate,
+ Extensions0 = ServerTbsCert#'TBSCertificate'.extensions,
+ %% need to remove authorityKeyIdentifier extension to cause DB lookup by signature
+ Extensions = delete_authority_key_extension(Extensions0, []),
+ NewExtensions = replace_key_usage_extension(Extensions, []),
+ NewServerTbsCert = ServerTbsCert#'TBSCertificate'{extensions = NewExtensions},
+
+ ct:log("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]),
+
+ TbsDer = public_key:pkix_encode('TBSCertificate', NewServerTbsCert, plain),
+ Sig = public_key:sign(TbsDer, md5, Key),
+ NewServerCert = ServerCert#'Certificate'{tbsCertificate = NewServerTbsCert, signature = Sig},
+ NewDerCert = public_key:pkix_encode('Certificate', NewServerCert, plain),
+ ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]),
+ NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)],
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ send_recv_result_active, []}},
+ {options, [{active, true} | NewServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ send_recv_result_active, []}},
+ {options, [{verify, verify_peer} | ClientOpts]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+replace_key_usage_extension([], Acc) ->
+ lists:reverse(Acc);
+replace_key_usage_extension([#'Extension'{extnID = ?'id-ce-keyUsage'} = E | Rest], Acc) ->
+ %% A nonstandard DER encoding of [digitalSignature, keyEncipherment]
+ Val = <<3, 2, 0, 16#A0>>,
+ replace_key_usage_extension(Rest, [E#'Extension'{extnValue = Val} | Acc]);
+replace_key_usage_extension([Head | Rest], Acc) ->
+ replace_key_usage_extension(Rest, [Head | Acc]).
+
+%%--------------------------------------------------------------------
+
invalid_signature_server() ->
[{doc,"Test client with invalid signature"}].
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index 529ae30862..c2e345763a 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -18,11 +18,11 @@
%%
-module(erl_id_trans).
-%% A identity transformer of Erlang abstract syntax.
+%% An identity transformer of Erlang abstract syntax.
%% This module only traverses legal Erlang code. This is most noticeable
%% in guards where only a limited number of expressions are allowed.
-%% N.B. if this module is to be used as a basis for tranforms then
+%% N.B. if this module is to be used as a basis for transforms then
%% all the error cases must be handled otherwise this module just crashes!
-export([parse_transform/2]).
@@ -53,6 +53,17 @@ form({attribute,Line,export,Es0}) ->
form({attribute,Line,import,{Mod,Is0}}) ->
Is1 = farity_list(Is0),
{attribute,Line,import,{Mod,Is1}};
+form({attribute,Line,export_type,Es0}) ->
+ Es1 = farity_list(Es0),
+ {attribute,Line,export_type,Es1};
+form({attribute,Line,optional_callbacks,Es0}) ->
+ try farity_list(Es0) of
+ Es1 ->
+ {attribute,Line,optional_callbacks,Es1}
+ catch
+ _:_ ->
+ {attribute,Line,optional_callbacks,Es0}
+ end;
form({attribute,Line,compile,C}) ->
{attribute,Line,compile,C};
form({attribute,Line,record,{Name,Defs0}}) ->
@@ -60,14 +71,28 @@ form({attribute,Line,record,{Name,Defs0}}) ->
{attribute,Line,record,{Name,Defs1}};
form({attribute,Line,asm,{function,N,A,Code}}) ->
{attribute,Line,asm,{function,N,A,Code}};
+form({attribute,Line,type,{N,T,Vs}}) ->
+ T1 = type(T),
+ Vs1 = variable_list(Vs),
+ {attribute,Line,type,{N,T1,Vs1}};
+form({attribute,Line,opaque,{N,T,Vs}}) ->
+ T1 = type(T),
+ Vs1 = variable_list(Vs),
+ {attribute,Line,opaque,{N,T1,Vs1}};
+form({attribute,Line,spec,{{N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,spec,{{N,A},FTs1}};
+form({attribute,Line,spec,{{M,N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,spec,{{M,N,A},FTs1}};
+form({attribute,Line,callback,{{N,A},FTs}}) ->
+ FTs1 = function_type_list(FTs),
+ {attribute,Line,callback,{{N,A},FTs1}};
form({attribute,Line,Attr,Val}) -> %The general attribute.
{attribute,Line,Attr,Val};
form({function,Line,Name0,Arity0,Clauses0}) ->
{Name,Arity,Clauses} = function(Name0, Arity0, Clauses0),
{function,Line,Name,Arity,Clauses};
-% Mnemosyne, ignore...
-form({rule,Line,Name,Arity,Body}) ->
- {rule,Line,Name,Arity,Body}; % Dont dig into this
%% Extra forms from the parser.
form({error,E}) -> {error,E};
form({warning,W}) -> {warning,W};
@@ -79,6 +104,12 @@ farity_list([{Name,Arity}|Fas]) ->
[{Name,Arity}|farity_list(Fas)];
farity_list([]) -> [].
+%% -type variable_list([Var]) -> [Var]
+
+variable_list([{var,Line,Var}|Vs]) ->
+ [{var,Line,Var}|variable_list(Vs)];
+variable_list([]) -> [].
+
%% -type record_defs([RecDef]) -> [RecDef].
%% N.B. Field names are full expressions here but only atoms are allowed
%% by the *parser*!
@@ -88,6 +119,16 @@ record_defs([{record_field,Line,{atom,La,A},Val0}|Is]) ->
[{record_field,Line,{atom,La,A},Val1}|record_defs(Is)];
record_defs([{record_field,Line,{atom,La,A}}|Is]) ->
[{record_field,Line,{atom,La,A}}|record_defs(Is)];
+record_defs([{typed_record_field,{record_field,Line,{atom,La,A},Val0},Type}|
+ Is]) ->
+ Val1 = expr(Val0),
+ Type1 = type(Type),
+ [{typed_record_field,{record_field,Line,{atom,La,A},Val1},Type1}|
+ record_defs(Is)];
+record_defs([{typed_record_field,{record_field,Line,{atom,La,A}},Type}|Is]) ->
+ Type1 = type(Type),
+ [{typed_record_field,{record_field,Line,{atom,La,A}},Type1}|
+ record_defs(Is)];
record_defs([]) -> [].
%% -type function(atom(), integer(), [Clause]) -> {atom(),integer(),[Clause]}.
@@ -196,9 +237,9 @@ pattern_grp([]) ->
bit_types([]) ->
[];
-bit_types([Atom | Rest]) when atom(Atom) ->
+bit_types([Atom | Rest]) when is_atom(Atom) ->
[Atom | bit_types(Rest)];
-bit_types([{Atom, Integer} | Rest]) when atom(Atom), integer(Integer) ->
+bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
[{Atom, Integer} | bit_types(Rest)].
@@ -226,7 +267,7 @@ pattern_fields([]) -> [].
%% -type guard([GuardTest]) -> [GuardTest].
-guard([G0|Gs]) when list(G0) ->
+guard([G0|Gs]) when is_list(G0) ->
[guard0(G0) | guard(Gs)];
guard(L) ->
guard0(L).
@@ -547,3 +588,97 @@ fun_clauses([C0|Cs]) ->
C1 = clause(C0),
[C1|fun_clauses(Cs)];
fun_clauses([]) -> [].
+
+function_type_list([{type,Line,bounded_fun,[Ft,Fc]}|Fts]) ->
+ Ft1 = function_type(Ft),
+ Fc1 = function_constraint(Fc),
+ [{type,Line,bounded_fun,[Ft1,Fc1]}|function_type_list(Fts)];
+function_type_list([Ft|Fts]) ->
+ [function_type(Ft)|function_type_list(Fts)];
+function_type_list([]) -> [].
+
+function_type({type,Line,'fun',[{type,Lt,product,As},B]}) ->
+ As1 = type_list(As),
+ B1 = type(B),
+ {type,Line,'fun',[{type,Lt,product,As1},B1]}.
+
+function_constraint([C|Cs]) ->
+ C1 = constraint(C),
+ [C1|function_constraint(Cs)];
+function_constraint([]) -> [].
+
+constraint({type,Line,constraint,[{atom,L,A},[V,T]]}) ->
+ V1 = type(V),
+ T1 = type(T),
+ {type,Line,constraint,[{atom,L,A},[V1,T1]]}.
+
+type({ann_type,Line,[{var,Lv,V},T]}) ->
+ T1 = type(T),
+ {ann_type,Line,[{var,Lv,V},T1]};
+type({atom,Line,A}) ->
+ {atom,Line,A};
+type({integer,Line,I}) ->
+ {integer,Line,I};
+type({op,Line,Op,T}) ->
+ T1 = type(T),
+ {op,Line,Op,T1};
+type({op,Line,Op,L,R}) ->
+ L1 = type(L),
+ R1 = type(R),
+ {op,Line,Op,L1,R1};
+type({type,Line,binary,[M,N]}) ->
+ M1 = type(M),
+ N1 = type(N),
+ {type,Line,binary,[M1,N1]};
+type({type,Line,'fun',[]}) ->
+ {type,Line,'fun',[]};
+type({type,Line,'fun',[{type,Lt,any},B]}) ->
+ B1 = type(B),
+ {type,Line,'fun',[{type,Lt,any},B1]};
+type({type,Line,range,[L,H]}) ->
+ L1 = type(L),
+ H1 = type(H),
+ {type,Line,range,[L1,H1]};
+type({type,Line,map,any}) ->
+ {type,Line,map,any};
+type({type,Line,map,Ps}) ->
+ Ps1 = map_pair_types(Ps),
+ {type,Line,map,Ps1};
+type({type,Line,record,[{atom,La,N}|Fs]}) ->
+ Fs1 = field_types(Fs),
+ {type,Line,record,[{atom,La,N}|Fs1]};
+type({remote_type,Line,[{atom,Lm,M},{atom,Ln,N},As]}) ->
+ As1 = type_list(As),
+ {remote_type,Line,[{atom,Lm,M},{atom,Ln,N},As1]};
+type({type,Line,tuple,any}) ->
+ {type,Line,tuple,any};
+type({type,Line,tuple,Ts}) ->
+ Ts1 = type_list(Ts),
+ {type,Line,tuple,Ts1};
+type({type,Line,union,Ts}) ->
+ Ts1 = type_list(Ts),
+ {type,Line,union,Ts1};
+type({var,Line,V}) ->
+ {var,Line,V};
+type({user_type,Line,N,As}) ->
+ As1 = type_list(As),
+ {user_type,Line,N,As1};
+type({type,Line,N,As}) ->
+ As1 = type_list(As),
+ {type,Line,N,As1}.
+
+map_pair_types([{type,Line,map_field_assoc,[K,V]}|Ps]) ->
+ K1 = type(K),
+ V1 = type(V),
+ [{type,Line,map_field_assoc,[K1,V1]}|map_pair_types(Ps)];
+map_pair_types([]) -> [].
+
+field_types([{type,Line,field_type,[{atom,La,A},T]}|Fs]) ->
+ T1 = type(T),
+ [{type,Line,field_type,[{atom,La,A},T1]}|field_types(Fs)];
+field_types([]) -> [].
+
+type_list([T|Ts]) ->
+ T1 = type(T),
+ [T1|type_list(Ts)];
+type_list([]) -> [].
diff --git a/lib/stdlib/src/dets_utils.erl b/lib/stdlib/src/dets_utils.erl
index 196158cd48..34a8ddddaa 100644
--- a/lib/stdlib/src/dets_utils.erl
+++ b/lib/stdlib/src/dets_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -747,6 +747,8 @@ all_allocated([{X,Y} | L], _X0, Y0, A) when Y0 < X ->
all_allocated_as_list(Head) ->
all_allocated_as_list(all(get_freelists(Head)), 0, Head#head.base, []).
+-dialyzer({no_improper_lists, all_allocated_as_list/4}).
+
all_allocated_as_list([], _X0, _Y0, []) ->
[];
all_allocated_as_list([], _X0, _Y0, A) ->
diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl
index 49126193b8..1bf53d91b1 100644
--- a/lib/stdlib/src/dets_v8.erl
+++ b/lib/stdlib/src/dets_v8.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,8 @@
%% For backward compatibility.
-export([sz2pos/1]).
+-dialyzer(no_improper_lists).
+
-compile({inline, [{sz2pos,1},{scan_skip,7}]}).
-compile({inline, [{skip_bytes,5}, {get_segp,1}]}).
-compile({inline, [{wl_lookup,5}]}).
diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl
index 361780c776..6c406fc03a 100644
--- a/lib/stdlib/src/dets_v9.erl
+++ b/lib/stdlib/src/dets_v9.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,8 @@
-export([cache_segps/3]).
+-dialyzer(no_improper_lists).
+
-compile({inline, [{max_objsize,1},{maxobjsize,1}]}).
-compile({inline, [{write_segment_file,6}]}).
-compile({inline, [{sz2pos,1},{adjsz,1}]}).
diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl
index 6ce3710f87..f921e28ef6 100644
--- a/lib/stdlib/src/dict.erl
+++ b/lib/stdlib/src/dict.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -333,6 +333,8 @@ update_counter(Key, Incr, D0) when is_number(Incr) ->
D0, Slot),
maybe_expand(D1, Ic).
+-dialyzer({no_improper_lists, counter_bkt/3}).
+
counter_bkt(Key, I, [?kv(Key,Val)|Bkt]) ->
{[?kv(Key,Val+I)|Bkt],0};
counter_bkt(Key, I, [Other|Bkt0]) ->
diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl
index e51e560542..8a4df95027 100644
--- a/lib/stdlib/src/digraph.erl
+++ b/lib/stdlib/src/digraph.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -338,6 +338,8 @@ edge(G, E) ->
%%
-spec new_edge_id(graph()) -> edge().
+-dialyzer({no_improper_lists, new_edge_id/1}).
+
new_edge_id(G) ->
NT = G#digraph.ntab,
[{'$eid', K}] = ets:lookup(NT, '$eid'),
@@ -350,6 +352,8 @@ new_edge_id(G) ->
%%
-spec new_vertex_id(graph()) -> vertex().
+-dialyzer({no_improper_lists, new_vertex_id/1}).
+
new_vertex_id(G) ->
NT = G#digraph.ntab,
[{'$vid', K}] = ets:lookup(NT, '$vid'),
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 45f616bb02..be7c2ec346 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -258,20 +258,7 @@ parse_file(Ifile, Options) ->
parse_file(Epp) ->
case parse_erl_form(Epp) of
{ok,Form} ->
- case Form of
- {attribute,La,record,{Record, Fields}} ->
- case normalize_typed_record_fields(Fields) of
- {typed, NewFields} ->
- [{attribute, La, record, {Record, NewFields}},
- {attribute, La, type,
- {{record, Record}, Fields, []}}
- |parse_file(Epp)];
- not_typed ->
- [Form|parse_file(Epp)]
- end;
- _ ->
- [Form|parse_file(Epp)]
- end;
+ [Form|parse_file(Epp)];
{error,E} ->
[{error,E}|parse_file(Epp)];
{eof,Location} ->
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index bcfeef7321..9c0a7fb7d5 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -33,8 +33,6 @@
vcount=0, % Variable counter
imports=[], % Imports
records=dict:new(), % Record definitions
- trecords=sets:new(), % Typed records
- uses_types=false, % Are there -spec or -type in the module
strict_ra=[], % strict record accesses
checked_ra=[] % successfully accessed records
}).
@@ -47,45 +45,18 @@
%% erl_lint without errors.
module(Fs0, Opts0) ->
Opts = compiler_options(Fs0) ++ Opts0,
- TRecs = typed_records(Fs0),
- UsesTypes = uses_types(Fs0),
- St0 = #exprec{compile = Opts, trecords = TRecs, uses_types = UsesTypes},
+ St0 = #exprec{compile = Opts},
{Fs,_St} = forms(Fs0, St0),
Fs.
compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
-typed_records(Fs) ->
- typed_records(Fs, sets:new()).
-
-typed_records([{attribute,_L,type,{{record, Name},_Defs,[]}} | Fs], Trecs) ->
- typed_records(Fs, sets:add_element(Name, Trecs));
-typed_records([_|Fs], Trecs) ->
- typed_records(Fs, Trecs);
-typed_records([], Trecs) ->
- Trecs.
-
-uses_types([{attribute,_L,spec,_}|_]) -> true;
-uses_types([{attribute,_L,type,_}|_]) -> true;
-uses_types([{attribute,_L,opaque,_}|_]) -> true;
-uses_types([_|Fs]) -> uses_types(Fs);
-uses_types([]) -> false.
-
-forms([{attribute,L,record,{Name,Defs}} | Fs], St0) ->
+forms([{attribute,_,record,{Name,Defs}}=Attr | Fs], St0) ->
NDefs = normalise_fields(Defs),
St = St0#exprec{records=dict:store(Name, NDefs, St0#exprec.records)},
{Fs1, St1} = forms(Fs, St),
- %% Check if we need to keep the record information for usage in types.
- case St#exprec.uses_types of
- true ->
- case sets:is_element(Name, St#exprec.trecords) of
- true -> {Fs1, St1};
- false -> {[{attribute,L,type,{{record,Name},Defs,[]}}|Fs1], St1}
- end;
- false ->
- {Fs1, St1}
- end;
+ {[Attr | Fs1], St1};
forms([{attribute,L,import,Is} | Fs0], St0) ->
St1 = import(Is, St0),
{Fs,St2} = forms(Fs0, St1),
@@ -513,7 +484,6 @@ lc_tq(Line, [F0 | Qs0], St0) ->
lc_tq(_Line, [], St0) ->
{[],St0#exprec{checked_ra = []}}.
-
%% normalise_fields([RecDef]) -> [Field].
%% Normalise the field definitions to always have a default value. If
%% none has been given then use 'undefined'.
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 9ef4acdf5f..4ca9a609a8 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -360,6 +360,9 @@ format_error({redefine_type, {TypeName, Arity}}) ->
[TypeName, gen_type_paren(Arity)]);
format_error({type_syntax, Constr}) ->
io_lib:format("bad ~w type", [Constr]);
+format_error(old_abstract_code) ->
+ io_lib:format("abstract code generated before Erlang/OTP 19.0 and "
+ "having typed record fields cannot be compiled", []);
format_error({redefine_spec, {M, F, A}}) ->
io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]);
format_error({redefine_spec, {F, A}}) ->
@@ -1143,7 +1146,7 @@ check_untyped_records(Forms, St0) ->
RecNames = dict:fetch_keys(St0#lint.records),
%% these are the records with field(s) containing type info
TRecNames = [Name ||
- {attribute,_,type,{{record,Name},Fields,_}} <- Forms,
+ {attribute,_,record,{Name,Fields}} <- Forms,
lists:all(fun ({typed_record_field,_,_}) -> true;
(_) -> false
end, Fields)],
@@ -1153,7 +1156,8 @@ check_untyped_records(Forms, St0) ->
[] -> St; % exclude records with no fields
[_|_] -> add_warning(L, {untyped_record, N}, St)
end
- end, St0, RecNames -- TRecNames);
+ end, St0, ordsets:subtract(ordsets:from_list(RecNames),
+ ordsets:from_list(TRecNames)));
false ->
St0
end.
@@ -2443,7 +2447,10 @@ record_def(Line, Name, Fs0, St0) ->
true -> add_error(Line, {redefine_record,Name}, St0);
false ->
{Fs1,St1} = def_fields(normalise_fields(Fs0), Name, St0),
- St1#lint{records=dict:store(Name, {Line,Fs1}, St1#lint.records)}
+ St2 = St1#lint{records=dict:store(Name, {Line,Fs1},
+ St1#lint.records)},
+ Types = [T || {typed_record_field, _, T} <- Fs0],
+ check_type({type, nowarn(), product, Types}, St2)
end.
%% def_fields([RecDef], RecordName, State) -> {[DefField],State}.
@@ -2646,11 +2653,6 @@ find_field(_F, []) -> error.
%% Attr :: 'type' | 'opaque'
%% Checks that a type definition is valid.
-type_def(_Attr, _Line, {record, _RecName}, Fields, [], St0) ->
- %% The record field names and such are checked in the record format.
- %% We only need to check the types.
- Types = [T || {typed_record_field, _, T} <- Fields],
- check_type({type, nowarn(), product, Types}, St0);
type_def(Attr, Line, TypeName, ProtoType, Args, St0) ->
TypeDefs = St0#lint.types,
Arity = length(Args),
@@ -2813,6 +2815,8 @@ check_type({user_type, L, TypeName, Args}, SeenVars, St) ->
lists:foldl(fun(T, {AccSeenVars, AccSt}) ->
check_type(T, AccSeenVars, AccSt)
end, {SeenVars, St1}, Args);
+check_type([{typed_record_field,Field,_T}|_], SeenVars, St) ->
+ {SeenVars, add_error(element(2, Field), old_abstract_code, St)};
check_type(I, SeenVars, St) ->
case erl_eval:partial_eval(I) of
{integer,_ILn,_Integer} -> {SeenVars, St};
@@ -2994,9 +2998,10 @@ add_missing_spec_warnings(Forms, St0, Type) ->
[{FA,L} || {function,L,F,A,_} <- Forms,
not lists:member(FA = {F,A}, Specs)];
exported ->
- Exps = gb_sets:to_list(St0#lint.exports) -- pseudolocals(),
+ Exps0 = gb_sets:to_list(St0#lint.exports) -- pseudolocals(),
+ Exps = Exps0 -- Specs,
[{FA,L} || {function,L,F,A,_} <- Forms,
- member(FA = {F,A}, Exps -- Specs)]
+ member(FA = {F,A}, Exps)]
end,
foldl(fun ({FA,L}, St) ->
add_warning(L, {missing_spec,FA}, St)
@@ -3009,7 +3014,9 @@ check_unused_types(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
L = gb_sets:to_list(ExpTs) ++ dict:fetch_keys(D),
UsedTypes = gb_sets:from_list(L),
FoldFun =
- fun(Type, #typeinfo{line = FileLine}, AccSt) ->
+ fun({{record, _}=_Type, 0}, _, AccSt) ->
+ AccSt; % Before Erlang/OTP 19.0
+ (Type, #typeinfo{line = FileLine}, AccSt) ->
case loc(FileLine, AccSt) of
{FirstFile, _} ->
case gb_sets:is_member(Type, UsedTypes) of
@@ -3531,6 +3538,8 @@ check_qlc_hrl(Line, M, F, As, St) ->
%% deprecated_function(Line, ModName, FuncName, [Arg], State) -> State.
%% Add warning for calls to deprecated functions.
+-dialyzer({no_match, deprecated_function/5}).
+
deprecated_function(Line, M, F, As, St) ->
Arity = length(As),
MFA = {M, F, Arity},
@@ -3560,6 +3569,7 @@ deprecated_function(Line, M, F, As, St) ->
end.
-dialyzer({no_match, deprecated_type/5}).
+
deprecated_type(L, M, N, As, St) ->
NAs = length(As),
case otp_internal:obsolete_type(M, N, NAs) of
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index aed857aa77..3aeaff8dc4 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@
check/1, check/2,
keycheck/2, keycheck/3]).
+-dialyzer(no_improper_lists).
+
-include_lib("kernel/include/file.hrl").
-define(CHUNKSIZE, 16384).
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 62b6ca8a21..2b4472cdf7 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2267,6 +2267,8 @@ ukeysplit_2(I, Y, EY, [Z | L], R) ->
ukeysplit_2(_I, Y, _EY, [], R) ->
[Y | R].
+-dialyzer({no_improper_lists, ukeymergel/3}).
+
ukeymergel(I, [T1, [H2 | T2], [H3 | T3] | L], Acc) ->
%% The fourth argument, [H2 | H3] (=HdM), may confuse type
%% checkers. Its purpose is to ensure that the tests H2 == HdM
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index b67b6f75d7..24b5fde1db 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -307,15 +307,18 @@ cleanup_filename({Old,OldRec,OldWarnings}) ->
add_record_definition({Name,FieldList}) ->
{KeyList,_} = lists:foldl(
- fun({record_field,_,{atom,Line0,FieldName}},{L,C}) ->
- {[{FieldName,C,{atom,Line0,undefined}}|L],C+1};
- ({record_field,_,{atom,_,FieldName},Def},{L,C}) ->
- {[{FieldName,C,Def}|L],C+1}
- end,
+ fun(F, {L,C}) -> {[record_field(F, C)|L],C+1} end,
{[],2},
FieldList),
put_records([{Name,KeyList}|get_records()]).
+record_field({record_field,_,{atom,Line0,FieldName}}, C) ->
+ {FieldName,C,{atom,Line0,undefined}};
+record_field({record_field,_,{atom,_,FieldName},Def}, C) ->
+ {FieldName,C,Def};
+record_field({typed_record_field,Field,_Type}, C) ->
+ record_field(Field, C).
+
forms([F0|Fs0]) ->
F1 = form(F0),
Fs1 = forms(Fs0),
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index bc70c296da..0dc2626ae8 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
%%----------------------------------------------------------------------
+-dialyzer({no_match, obsolete/3}).
+
-type tag() :: 'deprecated' | 'removed'. %% | 'experimental'.
-type mfas() :: mfa() | {atom(), atom(), [byte()]}.
-type release() :: string().
@@ -697,18 +699,20 @@ is_snmp_agent_function(del_agent_caps, 1) -> true;
is_snmp_agent_function(get_agent_caps, 0) -> true;
is_snmp_agent_function(_, _) -> false.
+-dialyzer({no_match, obsolete_type/3}).
+
-spec obsolete_type(module(), atom(), arity()) ->
'no' | {tag(), string()} | {tag(), mfas(), release()}.
-dialyzer({no_match, obsolete_type/3}).
obsolete_type(Module, Name, NumberOfVariables) ->
case obsolete_type_1(Module, Name, NumberOfVariables) of
- {deprecated=Tag,{_,_,_}=Replacement} ->
- {Tag,Replacement,"in a future release"};
+ {deprecated=Tag,{_,_,_}=Replacement} ->
+ {Tag,Replacement,"in a future release"};
{_,String}=Ret when is_list(String) ->
Ret;
- {_,_,_}=Ret ->
- Ret;
+ {_,_,_}=Ret ->
+ Ret;
no ->
no
end.
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 24e64efee7..b396ba7057 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,6 +51,8 @@
-export([template_state/0, aux_name/3, name_suffix/2, vars/1,
var_ufold/2, var_fold/3, all_selections/1]).
+-dialyzer(no_improper_lists).
+
%% When cache=list lists bigger than ?MAX_LIST_SIZE bytes are put on
%% file. Also used when merge join finds big equivalence classes.
-define(MAX_LIST_SIZE, 512*1024).
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 9f69cd5003..e4b9768b12 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -1914,9 +1914,9 @@ expand_pattern_records(P, State) ->
expand_expr_records(E, State) ->
RecordDefs = State#state.records,
A = anno1(),
- Forms = RecordDefs ++ [{function,A,foo,0,[{clause,A,[],[],[pe(E)]}]}],
- [{function,_,foo,0,[{clause,_,[],[],[NE]}]}] =
- erl_expand_records:module(Forms, [no_strict_record_tests]),
+ Forms0 = RecordDefs ++ [{function,A,foo,0,[{clause,A,[],[],[pe(E)]}]}],
+ Forms = erl_expand_records:module(Forms0, [no_strict_record_tests]),
+ {function,_,foo,0,[{clause,_,[],[],[NE]}]} = lists:last(Forms),
NE.
%% Partial evaluation.
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index dc060e82d9..d455abf7b0 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -256,6 +256,8 @@ exs64_uniform(Max, {Alg, R}) ->
%% =====================================================================
-type exsplus_state() :: nonempty_improper_list(uint58(), uint58()).
+-dialyzer({no_improper_lists, exsplus_seed/1}).
+
exsplus_seed({A1, A2, A3}) ->
{_, R1} = exsplus_next([(((A1 * 4294967197) + 1) band ?UINT58MASK)|
(((A2 * 4294967231) + 1) band ?UINT58MASK)]),
@@ -263,6 +265,8 @@ exsplus_seed({A1, A2, A3}) ->
tl(R1)]),
R2.
+-dialyzer({no_improper_lists, exsplus_next/1}).
+
%% Advance xorshift116+ state for one step and generate 58bit unsigned integer
-spec exsplus_next(exsplus_state()) -> {uint58(), exsplus_state()}.
exsplus_next([S1|S0]) ->
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index ce1d9eb0ff..82a3a2be4f 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -917,9 +917,9 @@ expand_records(UsedRecords, E0) ->
RecordDefs = [Def || {_Name,Def} <- UsedRecords],
L = erl_anno:new(1),
E = prep_rec(E0),
- Forms = RecordDefs ++ [{function,L,foo,0,[{clause,L,[],[],[E]}]}],
- [{function,L,foo,0,[{clause,L,[],[],[NE]}]}] =
- erl_expand_records:module(Forms, [strict_record_tests]),
+ Forms0 = RecordDefs ++ [{function,L,foo,0,[{clause,L,[],[],[E]}]}],
+ Forms = erl_expand_records:module(Forms0, [strict_record_tests]),
+ {function,L,foo,0,[{clause,L,[],[],[NE]}]} = lists:last(Forms),
prep_rec(NE).
prep_rec({value,_CommandN,_V}=Value) ->
@@ -1081,6 +1081,8 @@ record_fields([{record_field,_,{atom,_,Field}} | Fs]) ->
[Field | record_fields(Fs)];
record_fields([{record_field,_,{atom,_,Field},_} | Fs]) ->
[Field | record_fields(Fs)];
+record_fields([{typed_record_field,Field,_Type} | Fs]) ->
+ record_fields([Field | Fs]);
record_fields([]) ->
[].
diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl
index 3e8e6f5101..617da11ba8 100644
--- a/lib/stdlib/src/unicode.erl
+++ b/lib/stdlib/src/unicode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -561,6 +561,8 @@ do_o_binary(F,L) ->
erlang:iolist_to_binary(List)
end.
+-dialyzer({no_improper_lists, do_o_binary2/2}).
+
do_o_binary2(_F,[]) ->
<<>>;
do_o_binary2(F,[H|T]) ->
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index bec0bd3f6d..f8ba6f18e9 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1566,6 +1566,8 @@ append_bins([_|_]=List, B) ->
append_bins([], B) ->
B.
+-dialyzer({no_improper_lists, pwrite_iolist/3}).
+
pwrite_iolist(B, Pos, Bin) ->
{Left, Right} = split_binary(B, Pos),
Sz = erlang:iolist_size(Bin),
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 0266a7fa6c..da5a079303 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -25,7 +25,7 @@
upcase_mac_1/1, upcase_mac_2/1,
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
- otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
+ otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
otp_11728/1, encoding/1, extends/1]).
@@ -68,7 +68,7 @@ all() ->
[rec_1, {group, upcase_mac}, include_local, predef_mac,
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
- overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
+ overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
encoding, extends].
@@ -1230,23 +1230,8 @@ otp_8470(Config) when is_list(Config) ->
?line receive _ -> fail() after 0 -> ok end,
ok.
-otp_8503(doc) ->
- ["OTP-8503. Record with no fields is considered typed."];
-otp_8503(suite) ->
- [];
-otp_8503(Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
- C = <<"-record(r, {}).">>,
- ?line File = filename:join(Dir, "otp_8503.erl"),
- ?line ok = file:write_file(File, C),
- ?line {ok, List} = epp:parse_file(File, [], []),
- ?line [_] = [F || {attribute,_,type,{{record,r},[],[]}}=F <- List],
- file:delete(File),
- ?line receive _ -> fail() after 0 -> ok end,
- ok.
-
otp_8562(doc) ->
- ["OTP-8503. Record with no fields is considered typed."];
+ ["OTP-8562. Record with no fields is considered typed."];
otp_8562(suite) ->
[];
otp_8562(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 6d97ae2718..d946469625 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2607,6 +2607,23 @@ otp_5878(Config) when is_list(Config) ->
">>,
?line [] = run_test2(Config, UsedByType, [warn_unused_record]),
+ %% Abstract code generated by OTP 18. Note that the type info for
+ %% record fields has been put in a separate form.
+ OldAbstract = [{attribute,1,file,{"rec.erl",1}},
+ {attribute,1,module,rec},
+ {attribute,3,export,[{t,0}]},
+ {attribute,7,record,{r,[{record_field,7,{atom,7,f}}]}},
+ {attribute,7,type,
+ {{record,r},
+ [{typed_record_field,
+ {record_field,7,{atom,7,f}},
+ {type,7,union,[{atom,7,undefined},{type,7,atom,[]}]}}],
+ []}},
+ {function,9,t,0,[{clause,9,[],[],[{record,10,r,[]}]}]},
+ {eof,11}],
+ {error,[{"rec.erl",[{7,erl_lint,old_abstract_code}]}],[]} =
+ compile:forms(OldAbstract, [return, report]),
+
ok.
otp_6885(doc) ->
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index 6bb518f46f..6a9478d0d2 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -342,8 +342,8 @@ records(doc) ->
records(Config) when is_list(Config) ->
?line setup(Config),
?line RD = <<"-record(t, {"
- "t1 = [],"
- "t2 = foo,"
+ "t1 = [] :: list(),"
+ "t2 = foo :: atom(),"
"t3,"
"t4"
"}).">>,
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 5aa81594cb..747b76abb6 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -393,7 +393,9 @@ records(Config) when is_list(Config) ->
Test = filename:join(?config(priv_dir, Config), "test.erl"),
Contents = <<"-module(test).
- -record(state, {bin, reply, leader}).
+ -record(state, {bin :: binary(),
+ reply = no,
+ leader = some :: atom()}).
-ifdef(test1).
-record(test1, {f}).
diff --git a/lib/tools/src/cprof.erl b/lib/tools/src/cprof.erl
index 0240f876bc..f6d68f0bf8 100644
--- a/lib/tools/src/cprof.erl
+++ b/lib/tools/src/cprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -114,6 +114,7 @@ analyse(Limit) when is_integer(Limit) ->
analyse(M) when is_atom(M) ->
analyse(M, 1).
+-dialyzer({no_improper_lists, analyse/2}).
analyse(M, Limit) when is_atom(M), is_integer(Limit) ->
L0 = [begin
MFA = {M,F,A},
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index 7c6fab0b75..c5c24c8eb3 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2251,6 +2251,8 @@ do_analyse(Table, Analyse) ->
?dbg(5, "do_analyse_1(_, _) ->~p~n", [Result]),
Result.
+-dialyzer({no_improper_lists, do_analyse_1/2}).
+
do_analyse_1(Table,
#analyse{group_leader = GroupLeader,
dest = Io,
@@ -2624,6 +2626,8 @@ funcstat_pd(Pid, Func1, Func0, Clocks) ->
funcstat_sort_r(FuncstatList, Element) ->
funcstat_sort_r_1(FuncstatList, Element, []).
+-dialyzer({no_improper_lists, funcstat_sort_r_1/3}).
+
funcstat_sort_r_1([], _, R) ->
postsort_r(lists:sort(R));
funcstat_sort_r_1([#funcstat{callers_sum = #clocks{} = Clocks,
@@ -2646,6 +2650,8 @@ funcstat_sort_r_1([#funcstat{callers_sum = #clocks{} = Clocks,
clocks_sort_r(L, E) ->
clocks_sort_r_1(L, E, []).
+-dialyzer({no_improper_lists, clocks_sort_r_1/3}).
+
clocks_sort_r_1([], _, R) ->
postsort_r(lists:sort(R));
clocks_sort_r_1([#clocks{} = C | L], E, R) ->
diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl
index 438ec93962..f69aa70244 100644
--- a/lib/tools/src/xref_utils.erl
+++ b/lib/tools/src/xref_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -245,6 +245,8 @@ select_last_application_version(AppVs) ->
TL = to_external(partition(1, relation(AppVs))),
[last(keysort(2, L)) || L <- TL].
+-record(scan, {collected = [], errors = [], seen = [], unreadable = []}).
+
%% scan_directory(Directory, Recurse, Collect, Watch) ->
%% {Collected, Errors, Seen, Unreadable}
%%
@@ -261,8 +263,9 @@ select_last_application_version(AppVs) ->
%% Unreadable.
%%
scan_directory(File, Recurse, Collect, Watch) ->
- Init = [[] | {[],[],[]}],
- [L | {E,J,U}] = find_files_dir(File, Recurse, Collect, Watch, Init),
+ Init = #scan{},
+ S = find_files_dir(File, Recurse, Collect, Watch, Init),
+ #scan{collected = L, errors = E, seen = J, unreadable = U} = S,
{reverse(L), reverse(E), reverse(J), reverse(U)}.
%% {Dir, Basename} | false
@@ -576,8 +579,7 @@ find_files_dir(Dir, Recurse, Collect, Watch, L) ->
{ok, Files} ->
find_files(sort(Files), Dir, Recurse, Collect, Watch, L);
{error, Error} ->
- [B | {E,J,U}] = L,
- [B | {[file_error(Dir, Error)|E],J,U}]
+ L#scan{errors = [file_error(Dir, Error)|L#scan.errors]}
end.
find_files([F | Fs], Dir, Recurse, Collect, Watch, L) ->
@@ -588,22 +590,23 @@ find_files([F | Fs], Dir, Recurse, Collect, Watch, L) ->
{ok, {_, directory, _, _}} ->
L;
Info ->
- [B | EJU = {E,J,U}] = L,
+ #scan{collected = B, errors = E,
+ seen = J, unreadable = U} = L,
Ext = filename:extension(File),
C = member(Ext, Collect),
case C of
true ->
case Info of
{ok, {_, file, readable, _}} ->
- [[{Dir,F} | B] | EJU];
+ L#scan{collected = [{Dir,F} | B]};
{ok, {_, file, unreadable, _}} ->
- [B | {E,J,[File|U]}];
+ L#scan{unreadable = [File|U]};
Error ->
- [B | {[Error|E],J,U}]
+ L#scan{errors = [Error|E]}
end;
false ->
case member(Ext, Watch) of
- true -> [B | {E,[File|J],U}];
+ true -> L#scan{seen = [File|J]};
false -> L
end
end
diff --git a/lib/tools/test/cover_SUITE_data/d.erl b/lib/tools/test/cover_SUITE_data/d.erl
index 696e27e49b..b1d8ebd62e 100644
--- a/lib/tools/test/cover_SUITE_data/d.erl
+++ b/lib/tools/test/cover_SUITE_data/d.erl
@@ -6,7 +6,7 @@
size/0]).
-export([init/0]). % spawn
--record(person, {name, age, location, moved=false}).
+-record(person, {name, age :: integer(), location, moved=false :: boolean()}).
%%%----------------------------------------------------------------------
%%% User interface functions
diff --git a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
index 2bbe0eea1a..2c5caab07b 100644
--- a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
+++ b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
@@ -152,6 +152,7 @@ parse_document(Rest, State) when is_record(State, xmerl_sax_parser_state) ->
%% [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
%% [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
%%----------------------------------------------------------------------
+-dialyzer({[no_fail_call, no_match], parse_xml_decl/2}).
parse_xml_decl(?STRING_EMPTY, State) ->
cf(?STRING_EMPTY, State, fun parse_xml_decl/2);
parse_xml_decl(?BYTE_ORDER_MARK_1, State) ->
@@ -1205,6 +1206,7 @@ send_character_event(_, true, String, State) ->
%% Description: Parse whitespaces.
%% [3] S ::= (#x20 | #x9 | #xD | #xA)+
%%----------------------------------------------------------------------
+-dialyzer({no_fail_call, whitespace/3}).
whitespace(?STRING_EMPTY, State, Acc) ->
case cf(?STRING_EMPTY, State, Acc, fun whitespace/3) of
{?STRING_EMPTY, State} ->
@@ -1716,6 +1718,7 @@ handle_external_entity({Tag, _Url}, State) ->
%% Result : {Rest, State}
%% Description: Parse the external entity.
%%----------------------------------------------------------------------
+-dialyzer({[no_fail_call, no_match], parse_external_entity_1/2}).
parse_external_entity_1(?STRING_EMPTY, #xmerl_sax_parser_state{file_type=Type} = State) ->
case catch cf(?STRING_EMPTY, State, fun parse_external_entity_1/2) of
{Rest, State1} when is_record(State1, xmerl_sax_parser_state) ->
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 2bf3172d87..829716dcdb 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1010,7 +1010,7 @@ scan_optional_version(T,S) ->
scan_enc_name([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_enc_name(MoreBytes, S1) end,
- fun(S1) -> ?fatal(expected_encoding_name, S1) end,
+ fatal_fun(expected_encoding_name),
S);
scan_enc_name([H|T], S0) when H >= $"; H =< $' ->
?bump_col(1),
@@ -1020,7 +1020,7 @@ scan_enc_name([H|T], S0) when H >= $"; H =< $' ->
scan_enc_name([], S=#xmerl_scanner{continuation_fun = F}, Delim, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_enc_name(MoreBytes, S1, Delim, Acc) end,
- fun(S1) -> ?fatal(expected_encoding_name, S1) end,
+ fatal_fun(expected_encoding_name),
S);
scan_enc_name([H|T], S0, Delim, Acc) when H >= $a, H =< $z ->
?bump_col(1),
@@ -1034,7 +1034,7 @@ scan_enc_name([H|_T],S,_Delim,_Acc) ->
scan_enc_name2([], S=#xmerl_scanner{continuation_fun = F}, Delim, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_enc_name2(MoreBytes, S1, Delim, Acc) end,
- fun(S1) -> ?fatal(expected_encoding_name, S1) end,
+ fatal_fun(expected_encoding_name),
S);
scan_enc_name2([H|T], S0, H, Acc) ->
?bump_col(1),
@@ -1058,7 +1058,7 @@ scan_enc_name2([H|T], S0, Delim, Acc) when H == $.; H == $_; H == $- ->
scan_xml_vsn([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_xml_vsn(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_xml_vsn([H|T], S) when H==$"; H==$'->
xml_vsn(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1}, H, []).
@@ -1066,7 +1066,7 @@ scan_xml_vsn([H|T], S) when H==$"; H==$'->
xml_vsn([], S=#xmerl_scanner{continuation_fun = F}, Delim, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> xml_vsn(MoreBytes, S1, Delim, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
xml_vsn([H|T], S=#xmerl_scanner{col = C}, H, Acc) ->
{lists:reverse(Acc), T, S#xmerl_scanner{col = C+1}};
@@ -1089,7 +1089,7 @@ xml_vsn([H|T], S=#xmerl_scanner{col = C}, Delim, Acc) ->
scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Pos, Ps) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Pos, Ps) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pi(Str = [H1,H2,H3 | T],S0=#xmerl_scanner{line = L, col = C}, Pos, Ps)
when H1==$x;H1==$X ->
@@ -1125,7 +1125,7 @@ scan_pi([], S=#xmerl_scanner{continuation_fun = F}, Target,
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pi(MoreBytes, S1, Target,
L, C, Pos, Ps, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pi("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event},
@@ -1152,7 +1152,7 @@ scan_pi2([], S=#xmerl_scanner{continuation_fun = F}, Target,
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pi2(MoreBytes, S1, Target,
L, C, Pos, Ps, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pi2("?>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event},
@@ -1180,7 +1180,7 @@ scan_pi2(Str, S0, Target, L, C, Pos, Ps, Acc) ->
scan_doctype([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_doctype(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_doctype(T, S) ->
{_,T1,S1} = mandatory_strip(T,S),
@@ -1194,7 +1194,7 @@ scan_doctype(T, S) ->
scan_doctype1([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_doctype1(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_doctype1("PUBLIC" ++ T, S0) ->
?bump_col(6),
@@ -1217,7 +1217,7 @@ scan_doctype1(T, S) ->
scan_doctype2([], S=#xmerl_scanner{continuation_fun = F},DTD) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_doctype2(MoreBytes, S1, DTD) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_doctype2("[" ++ T, S0, DTD) ->
?bump_col(1),
@@ -1237,7 +1237,7 @@ scan_doctype2(_T,S,_DTD) ->
scan_doctype3([], S=#xmerl_scanner{continuation_fun = F},DTD) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_doctype3(MoreBytes, S1,DTD) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_doctype3("%" ++ T, S0, DTD) ->
?bump_col(1),
@@ -1549,7 +1549,7 @@ scan_decl_sep(T,S) ->
scan_conditional_sect([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_conditional_sect(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_conditional_sect("IGNORE" ++ T, S0) ->
?bump_col(6),
@@ -1582,7 +1582,7 @@ scan_ignore(Str,S) ->
scan_ignore([], S=#xmerl_scanner{continuation_fun = F},Level) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_ignore(MoreBytes, S1,Level) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_ignore("<![" ++ T, S0,Level) ->
%% nested conditional section. Topmost condition is ignore, though
@@ -1603,7 +1603,7 @@ scan_ignore([_H|T],S0,Level) ->
scan_include([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_include(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_include("]]>" ++ T, S0) ->
?bump_col(3),
@@ -1745,7 +1745,7 @@ update_attributes1([],Acc) ->
scan_attdef([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_attdef(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_attdef(T, S) ->
scan_attdef(T, S, _AttrAcc = []).
@@ -1754,7 +1754,7 @@ scan_attdef(T, S) ->
scan_attdef([], S=#xmerl_scanner{continuation_fun = F}, Attrs) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_attdef(MoreBytes, S1, Attrs) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_attdef(">" ++ T, S0, Attrs) ->
?bump_col(1),
@@ -1798,7 +1798,7 @@ scan_attdef2(T, S, Attrs) ->
scan_att_type([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_att_type(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_att_type("CDATA" ++ T, S0) ->
?bump_col(5),
@@ -1856,7 +1856,7 @@ scan_att_type("%" ++ T, S0) ->
scan_notation_type([], S=#xmerl_scanner{continuation_fun = F}, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_notation_type(MoreBytes, S1, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_notation_type(")" ++ T, S0, Acc) ->
?bump_col(1),
@@ -1889,7 +1889,7 @@ notation_exists(Name, #xmerl_scanner{rules_read_fun = Read,
scan_enumeration([], S=#xmerl_scanner{continuation_fun = F}, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_enumeration(MoreBytes, S1, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_enumeration(")" ++ T, S0, Acc) ->
?bump_col(1),
@@ -1907,7 +1907,7 @@ scan_enumeration("|" ++ T, S0, Acc) ->
scan_default_decl([], S=#xmerl_scanner{continuation_fun = F}, Type) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_default_decl(MoreBytes, S1, Type) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_default_decl("#REQUIRED" ++ T, S0, _Type) ->
?bump_col(9),
@@ -1936,7 +1936,7 @@ default_value(T, S, Type) ->
scan_entity([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_entity(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_entity("%" ++ T, #xmerl_scanner{rules_write_fun = Write} = S0) ->
%% parameter entity
@@ -1974,7 +1974,7 @@ scan_entity_completion(T,S) ->
scan_entity_def([], S=#xmerl_scanner{continuation_fun = F}, EName) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_entity_def(MoreBytes, S1, EName) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_entity_def("'" ++ T, S0, EName) ->
?bump_col(1),
@@ -2015,7 +2015,7 @@ scan_entity_def(Str, S, EName) ->
scan_ndata_decl([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_ndata_decl(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_ndata_decl(Str = ">"++_T, S) ->
{[], Str, S};
@@ -2062,7 +2062,7 @@ scan_element("/", S=#xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_element("/" ++ MoreBytes, S1,
Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_element([], S=#xmerl_scanner{continuation_fun = F},
Pos, Name, StartL, StartC, Attrs, Lang, Parents,
@@ -2071,7 +2071,7 @@ scan_element([], S=#xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_element(MoreBytes, S1,
Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_element("/>" ++ T, S0 = #xmerl_scanner{hook_fun = Hook,
event_fun = Event,
@@ -2099,7 +2099,7 @@ scan_element(">", S=#xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_element(">" ++ MoreBytes, S1,
Pos, Name, StartL, StartC, Attrs,
Lang,Parents,NSI,NS,SpaceDefault) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_element(">" ++ T, S0 = #xmerl_scanner{event_fun = Event,
hook_fun = Hook,
@@ -2344,7 +2344,7 @@ keyreplaceadd(_K, _Pos, [], Obj) ->
scan_att_value([], S=#xmerl_scanner{continuation_fun = F},AT) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_att_value(MoreBytes, S1, AT) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_att_value("%"++_T,S=#xmerl_scanner{environment=prolog},_AttType) ->
?fatal({error,{wfc_PEs_In_Internal_Subset}},S);
@@ -2385,7 +2385,7 @@ scan_att_chars([],S=#xmerl_scanner{continuation_fun=F},H,Acc,TmpAcc,AT,IsNorm)->
F(fun(MoreBytes, S1) ->
scan_att_chars(MoreBytes, S1, H, Acc,TmpAcc,AT,IsNorm)
end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_att_chars([H|T], S0, H, Acc, TmpAcc,AttType,IsNorm) -> % End quote
?bump_col(1),
@@ -2518,7 +2518,7 @@ scan_content("<", S= #xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_content("<" ++ MoreBytes, S1,
Pos, Name, Attrs,
Space, Lang, Parents, NS, Acc,[]) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_content([], S=#xmerl_scanner{environment={external,{entity,_}}},
_Pos, _Name, _Attrs, _Space, _Lang, _Parents, _NS, Acc,_) ->
@@ -2532,7 +2532,7 @@ scan_content([], S=#xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_content(MoreBytes, S1,
Pos, Name, Attrs,
Space, Lang, Parents, NS, Acc,[]) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_content("</" ++ T, S0, _Pos, Name, _Attrs, _Space, _Lang,
_Parents, _NS, Acc,[]) ->
@@ -2636,7 +2636,7 @@ scan_content_markup([], S=#xmerl_scanner{continuation_fun = F},
F(fun(MoreBytes, S1) -> scan_content_markup(
MoreBytes,S1,Pos,Name,
Attrs,Space,Lang,Parents,NS) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_content_markup("![CDATA[" ++ T, S0, Pos, _Name, _Attrs,
_Space, _Lang, Parents, _NS) ->
@@ -2664,7 +2664,7 @@ scan_char_data([], S=#xmerl_scanner{environment=internal_parsed_entity},
scan_char_data([], S=#xmerl_scanner{continuation_fun = F}, Space, _MUD,Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_char_data(MoreBytes,S1,Space,_MUD,Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_char_data([$&|T], S,Space,"&",Acc) ->
scan_char_data(T, S, Space,[], [$&|Acc]);
@@ -2716,7 +2716,7 @@ scan_cdata(Str, S, Pos, Parents) ->
scan_cdata([], S=#xmerl_scanner{continuation_fun = F}, Pos, Parents, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_cdata(MoreBytes, S1, Pos, Parents, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_cdata("]]>" ++ T, S0, Pos, Parents, Acc) ->
?bump_col(3),
@@ -2741,7 +2741,7 @@ scan_cdata(Str, S0, Pos, Parents, Acc) ->
scan_reference([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_reference(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_reference("#x" ++ T, S0) ->
%% [66] CharRef
@@ -2783,7 +2783,7 @@ scan_reference(T, S) ->
scan_entity_ref([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_entity_ref(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_entity_ref("amp;" ++ T, S0) ->
?bump_col(4),
@@ -2868,7 +2868,7 @@ expand_reference(Name, #xmerl_scanner{rules_read_fun = Read} = S) ->
scan_char_ref_dec([], S=#xmerl_scanner{continuation_fun = F}, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_char_ref_dec(MoreBytes, S1, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_char_ref_dec([H|T], S0, Acc) when H >= $0, H =< $9 ->
?bump_col(1),
@@ -2883,7 +2883,7 @@ scan_char_ref_dec(";" ++ T, S0, Acc) ->
scan_char_ref_hex([], S=#xmerl_scanner{continuation_fun = F}, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_char_ref_hex(MoreBytes, S1, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_char_ref_hex([H|T], S0, Acc) when H >= $0, H =< $9 ->
?bump_col(1),
@@ -2957,7 +2957,7 @@ scan_name_no_colons(Str, S) ->
scan_name([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_name(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_name(Str = [$:|T], S0 = #xmerl_scanner{namespace_conformant = NSC}) ->
if NSC == false ->
@@ -3007,7 +3007,7 @@ scan_nmtoken(Str, S, Acc, NSC) ->
scan_nmtoken([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_nmtoken(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_nmtoken("%"++T, S0=#xmerl_scanner{environment={external,_}}) ->
?bump_col(1),
@@ -3084,7 +3084,7 @@ isLatin1(_,_) ->
scan_system_literal([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_system_literal(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_system_literal("\"" ++ T, S) ->
scan_system_literal(T, S, $", []);
@@ -3096,7 +3096,7 @@ scan_system_literal([], S=#xmerl_scanner{continuation_fun = F},
Delimiter, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_system_literal(MoreBytes,S1,Delimiter,Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_system_literal([H|T], S, H, Acc) ->
{lists:reverse(Acc), T, S#xmerl_scanner{col = S#xmerl_scanner.col+1}};
@@ -3114,7 +3114,7 @@ scan_system_literal(Str, S, Delimiter, Acc) ->
scan_pubid_literal([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pubid_literal(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pubid_literal([H|T], S) when H == $"; H == $' ->
scan_pubid_literal(T, S#xmerl_scanner{col = S#xmerl_scanner.col+1}, H, []);
@@ -3126,7 +3126,7 @@ scan_pubid_literal([], S=#xmerl_scanner{continuation_fun = F},
Delimiter, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pubid_literal(MoreBytes,S1,Delimiter,Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pubid_literal([H|T], S, H, Acc) ->
{lists:reverse(Acc), T, S#xmerl_scanner{col = S#xmerl_scanner.col+1}};
@@ -3161,7 +3161,7 @@ is_pubid_char(X) ->
scan_contentspec([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_contentspec(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_contentspec("EMPTY" ++ T, S0) ->
?bump_col(5),
@@ -3195,7 +3195,7 @@ scan_elem_content([], S=#xmerl_scanner{continuation_fun = F},
Context, Mode, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes,S1) -> scan_elem_content(MoreBytes,S1,Context,Mode,Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_elem_content(")" ++ T, S0, Context, Mode0, Acc0) ->
?bump_col(1),
@@ -3282,7 +3282,7 @@ format_elem_content(Other) -> Other.
scan_occurrence([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_occurrence(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_occurrence([$?|T], S0) ->
?bump_col(1),
@@ -3433,7 +3433,7 @@ wfc_whitespace_betw_attrs([$> |_]=L,S) ->
wfc_whitespace_betw_attrs([],S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> wfc_whitespace_betw_attrs(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
wfc_whitespace_betw_attrs(_,S) ->
?fatal({whitespace_required_between_attributes},S).
@@ -3477,7 +3477,7 @@ vc_Element_valid(_,_) ->
scan_pe_def([], S=#xmerl_scanner{continuation_fun = F}, PEName) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_pe_def(MoreBytes, S1, PEName) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_pe_def("'" ++ T, S0, PEName) ->
?bump_col(1),
@@ -3510,7 +3510,7 @@ scan_notation_decl(T, #xmerl_scanner{rules_write_fun = Write,
scan_notation_decl1([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_notation_decl1(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_notation_decl1("SYSTEM" ++ T, S0) ->
?bump_col(6),
@@ -3536,7 +3536,7 @@ scan_notation_decl1("PUBLIC" ++ T, S0) ->
scan_external_id([], S=#xmerl_scanner{continuation_fun = F}) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_external_id(MoreBytes, S1) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_external_id("SYSTEM" ++ T, S0) ->
?bump_col(6),
@@ -3582,7 +3582,7 @@ scan_entity_value([], S=#xmerl_scanner{continuation_fun = F},
scan_entity_value(MoreBytes,S1,
Delim,Acc,PEName,Namespace,PENesting)
end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_entity_value([Delim|T], S=#xmerl_scanner{validation=dtd},
Delim,_Acc,PEName,_NS,PENesting) when length(PENesting) /= 0 ->
@@ -3850,7 +3850,7 @@ scan_comment1([], S=#xmerl_scanner{continuation_fun = F},
Pos, Comment, Acc) ->
?dbg("cont()...~n", []),
F(fun(MoreBytes, S1) -> scan_comment1(MoreBytes, S1, Pos, Comment, Acc) end,
- fun(S1) -> ?fatal(unexpected_end, S1) end,
+ fatal_fun(unexpected_end),
S);
scan_comment1("-->" ++ T, S0 = #xmerl_scanner{col = C,
event_fun = Event,
@@ -4100,6 +4100,13 @@ handle_schema_result({error,Reason},S5) ->
%%% Helper functions
+-compile({inline, [fatal_fun/1]}).
+
+-spec fatal_fun(_) -> fun((_) -> no_return()).
+
+fatal_fun(Reason) ->
+ fun(S) -> ?fatal(Reason, S) end.
+
fatal(Reason, S) ->
exit({fatal, {Reason,
{file,S#xmerl_scanner.filename},