diff options
-rw-r--r-- | lib/tools/src/xref_base.erl | 3 | ||||
-rw-r--r-- | lib/tools/src/xref_reader.erl | 55 | ||||
-rw-r--r-- | lib/tools/test/xref_SUITE.erl | 3 |
3 files changed, 49 insertions, 12 deletions
diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl index f298a1ce81..8d2cc07e40 100644 --- a/lib/tools/src/xref_base.erl +++ b/lib/tools/src/xref_base.erl @@ -809,7 +809,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); diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl index 41b93caaeb..6c4a1c4d8e 100644 --- a/lib/tools/src/xref_reader.erl +++ b/lib/tools/src/xref_reader.erl @@ -42,17 +42,15 @@ %% experimental; -xref(FunEdge) is recognized. lattrs=[], % local calls, {{mfa(),mfa()},Line} xattrs=[], % external calls, -"- - battrs=[] % badly formed xref attributes, term(). + battrs=[] % badly formed xref attributes, term(). }). -include("xref.hrl"). -%% sys_pre_expand has modified the forms slightly compared to what -%% erl_id_trans recognizes. - %% The versions of the abstract code are as follows: -%% R7: abstract_v1 -%% R8: abstract_v2 +%% R7: abstract_v1 +%% R8: abstract_v2 +%% R9C: raw_abstract_v1 %% -> {ok, Module, {DefAt, CallAt, LC, XC, X, Attrs}, Unresolved}} | EXIT %% Attrs = {ALC, AXC, Bad} @@ -92,7 +90,12 @@ form({function, Anno, Name, Arity, Clauses}, S) -> Line = erl_anno:line(Anno), S2 = S1#xrefr{def_at = [{MFA,Line} | S#xrefr.def_at]}, S3 = clauses(Clauses, S2), - S3#xrefr{function = []}. + S3#xrefr{function = []}; +form(_, S) -> + %% OTP 20. Other uninteresting forms such as {eof, _} and {warning, _}. + %% Exposed because sys_pre_expand is no longer run. + S. + clauses(Cls, S) -> #xrefr{funvars = FunVars, matches = Matches} = S, @@ -109,6 +112,8 @@ clauses([{clause, _Line, _H, G, B} | Cs], FunVars, Matches, S) -> clauses([], _FunVars, _Matches, S) -> S. +attr(NotList, Ln, M, Fun, AL, AX, B, S) when not is_list(NotList) -> + attr([NotList], Ln, M, Fun, AL, AX, B, S); attr([E={From, To} | As], Ln, M, Fun, AL, AX, B, S) -> case mfa(From, M) of {_, _, MFA} when MFA =:= Fun; [] =:= Fun -> @@ -154,6 +159,15 @@ expr({'try',_Line,Es,Scs,Ccs,As}, S) -> S2 = clauses(Scs, S1), S3 = clauses(Ccs, S2), expr(As, S3); +expr({'fun', Line, {function,M,F,A}}, S) + when is_atom(M), is_atom(F), is_integer(A) -> + %% This is the old format for external funs, generated by a pre-R15 + %% compiler. Exposed in OTP 20 because sys_pre_expand is no longer + %% run. + Fun = {'fun', Line, {function, {atom,Line,M}, + {atom,Line,F}, + {integer,Line,A}}}, + expr(Fun, S); expr({'fun', Line, {function, {atom,_,Mod}, {atom,_,Name}, {integer,_,Arity}}}, S) -> @@ -168,14 +182,21 @@ expr({'fun', Line, {function, Mod, Name, _Arity}}, S) -> %% New format in R15. M:F/A (one or more variables). As = {var, Line, '_'}, external_call(erlang, apply, [Mod, Name, As], Line, true, S); +%% Only abstract_v1 and abstract_v2. expr({'fun', Line, {function, Name, Arity}, _Extra}, S) -> %% Added in R8. handle_call(local, S#xrefr.module, Name, Arity, Line, S); expr({'fun', _Line, {clauses, Cs}, _Extra}, S) -> clauses(Cs, S); -expr({named_fun, _Line, '_', Cs, _Extra}, S) -> +%% End abstract_v1 and abstract_v2. +expr({'fun', Line, {function, Name, Arity}}, S) -> + %% Added in OTP 20. + handle_call(local, S#xrefr.module, Name, Arity, Line, S); +expr({'fun', _Line, {clauses, Cs}}, S) -> + clauses(Cs, S); +expr({named_fun, _Line, '_', Cs}, S) -> clauses(Cs, S); -expr({named_fun, _Line, Name, Cs, _Extra}, S) -> +expr({named_fun, _Line, Name, Cs}, S) -> S1 = S#xrefr{funvars = [Name | S#xrefr.funvars]}, clauses(Cs, S1); expr({call, Line, {atom, _, Name}, As}, S) -> @@ -193,7 +214,12 @@ expr({match, _Line, {var,_,Var}, {'fun', _, {clauses, Cs}, _Extra}}, S) -> %% that are passed around by the "expansion" of list comprehension. S1 = S#xrefr{funvars = [Var | S#xrefr.funvars]}, clauses(Cs, S1); -expr({match, _Line, {var,_,Var}, {named_fun, _, _, _, _} = Fun}, S) -> +expr({match, _Line, {var,_,Var}, {'fun', _, {clauses, Cs}}}, S) -> + %% OTP 20. Exposed because sys_pre_expand is no longer run. + S1 = S#xrefr{funvars = [Var | S#xrefr.funvars]}, + clauses(Cs, S1); +expr({match, _Line, {var,_,Var}, {named_fun, _, _, _} = Fun}, S) -> + %% OTP 20. Exposed because sys_pre_expand is no longer run. S1 = S#xrefr{funvars = [Var | S#xrefr.funvars]}, expr(Fun, S1); expr({match, _Line, {var,_,Var}, E}, S) -> @@ -295,10 +321,17 @@ check_funarg(W, ArgsList, Line, S) -> expr(ArgsList, S1). funarg({'fun', _, _Clauses, _Extra}, _S) -> true; +funarg({'fun', _, {clauses, _}}, _S) -> + %% OTP 20. sys_pre_expand not run. + true; +funarg({'fun', _, {function, _, _}}, _S) -> + %% OTP 20. sys_pre_expand not run. + true; funarg({'fun', _, {function,_,_,_}}, _S) -> %% New abstract format for fun M:F/A in R15. true; -funarg({named_fun, _, _, _, _}, _S) -> +funarg({named_fun, _, _, _}, _S) -> + %% OTP 20. sys_pre_expand not run. true; funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars); funarg(_, _S) -> false. diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index 01dbac6ecb..f308ea1204 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1222,6 +1222,9 @@ read2(Conf) when is_list(Conf) -> f() -> %% Duplicated unresolved calls are ignored: (f())(foo,bar),(f())(foo,bar). % POS1 + + %% Warning forms must be ignored. + -warning(must_not_crash). ">>, ok = file:write_file(File, Test), {ok, read2} = compile:file(File, [debug_info,{outdir,Dir}]), |