diff options
Diffstat (limited to 'lib/dialyzer/src')
-rw-r--r-- | lib/dialyzer/src/Makefile | 12 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer.erl | 11 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 15 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_behaviours.erl | 37 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_callgraph.erl | 7 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_cl.erl | 27 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_codeserver.erl | 9 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_contracts.erl | 34 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_dataflow.erl | 2 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_gui.erl | 5 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_gui_wx.erl | 5 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_typesig.erl | 75 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_utils.erl | 11 |
13 files changed, 137 insertions, 113 deletions
diff --git a/lib/dialyzer/src/Makefile b/lib/dialyzer/src/Makefile index 63cc1c98f1..bb2edd419a 100644 --- a/lib/dialyzer/src/Makefile +++ b/lib/dialyzer/src/Makefile @@ -108,22 +108,22 @@ clean: # ---------------------------------------------------- $(EBIN)/dialyzer_cl_parse.$(EMULATOR): dialyzer_cl_parse.erl ../vsn.mk - erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_cl_parse.erl + $(erlc_verbose)erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_cl_parse.erl $(EBIN)/dialyzer_plt.$(EMULATOR): dialyzer_plt.erl ../vsn.mk - erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_plt.erl + $(erlc_verbose)erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_plt.erl $(EBIN)/dialyzer_gui.$(EMULATOR): dialyzer_gui.erl ../vsn.mk - erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_gui.erl + $(erlc_verbose)erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_gui.erl $(EBIN)/dialyzer_gui_wx.$(EMULATOR): dialyzer_gui_wx.erl ../vsn.mk - erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_gui_wx.erl + $(erlc_verbose)erlc -W $(ERL_COMPILE_FLAGS) -DVSN="\"v$(VSN)\"" -o$(EBIN) dialyzer_gui_wx.erl $(APP_TARGET): $(APP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ # --------------------------------------------------------------------- # dependencies -- I wish they were somehow automatically generated diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index a785ea5502..822aa0826a 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -383,8 +383,6 @@ message_to_string({pattern_match_cov, [Pat, Type]}) -> message_to_string({unmatched_return, [Type]}) -> io_lib:format("Expression produces a value of type ~s," " but this value is unmatched\n", [Type]); -message_to_string({unused_fun, []}) -> - io_lib:format("Function will never be called\n", []); message_to_string({unused_fun, [F, A]}) -> io_lib:format("Function ~w/~w will never be called\n", [F, A]); %%----- Warnings for specs and contracts ------------------- @@ -411,9 +409,10 @@ message_to_string({extra_range, [M, F, A, ExtraRanges, SigRange]}) -> io_lib:format("The specification for ~w:~w/~w states that the function" " might also return ~s but the inferred return is ~s\n", [M, F, A, ExtraRanges, SigRange]); -message_to_string({overlapping_contract, []}) -> - "Overloaded contract has overlapping domains;" - " such contracts are currently unsupported and are simply ignored\n"; +message_to_string({overlapping_contract, [M, F, A]}) -> + io_lib:format("Overloaded contract for ~w:~w/~w has overlapping domains;" + " such contracts are currently unsupported and are simply ignored\n", + [M, F, A]); message_to_string({spec_missing_fun, [M, F, A]}) -> io_lib:format("Contract for function that does not exist: ~w:~w/~w\n", [M, F, A]); diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 86618a4915..0fbaf1d47c 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -2,7 +2,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -255,14 +255,17 @@ compile_and_store(Files, #analysis_state{codeserver = CServer, CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer), case Failed =:= [] of true -> - NewFiles = lists:zip(lists:reverse(Modules), Files), ModDict = - lists:foldl(fun({Mod, F}, Dict) -> dict:append(Mod, F, Dict) end, - dict:new(), NewFiles), + lists:foldl(fun(F, Dict) -> + ModFile = lists:last(filename:split(F)), + Mod = filename:basename(ModFile, ".beam"), + dict:append(Mod, F, Dict) + end, + dict:new(), Files), check_for_duplicate_modules(ModDict); false -> - Msg = io_lib:format("Could not scan the following file(s): ~p", - [lists:flatten(Failed)]), + Msg = io_lib:format("Could not scan the following file(s):~n~s", + [[Reason || {_Filename, Reason} <- Failed]]), exit({error, Msg}) end, {T2, _} = statistics(runtime), diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl index 36aef2a37f..2b9a69ce77 100644 --- a/lib/dialyzer/src/dialyzer_behaviours.erl +++ b/lib/dialyzer/src/dialyzer_behaviours.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2012. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,8 +25,6 @@ %%% %%% Created : 28 Oct 2009 by Stavros Aronis <[email protected]> %%%------------------------------------------------------------------- -%%% NOTE: This module is currently experimental -- do NOT rely on it! -%%%------------------------------------------------------------------- -module(dialyzer_behaviours). @@ -127,15 +125,12 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest], erl_types:t_to_string(CbReturnType, Records)]}|Acc00] end end, - Acc02 = - case erl_types:any_none( - erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of - false -> Acc01; - true -> - find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour, - Function, Arity, Records, 1, Acc01) - end, - Acc02 + case erl_types:any_none(erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of + false -> Acc01; + true -> + find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour, + Function, Arity, Records, 1, Acc01) + end end, Acc2 = case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of @@ -157,16 +152,14 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest], erl_types:t_to_string(ExtraType, Records), erl_types:t_to_string(CbReturnType, Records)]}|Acc10] end, - Acc12 = - case erl_types:any_none( - erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of - false -> Acc11; - true -> - find_mismatching_args({spec, File, Line}, SpecArgTypes, - CbArgTypes, Behaviour, Function, - Arity, Records, 1, Acc11) - end, - Acc12 + case erl_types:any_none( + erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of + false -> Acc11; + true -> + find_mismatching_args({spec, File, Line}, SpecArgTypes, + CbArgTypes, Behaviour, Function, + Arity, Records, 1, Acc11) + end end, NewAcc = Acc2, check_all_callbacks(Module, Behaviour, Rest, State, NewAcc). diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index 64e0ee88af..b9ad3f857d 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -798,10 +798,7 @@ condensation(G) -> fun({V1, V2}) -> I1 = ets:lookup_element(V2I, V1, 2), I2 = ets:lookup_element(V2I, V2, 2), - case I1 =:= I2 of - true -> true; - false -> ets:insert(I2I, {I1, I2}) - end + I1 =:= I2 orelse ets:insert(I2I, {I1, I2}) end, lists:foreach(Fun1, digraph:edges(G)), Fun3 = diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 6732d96b98..365c0b36d4 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -488,6 +488,7 @@ expand_dependent_modules_1([Mod|Mods], Included, ModDeps) -> expand_dependent_modules_1([], Included, _ModDeps) -> Included. +-define(MIN_PARALLELISM, 7). -define(MIN_FILES_FOR_NATIVE_COMPILE, 20). -spec hipe_compile([file:filename()], #options{}) -> 'ok'. @@ -501,11 +502,14 @@ hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) -> case erlang:system_info(hipe_architecture) of undefined -> ok; _ -> - Mods = [lists, dict, gb_sets, gb_trees, ordsets, sets, + Mods = [lists, dict, digraph, digraph_utils, ets, + gb_sets, gb_trees, ordsets, sets, sofs, cerl, cerl_trees, erl_types, erl_bif_types, - dialyzer_analysis_callgraph, dialyzer_codeserver, - dialyzer_dataflow, dialyzer_dep, dialyzer_plt, - dialyzer_succ_typings, dialyzer_typesig], + dialyzer_analysis_callgraph, dialyzer, dialyzer_behaviours, + dialyzer_codeserver, dialyzer_contracts, + dialyzer_coordinator, dialyzer_dataflow, dialyzer_dep, + dialyzer_plt, dialyzer_succ_typings, dialyzer_typesig, + dialyzer_worker], report_native_comp(Options), {T1, _} = statistics(wall_clock), native_compile(Mods), @@ -515,12 +519,12 @@ hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) -> end. native_compile(Mods) -> - case erlang:system_info(schedulers) of - %% N when N > 1 -> - %% Parent = self(), - %% Pids = [spawn(fun () -> Parent ! {self(), hc(M)} end) || M <- Mods], - %% lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids); - _ -> % 1 -> + case dialyzer_utils:parallelism() > ?MIN_PARALLELISM of + true -> + Parent = self(), + Pids = [spawn(fun () -> Parent ! {self(), hc(M)} end) || M <- Mods], + lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids); + false -> lists:foreach(fun (Mod) -> hc(Mod) end, Mods) end. @@ -529,6 +533,7 @@ hc(Mod) -> case code:is_module_native(Mod) of true -> ok; false -> + %% io:format(" ~s", [Mod]), {ok, Mod} = hipe:c(Mod), ok end. diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index 9989118671..216e06219c 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -100,10 +100,7 @@ ets_dict_to_dict(Table) -> ets:foldl(Fold, dict:new(), Table). ets_set_is_element(Key, Table) -> - case ets:lookup(Table, Key) of - [] -> false; - _ -> true - end. + ets:lookup(Table, Key) =/= []. ets_set_insert_set(Set, Table) -> ets_set_insert_list(sets:to_list(Set), Table). @@ -116,7 +113,7 @@ ets_set_to_set(Table) -> ets:foldl(Fold, sets:new(), Table). ets_read_concurrent_table(Name) -> - ets:new(Name,[{read_concurrency, true}]). + ets:new(Name, [{read_concurrency, true}]). %%-------------------------------------------------------------------- diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 0b932d5a1f..332a326b0d 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -254,14 +254,35 @@ check_extraneous([C|Cs], SuccType) -> end. check_extraneous_1(Contract, SuccType) -> - CRngs = erl_types:t_elements(erl_types:t_fun_range(Contract)), + CRng = erl_types:t_fun_range(Contract), + CRngs = erl_types:t_elements(CRng), STRng = erl_types:t_fun_range(SuccType), ?debug("CR = ~p\nSR = ~p\n", [CRngs, STRng]), - case [CR || CR <- CRngs, erl_types:t_is_none(erl_types:t_inf(CR, STRng, opaque))] of - [] -> ok; + case [CR || CR <- CRngs, + erl_types:t_is_none(erl_types:t_inf(CR, STRng, opaque))] of + [] -> + CRngList = list_part(CRng), + STRngList = list_part(STRng), + case is_not_nil_list(CRngList) andalso is_not_nil_list(STRngList) of + false -> ok; + true -> + CRngElements = erl_types:t_list_elements(CRngList), + STRngElements = erl_types:t_list_elements(STRngList), + Inf = erl_types:t_inf(CRngElements, STRngElements, opaque), + case erl_types:t_is_none(Inf) of + true -> {error, invalid_contract}; + false -> ok + end + end; CRs -> {error, {extra_range, erl_types:t_sup(CRs), STRng}} end. +list_part(Type) -> + erl_types:t_inf(erl_types:t_list(), Type, opaque). + +is_not_nil_list(Type) -> + erl_types:t_is_list(Type) andalso not erl_types:t_is_nil(Type). + %% This is the heart of the "range function" -spec process_contracts([contract_pair()], [erl_types:erl_type()]) -> erl_types:erl_type(). @@ -499,6 +520,8 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract}}|Left], case check_contract(Contract, Sig) of {error, invalid_contract} -> [invalid_contract_warning(MFA, FileLine, Sig, RecDict)|Acc]; + {error, {overlapping_contract, []}} -> + [overlapping_contract_warning(MFA, FileLine)|Acc]; {error, {extra_range, ExtraRanges, STRange}} -> Warn = case t_from_forms_without_remote(Contract#contract.forms, @@ -550,6 +573,9 @@ invalid_contract_warning({M, F, A}, FileLine, SuccType, RecDict) -> SuccTypeStr = dialyzer_utils:format_sig(SuccType, RecDict), {?WARN_CONTRACT_TYPES, FileLine, {invalid_contract, [M, F, A, SuccTypeStr]}}. +overlapping_contract_warning({M, F, A}, FileLine) -> + {?WARN_CONTRACT_TYPES, FileLine, {overlapping_contract, [M, F, A]}}. + extra_range_warning({M, F, A}, FileLine, ExtraRanges, STRange) -> ERangesStr = erl_types:t_to_string(ExtraRanges), STRangeStr = erl_types:t_to_string(STRange), diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index 0ef008bc58..6956850f1a 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -2769,7 +2769,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab, true -> {Warn, Msg} = case dialyzer_callgraph:lookup_name(FunLbl, Callgraph) of - error -> {true, {unused_fun, []}}; + error -> {false, {}}; {ok, {_M, F, A} = MFA} -> {not sets:is_element(MFA, NoWarnUnused), {unused_fun, [F, A]}} diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl index ac9844c22c..97e5752577 100644 --- a/lib/dialyzer/src/dialyzer_gui.erl +++ b/lib/dialyzer/src/dialyzer_gui.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------------ %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1331,7 +1331,8 @@ build_analysis_record(#gui_state{mode = Mode, menu = Menu, options = Options, #analysis{defines = Options#options.defines, include_dirs = Options#options.include_dirs, plt = InitPlt, - start_from = StartFrom}. + start_from = StartFrom, + solvers = Options#options.solvers}. get_anal_files(#gui_state{chosen_box = ChosenBox}, StartFrom) -> Files = gs:read(ChosenBox, items), diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index c6f7c56227..08f31c1e13 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -2,7 +2,7 @@ %%------------------------------------------------------------------------ %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -810,7 +810,8 @@ build_analysis_record(#gui_state{mode = Mode, menu = Menu, options = Options, #analysis{defines = Options#options.defines, include_dirs = Options#options.include_dirs, plt = InitPlt, - start_from = StartFrom}. + start_from = StartFrom, + solvers = Options#options.solvers}. get_anal_files(#gui_state{files_to_analyze = Files}, StartFrom) -> FilteredMods = diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 0df003a035..a418a11e65 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -246,18 +246,27 @@ traverse(Tree, DefinedVars, State) -> Val = cerl:bitstr_val(Tree), {State1, [SizeType, ValType]} = traverse_list([Size, Val], DefinedVars, State), - {State2, TypeConstr} = + {State2, TypeConstr, BinValTypeConstr} = case cerl:bitstr_bitsize(Tree) of - all -> {State1, t_bitstr(UnitVal, 0)}; - utf -> {State1, t_binary()}; % contains an integer number of bytes - N when is_integer(N) -> {State1, t_bitstr(0, N)}; + all -> + T = t_bitstr(UnitVal, 0), + {State1, T, T}; + utf -> + %% contains an integer number of bytes + T = t_binary(), + {State1, T, T}; + N when is_integer(N) -> + {State1, t_bitstr(0, N), t_bitstr(1, N)}; any -> % Size is not a literal + T1 = ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType]), + T2 = + ?mk_fun_var(bitstr_constr(SizeType, UnitVal, match), [SizeType]), {state__store_conj(SizeType, sub, t_non_neg_integer(), State1), - ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])} + T1, T2} end, ValTypeConstr = case cerl:concrete(cerl:bitstr_type(Tree)) of - binary -> TypeConstr; + binary -> BinValTypeConstr; float -> case state__is_in_match(State1) of true -> t_float(); @@ -947,12 +956,20 @@ get_type_test({erlang, is_tuple, 1}) -> {ok, t_tuple()}; get_type_test({M, F, A}) when is_atom(M), is_atom(F), is_integer(A) -> error. bitstr_constr(SizeType, UnitVal) -> + bitstr_constr(SizeType, UnitVal, construct). + +bitstr_constr(SizeType, UnitVal, ConstructOrMatch) -> + Unit = + case ConstructOrMatch of + construct -> 0; + match -> 1 + end, fun(Map) -> TmpSizeType = lookup_type(SizeType, Map), case t_is_subtype(TmpSizeType, t_non_neg_integer()) of true -> case t_number_vals(TmpSizeType) of - [OneSize] -> t_bitstr(0, OneSize * UnitVal); + [OneSize] -> t_bitstr(Unit, OneSize * UnitVal); _ -> MinSize = erl_types:number_min(TmpSizeType), t_bitstr(UnitVal, MinSize * UnitVal) @@ -1543,12 +1560,11 @@ get_bif_constr({erlang, '==', 2}, Dst, [Arg1, Arg2] = Args, _State) -> mk_constraint(Arg1, sub, ArgV1), mk_constraint(Arg2, sub, ArgV2)]); get_bif_constr({erlang, element, 2} = _BIF, Dst, Args, - #state{cs = Constrs} = State) -> + #state{cs = Constrs, opaques = Opaques}) -> GenType = erl_bif_types:type(erlang, element, 2), case t_is_none(GenType) of true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error); false -> - Opaques = State#state.opaques, Fun = fun(Map) -> [I, T] = ATs = lookup_type_list(Args, Map), ATs2 = case lists:member(T, Opaques) of @@ -1771,8 +1787,9 @@ minimize_state(#state{ opaques = Opaques, solvers = Solvers }) -> - ETSCMap = ets:new(cmap,[{read_concurrency, true}]), - ETSPropTypes = ets:new(prop_types,[{read_concurrency, true}]), + Opts = [{read_concurrency, true}], + ETSCMap = ets:new(cmap, Opts), + ETSPropTypes = ets:new(prop_types, Opts), true = ets:insert(ETSCMap, dict:to_list(CMap)), true = ets:insert(ETSPropTypes, dict:to_list(PropTypes)), #state @@ -2112,11 +2129,11 @@ restore_local_map(#v2_state{constr_data = ConData}, Id, Map0) -> {ok, failed} -> Map0; {ok, {[],_}} -> Map0; {ok, {Part0,U}} -> - Part = [{K,V} || {K,V} <- Part0, not lists:member(K, U)], + Part = [KV || {K,_V} = KV <- Part0, not lists:member(K, U)], ?debug("restore local map Id=~w U=~w\n", [Id, U]), pp_map("Part", dict:from_list(Part)), pp_map("Map0", Map0), - Map = lists:foldl(fun({K,V}, D) -> dict:store(K, V, D)end, Map0, Part), + Map = lists:foldl(fun({K,V}, D) -> dict:store(K, V, D) end, Map0, Part), pp_map("Map", Map), Map end. @@ -2582,19 +2599,8 @@ enter_type(Key, Val, Map) when is_integer(Key) -> end end; enter_type(Key, Val, Map) -> - ?debug("Entering ~s :: ~s\n", [format_type(Key), format_type(Val)]), KeyName = t_var_name(Key), - case t_is_any(Val) of - true -> - erase_type(KeyName, Map); - false -> - LimitedVal = t_limit(Val, ?INTERNAL_TYPE_LIMIT), - case dict:find(KeyName, Map) of - {ok, LimitedVal} -> Map; - {ok, _} -> map_store(KeyName, LimitedVal, Map); - error -> map_store(KeyName, LimitedVal, Map) - end - end. + enter_type(KeyName, Val, Map). enter_type_lists([Key|KeyTail], [Val|ValTail], Map) -> Map1 = enter_type(Key, Val, Map), @@ -3386,16 +3392,6 @@ pp_constraints([#constraint{}=C], Level, MaxDepth, _State) -> pp_constraints([#constraint{}=C|Tail], Level, MaxDepth, State) -> pp_op(C, Level), pp_constraints(Tail, Level, MaxDepth, State); -pp_constraints([#constraint_list{type = Type, list = List, id = Id}], - Level, MaxDepth, State) -> - pp_indent(Level), - case Type of - conj -> io:format("Conj ~w (", [Id]); - disj -> io:format("Disj ~w (", [Id]) - end, - NewMaxDepth = pp_constraints(List, Level + 1, MaxDepth, State), - io:format(")", []), - NewMaxDepth; pp_constraints([#constraint_list{type = Type, list = List, id = Id}|Tail], Level, MaxDepth, State) -> pp_indent(Level), @@ -3404,8 +3400,11 @@ pp_constraints([#constraint_list{type = Type, list = List, id = Id}|Tail], disj -> io:format("Disj ~w (", [Id]) end, NewMaxDepth = pp_constraints(List, Level+1, MaxDepth, State), - io:format(")", []), - pp_constraints(Tail, Level, NewMaxDepth, State). + io:format(")"), + case Tail =:= [] of + true -> NewMaxDepth + 1; + false -> pp_constraints(Tail, Level, NewMaxDepth, State) + end. pp_op(#constraint{lhs = Lhs, op = Op, rhs = Rhs}, Level) -> pp_indent(Level), diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 8046b48838..a4c4d37a0f 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -219,15 +219,18 @@ get_record_and_type_info([], _Module, Records, RecDict) -> end. add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, RecDict) -> - case erl_types:type_is_defined(TypeOrOpaque, Name, RecDict) of + Arity = length(ArgForms), + case erl_types:type_is_defined(TypeOrOpaque, Name, Arity, RecDict) of true -> - throw({error, flat_format("Type ~s already defined\n", [Name])}); + Msg = flat_format("Type ~s/~w already defined\n", [Name, Arity]), + throw({error, Msg}); false -> ArgTypes = [erl_types:t_from_form(X) || X <- ArgForms], case lists:all(fun erl_types:t_is_var/1, ArgTypes) of true -> ArgNames = [erl_types:t_var_name(X) || X <- ArgTypes], - dict:store({TypeOrOpaque, Name}, {Module, TypeForm, ArgNames}, RecDict); + dict:store({TypeOrOpaque, Name, Arity}, + {Module, TypeForm, ArgNames}, RecDict); false -> throw({error, flat_format("Type declaration for ~w does not " "have variables as parameters", [Name])}) |