diff options
Diffstat (limited to 'lib/dialyzer/src')
-rw-r--r-- | lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 11 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_contracts.erl | 7 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_dataflow.erl | 18 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_utils.erl | 43 |
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]) -> |