From d775f62fd8f9f02679e0c5dd0ad3428dc22f7b93 Mon Sep 17 00:00:00 2001 From: Maria Christakis Date: Mon, 22 Mar 2010 14:43:43 +0200 Subject: Add handling of unknown types --- lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 21 +++++++++++++ lib/dialyzer/src/dialyzer_cl.erl | 39 ++++++++++++++++++++++-- lib/hipe/cerl/erl_types.erl | 8 ++--- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index cf5829a342..e3dd690470 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -96,6 +96,9 @@ loop(#server_state{parent = Parent, legal_warnings = LegalWarnings} = State, end; {AnalPid, ext_calls, NewExtCalls} -> loop(State, Analysis, NewExtCalls); + {AnalPid, ext_types, ExtTypes} -> + send_ext_types(Parent, ExtTypes), + loop(State, Analysis, ExtCalls); {AnalPid, unknown_behaviours, UnknownBehaviour} -> send_unknown_behaviours(Parent, UnknownBehaviour), loop(State, Analysis, ExtCalls); @@ -168,6 +171,7 @@ analysis_start(Parent, Analysis) -> false -> Callgraph end, State3 = analyze_callgraph(NewCallgraph, State2#analysis_state{plt = Plt1}), + rcv_and_send_ext_types(Parent), NonExports = sets:subtract(sets:from_list(AllNodes), Exports), NonExportsList = sets:to_list(NonExports), Plt3 = dialyzer_plt:delete_list(State3#analysis_state.plt, NonExportsList), @@ -481,6 +485,19 @@ default_includes(Dir) -> %% Handle Messages %%------------------------------------------------------------------- +rcv_and_send_ext_types(Parent) -> + Self = self(), + Self ! {Self, done}, + ExtTypes = rcv_ext_types(Self, []), + Parent ! {Self, ext_types, ExtTypes}. + +rcv_ext_types(Self, ExtTypes) -> + receive + {Self, ext_types, ExtType} -> + rcv_ext_types(Self, [ExtType|ExtTypes]); + {Self, done} -> lists:usort(ExtTypes) + end. + send_log(Parent, Msg) -> Parent ! {self(), log, Msg}, ok. @@ -503,6 +520,10 @@ send_ext_calls(Parent, ExtCalls) -> Parent ! {self(), ext_calls, ExtCalls}, ok. +send_ext_types(Parent, ExtTypes) -> + Parent ! {self(), ext_types, ExtTypes}, + ok. + send_unknown_behaviours(Parent, UnknownBehaviours) -> Parent ! {self(), unknown_behaviours, UnknownBehaviours}, ok. diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index d533e734db..703eef67ab 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -38,6 +38,7 @@ {backend_pid :: pid(), erlang_mode = false :: boolean(), external_calls = [] :: [mfa()], + external_types = [] :: [mfa()], legal_warnings = ordsets:new() :: [dial_warn_tag()], mod_deps = dict:new() :: dict(), output = standard_io :: io:device(), @@ -538,6 +539,8 @@ cl_loop(State, LogCache) -> return_value(State, NewPlt); {BackendPid, ext_calls, ExtCalls} -> cl_loop(State#cl_state{external_calls = ExtCalls}, LogCache); + {BackendPid, ext_types, ExtTypes} -> + cl_loop(State#cl_state{external_types = ExtTypes}, LogCache); {BackendPid, mod_deps, ModDeps} -> NewState = State#cl_state{mod_deps = ModDeps}, cl_loop(NewState, LogCache); @@ -613,6 +616,7 @@ return_value(State = #cl_state{erlang_mode = ErlangMode, false -> print_warnings(State), print_ext_calls(State), + print_ext_types(State), print_unknown_behaviours(State), maybe_close_output_file(State), {RetValue, []}; @@ -649,10 +653,41 @@ do_print_ext_calls(Output, [{M,F,A}|T], Before) -> do_print_ext_calls(_, [], _) -> ok. +print_ext_types(#cl_state{report_mode = quiet}) -> + ok; +print_ext_types(#cl_state{output = Output, + external_calls = Calls, + external_types = Types, + stored_warnings = Warnings, + output_format = Format}) -> + case Types =:= [] of + true -> ok; + false -> + case Warnings =:= [] andalso Calls =:= [] of + true -> io:nl(Output); %% Need to do a newline first + false -> ok + end, + case Format of + formatted -> + io:put_chars(Output, "Unknown types:\n"), + do_print_ext_types(Output, Types, " "); + raw -> + io:put_chars(Output, "%% Unknown functions:\n"), + do_print_ext_types(Output, Types, "%% ") + end + end. + +do_print_ext_types(Output, [{M,F,A}|T], Before) -> + io:format(Output, "~s~p:~p/~p\n", [Before,M,F,A]), + do_print_ext_types(Output, T, Before); +do_print_ext_types(_, [], _) -> + ok. + %%print_unknown_behaviours(#cl_state{report_mode = quiet}) -> %% ok; print_unknown_behaviours(#cl_state{output = Output, - external_calls = Calls, + external_calls = Calls, + external_types = Types, stored_warnings = Warnings, unknown_behaviours = DupBehaviours, legal_warnings = LegalWarnings, @@ -662,7 +697,7 @@ print_unknown_behaviours(#cl_state{output = Output, false -> ok; true -> Behaviours = lists:usort(DupBehaviours), - case Warnings =:= [] andalso Calls =:= [] of + case Warnings =:= [] andalso Calls =:= [] andalso Types =:= [] of true -> io:nl(Output); %% Need to do a newline first false -> ok end, diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 8094cc505a..40697ea8ed 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -699,14 +699,12 @@ t_solve_remote(T, _ET, _R, _C) -> {T, []}. t_solve_remote_type(#remote{mod = RemMod, name = Name, args = Args} = RemType, ET, R, C) -> + ArgsLen = length(Args), case dict:find(RemMod, R) of error -> - Msg = io_lib:format("Cannot locate module ~w to " - "resolve the remote type: ~w:~w()~n", - [RemMod, RemMod, Name]), - throw({error, Msg}); + self() ! {self(), ext_types, {RemMod, Name, ArgsLen}}, + {t_any(), []}; {ok, RemDict} -> - ArgsLen = length(Args), MFA = {RemMod, Name, ArgsLen}, case sets:is_element(MFA, ET) of true -> -- cgit v1.2.3