Skip to content

Commit 84010d4

Browse files
author
José Valim
committed
Ensure private functions are not exported, closes #2587
1 parent a91aa70 commit 84010d4

File tree

3 files changed

+29
-18
lines changed

3 files changed

+29
-18
lines changed

lib/elixir/src/elixir_def.erl

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ unwrap_definitions(File, Module) ->
234234

235235
{All, Private} = unwrap_definition(ets:tab2list(Table), File, Module, CTable, [], []),
236236
Unreachable = elixir_locals:warn_unused_local(File, Module, Private),
237-
split_definition(All, Unreachable, [], [], [], [], {[], []}).
237+
split_definition(All, Unreachable, [], [], [], [], [], {[], []}).
238238

239239
unwrap_definition([Fun|T], File, Module, CTable, All, Private) ->
240240
{Tuple, Kind, Line, _, Check, Location, {Defaults, _, _}} = Fun,
@@ -263,31 +263,35 @@ unwrap_definition([], _File, _Module, _CTable, All, Private) ->
263263
{All, Private}.
264264

265265
split_definition([{Tuple, def, Line, Location, Body}|T], Unreachable,
266-
Def, Defp, Defmacro, Defmacrop, Functions) ->
266+
Def, Defp, Defmacro, Defmacrop, Exports, Functions) ->
267267
split_definition(T, Unreachable, [Tuple|Def], Defp, Defmacro, Defmacrop,
268+
[export(def, Tuple)|Exports],
268269
add_definition(Line, Location, Body, Functions));
269270

270271
split_definition([{Tuple, defp, Line, Location, Body}|T], Unreachable,
271-
Def, Defp, Defmacro, Defmacrop, Functions) ->
272+
Def, Defp, Defmacro, Defmacrop, Exports, Functions) ->
272273
case lists:member(Tuple, Unreachable) of
273274
false ->
274275
split_definition(T, Unreachable, Def, [Tuple|Defp], Defmacro, Defmacrop,
275-
add_definition(Line, Location, Body, Functions));
276+
Exports, add_definition(Line, Location, Body, Functions));
276277
true ->
277-
split_definition(T, Unreachable, Def, [Tuple|Defp], Defmacro, Defmacrop, Functions)
278+
split_definition(T, Unreachable, Def, [Tuple|Defp], Defmacro, Defmacrop,
279+
Exports, Functions)
278280
end;
279281

280282
split_definition([{Tuple, defmacro, Line, Location, Body}|T], Unreachable,
281-
Def, Defp, Defmacro, Defmacrop, Functions) ->
283+
Def, Defp, Defmacro, Defmacrop, Exports, Functions) ->
282284
split_definition(T, Unreachable, Def, Defp, [Tuple|Defmacro], Defmacrop,
285+
[export(defmacro, Tuple)|Exports],
283286
add_definition(Line, Location, Body, Functions));
284287

285288
split_definition([{Tuple, defmacrop, _Line, _Location, _Body}|T], Unreachable,
286-
Def, Defp, Defmacro, Defmacrop, Functions) ->
287-
split_definition(T, Unreachable, Def, Defp, Defmacro, [Tuple|Defmacrop], Functions);
289+
Def, Defp, Defmacro, Defmacrop, Exports, Functions) ->
290+
split_definition(T, Unreachable, Def, Defp, Defmacro, [Tuple|Defmacrop],
291+
Exports, Functions);
288292

289-
split_definition([], _Unreachable, Def, Defp, Defmacro, Defmacrop, {Head, Tail}) ->
290-
{Def, Defp, Defmacro, Defmacrop, Head ++ Tail}.
293+
split_definition([], _Unreachable, Def, Defp, Defmacro, Defmacrop, Exports, {Head, Tail}) ->
294+
{Def, Defp, Defmacro, Defmacrop, Exports, Head ++ Tail}.
291295

292296
%% Helpers
293297

lib/elixir/src/elixir_module.erl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ do_compile(Line, Module, Block, Vars, E) ->
6060
[elixir_locals:record_local(Tuple, Module) || Tuple <- OnLoad]
6161
end,
6262

63-
{Def, Defp, Defmacro, Defmacrop, Functions} =
63+
{Def, Defp, Defmacro, Defmacrop, Exports, Functions} =
6464
elixir_def:unwrap_definitions(File, Module),
6565

66-
{All, Forms0} = functions_form(Line, File, Module, Def, Defp, Defmacro, Defmacrop, Functions),
66+
{All, Forms0} = functions_form(Line, File, Module, Def, Defp,
67+
Defmacro, Defmacrop, Exports, Functions),
6768
Forms1 = specs_form(Module, Defmacro, Defmacrop, Forms0),
6869
Forms2 = types_form(Line, File, Module, Forms1),
6970
Forms3 = attributes_form(Line, File, Module, Forms2),
@@ -149,15 +150,13 @@ eval_callbacks(Line, Module, Name, Args, E) ->
149150

150151
%% Return the form with exports and function declarations.
151152

152-
functions_form(Line, File, Module, Def, Defp, Defmacro, Defmacrop, Body) ->
153-
All = Def ++ Defp ++ Defmacro ++ Defmacrop,
153+
functions_form(Line, File, Module, Def, Defp, Defmacro, Defmacrop, Exports, Body) ->
154+
All = Def ++ Defmacro ++ Defp ++ Defmacrop,
154155
{Spec, Info} = add_info_function(Line, File, Module, All, Def, Defmacro),
155156

156-
NewBody = [Spec, Info|Body],
157-
Export = [{Name, Arity} || {function, _, Name, Arity, _} <- NewBody],
158-
159157
{[{'__info__',1}|All],
160-
[{attribute, Line, export, lists:sort(Export)} | NewBody]}.
158+
[{attribute, Line, export, lists:sort([{'__info__',1}|Exports])},
159+
Spec, Info | Body]}.
161160

162161
%% Add attributes handling to the form
163162

lib/elixir/test/elixir/kernel_test.exs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ defmodule KernelTest do
113113
assert not ({:__info__, 1} in Kernel.__info__(:functions))
114114
end
115115

116+
def exported?, do: not_exported?
117+
defp not_exported?, do: true
118+
119+
test "function_exported?/3" do
120+
assert function_exported?(__MODULE__, :exported?, 0)
121+
refute function_exported?(__MODULE__, :not_exported?, 0)
122+
end
123+
116124
test "macro_exported?/3" do
117125
assert macro_exported?(Kernel, :in, 2) == true
118126
assert macro_exported?(Kernel, :def, 1) == true

0 commit comments

Comments
 (0)