Skip to content

Commit

Permalink
Merge pull request #4598 from bjorng/bjorn/compiler/opportunistic-war…
Browse files Browse the repository at this point in the history
…nings/OTP-17260

Support suppressing opportunistic compiler warnings
  • Loading branch information
bjorng authored Mar 12, 2021
2 parents 3a7873f + b217b21 commit 27622dd
Show file tree
Hide file tree
Showing 9 changed files with 416 additions and 245 deletions.
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

0 comments on commit 27622dd

Please sign in to comment.