Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support suppressing opportunistic compiler warnings #4598

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 36 additions & 22 deletions lib/compiler/doc/src/compile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -772,29 +772,43 @@ module.beam: module.erl \
</item>
</taglist>

<p>Another class of warnings is generated by the compiler
during optimization and code generation. They warn about
patterns that will never match (such as <c>a=b</c>), guards
that always evaluate to false, and expressions that
always fail (such as <c>atom+42</c>).</p>
<p>Those warnings cannot be disabled (except by
disabling all warnings).</p>
<p>Other kinds of warnings are <em>opportunistic
warnings</em>. They are generated when the compiler happens to
notice potential issues during optimization and code
generation.</p>

<note>
<p>The compiler does not warn for expressions that it
does not attempt to optimize. For example, the compiler will
emit a warning for <c>1/0</c> but not for <c>X/0</c>,
because <c>1/0</c> is a constant expression that the compiler
will attempt to evaluate.</p>

<p>The absence of warnings does not mean that there are no
remaining errors in the code.</p>
</note>

<p>Opportunistic warnings can be disabled using the following
options:</p>

<taglist>
<tag><c>nowarn_opportunistic</c></tag>
<item><p>Disable all opportunistic warnings.</p></item>

<tag><c>nowarn_failed</c></tag>
<item><p>Disable warnings for expressions that will always
fail (such as <c>atom+42</c>).</p></item>

<tag><c>nowarn_ignored</c></tag>
<item><p>Disable warnings for expressions whose
values are ignored.</p></item>

<tag><c>nowarn_nomatch</c></tag>
<item><p>Disable warnings for patterns that will never match
(such as <c>a=b</c>) and for guards that always evaluate to
<c>false</c>.</p></item>
</taglist>

<note>
<p>The compiler does not warn for expressions that it
does not attempt to optimize. For example, the compiler tries
to evaluate <c>1/0</c>, detects that it will cause an
exception, and emits a warning. However,
the compiler is silent about the similar expression,
<c>X/0</c>, because of the variable in it. Thus, the compiler does
not even try to evaluate and therefore it emits no warnings.</p>
</note>

<warning>
<p>The absence of warnings does not mean that
there are no remaining errors in the code.</p>
</warning>

<note>
<p>All options, except the include path
(<c>{i,Dir}</c>), can also be given in the file with attribute
Expand Down
38 changes: 37 additions & 1 deletion lib/compiler/src/compile.erl
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ run_eprof({_,Fun}, Code, _, St) ->
Fun(Code, St).

comp_ret_ok(Code, #compile{warnings=Warn0,module=Mod,options=Opts}=St) ->
Warn1 = filter_warnings(Warn0, Opts),
case werror(St) of
true ->
case member(report_warnings, Opts) of
Expand All @@ -525,7 +526,7 @@ comp_ret_ok(Code, #compile{warnings=Warn0,module=Mod,options=Opts}=St) ->
end,
comp_ret_err(St);
false ->
Warn = messages_per_file(Warn0),
Warn = messages_per_file(Warn1),
report_warnings(St#compile{warnings = Warn}),
Ret1 = case member(binary, Opts) andalso
not member(no_code_generation, Opts) of
Expand Down Expand Up @@ -1720,6 +1721,41 @@ report_warnings(#compile{options=Opts,warnings=Ws0}) ->
false -> ok
end.

%%%
%%% Filter warnings.
%%%

filter_warnings(Ws, Opts) ->
Ignore = ignore_tags(Opts, sets:new([{version,2}])),
filter_warnings_1(Ws, Ignore).

filter_warnings_1([{Source,Ws0}|T], Ignore) ->
Ws = [W || W <- Ws0, not ignore_warning(W, Ignore)],
[{Source,Ws}|filter_warnings_1(T, Ignore)];
filter_warnings_1([], _Ignore) -> [].

ignore_warning({_Location,Pass,{Category,_}}, Ignore) ->
IgnoreMod = case Pass of
v3_core -> true;
sys_core_fold -> true;
v3_kernel -> true;
_ -> false
end,
IgnoreMod andalso sets:is_element(Category, Ignore);
ignore_warning(_, _) -> false.

ignore_tags([nowarn_opportunistic|_], _Ignore) ->
sets:from_list([failed,ignored,nomatch], [{version,2}]);
ignore_tags([nowarn_failed|Opts], Ignore) ->
ignore_tags(Opts, sets:add_element(failed, Ignore));
ignore_tags([nowarn_ignored|Opts], Ignore) ->
ignore_tags(Opts, sets:add_element(ignored, Ignore));
ignore_tags([nowarn_nomatch|Opts], Ignore) ->
ignore_tags(Opts, sets:add_element(nomatch, Ignore));
ignore_tags([_|Opts], Ignore) ->
ignore_tags(Opts, Ignore);
ignore_tags([], Ignore) -> Ignore.

%% erlfile(Dir, Base) -> ErlFile
%% outfile(Base, Extension, Options) -> OutputFile
%% objfile(Base, Target, Options) -> ObjFile
Expand Down
Loading