diff options
author | Hans Bolinder <[email protected]> | 2014-02-24 08:43:22 +0100 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2014-02-24 08:43:22 +0100 |
commit | f4bafbfdc7183b4297b96c884a61545000eb7fbd (patch) | |
tree | 66e0bb64e5b3153bdd62823b56fef43b60a590ee /lib/dialyzer | |
parent | 502b13aaf568e351bc30e44d0e14c063cbf5fc5a (diff) | |
download | otp-f4bafbfdc7183b4297b96c884a61545000eb7fbd.tar.gz otp-f4bafbfdc7183b4297b96c884a61545000eb7fbd.tar.bz2 otp-f4bafbfdc7183b4297b96c884a61545000eb7fbd.zip |
FIx handling of 'on_load' attribute
[pull request from Kostis Sagonas]
The handling of functions appearing in an 'on_load' attribute was wrong.
Instead of considering the functions specified in these attributes as
escaping from the module and performing a full analysis starting from
them, the code just bypassed this analysis and only suppressed unused
warning messages for these functions. This worked for most of the cases
but resulted in functions (directly or indirectly) called by 'on_load'
functions being reported as not called by the module.
Such a case existed in the code of the 'crypto' application.
To solve these issues the initialization code for functions escaping
from the module was changed and the test for the on_load functionality
was appropriately extended.
Diffstat (limited to 'lib/dialyzer')
-rw-r--r-- | lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 11 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_dep.erl | 23 | ||||
-rw-r--r-- | lib/dialyzer/test/small_SUITE_data/src/on_load.erl | 7 |
3 files changed, 27 insertions, 14 deletions
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 0fbaf1d47c..4ab2d8a687 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -168,7 +168,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), @@ -423,11 +423,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 a81ea1a98b..2923e06df4 100644 --- a/lib/dialyzer/src/dialyzer_dep.erl +++ b/lib/dialyzer/src/dialyzer_dep.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -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. |