1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(warnings_SUITE).
21
22%%-define(STANDALONE, true).
23
24-ifdef(STANDALONE).
25-define(line, put(line, ?LINE), ).
26-define(config(X,Y), foo).
27-define(privdir, "warnings_SUITE_priv").
28-define(t, test_server).
29-else.
30-include_lib("common_test/include/ct.hrl").
31-define(datadir, proplists:get_value(data_dir, Conf)).
32-define(privdir, proplists:get_value(priv_dir, Conf)).
33-endif.
34
35-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
36	 init_per_group/2,end_per_group/2,
37	 init_per_testcase/2,end_per_testcase/2]).
38
39-export([pattern/1,pattern2/1,pattern3/1,pattern4/1,
40	 guard/1,bad_arith/1,bool_cases/1,bad_apply/1,
41         files/1,effect/1,bin_opt_info/1,bin_construction/1,
42	 comprehensions/1,maps/1,maps_bin_opt_info/1,
43         redundant_boolean_clauses/1,
44	 latin1_fallback/1,underscore/1,no_warnings/1,
45	 bit_syntax/1,inlining/1,tuple_calls/1]).
46
47init_per_testcase(_Case, Config) ->
48    Config.
49
50end_per_testcase(_Case, _Config) ->
51    ok.
52
53suite() ->
54    [{ct_hooks,[ts_install_cth]},
55     {timetrap,{minutes,2}}].
56
57all() ->
58    [{group,p}].
59
60groups() ->
61    [{p,test_lib:parallel(),
62      [pattern,pattern2,pattern3,pattern4,guard,
63       bad_arith,bool_cases,bad_apply,files,effect,
64       bin_opt_info,bin_construction,comprehensions,maps,
65       maps_bin_opt_info,
66       redundant_boolean_clauses,latin1_fallback,
67       underscore,no_warnings,bit_syntax,inlining,
68       tuple_calls]}].
69
70init_per_suite(Config) ->
71    test_lib:recompile(?MODULE),
72    Config.
73
74end_per_suite(_Config) ->
75    ok.
76
77init_per_group(_GroupName, Config) ->
78    Config.
79
80end_per_group(_GroupName, Config) ->
81    Config.
82
83
84pattern(Config) when is_list(Config) ->
85    %% Test warnings generated by v3_core.
86    Ts = [{pattern,
87           <<"%% Just a comment here.
88              f(a={glurf,2}=A) -> A.
89
90              g(A) ->
91                 case A of
92                   a=[_|_] -> error;
93                   Other -> true
94                 end.
95
96              foo(X) ->
97                 a = {nisse,b} = X.
98           ">>,
99	   [warn_unused_vars],
100	   {warnings,
101	    [{2,v3_core,nomatch},
102	     {6,v3_core,nomatch},
103	     {11,v3_core,nomatch} ] }}],
104    [] = run(Config, Ts),
105    ok.
106
107pattern2(Config) when is_list(Config) ->
108    %% Test warnings generated by sys_core_fold.
109    %% If we disable Core Erlang optimizations, we expect that
110    %% v3_kernel should generate some of the warnings.
111    Source = <<"f(A) -> ok;
112              f(B) -> error.
113	      t(A, B, C) ->
114	        case {A,B,C} of
115	          {a,B} -> ok;
116	          {_,B} -> ok
117                end.
118           ">>,
119
120    %% Test warnings from sys_core_fold.
121    Ts = [{pattern2,
122	   Source,
123	   [nowarn_unused_vars],
124	   {warnings,[{2,sys_core_fold,{nomatch_shadow,1}},
125		      {4,sys_core_fold,no_clause_match},
126		      {5,sys_core_fold,nomatch_clause_type},
127		      {6,sys_core_fold,nomatch_clause_type}]}}],
128    [] = run(Config, Ts),
129
130    %% Disable Core Erlang optimizations. v3_kernel should produce
131    %% a warning for the clause that didn't match.
132    Ts2 = [{pattern2,
133	    Source,
134	    [nowarn_unused_vars,no_copt],
135	    {warnings,
136	     [{2,v3_kernel,{nomatch_shadow,1}}]}}],
137    [] = run(Config, Ts2),
138    ok.
139
140pattern3(Config) when is_list(Config) ->
141    %% Test warnings generated by the pattern matching compiler
142    %% in v3_kernel.
143
144    Ts = [{pattern3,
145	   <<"
146	    f({A,_}) -> {ok,A};
147	    f([_|_]=B) -> {ok,B};
148	    f({urk,nisse}) -> urka_glurka.
149           ">>,
150	   [nowarn_unused_vars],
151	   {warnings,
152	    [{4,v3_kernel,{nomatch_shadow,2}}]}}],
153    [] = run(Config, Ts),
154
155    ok.
156
157pattern4(Config) when is_list(Config) ->
158    %% Test warnings for clauses that cannot possibly match.
159
160    Ts = [{pattern4,
161	   <<"
162             t() ->
163               case true of
164                 false -> a;
165                 true -> b
166               end.
167
168             fi() ->
169               case true of
170                 false -> a;
171                 false -> b
172               end,
173               case true of
174                 true -> a;
175                 true -> b;
176                 X -> X
177               end,
178               case boolean of
179                 true -> a;
180                 false -> b
181               end.
182             int() ->
183               case 42 of
184                 [a|b] -> no;
185                 <<1>> -> no;
186                 <<X>> -> no;
187                 17 -> no;
188                 [] -> no;
189                 a -> no;
190                 {a,b,c} -> no
191               end.
192             tuple() ->
193               case {x,y,z} of
194                 \"xyz\" -> no;
195                 [a|b] -> no;
196                 <<1>> -> no;
197                 <<X>> -> no;
198                 17 -> no;
199                 [] -> no;
200                 a -> no;
201                 {a,b,c} -> no;
202                 {x,y} -> no
203               end.
204           ">>,
205	   [nowarn_unused_vars],
206	   {warnings,
207	    [{9,sys_core_fold,no_clause_match},
208             {11,sys_core_fold,nomatch_shadow},
209             {15,sys_core_fold,nomatch_shadow},
210	     {18,sys_core_fold,no_clause_match},
211	     {23,sys_core_fold,no_clause_match},
212	     {33,sys_core_fold,no_clause_match}
213	    ]}}],
214    [] = run(Config, Ts),
215
216    ok.
217
218guard(Config) when is_list(Config) ->
219    %% Test warnings for false guards.
220
221    Ts = [{guard,
222	   <<"
223              t(A, B) when element(x, dum) -> ok.
224
225              tt(A, B) when 1 == 2 -> ok.
226
227              ttt() when element(x, dum) -> ok.
228
229              t4(T, F) when element({F}, T) -> ok.
230              t5(T, F) when element([F], T) -> ok.
231              t6(Pos, F) when element(Pos, [F]) -> ok.
232              t7(Pos) when element(Pos, []) -> ok.
233           ">>,
234	   [nowarn_unused_vars],
235	   {warnings,
236	    [{2,sys_core_fold,no_clause_match},
237	     {2,sys_core_fold,nomatch_guard},
238	     {2,sys_core_fold,{eval_failure,badarg}},
239	     {4,sys_core_fold,no_clause_match},
240	     {4,sys_core_fold,nomatch_guard},
241	     {6,sys_core_fold,no_clause_match},
242	     {6,sys_core_fold,nomatch_guard},
243	     {6,sys_core_fold,{eval_failure,badarg}},
244	     {8,sys_core_fold,no_clause_match},
245	     {8,sys_core_fold,nomatch_guard},
246	     {8,sys_core_fold,{eval_failure,badarg}},
247	     {9,sys_core_fold,no_clause_match},
248	     {9,sys_core_fold,nomatch_guard},
249	     {9,sys_core_fold,{eval_failure,badarg}},
250	     {10,sys_core_fold,no_clause_match},
251	     {10,sys_core_fold,nomatch_guard},
252	     {10,sys_core_fold,{eval_failure,badarg}},
253	     {11,sys_core_fold,no_clause_match},
254	     {11,sys_core_fold,nomatch_guard},
255	     {11,sys_core_fold,{eval_failure,badarg}}
256	    ]}}],
257    [] = run(Config, Ts),
258
259    ok.
260
261bad_arith(Config) when is_list(Config) ->
262    Ts = [{bad_arith,
263           <<"f() ->
264                if
265                  a + 3 > 3 -> ok;
266          	 true -> error
267              end.
268
269              g(A) ->
270                if
271                  is_integer(A), a + 3 > 3 -> ok;
272                  a + 3 > 42, is_integer(A) -> ok;
273          	 true -> error
274              end.
275
276              h(A) ->
277                a + 3 + A.
278           ">>,
279	   [],
280	   {warnings,
281	    [{3,sys_core_fold,nomatch_guard},
282	     {3,sys_core_fold,{eval_failure,badarith}},
283	     {9,sys_core_fold,nomatch_guard},
284	     {9,sys_core_fold,{eval_failure,badarith}},
285	     {10,sys_core_fold,nomatch_guard},
286	     {10,sys_core_fold,{eval_failure,badarith}},
287	     {15,sys_core_fold,{eval_failure,badarith}}
288	    ] }}],
289    [] = run(Config, Ts),
290    ok.
291
292bool_cases(Config) when is_list(Config) ->
293    Ts = [{bool_cases,
294	   <<"
295            f(A, B) ->
296               case A > B of
297                 true -> true;
298                 false -> false;
299                 Other -> {error,not_bool}
300               end.
301
302            g(A, B) ->
303               case A =/= B of
304                 false -> false;
305                 true -> true;
306                 Other -> {error,not_bool}
307               end.
308
309	    h(Bool) ->
310              case not Bool of
311	        maybe -> strange;
312	        false -> ok;
313	        true -> error
314            end.
315           ">>,
316	   [nowarn_unused_vars],
317	   {warnings,
318	    [{6,sys_core_fold,nomatch_shadow},
319	     {13,sys_core_fold,nomatch_shadow},
320	     {18,sys_core_fold,nomatch_clause_type} ]} }],
321    [] = run(Config, Ts),
322    ok.
323
324bad_apply(Config) when is_list(Config) ->
325    Ts = [{bad_apply,
326	   <<"
327             t(1) -> 42:42();
328             t(2) -> erlang:42();
329             t(3) -> 42:start();
330             t(4) -> []:start();
331             t(5) -> erlang:[]().
332           ">>,
333	   [],
334	   {warnings,
335	    [{2,v3_kernel,bad_call},
336	     {3,v3_kernel,bad_call},
337	     {4,v3_kernel,bad_call},
338	     {5,v3_kernel,bad_call},
339	     {6,v3_kernel,bad_call}]}}],
340    [] = run(Config, Ts),
341
342    %% Also verify that the generated code generates the correct error.
343    try erlang:42() of
344	      _ -> ct:fail(should_fail)
345	  catch
346	      error:badarg -> ok
347	  end,
348    ok.
349
350files(Config) when is_list(Config) ->
351    Ts = [{files_1,
352	   <<"
353              -file(\"file1\", 14).
354
355              t1() ->
356                  1/0.
357
358              -file(\"file2\", 7).
359
360              t2() ->
361                  1/0.
362           ">>,
363           [],
364           {warnings,
365            [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]},
366             {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}],
367
368    [] = run(Config, Ts),
369    ok.
370
371%% Test warnings for term construction and BIF calls in effect context.
372effect(Config) when is_list(Config) ->
373    Ts = [{effect,
374	   <<"
375             t(X) ->
376               case X of
377              	warn_lc ->
378              	    [is_integer(Z) || Z <- [1,2,3]];
379              	warn_lc_2 ->
380              	    [{error,Z} || Z <- [1,2,3]];
381              	warn_lc_3 ->
382              	    [{error,abs(Z)} || Z <- [1,2,3]];
383              	no_warn_lc ->
384              	    [put(last_integer, Z) || Z <- [1,2,3]]; %no warning
385              	unused_tuple_literal ->
386              	    {a,b,c};
387              	unused_list_literal ->
388              	    [1,2,3,4];
389              	unused_integer ->
390              	    42;
391              	unused_arith ->
392              	    X*X;
393              	nested ->
394              	    [{ok,node(),?MODULE:foo(),self(),[time(),date()],time()},
395              	     is_integer(X)];
396              	unused_bit_syntax ->
397              	    <<X:8>>;
398              	unused_fun ->
399              	    fun() -> {ok,X} end;
400		unused_named_fun ->
401		    fun F(0) -> 1;
402                        F(N) -> N*F(N-1)
403                    end;
404              	unused_atom ->
405              	    ignore;				%no warning
406              	unused_nil ->
407              	    [];					%no warning
408                comp_op ->
409                    X =:= 2;
410                cookie ->
411                    erlang:get_cookie();
412		result_ignore ->
413                    _ = list_to_integer(X);
414                warn_lc_4 ->
415                    %% No warning because of assignment to _.
416                    [_ = abs(Z) || Z <- [1,2,3]]
417               end,
418               ok.
419
420             %% No warnings should be generated in the following functions.
421             m1(X, Sz) ->
422                if
423             	  Sz =:= 0 -> X = 0;
424             	  true -> ok
425                end,
426                ok.
427
428             m2(X, Sz) ->
429                if
430             	  Sz =:= 0 -> X = {a,Sz};
431             	  true -> ok
432                end,
433                ok.
434
435             m3(X, Sz) ->
436                if
437             	  Sz =:= 0 -> X = [a,Sz];
438             	  true -> ok
439                end,
440                ok.
441
442             m4(X, Sz, Var) ->
443                if
444             	  Sz =:= 0 -> X = Var;
445             	  true -> ok
446                end,
447                ok.
448
449             m5(X, Sz) ->
450                if
451             	   Sz =:= 0 -> X = {a,b,c};
452             	   true -> ok
453                end,
454                ok.
455
456             m6(X, Sz) ->
457                if
458             	  Sz =:= 0 -> X = {a,Sz,[1,2,3]};
459             	  true -> ok
460                end,
461                ok.
462
463             m7(X, Sz) ->
464                if
465             	  Sz =:= 0 -> X = {a,Sz,[1,2,3],abs(Sz)};
466             	  true -> ok
467                end,
468                ok.
469
470             m8(A, B) ->
471                case {A,B} of
472                  V -> V
473                end,
474                ok.
475
476             m9(Bs) ->
477                [{B,ok} = {B,foo:bar(B)} || B <- Bs],
478                ok.
479
480             m10(ConfigTableSize) ->
481               case ConfigTableSize of
482                 apa ->
483                   CurrentConfig = {id(camel_phase3),id(sms)},
484                   case CurrentConfig of
485                     {apa, bepa} -> ok;
486		     _ -> ok
487	           end
488               end,
489               ok.
490
491             id(I) -> I.
492             ">>,
493	   [],
494	   {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
495		      {7,sys_core_fold,useless_building},
496		      {9,sys_core_fold,result_ignored},
497		      {9,sys_core_fold,useless_building},
498		      {13,sys_core_fold,useless_building},
499		      {15,sys_core_fold,useless_building},
500		      {17,sys_core_fold,useless_building},
501		      {19,sys_core_fold,result_ignored},
502		      {21,sys_core_fold,useless_building},
503		      {21,sys_core_fold,{no_effect,{erlang,date,0}}},
504		      {21,sys_core_fold,{no_effect,{erlang,node,0}}},
505		      {21,sys_core_fold,{no_effect,{erlang,self,0}}},
506		      {21,sys_core_fold,{no_effect,{erlang,time,0}}},
507		      {22,sys_core_fold,useless_building},
508		      {22,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
509		      {24,sys_core_fold,useless_building},
510		      {26,sys_core_fold,useless_building},
511		      {28,sys_core_fold,useless_building},
512		      {36,sys_core_fold,{no_effect,{erlang,'=:=',2}}},
513		      {38,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}],
514    [] = run(Config, Ts),
515    ok.
516
517bin_opt_info(Config) when is_list(Config) ->
518    Code = <<"
519             t1(Bin) ->
520               case Bin of
521	         _ when byte_size(Bin) > 20 -> erlang:error(too_long);
522                 <<_,T/binary>> -> t1(T);
523	         <<>> -> ok
524             end.
525
526             t2(<<_,T/bytes>>) ->
527               split_binary(T, 4).
528           ">>,
529    Ts1 = [{bsm1,
530	    Code,
531	    [bin_opt_info],
532	    {warnings,
533	     [{4,sys_core_bsm,orig_bin_var_used_in_guard},
534	      {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}},
535	      {9,beam_bsm,{no_bin_opt,
536			   {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}],
537    [] = run(Config, Ts1),
538
539    %% For coverage: don't give the bin_opt_info option.
540    Ts2 = [{bsm2,
541	    Code,
542	    [],
543	    []}],
544    [] = run(Config, Ts2),
545    ok.
546
547bin_construction(Config) when is_list(Config) ->
548    Ts = [{bin_construction,
549	   <<"
550             t() ->
551                 Bin = <<1,2,3>>,
552                 <<Bin:4/binary>>.
553
554             x() ->
555                 Bin = <<1,2,3,7:4>>,
556                 <<Bin/binary>>.
557           ">>,
558	   [],
559	   {warnings,[{4,sys_core_fold,embedded_binary_size},
560		      {8,sys_core_fold,{embedded_unit,8,28}}]}}],
561    [] = run(Config, Ts),
562
563    ok.
564
565comprehensions(Config) when is_list(Config) ->
566    Ts = [{tautologic_guards,
567           <<"
568             f() -> [ true || true ].
569             g() -> << <<1>> || true >>.
570           ">>,
571           [], []}],
572    run(Config, Ts),
573    ok.
574
575maps(Config) when is_list(Config) ->
576    Ts = [{bad_map,
577           <<"
578             t() ->
579                 case maybe_map of
580                     #{} -> ok;
581                     not_map -> error
582                 end.
583             x() ->
584                 case true of
585                     #{}  -> error;
586                     true -> ok
587                 end.
588           ">>,
589           [],
590           {warnings,[{3,sys_core_fold,no_clause_match},
591                      {9,sys_core_fold,nomatch_clause_type}]}},
592	   {bad_map_src1,
593           <<"
594             t() ->
595		 M = {a,[]},
596		 {'EXIT',{badarg,_}} = (catch(M#{ a => 1 })),
597		 ok.
598           ">>,
599           [],
600	   {warnings,[{4,sys_core_fold,{eval_failure,badmap}}]}},
601	   {bad_map_src2,
602           <<"
603             t() ->
604		 M = id({a,[]}),
605		 {'EXIT',{badarg,_}} = (catch(M#{ a => 1})),
606		 ok.
607	     id(I) -> I.
608           ">>,
609	   [inline],
610	    []},
611	   {bad_map_src3,
612           <<"
613             t() ->
614		 {'EXIT',{badarg,_}} = (catch <<>>#{ a := 1}),
615		 ok.
616           ">>,
617           [],
618	   {warnings,[{3,v3_core,badmap}]}},
619	   {ok_map_literal_key,
620           <<"
621             t() ->
622		 V = id(1),
623		 M = id(#{ <<$h,$i>> => V }),
624		 V = case M of
625		    #{ <<0:257>> := Val } -> Val;
626		    #{ <<$h,$i>> := Val } -> Val
627		 end,
628		 ok.
629	     id(I) -> I.
630           ">>,
631           [],
632	   []},
633           {repeated_keys1,
634           <<"
635             foo1() ->
636                 #{a=>1,
637                   b=> 2,
638                   a=>3}.
639
640             bar1(M) ->
641                 M#{a=>1, b=> 2, a:=3}.
642
643             baz1(M) ->
644                 M#{a=>1, b=> 2, a:=3}.
645
646             foo2() ->
647                 #{\"a\"=>1, \"b\"=> 2, \"a\"=>3}.
648
649             bar2(M) ->
650                 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}.
651
652             baz2(M) ->
653                 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}.
654
655             foo3() ->
656                 #{\"a\"=>1,
657                   \"b\"=> 2,
658                   \"a\"=>3}.
659
660             bar3(M) ->
661                 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}.
662
663             baz3(M) ->
664                 M#{<<\"a\">>=>1, <<\"b\">>=> 2, <<\"a\">>:=3}.
665           ">>,
666           [],
667           {warnings,[{3,v3_core,{map_key_repeated,a}},
668                      {8,v3_core,{map_key_repeated,a}},
669                      {11,v3_core,{map_key_repeated,a}},
670                      {14,v3_core,{map_key_repeated,"a"}},
671                      {17,v3_core,{map_key_repeated,"a"}},
672                      {20,v3_core,{map_key_repeated,"a"}},
673                      {23,v3_core,{map_key_repeated,"a"}},
674                      {28,v3_core,{map_key_repeated,"a"}},
675                      {31,v3_core,{map_key_repeated,<<"a">>}}]}},
676           {repeated_keys2,
677           <<"
678             foo4(K) ->
679                 #{\"a\"=>1, K => 1, \"b\"=> 2, \"a\"=>3, K=>2}.
680
681             bar4(M,K) ->
682                 M#{a=>1, K =>1, b=> 2, a:=3, K=>2}.
683
684             baz4(M,K) ->
685                 M#{<<\"a\">>=>1,
686                     K => 1, <<\"b\">>=> 2,
687                     <<\"a\">>:=3, K=>2}.
688
689             foo5(K) ->
690                 #{{\"a\",1}=>1, K => 1, \"b\"=> 2, {\"a\",1}=>3, K=>2}.
691
692             bar5(M,K) ->
693                 M#{{\"a\",<<\"b\">>}=>1, K =>1,
694                    \"b\"=> 2, {\"a\",<<\"b\">>}:=3, K=>2}.
695
696             baz5(M,K) ->
697                 M#{{<<\"a\">>,1}=>1, K => 1,
698                    <<\"b\">>=> 2, {<<\"a\">>,1}:=3,K=>2}.
699
700             foo6(K) ->
701                 #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2, #{\"a\"=>1}=>3, K=>2}.
702
703             bar6(M,K) ->
704                 M#{#{\"a\"=><<\"b\">>}=>1, K =>1,
705                    \"b\"=> 2, #{\"a\"=><<\"b\">>}:=3, K=>2}.
706
707             baz6(M,K) ->
708                 M#{#{<<\"a\">>=>1}=>1,
709                    K => 1,
710                    <<\"b\">>=> 2,
711                    #{<<\"a\">>=>1}:=3,K=>2}.
712
713             foo7(K) ->
714                 M1 = #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2},
715                 M1#{#{\"a\"=>1}=>3, K=>2}.
716
717             bar7(M,K) ->
718                 M1 = M#{#{\"a\"=><<\"b\">>}=>1, K =>1, \"b\"=> 2},
719                 M1#{#{\"a\"=><<\"b\">>}:=3, K=>2}.
720
721             baz7(M,K) ->
722                 M1 = M#{#{<<\"a\">>=>1}=>1,
723                    K => 1,
724                    <<\"b\">>=> 2},
725                 M1#{#{<<\"a\">>=>1}:=3,K=>2}.
726          ">>,
727           [],
728           {warnings,[{3,v3_core,{map_key_repeated,"a"}},
729                      {6,v3_core,{map_key_repeated,a}},
730                      {9,v3_core,{map_key_repeated,<<"a">>}},
731                      {14,v3_core,{map_key_repeated,{"a",1}}},
732                      {17,v3_core,{map_key_repeated,{"a",<<"b">>}}},
733                      {21,v3_core,{map_key_repeated,{<<"a">>,1}}},
734                      {25,v3_core,{map_key_repeated,#{"a" => 1}}},
735                      {28,v3_core,{map_key_repeated,#{"a" => <<"b">>}}},
736                      {32,v3_core,{map_key_repeated,#{<<"a">> => 1}}}]}}
737         ],
738    run(Config, Ts),
739    ok.
740
741maps_bin_opt_info(Config) when is_list(Config) ->
742    Ts = [{map_bsm,
743           <<"
744             t1(<<0:8,7:8,T/binary>>,#{val := I}=M) ->
745                 t1(T, M#{val := I+1});
746             t1(<<_:8>>,M) ->
747                 M.
748           ">>,
749           [bin_opt_info],
750           {warnings,[{2,beam_bsm,bin_opt}]}}],
751    [] = run(Config, Ts),
752    ok.
753
754redundant_boolean_clauses(Config) when is_list(Config) ->
755    Ts = [{redundant_boolean_clauses,
756           <<"
757             t(X) ->
758                 case X == 0 of
759                     false -> no;
760                     false -> no;
761                     true -> yes
762                 end.
763           ">>,
764           [],
765           {warnings,[{5,sys_core_fold,nomatch_shadow}]}}],
766    run(Config, Ts),
767    ok.
768
769latin1_fallback(Conf) when is_list(Conf) ->
770    DataDir = ?privdir,
771    IncFile = filename:join(DataDir, "include_me.hrl"),
772    file:write_file(IncFile, <<"%% ",246," in include file\n">>),
773    Ts1 = [{latin1_fallback1,
774	    %% Test that the compiler fall backs to latin-1 with
775	    %% a warning if a file has no encoding and does not
776	    %% contain correct UTF-8 sequences.
777	    <<"%% Bj",246,"rn
778              t(_) -> \"",246,"\";
779              t(x) -> ok.
780              ">>,
781	    [],
782	    {warnings,[{1,compile,reparsing_invalid_unicode},
783		       {3,sys_core_fold,{nomatch_shadow,2}}]}}],
784    [] = run(Conf, Ts1),
785
786    Ts2 = [{latin1_fallback2,
787	    %% Test that the compiler fall backs to latin-1 with
788	    %% a warning if a file has no encoding and does not
789	    %% contain correct UTF-8 sequences.
790	    <<"
791
792	      -include(\"include_me.hrl\").
793              ">>,
794	    [],
795	    {warnings,[{1,compile,reparsing_invalid_unicode}]}
796	   }],
797    [] = run(Conf, Ts2),
798
799    Ts3 = [{latin1_fallback3,
800	    %% Test that the compiler fall backs to latin-1 with
801	    %% a warning if a file has no encoding and does not
802	    %% contain correct UTF-8 sequences.
803	    <<"-ifdef(NOTDEFINED).
804              t(_) -> \"",246,"\";
805              t(x) -> ok.
806              -endif.
807              ">>,
808	    [],
809	    {warnings,[{2,compile,reparsing_invalid_unicode}]}}],
810    [] = run(Conf, Ts3),
811
812    ok.
813
814underscore(Config) when is_list(Config) ->
815    S0 = <<"f(A) ->
816              _VAR1 = <<A>>,
817              _VAR2 = {ok,A},
818              _VAR3 = [A],
819              ok.
820	    g(A) ->
821              _VAR1 = A/0,
822              _VAR2 = date(),
823	      ok.
824            h() ->
825               _VAR1 = fun() -> ok end,
826	      ok.
827            i(A) ->
828               _VAR1 = #{A=>42},
829	      ok.
830	 ">>,
831    Ts0 = [{underscore0,
832	    S0,
833	    [],
834	    {warnings,[{2,sys_core_fold,useless_building},
835		       {3,sys_core_fold,useless_building},
836		       {4,sys_core_fold,useless_building},
837		       {7,sys_core_fold,result_ignored},
838		       {8,sys_core_fold,{no_effect,{erlang,date,0}}},
839		       {11,sys_core_fold,useless_building},
840		       {14,sys_core_fold,useless_building}
841		      ]}}],
842    [] = run(Config, Ts0),
843
844    %% Replace all "_VAR<digit>" variables with a plain underscore.
845    %% Now there should be no warnings.
846    S1 = re:replace(S0, "_VAR\\d+", "_", [global]),
847    io:format("~s\n", [S1]),
848    Ts1 = [{underscore1,S1,[],[]}],
849    [] = run(Config, Ts1),
850
851    ok.
852
853no_warnings(Config) when is_list(Config) ->
854    Ts = [{no_warnings,
855           <<"-record(r, {s=ordsets:new(),a,b}).
856
857              a() ->
858                R = #r{},			%No warning expected.
859                {R#r.a,R#r.b}.
860
861              b(X) ->
862                T = true,
863                Var = [X],			%No warning expected.
864                case T of
865	          false -> Var;
866                  true -> []
867                end.
868
869              c() ->
870                R0 = {r,\"abc\",undefined,os:timestamp()}, %No warning.
871                case R0 of
872	          {r,V1,_V2,V3} -> {r,V1,\"def\",V3}
873                end.
874
875              d(In0, Bool) ->
876                {In1,Int} = case id(Bool) of
877                              false -> {In0,0}
878                            end,
879                [In1,Int].
880
881              id(I) -> I.
882           ">>,
883           [],
884           []}],
885    run(Config, Ts),
886    ok.
887
888bit_syntax(Config) ->
889    Ts = [{?FUNCTION_NAME,
890	   <<"a(<<-1>>) -> ok;
891              a(<<1023>>) -> ok;
892              a(<<777/signed>>) -> ok;
893              a(<<a/binary>>) -> ok;
894              a(<<a/integer>>) -> ok;
895              a(<<a/float>>) -> ok;
896              a(<<a/utf8>>) -> ok;
897              a(<<a/utf16>>) -> ok;
898              a(<<a/utf32>>) -> ok;
899              a(<<a/utf32>>) -> ok.
900              b(Bin) -> Sz = bad, <<42:Sz>> = Bin.
901              c(Sz, Bin) ->
902                case Bin of
903                  <<-42:Sz/unsigned>> -> ok;
904                  <<42:Sz/float>> -> ok;
905                  <<42:Sz/binary>> -> ok
906                end.
907             ">>,
908	   [],
909	   {warnings,[{1,sys_core_fold,no_clause_match},
910		      {1,sys_core_fold,{nomatch_bit_syntax_unsigned,-1}},
911		      {2,sys_core_fold,{nomatch_bit_syntax_truncated,
912					unsigned,1023,8}},
913		      {3,sys_core_fold,{nomatch_bit_syntax_truncated,
914					signed,777,8}},
915		      {4,sys_core_fold,{nomatch_bit_syntax_type,a,binary}},
916		      {5,sys_core_fold,{nomatch_bit_syntax_type,a,integer}},
917		      {6,sys_core_fold,{nomatch_bit_syntax_type,a,float}},
918		      {7,sys_core_fold,{nomatch_bit_syntax_type,a,utf8}},
919		      {8,sys_core_fold,{nomatch_bit_syntax_type,a,utf16}},
920		      {9,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}},
921		      {10,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}},
922		      {11,sys_core_fold,no_clause_match},
923		      {11,sys_core_fold,{nomatch_bit_syntax_size,bad}},
924		      {14,sys_core_fold,{nomatch_bit_syntax_unsigned,-42}},
925		      {16,sys_core_fold,{nomatch_bit_syntax_type,42,binary}}
926		     ]}
927	  }],
928    run(Config, Ts),
929    ok.
930
931inlining(Config) ->
932    %% Make sure that no spurious warnings are generated
933    %% when inlining.
934    Ts = [{inlining_1,
935           <<"-compile(inline).
936              compute1(X) -> add(X, 0).
937              add(1, 0) -> 1;
938              add(1, Y) -> 1 + Y;
939              add(X, Y) -> X + Y.
940           ">>,
941           [],
942           []},
943	  {inlining_2,
944           <<"-compile({inline,[add/2]}).
945              compute1(X) -> add(X, 0).
946              add(1, 0) -> 1;
947              add(1, Y) -> 1 + Y;
948              add(X, Y) -> X + Y.
949           ">>,
950           [],
951           []}
952	 ],
953    run(Config, Ts),
954    ok.
955
956tuple_calls(Config) ->
957    %% Make sure that no spurious warnings are generated.
958    Ts = [{inlining_1,
959           <<"-compile(tuple_calls).
960              dispatch(X) ->
961                (list_to_atom(\"prefix_\" ++
962                atom_to_list(suffix))):doit(X).
963           ">>,
964           [],
965           []}
966	 ],
967    run(Config, Ts),
968    ok.
969
970%%%
971%%% End of test cases.
972%%%
973
974run(Config, Tests) ->
975    F = fun({N,P,Ws,E}, BadL) ->
976                case catch run_test(Config, P, Ws) of
977                    E ->
978                        BadL;
979                    Bad ->
980                        io:format("~nTest ~p failed. Expected~n  ~p~n"
981                                  "but got~n  ~p~n", [N, E, Bad]),
982			fail()
983                end
984        end,
985    lists:foldl(F, [], Tests).
986
987
988%% Compiles a test module and returns the list of errors and warnings.
989
990run_test(Conf, Test0, Warnings) ->
991    Module = "warnings_"++test_lib:uniq(),
992    Filename = Module ++ ".erl",
993    DataDir = ?privdir,
994    Test = ["-module(", Module, "). ", Test0],
995    File = filename:join(DataDir, Filename),
996    Opts = [binary,export_all,return|Warnings],
997    ok = file:write_file(File, Test),
998
999    %% Compile once just to print all warnings.
1000    compile:file(File, [binary,export_all,report|Warnings]),
1001
1002    %% Test result of compilation.
1003    Res = case compile:file(File, Opts) of
1004	      {ok, _M, Bin, []} when is_binary(Bin) ->
1005		  [];
1006	      {ok, _M, Bin, Ws0} when is_binary(Bin) ->
1007		  %% We are not interested in warnings from
1008		  %% erl_lint here.
1009		  WsL = [{F,[W || {_,Mod,_}=W <- Ws,
1010				  Mod =/= erl_lint]} ||
1011			    {F,Ws} <- Ws0],
1012		  case WsL of
1013		      [{_File,Ws}] -> {warnings, Ws};
1014		      _ -> list_to_tuple([warnings, WsL])
1015		  end
1016	  end,
1017    file:delete(File),
1018    Res.
1019
1020fail() ->
1021    ct:fail(failed).
1022