Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
8181-erl_lint-Warn-on-remote-calling-non-export...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 8181-erl_lint-Warn-on-remote-calling-non-exported-functio.patch of Package erlang
From d87a951037b8b3c5630a05e2eeafea62a3d657c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Wed, 20 Nov 2024 16:41:07 +0100 Subject: [PATCH] erl_lint: Warn on remote-calling non-exported functions Fixes #9092 --- lib/eunit/src/eunit_test.erl | 1 + lib/stdlib/src/erl_lint.erl | 29 ++++++++++++++++++--- lib/stdlib/test/erl_lint_SUITE.erl | 41 +++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl index ccb12ddd0e..7bccb9f394 100644 --- a/lib/eunit/src/eunit_test.erl +++ b/lib/eunit/src/eunit_test.erl @@ -29,6 +29,7 @@ -export([run_testfun/1, mf_wrapper/2, enter_context/4, multi_setup/1]). +-compile(nowarn_unexported_function). -include("eunit.hrl"). -include("eunit_internal.hrl"). diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index e05cf24e60..8a15221d65 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -274,6 +274,8 @@ format_error({define_import,{F,A}}) -> io_lib:format("defining imported function ~tw/~w", [F,A]); format_error({unused_function,{F,A}}) -> io_lib:format("function ~tw/~w is unused", [F,A]); +format_error({unexported_function, MFA}) -> + io_lib:format("function ~ts is not exported", [format_mfa(MFA)]); format_error({call_to_redefined_bif,{F,A}}) -> io_lib:format("ambiguous call of overridden auto-imported BIF ~w/~w~n" " - use erlang:~w/~w or \"-compile({no_auto_import,[~w/~w]}).\" " @@ -852,6 +854,9 @@ start(File, Opts) -> {ill_defined_optional_callbacks, bool_option(warn_ill_defined_optional_callbacks, nowarn_ill_defined_optional_callbacks, + true, Opts)}, + {unexported_function, + bool_option(warn_unexported_function, nowarn_unexported_function, true, Opts)} ], Enabled1 = [Category || {Category,true} <- Enabled0], @@ -2772,8 +2777,10 @@ expr({'fun',Anno,Body}, Vt, St) -> true -> {[],St}; false -> {[],call_function(Anno, F, A, St)} end; - {function,M,F,A} -> - expr_list([M,F,A], Vt, St) + {function, {atom, _, M}, {atom, _, F}, {integer, _, A}} -> + {[], check_unexported_function(Anno, M, F, A, St)}; + {function,M,F,A} -> + expr_list([M,F,A], Vt, St) end; expr({named_fun,_,'_',Cs}, Vt, St) -> fun_clauses(Cs, Vt, St); @@ -2796,7 +2803,8 @@ expr({call,Anno,{remote,_Ar,{atom,_Am,M},{atom,Af,F}},As}, Vt, St0) -> St1 = keyword_warning(Af, F, St0), St2 = check_remote_function(Anno, M, F, As, St1), St3 = check_module_name(M, Anno, St2), - expr_list(As, Vt, St3); + St4 = check_unexported_function(Anno, M, F, length(As), St3), + expr_list(As, Vt, St4); expr({call,Anno,{remote,_Ar,M,F},As}, Vt, St0) -> St1 = keyword_warning(Anno, M, St0), St2 = keyword_warning(Anno, F, St1), @@ -3023,6 +3031,21 @@ is_valid_call(Call) -> _ -> true end. +%% Raises a warning if we're remote-calling an unexported function (or +%% referencing it with `fun M:F/A`), as this is likely to be unintentional. +check_unexported_function(Anno, M, F, A, + #lint{module=M, + compile=Opts, + exports=Es} = St) -> + case (is_warn_enabled(unexported_function, St) + andalso (not lists:member(export_all, Opts)) + andalso (not gb_sets:is_element({F, A}, Es))) of + true -> add_warning(Anno, {unexported_function, {M, F, A}}, St); + false -> St + end; +check_unexported_function(_Anno, _M, _F, _A, St) -> + St. + %% record_def(Anno, RecordName, [RecField], State) -> State. %% Add a record definition if it does not already exist. Normalise %% so that all fields have explicit initial value. diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 10bd35c566..c8305d4668 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1181,7 +1181,42 @@ unused_function(Config) when is_list(Config) -> 32*X. ">>, {[]}, %Tuple indicates no 'export_all'. - []}], + []}, + + %% Raises a warning that flurb/1 is unused, and that we should + %% probably export it because it's referenced in t/0 and u/1. + {func4, + <<"-export([t/0, u/1]). + + t() -> + fun ?MODULE:flurb/1. + u(X) -> + ?MODULE:flurb(X). + + flurb(X) -> + 32*X. + ">>, + {[]}, %% Tuple indicates no 'export_all'. + {warnings,[{{4,18},erl_lint,{unexported_function,{lint_test,flurb,1}}}, + {{6,19},erl_lint,{unexported_function,{lint_test,flurb,1}}}, + {{8,15},erl_lint,{unused_function,{flurb,1}}}]}}, + + %% Turn off warnings for unexported functions using a -compile() + %% directive. + {func5, + <<"-export([t/0, u/1]). + -compile(nowarn_unexported_function). + + t() -> + fun ?MODULE:flurb/1. + u(X) -> + ?MODULE:flurb(X). + + flurb(X) -> + 32*X. + ">>, + {[]}, %% Tuple indicates no 'export_all'. + {warnings,[{{9,15},erl_lint,{unused_function,{flurb,1}}}]}}], [] = run(Config, Ts), ok. @@ -2736,7 +2771,7 @@ otp_5644(Config) when is_list(Config) -> i(X) -> X. ">>, - [], + [nowarn_unexported_function], []}], [] = run(Config, Ts), ok. @@ -3185,7 +3220,7 @@ bif_clash(Config) when is_list(Config) -> size({N,_}) -> N. ">>, - [], + [nowarn_unexported_function], {errors,[{{2,19},erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}}, %% Verify that warnings cannot be turned off in the old way. -- 2.43.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor