diff options
Diffstat (limited to 'lib/tools/src/xref_base.erl')
-rw-r--r-- | lib/tools/src/xref_base.erl | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl index f298a1ce81..a28c6ee283 100644 --- a/lib/tools/src/xref_base.erl +++ b/lib/tools/src/xref_base.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -400,26 +400,28 @@ analysis(locals_not_used, functions) -> %% used (indirectly) from any export: "(domain EE + range EE) * L". %% But then we only get locals that make some calls, so we add %% locals that are not used at all: "L * (UU + XU - LU)". - "L * ((UU + XU - LU) + domain EE + range EE)"; + %% We also need to exclude functions with the -on_load() attribute: + %% (L - OL) is used rather than just L. + "(L - OL) * ((UU + XU - LU) + domain EE + range EE)"; analysis(exports_not_used, _) -> %% Local calls are not considered here. "X * UU" would do otherwise. "X - XU"; analysis({call, F}, functions) -> - make_query("range (E | ~w : Fun)", [F]); + make_query("range (E | ~tw : Fun)", [F]); analysis({use, F}, functions) -> - make_query("domain (E || ~w : Fun)", [F]); + make_query("domain (E || ~tw : Fun)", [F]); analysis({module_call, M}, _) -> - make_query("range (ME | ~w : Mod)", [M]); + make_query("range (ME | ~tw : Mod)", [M]); analysis({module_use, M}, _) -> - make_query("domain (ME || ~w : Mod)", [M]); + make_query("domain (ME || ~tw : Mod)", [M]); analysis({application_call, A}, _) -> - make_query("range (AE | ~w : App)", [A]); + make_query("range (AE | ~tw : App)", [A]); analysis({application_use, A}, _) -> - make_query("domain (AE || ~w : App)", [A]); + make_query("domain (AE || ~tw : App)", [A]); analysis({release_call, R}, _) -> - make_query("range (RE | ~w : Rel)", [R]); + make_query("range (RE | ~tw : Rel)", [R]); analysis({release_use, R}, _) -> - make_query("domain (RE || ~w : Rel)", [R]); + make_query("domain (RE || ~tw : Rel)", [R]); analysis(deprecated_function_calls, functions) -> "XC || DF"; analysis({deprecated_function_calls,Flag}, functions) -> @@ -809,7 +811,8 @@ abst(File, Builtins, _Mode = functions) -> {exports,X0}, {attributes,A}]}} -> %% R9C- Forms0 = epp:interpret_file_attribute(Code), - {_,_,Forms,_} = sys_pre_expand:module(Forms0, []), + Forms1 = erl_expand_records:module(Forms0, []), + Forms = erl_internal:add_predefined_functions(Forms1), X = mfa_exports(X0, A, M), D = deprecated(A, X, M), xref_reader:module(M, Forms, Builtins, X, D); @@ -917,7 +920,7 @@ do_add_module(S, XMod, Unres, Data) -> {ok, Ms, Bad, NS}. prepare_module(_Mode = functions, XMod, Unres0, Data) -> - {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr} = Data, + {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr, OL0} = Data, %% Bad is a list of bad values of 'xref' attributes. {ALC0,AXC0,Bad0} = Attrs, FT = [tspec(func)], @@ -934,6 +937,7 @@ prepare_module(_Mode = functions, XMod, Unres0, Data) -> ALC1 = xref_utils:xset(ALC0, PCA), UnresCalls = xref_utils:xset(Unres0, PCA), Unres = domain(UnresCalls), + OL1 = xref_utils:xset(OL0, FT), DefinedFuns = domain(DefAt), {AXC, ALC, Bad1, LPreCAt2, XPreCAt2} = @@ -954,7 +958,7 @@ prepare_module(_Mode = functions, XMod, Unres0, Data) -> {DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X), {EE, ECallAt} = inter_graph(X, L, LC, XC, CallAt), {ok, {functions, XMod, [DefAt,L,X,LCallAt,XCallAt,CallAt,LC,XC,EE,ECallAt, - DF1,DF_11,DF_21,DF_31], NoCalls, Unres}, + OL1,DF1,DF_11,DF_21,DF_31], NoCalls, Unres}, DBad++Bad}; prepare_module(_Mode = modules, XMod, _Unres, Data) -> {X0, I0, Depr} = Data, @@ -966,7 +970,7 @@ prepare_module(_Mode = modules, XMod, _Unres, Data) -> finish_module({functions, XMod, List, NoCalls, Unres}, S) -> ok = check_module(XMod, S), [DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,LC2,XC2,EE2,ECallAt2, - DF2,DF_12,DF_22,DF_32] = pack(List), + OL2,DF2,DF_12,DF_22,DF_32] = pack(List), LU = range(LC2), @@ -975,7 +979,7 @@ finish_module({functions, XMod, List, NoCalls, Unres}, S) -> M = XMod#xref_mod.name, MS = xref_utils:xset(M, atom), T = from_sets({MS,DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2, - LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined, + LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined,OL2, DF2,DF_12,DF_22,DF_32}), NoUnres = XMod#xref_mod.no_unresolved, @@ -1219,7 +1223,7 @@ do_set_up(S, VerboseOpt) -> %% If data has been supplied using add_module/9 (and that is the only %% sanctioned way), then DefAt, L, X, LCallAt, XCallAt, CallAt, XC, LC, -%% and LU are guaranteed to be functions (with all supplied +%% LU and OL are guaranteed to be functions (with all supplied %% modules as domain (disregarding unknown modules, that is, modules %% not supplied but hosting unknown functions)). %% As a consequence, V and E are also functions. V is defined for unknown @@ -1232,8 +1236,8 @@ do_set_up(S, VerboseOpt) -> do_set_up(S) when S#xref.mode =:= functions -> ModDictList = dict:to_list(S#xref.modules), [DefAt0, L, X0, LCallAt, XCallAt, CallAt, LC, XC, LU, - EE0, ECallAt, UC, LPredefined, - Mod_DF,Mod_DF_1,Mod_DF_2,Mod_DF_3] = make_families(ModDictList, 18), + EE0, ECallAt, UC, LPredefined, OL, + Mod_DF,Mod_DF_1,Mod_DF_2,Mod_DF_3] = make_families(ModDictList, 19), {XC_1, XU, XPredefined} = do_set_up_1(XC), LC_1 = user_family(union_of_family(LC)), @@ -1313,13 +1317,14 @@ do_set_up(S) when S#xref.mode =:= functions -> UC_1 = user_family(union_of_family(UC)), ?FORMAT("DefAt ~p~n", [DefAt]), - ?FORMAT("U=~p~nLib=~p~nB=~p~nLU=~p~nXU=~p~nUU=~p~n", [U,Lib,B,LU,XU,UU]), + ?FORMAT("U=~p~nLib=~p~nB=~p~nLU=~p~nXU=~p~nUU=~p~nOL=~p~n", + [U,Lib,B,LU,XU,UU,OL]), ?FORMAT("E_1=~p~nLC_1=~p~nXC_1=~p~n", [E_1,LC_1,XC_1]), ?FORMAT("EE=~p~nEE_1=~p~nECallAt=~p~n", [EE, EE_1, ECallAt]), ?FORMAT("DF=~p~nDF_1=~p~nDF_2=~p~nDF_3=~p~n", [DF, DF_1, DF_2, DF_3]), Vs = [{'L',L}, {'X',X},{'F',F},{'U',U},{'B',B},{'UU',UU}, - {'XU',XU},{'LU',LU},{'V',V},{v,V}, + {'XU',XU},{'LU',LU},{'V',V},{v,V},{'OL',OL}, {'LC',{LC,LC_1}},{'XC',{XC,XC_1}},{'E',{E,E_1}},{e,{E,E_1}}, {'EE',{EE,EE_1}},{'UC',{UC,UC_1}}, {'M',M},{'A',A},{'R',R}, @@ -1404,6 +1409,7 @@ var_type('U') -> {function, vertex}; var_type('UU') -> {function, vertex}; var_type('V') -> {function, vertex}; var_type('X') -> {function, vertex}; +var_type('OL') -> {function, vertex}; var_type('XU') -> {function, vertex}; var_type('DF') -> {function, vertex}; var_type('DF_1') -> {function, vertex}; @@ -1832,9 +1838,9 @@ message(true, What, Arg) -> unreadable -> io:format("Skipping ~ts (unreadable)~n", [Arg]); xref_attr -> - io:format("~ts: Skipping 'xref' attribute ~w~n", Arg); + io:format("~ts: Skipping 'xref' attribute ~tw~n", Arg); depr_attr -> - io:format("~ts: Skipping 'deprecated' attribute ~w~n", Arg); + io:format("~ts: Skipping 'deprecated' attribute ~tw~n", Arg); lib_search -> io:format("Scanning library path for BEAM files... ", []); lib_check -> |