aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/src')
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl11
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl7
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl18
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl43
4 files changed, 69 insertions, 10 deletions
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index 6a33a2acb3..af1c2b7e3a 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -373,7 +373,16 @@ compile_byte(File, Callgraph, CServer, UseContracts) ->
{error, " Could not get abstract code for: " ++ File ++ "\n" ++
" Recompile with +debug_info or analyze starting from source code"};
{ok, AbstrCode} ->
- compile_common(File, AbstrCode, [], Callgraph, CServer, UseContracts)
+ compile_byte(File, AbstrCode, Callgraph, CServer, UseContracts)
+ end.
+
+compile_byte(File, AbstrCode, Callgraph, CServer, UseContracts) ->
+ case dialyzer_utils:get_compile_options_from_beam(File) of
+ error ->
+ {error, " Could not get compile options for: " ++ File ++ "\n" ++
+ " Recompile or analyze starting from source code"};
+ {ok, CompOpts} ->
+ compile_common(File, AbstrCode, CompOpts, Callgraph, CServer, UseContracts)
end.
compile_common(File, AbstrCode, CompOpts, Callgraph, CServer, UseContracts) ->
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 1d2dfc7b2d..f27fc1a842 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -20,8 +20,6 @@
-module(dialyzer_contracts).
--compile(export_all).
-
-export([check_contract/2,
check_contracts/4,
contracts_without_fun/3,
@@ -686,7 +684,7 @@ picky_contract_check(CSig0, Sig0, MFA, FileLine, Contract, RecDict, Acc) ->
true -> Acc;
false ->
case extra_contract_warning(MFA, FileLine, Contract,
- CSig, Sig, RecDict) of
+ CSig0, Sig0, RecDict) of
no_warning -> Acc;
{warning, Warning} -> [Warning|Acc]
end
@@ -752,7 +750,8 @@ is_remote_types_related(Contract, CSig, Sig, RecDict) ->
t_from_forms_without_remote([{FType, []}], RecDict) ->
Type0 = erl_types:t_from_form(FType, RecDict),
- {ok, erl_types:subst_all_remote(Type0, erl_types:t_none())};
+ Type1 = erl_types:subst_all_remote(Type0, erl_types:t_none()),
+ {ok, erl_types:subst_all_vars_to_any(Type1)};
t_from_forms_without_remote([{_FType, _Constrs}], _RecDict) ->
%% 'When' constraints
unsupported;
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 92aab68ad6..03005e689f 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -93,6 +93,8 @@
-define(TYPE_LIMIT, 3).
+-define(BITS, 128).
+
-record(state, {callgraph :: dialyzer_callgraph:callgraph(),
envs :: env_tab(),
fun_tab :: fun_tab(),
@@ -1610,10 +1612,18 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
SizeVal = lists:max(List),
Flags = cerl:concrete(cerl:bitstr_flags(Seg)),
N = SizeVal * UnitVal,
- case lists:member(signed, Flags) of
- true -> t_from_range(-(1 bsl (N - 1)), 1 bsl (N - 1) - 1);
- false -> t_from_range(0, 1 bsl N - 1)
- end
+ case N >= ?BITS of
+ true ->
+ case lists:member(signed, Flags) of
+ true -> t_from_range(neg_inf, pos_inf);
+ false -> t_from_range(0, pos_inf)
+ end;
+ false ->
+ case lists:member(signed, Flags) of
+ true -> t_from_range(-(1 bsl (N - 1)), 1 bsl (N - 1) - 1);
+ false -> t_from_range(0, 1 bsl N - 1)
+ end
+ end
end
end,
{Map2, [_]} = bind_pat_vars([Val], [ValConstr], [], Map1, State, false),
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index e1bcd72c0b..4e2ec67b35 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -31,6 +31,7 @@
format_sig/1,
format_sig/2,
get_abstract_code_from_beam/1,
+ get_compile_options_from_beam/1,
get_abstract_code_from_src/1,
get_abstract_code_from_src/2,
get_core_from_abstract_code/1,
@@ -136,6 +137,26 @@ get_abstract_code_from_beam(File) ->
error
end.
+-spec get_compile_options_from_beam(file:filename()) -> 'error' | {'ok', [compile:option()]}.
+
+get_compile_options_from_beam(File) ->
+ case beam_lib:chunks(File, [compile_info]) of
+ {ok, {_, List}} ->
+ case lists:keyfind(compile_info, 1, List) of
+ {compile_info, CompInfo} -> compile_info_to_options(CompInfo);
+ _ -> error
+ end;
+ _ ->
+ %% No or unsuitable compile info.
+ error
+ end.
+
+compile_info_to_options(CompInfo) ->
+ case lists:keyfind(options, 1, CompInfo) of
+ {options, CompOpts} -> {ok, CompOpts};
+ _ -> error
+ end.
+
-type get_core_from_abs_ret() :: {'ok', cerl:c_module()} | 'error'.
-spec get_core_from_abstract_code(abstract_code()) -> get_core_from_abs_ret().
@@ -150,7 +171,9 @@ get_core_from_abstract_code(AbstrCode, Opts) ->
%% performed them. In some cases we end up in trouble when
%% performing them again.
AbstrCode1 = cleanup_parse_transforms(AbstrCode),
- try compile:forms(AbstrCode1, Opts ++ src_compiler_opts()) of
+ %% Remove parse_transforms (and other options) from compile options.
+ Opts2 = cleanup_compile_options(Opts),
+ try compile:forms(AbstrCode1, Opts2 ++ src_compiler_opts()) of
{ok, _, Core} -> {ok, Core};
_What -> error
catch
@@ -419,6 +442,24 @@ cleanup_parse_transforms([Other|Left]) ->
cleanup_parse_transforms([]) ->
[].
+-spec cleanup_compile_options([compile:option()]) -> [compile:option()].
+
+%% Using abstract, not asm or core.
+cleanup_compile_options([from_asm|Opts]) ->
+ Opts;
+cleanup_compile_options([asm|Opts]) ->
+ Opts;
+cleanup_compile_options([from_core|Opts]) ->
+ Opts;
+%% The parse transform will already have been applied, may cause problems if it
+%% is re-applied.
+cleanup_compile_options([{parse_transform, _}|Opts]) ->
+ Opts;
+cleanup_compile_options([Other|Opts]) ->
+ [Other|cleanup_compile_options(Opts)];
+cleanup_compile_options([]) ->
+ [].
+
-spec format_errors([{module(), string()}]) -> [string()].
format_errors([{Mod, Errors}|Left]) ->