diff options
Diffstat (limited to 'lib/dialyzer')
-rw-r--r-- | lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 9 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_dep.erl | 21 | ||||
-rw-r--r-- | lib/dialyzer/test/small_SUITE_data/src/on_load.erl | 7 |
3 files changed, 25 insertions, 12 deletions
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 3de020cb01..2a633c5e37 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -172,7 +172,7 @@ analysis_start(Parent, Analysis) -> throw:{error, _ErrorMsg} = Error -> exit(Error) end, NewPlt0 = dialyzer_plt:insert_types(Plt, dialyzer_codeserver:get_records(NewCServer)), - ExpTypes = dialyzer_codeserver:get_exported_types(NewCServer), + ExpTypes = dialyzer_codeserver:get_exported_types(NewCServer), NewPlt1 = dialyzer_plt:insert_exported_types(NewPlt0, ExpTypes), State0 = State#analysis_state{plt = NewPlt1}, dump_callgraph(Callgraph, State0, Analysis), @@ -427,11 +427,8 @@ abs_get_nowarn(Abs, M) -> false -> [{M, F, A} || {function, _, F, A, _} <- Abs]; % all functions true -> - OnLoad = - lists:flatten([{M, F, A} || {attribute, _, on_load, {F, A}} <- Abs]), - OnLoad ++ [{M, F, A} || - {nowarn_unused_function, FAs} <- Opts, - {F, A} <- lists:flatten([FAs])] + [{M, F, A} || {nowarn_unused_function, FAs} <- Opts, + {F, A} <- lists:flatten([FAs])] end. get_exported_types_from_core(Core) -> diff --git a/lib/dialyzer/src/dialyzer_dep.erl b/lib/dialyzer/src/dialyzer_dep.erl index 5c1245ae47..f1ac41ff04 100644 --- a/lib/dialyzer/src/dialyzer_dep.erl +++ b/lib/dialyzer/src/dialyzer_dep.erl @@ -65,7 +65,7 @@ analyze(Tree) -> %% io:format("Handling ~w\n", [cerl:atom_val(cerl:module_name(Tree))]), {_, State} = traverse(Tree, map__new(), state__new(Tree), top), Esc = state__esc(State), - %% Add dependency from 'external' to all escaping function + %% Add dependency from 'external' to all escaping functions State1 = state__add_deps(external, output(Esc), State), Deps = state__deps(State1), Calls = state__calls(State1), @@ -486,11 +486,22 @@ all_vars(Tree, AccIn) -> state__new(Tree) -> Exports = set__from_list([X || X <- cerl:module_exports(Tree)]), - InitEsc = set__from_list([cerl_trees:get_label(Fun) - || {Var, Fun} <- cerl:module_defs(Tree), - set__is_element(Var, Exports)]), + %% get the labels of all exported functions + ExpLs = [cerl_trees:get_label(Fun) || {Var, Fun} <- cerl:module_defs(Tree), + set__is_element(Var, Exports)], + %% make sure to also initiate an analysis from all functions called + %% from on_load attributes; in Core these exist as a list of {F,A} pairs + OnLoadFAs = lists:flatten([cerl:atom_val(Args) + || {Attr, Args} <- cerl:module_attrs(Tree), + cerl:atom_val(Attr) =:= on_load]), + OnLoadLs = [cerl_trees:get_label(Fun) + || {Var, Fun} <- cerl:module_defs(Tree), + lists:member(cerl:var_name(Var), OnLoadFAs)], + %% init the escaping function labels to exported + called from on_load + InitEsc = set__from_list(OnLoadLs ++ ExpLs), Arities = cerl_trees:fold(fun find_arities/2, dict:new(), Tree), - #state{deps = map__new(), esc = InitEsc, call = map__new(), arities = Arities, letrecs = map__new()}. + #state{deps = map__new(), esc = InitEsc, call = map__new(), + arities = Arities, letrecs = map__new()}. find_arities(Tree, AccMap) -> case cerl:is_c_fun(Tree) of diff --git a/lib/dialyzer/test/small_SUITE_data/src/on_load.erl b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl index 16533a9caa..7242ac2016 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/on_load.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl @@ -1,4 +1,6 @@ %%% This is to ensure that "on_load" functions are never reported as unused. +%%% In addition, all functions called by a function in an on_load attribute +%%% should be considered as called by an entry point of the module. -module(on_load). @@ -8,4 +10,7 @@ foo() -> ok. -bar() -> ok. +bar() -> gazonk(17). + +gazonk(N) when N < 42 -> gazonk(N+1); +gazonk(42) -> ok. |