diff options
Diffstat (limited to 'lib/compiler/test/warnings_SUITE.erl')
| -rw-r--r-- | lib/compiler/test/warnings_SUITE.erl | 435 |
1 files changed, 361 insertions, 74 deletions
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index ad4ad91f74..857995b6a6 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2013. All Rights Reserved. +%% Copyright Ericsson AB 2003-2017. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -26,9 +27,9 @@ -define(privdir, "warnings_SUITE_priv"). -define(t, test_server). -else. --include_lib("test_server/include/test_server.hrl"). --define(datadir, ?config(data_dir, Conf)). --define(privdir, ?config(priv_dir, Conf)). +-include_lib("common_test/include/ct.hrl"). +-define(datadir, proplists:get_value(data_dir, Conf)). +-define(privdir, proplists:get_value(priv_dir, Conf)). -endif. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -38,22 +39,20 @@ -export([pattern/1,pattern2/1,pattern3/1,pattern4/1, guard/1,bad_arith/1,bool_cases/1,bad_apply/1, files/1,effect/1,bin_opt_info/1,bin_construction/1, - comprehensions/1,maps/1,redundant_boolean_clauses/1, - latin1_fallback/1]). - -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(2)). + comprehensions/1,maps/1,maps_bin_opt_info/1, + redundant_boolean_clauses/1, + latin1_fallback/1,underscore/1,no_warnings/1, + bit_syntax/1,inlining/1]). init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> test_lib:recompile(?MODULE), @@ -64,7 +63,9 @@ groups() -> [pattern,pattern2,pattern3,pattern4,guard, bad_arith,bool_cases,bad_apply,files,effect, bin_opt_info,bin_construction,comprehensions,maps, - redundant_boolean_clauses,latin1_fallback]}]. + maps_bin_opt_info, + redundant_boolean_clauses,latin1_fallback, + underscore,no_warnings,bit_syntax,inlining]}]. init_per_suite(Config) -> Config. @@ -99,7 +100,7 @@ pattern(Config) when is_list(Config) -> [{2,v3_core,nomatch}, {6,v3_core,nomatch}, {11,v3_core,nomatch} ] }}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. pattern2(Config) when is_list(Config) -> @@ -123,7 +124,7 @@ pattern2(Config) when is_list(Config) -> {4,sys_core_fold,no_clause_match}, {5,sys_core_fold,nomatch_clause_type}, {6,sys_core_fold,nomatch_clause_type}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), %% Disable Core Erlang optimizations. v3_kernel should produce %% a warning for the clause that didn't match. @@ -132,7 +133,7 @@ pattern2(Config) when is_list(Config) -> [nowarn_unused_vars,no_copt], {warnings, [{2,v3_kernel,{nomatch_shadow,1}}]}}], - ?line [] = run(Config, Ts2), + [] = run(Config, Ts2), ok. pattern3(Config) when is_list(Config) -> @@ -148,7 +149,7 @@ pattern3(Config) when is_list(Config) -> [nowarn_unused_vars], {warnings, [{4,v3_kernel,{nomatch_shadow,2}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -209,7 +210,7 @@ pattern4(Config) when is_list(Config) -> {23,sys_core_fold,no_clause_match}, {33,sys_core_fold,no_clause_match} ]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -252,7 +253,7 @@ guard(Config) when is_list(Config) -> {11,sys_core_fold,nomatch_guard}, {11,sys_core_fold,{eval_failure,badarg}} ]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -284,7 +285,7 @@ bad_arith(Config) when is_list(Config) -> {10,sys_core_fold,{eval_failure,badarith}}, {15,sys_core_fold,{eval_failure,badarith}} ] }}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. bool_cases(Config) when is_list(Config) -> @@ -316,7 +317,7 @@ bool_cases(Config) when is_list(Config) -> [{6,sys_core_fold,nomatch_shadow}, {13,sys_core_fold,nomatch_shadow}, {18,sys_core_fold,nomatch_clause_type} ]} }], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. bad_apply(Config) when is_list(Config) -> @@ -335,11 +336,11 @@ bad_apply(Config) when is_list(Config) -> {4,v3_kernel,bad_call}, {5,v3_kernel,bad_call}, {6,v3_kernel,bad_call}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), %% Also verify that the generated code generates the correct error. - ?line try erlang:42() of - _ -> ?line ?t:fail() + try erlang:42() of + _ -> ct:fail(should_fail) catch error:badarg -> ok end, @@ -363,12 +364,12 @@ files(Config) when is_list(Config) -> [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]}, {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. %% Test warnings for term construction and BIF calls in effect context. effect(Config) when is_list(Config) -> - Ts = [{lc, + Ts = [{effect, <<" t(X) -> case X of @@ -474,6 +475,19 @@ effect(Config) when is_list(Config) -> m9(Bs) -> [{B,ok} = {B,foo:bar(B)} || B <- Bs], ok. + + m10(ConfigTableSize) -> + case ConfigTableSize of + apa -> + CurrentConfig = {id(camel_phase3),id(sms)}, + case CurrentConfig of + {apa, bepa} -> ok; + _ -> ok + end + end, + ok. + + id(I) -> I. ">>, [], {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, @@ -496,7 +510,7 @@ effect(Config) when is_list(Config) -> {28,sys_core_fold,useless_building}, {36,sys_core_fold,{no_effect,{erlang,'=:=',2}}}, {38,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. bin_opt_info(Config) when is_list(Config) -> @@ -515,18 +529,18 @@ bin_opt_info(Config) when is_list(Config) -> Code, [bin_opt_info], {warnings, - [{4,sys_core_fold,orig_bin_var_used_in_guard}, + [{4,sys_core_bsm,orig_bin_var_used_in_guard}, {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}}, {9,beam_bsm,{no_bin_opt, {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}], - ?line [] = run(Config, Ts1), + [] = run(Config, Ts1), %% For coverage: don't give the bin_opt_info option. Ts2 = [{bsm2, Code, [], []}], - ?line [] = run(Config, Ts2), + [] = run(Config, Ts2), ok. bin_construction(Config) when is_list(Config) -> @@ -543,7 +557,7 @@ bin_construction(Config) when is_list(Config) -> [], {warnings,[{4,sys_core_fold,embedded_binary_size}, {8,sys_core_fold,{embedded_unit,8,28}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -578,11 +592,11 @@ maps(Config) when is_list(Config) -> <<" t() -> M = {a,[]}, - {'EXIT',{badarg,_}} = (catch(M#{ a => 1})), + {'EXIT',{badarg,_}} = (catch(M#{ a => 1 })), ok. ">>, [], - {warnings,[{4,v3_kernel,bad_map}]}}, + {warnings,[{4,sys_core_fold,{eval_failure,badmap}}]}}, {bad_map_src2, <<" t() -> @@ -592,7 +606,7 @@ maps(Config) when is_list(Config) -> id(I) -> I. ">>, [inline], - {warnings,[{4,v3_kernel,bad_map}]}}, + []}, {bad_map_src3, <<" t() -> @@ -600,8 +614,8 @@ maps(Config) when is_list(Config) -> ok. ">>, [], - {warnings,[{3,v3_core,bad_map}]}}, - {bad_map_literal_key, + {warnings,[{3,v3_core,badmap}]}}, + {ok_map_literal_key, <<" t() -> V = id(1), @@ -614,10 +628,128 @@ maps(Config) when is_list(Config) -> id(I) -> I. ">>, [], - {warnings,[{6,v3_core,nomatch}]}}], + []}, + {repeated_keys1, + <<" + foo1() -> + #{a=>1, + b=> 2, + a=>3}. + + bar1(M) -> + M#{a=>1, b=> 2, a:=3}. + + baz1(M) -> + M#{a=>1, b=> 2, a:=3}. + + foo2() -> + #{\"a\"=>1, \"b\"=> 2, \"a\"=>3}. + + bar2(M) -> + M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. + + baz2(M) -> + M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. + + foo3() -> + #{\"a\"=>1, + \"b\"=> 2, + \"a\"=>3}. + + bar3(M) -> + M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. + + baz3(M) -> + M#{<<\"a\">>=>1, <<\"b\">>=> 2, <<\"a\">>:=3}. + ">>, + [], + {warnings,[{3,v3_core,{map_key_repeated,a}}, + {8,v3_core,{map_key_repeated,a}}, + {11,v3_core,{map_key_repeated,a}}, + {14,v3_core,{map_key_repeated,"a"}}, + {17,v3_core,{map_key_repeated,"a"}}, + {20,v3_core,{map_key_repeated,"a"}}, + {23,v3_core,{map_key_repeated,"a"}}, + {28,v3_core,{map_key_repeated,"a"}}, + {31,v3_core,{map_key_repeated,<<"a">>}}]}}, + {repeated_keys2, + <<" + foo4(K) -> + #{\"a\"=>1, K => 1, \"b\"=> 2, \"a\"=>3, K=>2}. + + bar4(M,K) -> + M#{a=>1, K =>1, b=> 2, a:=3, K=>2}. + + baz4(M,K) -> + M#{<<\"a\">>=>1, + K => 1, <<\"b\">>=> 2, + <<\"a\">>:=3, K=>2}. + + foo5(K) -> + #{{\"a\",1}=>1, K => 1, \"b\"=> 2, {\"a\",1}=>3, K=>2}. + + bar5(M,K) -> + M#{{\"a\",<<\"b\">>}=>1, K =>1, + \"b\"=> 2, {\"a\",<<\"b\">>}:=3, K=>2}. + + baz5(M,K) -> + M#{{<<\"a\">>,1}=>1, K => 1, + <<\"b\">>=> 2, {<<\"a\">>,1}:=3,K=>2}. + + foo6(K) -> + #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2, #{\"a\"=>1}=>3, K=>2}. + + bar6(M,K) -> + M#{#{\"a\"=><<\"b\">>}=>1, K =>1, + \"b\"=> 2, #{\"a\"=><<\"b\">>}:=3, K=>2}. + + baz6(M,K) -> + M#{#{<<\"a\">>=>1}=>1, + K => 1, + <<\"b\">>=> 2, + #{<<\"a\">>=>1}:=3,K=>2}. + + foo7(K) -> + M1 = #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2}, + M1#{#{\"a\"=>1}=>3, K=>2}. + + bar7(M,K) -> + M1 = M#{#{\"a\"=><<\"b\">>}=>1, K =>1, \"b\"=> 2}, + M1#{#{\"a\"=><<\"b\">>}:=3, K=>2}. + + baz7(M,K) -> + M1 = M#{#{<<\"a\">>=>1}=>1, + K => 1, + <<\"b\">>=> 2}, + M1#{#{<<\"a\">>=>1}:=3,K=>2}. + ">>, + [], + {warnings,[{3,v3_core,{map_key_repeated,"a"}}, + {6,v3_core,{map_key_repeated,a}}, + {9,v3_core,{map_key_repeated,<<"a">>}}, + {14,v3_core,{map_key_repeated,{"a",1}}}, + {17,v3_core,{map_key_repeated,{"a",<<"b">>}}}, + {21,v3_core,{map_key_repeated,{<<"a">>,1}}}, + {25,v3_core,{map_key_repeated,#{"a" => 1}}}, + {28,v3_core,{map_key_repeated,#{"a" => <<"b">>}}}, + {32,v3_core,{map_key_repeated,#{<<"a">> => 1}}}]}} + ], run(Config, Ts), ok. +maps_bin_opt_info(Config) when is_list(Config) -> + Ts = [{map_bsm, + <<" + t1(<<0:8,7:8,T/binary>>,#{val := I}=M) -> + t1(T, M#{val := I+1}); + t1(<<_:8>>,M) -> + M. + ">>, + [bin_opt_info], + {warnings,[{2,beam_bsm,bin_opt}]}}], + [] = run(Config, Ts), + ok. + redundant_boolean_clauses(Config) when is_list(Config) -> Ts = [{redundant_boolean_clauses, <<" @@ -662,6 +794,162 @@ latin1_fallback(Conf) when is_list(Conf) -> {warnings,[{1,compile,reparsing_invalid_unicode}]} }], [] = run(Conf, Ts2), + + Ts3 = [{latin1_fallback3, + %% Test that the compiler fall backs to latin-1 with + %% a warning if a file has no encoding and does not + %% contain correct UTF-8 sequences. + <<"-ifdef(NOTDEFINED). + t(_) -> \"",246,"\"; + t(x) -> ok. + -endif. + ">>, + [], + {warnings,[{2,compile,reparsing_invalid_unicode}]}}], + [] = run(Conf, Ts3), + + ok. + +underscore(Config) when is_list(Config) -> + S0 = <<"f(A) -> + _VAR1 = <<A>>, + _VAR2 = {ok,A}, + _VAR3 = [A], + ok. + g(A) -> + _VAR1 = A/0, + _VAR2 = date(), + ok. + h() -> + _VAR1 = fun() -> ok end, + ok. + i(A) -> + _VAR1 = #{A=>42}, + ok. + ">>, + Ts0 = [{underscore0, + S0, + [], + {warnings,[{2,sys_core_fold,useless_building}, + {3,sys_core_fold,useless_building}, + {4,sys_core_fold,useless_building}, + {7,sys_core_fold,result_ignored}, + {8,sys_core_fold,{no_effect,{erlang,date,0}}}, + {11,sys_core_fold,useless_building}, + {14,sys_core_fold,useless_building} + ]}}], + [] = run(Config, Ts0), + + %% Replace all "_VAR<digit>" variables with a plain underscore. + %% Now there should be no warnings. + S1 = re:replace(S0, "_VAR\\d+", "_", [global]), + io:format("~s\n", [S1]), + Ts1 = [{underscore1,S1,[],[]}], + [] = run(Config, Ts1), + + ok. + +no_warnings(Config) when is_list(Config) -> + Ts = [{no_warnings, + <<"-record(r, {s=ordsets:new(),a,b}). + + a() -> + R = #r{}, %No warning expected. + {R#r.a,R#r.b}. + + b(X) -> + T = true, + Var = [X], %No warning expected. + case T of + false -> Var; + true -> [] + end. + + c() -> + R0 = {r,\"abc\",undefined,os:timestamp()}, %No warning. + case R0 of + {r,V1,_V2,V3} -> {r,V1,\"def\",V3} + end. + + d(In0, Bool) -> + {In1,Int} = case id(Bool) of + false -> {In0,0} + end, + [In1,Int]. + + id(I) -> I. + ">>, + [], + []}], + run(Config, Ts), + ok. + +bit_syntax(Config) -> + Ts = [{?FUNCTION_NAME, + <<"a(<<-1>>) -> ok; + a(<<1023>>) -> ok; + a(<<777/signed>>) -> ok; + a(<<a/binary>>) -> ok; + a(<<a/integer>>) -> ok; + a(<<a/float>>) -> ok; + a(<<a/utf8>>) -> ok; + a(<<a/utf16>>) -> ok; + a(<<a/utf32>>) -> ok; + a(<<a/utf32>>) -> ok. + b(Bin) -> Sz = bad, <<42:Sz>> = Bin. + c(Sz, Bin) -> + case Bin of + <<-42:Sz/unsigned>> -> ok; + <<42:Sz/float>> -> ok; + <<42:Sz/binary>> -> ok + end. + ">>, + [], + {warnings,[{1,sys_core_fold,no_clause_match}, + {1,sys_core_fold,{nomatch_bit_syntax_unsigned,-1}}, + {2,sys_core_fold,{nomatch_bit_syntax_truncated, + unsigned,1023,8}}, + {3,sys_core_fold,{nomatch_bit_syntax_truncated, + signed,777,8}}, + {4,sys_core_fold,{nomatch_bit_syntax_type,a,binary}}, + {5,sys_core_fold,{nomatch_bit_syntax_type,a,integer}}, + {6,sys_core_fold,{nomatch_bit_syntax_type,a,float}}, + {7,sys_core_fold,{nomatch_bit_syntax_type,a,utf8}}, + {8,sys_core_fold,{nomatch_bit_syntax_type,a,utf16}}, + {9,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, + {10,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, + {11,sys_core_fold,no_clause_match}, + {11,sys_core_fold,{nomatch_bit_syntax_size,bad}}, + {14,sys_core_fold,{nomatch_bit_syntax_unsigned,-42}}, + {16,sys_core_fold,{nomatch_bit_syntax_type,42,binary}} + ]} + }], + run(Config, Ts), + ok. + +inlining(Config) -> + %% Make sure that no spurious warnings are generated + %% when inlining. + Ts = [{inlining_1, + <<"-compile(inline). + compute1(X) -> add(X, 0). + add(1, 0) -> 1; + add(1, Y) -> 1 + Y; + add(X, Y) -> X + Y. + ">>, + [], + []}, + {inlining_2, + <<"-compile({inline,[add/2]}). + compute1(X) -> add(X, 0). + add(1, 0) -> 1; + add(1, Y) -> 1 + Y; + add(X, Y) -> X + Y. + ">>, + [], + []} + ], + run(Config, Ts), ok. %%% @@ -674,7 +962,7 @@ run(Config, Tests) -> E -> BadL; Bad -> - ?t:format("~nTest ~p failed. Expected~n ~p~n" + io:format("~nTest ~p failed. Expected~n ~p~n" "but got~n ~p~n", [N, E, Bad]), fail() end @@ -685,35 +973,34 @@ run(Config, Tests) -> %% Compiles a test module and returns the list of errors and warnings. run_test(Conf, Test0, Warnings) -> - Mod = "warnings_"++test_lib:uniq(), - Filename = Mod ++ ".erl", - ?line DataDir = ?privdir, - Test = ["-module(", Mod, "). ", Test0], - ?line File = filename:join(DataDir, Filename), - ?line Opts = [binary,export_all,return|Warnings], - ?line ok = file:write_file(File, Test), + Module = "warnings_"++test_lib:uniq(), + Filename = Module ++ ".erl", + DataDir = ?privdir, + Test = ["-module(", Module, "). ", Test0], + File = filename:join(DataDir, Filename), + Opts = [binary,export_all,return|Warnings], + ok = file:write_file(File, Test), %% Compile once just to print all warnings. - ?line compile:file(File, [binary,export_all,report|Warnings]), + compile:file(File, [binary,export_all,report|Warnings]), %% Test result of compilation. - ?line Res = case compile:file(File, Opts) of - {ok, _M, Bin, []} when is_binary(Bin) -> - []; - {ok, _M, Bin, Ws0} when is_binary(Bin) -> - %% We are not interested in warnings from - %% erl_lint here. - WsL = [{F,[W || {_,Mod,_}=W <- Ws, - Mod =/= erl_lint]} || - {F,Ws} <- Ws0], - case WsL of - [{_File,Ws}] -> {warnings, Ws}; - _ -> list_to_tuple([warnings, WsL]) - end - end, + Res = case compile:file(File, Opts) of + {ok, _M, Bin, []} when is_binary(Bin) -> + []; + {ok, _M, Bin, Ws0} when is_binary(Bin) -> + %% We are not interested in warnings from + %% erl_lint here. + WsL = [{F,[W || {_,Mod,_}=W <- Ws, + Mod =/= erl_lint]} || + {F,Ws} <- Ws0], + case WsL of + [{_File,Ws}] -> {warnings, Ws}; + _ -> list_to_tuple([warnings, WsL]) + end + end, file:delete(File), Res. fail() -> - io:format("failed~n"), - ?t:fail(). + ct:fail(failed). |
