1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1999-2019. 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(erl_lint_SUITE).
21
22%%-define(debug, true).
23
24-ifdef(debug).
25-define(line, put(line, ?LINE), ).
26-define(config(X,Y), foo).
27-define(datadir, "erl_lint_SUITE_data").
28-define(privdir, "erl_lint_SUITE_priv").
29-define(t, test_server).
30-else.
31-include_lib("common_test/include/ct.hrl").
32-define(datadir, proplists:get_value(data_dir, Conf)).
33-define(privdir, proplists:get_value(priv_dir, Conf)).
34-endif.
35
36-export([all/0, suite/0, groups/0]).
37
38-export([unused_vars_warn_basic/1,
39         unused_vars_warn_lc/1,
40         unused_vars_warn_rec/1,
41         unused_vars_warn_fun/1,
42         unused_vars_OTP_4858/1,
43         unused_unsafe_vars_warn/1,
44         export_vars_warn/1,
45         shadow_vars/1,
46         unused_import/1,
47         unused_function/1,
48         unsafe_vars/1,unsafe_vars2/1,
49         unsafe_vars_try/1,
50         unsized_binary_in_bin_gen_pattern/1,
51         guard/1, otp_4886/1, otp_4988/1, otp_5091/1, otp_5276/1, otp_5338/1,
52         otp_5362/1, otp_5371/1, otp_7227/1, otp_5494/1, otp_5644/1, otp_5878/1,
53         otp_5917/1, otp_6585/1, otp_6885/1, otp_10436/1, otp_11254/1,
54         otp_11772/1, otp_11771/1, otp_11872/1,
55         export_all/1,
56         bif_clash/1,
57         behaviour_basic/1, behaviour_multiple/1, otp_11861/1,
58         otp_7550/1,
59         otp_8051/1,
60         format_warn/1,
61         on_load_successful/1, on_load_failing/1,
62         too_many_arguments/1,
63         basic_errors/1,bin_syntax_errors/1,
64         predef/1,
65         maps/1,maps_type/1,maps_parallel_match/1,
66         otp_11851/1,otp_11879/1,otp_13230/1,
67         record_errors/1, otp_11879_cont/1,
68         non_latin1_module/1, otp_14323/1,
69         stacktrace_syntax/1,
70         otp_14285/1, otp_14378/1,
71         external_funs/1,otp_15456/1,otp_15563/1,
72         unused_type/1]).
73
74suite() ->
75    [{ct_hooks,[ts_install_cth]},
76     {timetrap,{minutes,1}}].
77
78all() ->
79    [{group, unused_vars_warn}, export_vars_warn,
80     shadow_vars, unused_import, unused_function,
81     unsafe_vars, unsafe_vars2, unsafe_vars_try, guard,
82     unsized_binary_in_bin_gen_pattern,
83     otp_4886, otp_4988, otp_5091, otp_5276, otp_5338,
84     otp_5362, otp_5371, otp_7227, otp_5494, otp_5644,
85     otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, otp_11254,
86     otp_11772, otp_11771, otp_11872, export_all,
87     bif_clash, behaviour_basic, behaviour_multiple, otp_11861,
88     otp_7550, otp_8051, format_warn, {group, on_load},
89     too_many_arguments, basic_errors, bin_syntax_errors, predef,
90     maps, maps_type, maps_parallel_match,
91     otp_11851, otp_11879, otp_13230,
92     record_errors, otp_11879_cont, non_latin1_module, otp_14323,
93     stacktrace_syntax, otp_14285, otp_14378, external_funs,
94     otp_15456, otp_15563, unused_type].
95
96groups() ->
97    [{unused_vars_warn, [],
98      [unused_vars_warn_basic, unused_vars_warn_lc,
99       unused_vars_warn_rec, unused_vars_warn_fun,
100       unused_vars_OTP_4858, unused_unsafe_vars_warn]},
101     {on_load, [], [on_load_successful, on_load_failing]}].
102
103
104%% Warnings for unused variables in some simple cases.
105unused_vars_warn_basic(Config) when is_list(Config) ->
106    Ts = [{basic1,
107           <<"f(F) -> % F unused.
108                ok.
109
110f(F, F) ->
111    ok.
112
113g(_X) ->
114    y.
115
116h(P) ->
117    P.
118
119x(N) ->
120    case a:b() of
121	[N|Y] -> % Y unused.
122	    ok
123    end.
124
125y(N, L) ->
126    lists:map(fun(T) -> T*N end, L).
127
128z(N, L) -> % N unused
129    lists:map(fun(N, T) -> T*N end, L).  % N shadowed.
130
131
132c(A) ->
133    case A of
134	1 -> B = []; % B unused.
135	2 -> B = []; % B unused.
136	3 -> B = f, B
137    end.
138">>,
139	   [warn_unused_vars],
140{warnings,[{1,erl_lint,{unused_var,'F'}},
141	   {15,erl_lint,{unused_var,'Y'}},
142	   {22,erl_lint,{unused_var,'N'}},
143	   {23,erl_lint,{shadowed_var,'N','fun'}},
144	   {28,erl_lint,{unused_var,'B'}},
145	   {29,erl_lint,{unused_var,'B'}}]}},
146          {basic2,
147           <<"-record(r, {x,y}).
148              f({X,Y}) -> {Z=X,Z=Y};
149              f([H|T]) -> [Z=H|Z=T];
150              f(#r{x=X,y=Y}) -> #r{x=A=X,y=A=Y}.
151              g({M, F}) -> (Z=M):(Z=F)();
152              g({M, F, Arg}) -> (Z=M):F(Z=Arg).
153              h(X, Y) -> (Z=X) + (Z=Y).">>,
154           [warn_unused_vars], []}],
155    [] = run(Config, Ts),
156    ok.
157
158%% Warnings for unused variables in list comprehensions.
159unused_vars_warn_lc(Config) when is_list(Config) ->
160    Ts = [{lc1,
161           <<"bin([X]) ->
162                  [A || <<A:X>> <- []]; % X used, not shadowed.
163              bin({X}) ->
164                  [X || <<X:X>> <- []]; % X used, and shadowed.
165              bin({X,Y,Z}) ->
166                  [{A,B} || <<A:X>> <- Z, <<B:Y>> <- Z];
167              bin([X,Y,Z]) -> % Y unused.
168                  [C || <<V:X>> <- Z, <<B:V>> <- Z, <<C:B>> <- Z].
169           ">>,
170           [warn_unused_vars],
171           {warnings, [{4,erl_lint,{shadowed_var,'X',generate}},
172                       {7,erl_lint,{unused_var,'Y'}}]}},
173
174          {lc2,
175           <<"bin([X]) ->
176                  [A || <<A:X>> <- []]; % X used, not shadowed.
177              bin({X}) ->
178                  [X || <<X:X>> <- []]; % X used, and shadowed.
179              bin({X,Y,Z}) ->
180                  [{A,B} || <<A:X>> <- Z, <<B:Y>> <- Z];
181              bin([X,Y,Z]) -> % Y unused.
182                  [C || <<V:X>> <- Z, <<B:V>> <- Z, <<C:B>> <- Z].
183           ">>,
184           [warn_unused_vars],
185           {warnings,[{4,erl_lint,{shadowed_var,'X',generate}},
186                      {7,erl_lint,{unused_var,'Y'}}]}},
187
188          {lc3,
189           <<"a([A]) ->
190                  B = foo,
191                  [{C,B} || {C,_} <- A];
192              a({A}) ->
193                  B = foo,
194                  [C || {C,_} <- [B,A]];
195              a({A,A}) ->
196                  B = foo,
197                  [C || {C,_} <- B, B < A].
198           ">>,
199           [warn_unused_vars],
200           []},
201
202          {lc4,
203           <<"b(A) ->
204                  B = foo, % B unused.
205                  [C || {C,_} <- A].
206           ">>,
207           [warn_unused_vars],
208           {warnings,[{2,erl_lint,{unused_var,'B'}}]}},
209
210          {lc5,
211           <<"c(A) ->
212                  B = foo,
213                  [C || {C,_} <- A],
214                  B.
215           ">>,
216           [warn_unused_vars],
217           []},
218
219          {lc6,
220           <<"d(A) ->
221                  B = foo,
222                  [{A,B} || {Id,_} <- A]. % Id unused.
223           ">>,
224           [warn_unused_vars],
225           {warnings,[{3,erl_lint,{unused_var,'Id'}}]}},
226
227          {lc7,
228           <<"e(A) ->
229                  B = foo, % B unused.
230                  [B || B <- A]. % B shadowed.
231           ">>,
232           [warn_unused_vars],
233           {warnings,[{2,erl_lint,{unused_var,'B'}},
234                      {3,erl_lint,{shadowed_var,'B',generate}}]}},
235
236          {lc8,
237           <<"f(A) ->
238                  B = foo,
239                  [B || B <- A], % B shadowed.
240                  B.
241           ">>,
242           [warn_unused_vars],
243           {warnings,[{3,erl_lint,{shadowed_var,'B',generate}}]}},
244
245          {lc9,
246           <<"g(A) ->
247                  B = foo, % B unused.
248                  [A || B <- A]. % B shadowed, B unused.
249           ">>,
250           [warn_unused_vars],
251           {warnings,[{2,erl_lint,{unused_var,'B'}},
252                      {3,erl_lint,{unused_var,'B'}},
253                      {3,erl_lint,{shadowed_var,'B',generate}}]}},
254
255          {lc10,
256           <<"h(A) ->
257                  B = foo,
258                  [A || B <- A], % B shadowed, B unused.
259                  B.
260           ">>,
261           [warn_unused_vars],
262           {warnings,[{3,erl_lint,{unused_var,'B'}},
263                      {3,erl_lint,{shadowed_var,'B',generate}}]}},
264
265          {lc11,
266           <<"i(X) ->
267                  [Z || Z <- X, % Z unused.
268                        Z = X <- [foo]]. % X and Z shadowed. X unused!
269           ">>,
270           [warn_unused_vars],
271           {warnings,[{2,erl_lint,{unused_var,'Z'}},
272                      {3,erl_lint,{unused_var,'X'}},
273                      {3,erl_lint,{shadowed_var,'X',generate}},
274                      {3,erl_lint,{shadowed_var,'Z',generate}}]}},
275
276          {lc12,
277           <<"j({X}) ->
278                  [Z || Z <- X, % Z unused.
279                        Z <- X = [[1,2,3]], % Z shadowed. Z unused.
280                        Z <- X, % Z shadowed. Z unused.
281                        Z <- X]; % Z shadowed.
282              j(X) ->
283                  [foo || X <- X, % X shadowed.
284                        X <-    % X shadowed. X unused.
285                             X =
286                                 Y = [[1,2,3]], % Y unused.
287                        X <- [], % X shadowed.
288                        X <- X]. % X shadowed. X unused.
289           ">>,
290           [warn_unused_vars],
291           {warnings,[{2,erl_lint,{unused_var,'Z'}},
292                      {3,erl_lint,{unused_var,'Z'}},
293                      {3,erl_lint,{shadowed_var,'Z',generate}},
294                      {4,erl_lint,{unused_var,'Z'}},
295                      {4,erl_lint,{shadowed_var,'Z',generate}},
296                      {5,erl_lint,{shadowed_var,'Z',generate}},
297                      {7,erl_lint,{shadowed_var,'X',generate}},
298                      {8,erl_lint,{unused_var,'X'}},
299                      {8,erl_lint,{shadowed_var,'X',generate}},
300                      {10,erl_lint,{unused_var,'Y'}},
301                      {11,erl_lint,{shadowed_var,'X',generate}},
302                      {12,erl_lint,{unused_var,'X'}},
303                      {12,erl_lint,{shadowed_var,'X',generate}}]}},
304
305          {lc13,
306           <<"k(X) ->
307                  [Z || Z <- Y = X]; % Y unused.
308              k(X) ->
309                  [Z || Z <- X = Y = X]; % Y unused!
310              k(X) ->
311                  [Z || Z <- begin X = Y = X, Y end];
312              k(X) ->
313                  [{Y,W} || W <- Y = X]; % Y unbound
314              k(X) ->
315                  [Z || Z <- (Y = X), % Y unused.
316                       Y > X]; % Y unbound.
317              k(X) ->
318                  [Y || Y = X > 3, Z = X]; % Z unused.
319              k(X) ->
320                  [Z || Y = X > 3, Z = X]. % Y unused.
321           ">>,
322           [warn_unused_vars],
323           {error,[{8,erl_lint,{unbound_var,'Y'}},
324                   {11,erl_lint,{unbound_var,'Y'}}],
325                  [{2,erl_lint,{unused_var,'Y'}},
326                   {4,erl_lint,{unused_var,'Y'}},
327                   {8,erl_lint,{unused_var,'Y'}},
328                   {10,erl_lint,{unused_var,'Y'}},
329                   {13,erl_lint,{unused_var,'Z'}},
330                   {15,erl_lint,{unused_var,'Y'}}]}},
331
332          {lc14,
333           <<"lc2() ->
334                  Z = [[1],[2],[3]],
335                  [X || Z <- Z, % Z shadowed.
336                        X <- Z].
337           ">>,
338           [warn_unused_vars],
339           {warnings,[{3,erl_lint,{shadowed_var,'Z',generate}}]}},
340
341          {lc15,
342           <<"lc3() ->
343                  Z = [1,2,3],
344                  [X || X <- Z,
345                        Z <- Z]. % Z shadowed. Z unused.
346           ">>,
347           [warn_unused_vars],
348           {warnings,[{4,erl_lint,{unused_var,'Z'}},
349                      {4,erl_lint,{shadowed_var,'Z',generate}}]}},
350
351          {lc16,
352           <<"bin(Z) ->
353                  case bar of
354                      true ->
355                          U = 2;
356                      false ->
357                          true
358                  end,
359                  case bar of
360                      true ->
361                          X = 2;
362                      false ->
363                          X = 3
364                  end,
365                  case foo of
366                      true ->
367                          Y = 3; % Y unused.
368                      false ->
369                          4
370                  end,
371                  case foo of
372                      1 ->
373                          U; % U unsafe.
374                      2 ->
375                          [Z || <<U:X>> <- Z]; % (X exported.) U unused.
376                      3 ->
377                          [Z || <<U:X>> <- Z], % (X exported.) U unused.
378                          U % U unsafe.
379                  end.
380           ">>,
381           [warn_unused_vars],
382           {error,[{22,erl_lint,{unsafe_var,'U',{'case',2}}},
383                   {27,erl_lint,{unsafe_var,'U',{'case',2}}}],
384            [{16,erl_lint,{unused_var,'Y'}},
385             {24,erl_lint,{unused_var,'U'}},
386             {26,erl_lint,{unused_var,'U'}}]}},
387
388          {lc17,
389           <<"bin(Z) ->
390                  %% This used to pass erl_lint...
391                  case bar of
392                      true ->
393                          U = 2;
394                      false ->
395                          true
396                  end,
397                  case bar of
398                      true ->
399                          X = 2;
400                      false ->
401                          X = 3
402                  end,
403                  case foo of
404                      true ->
405                          Y = 3; % Y unused.
406                      false ->
407                          4
408                  end,
409                  [Z || <<U:X>> <- Z], % (X exported.) U unused.
410                  U. % U unsafe.
411           ">>,
412           [warn_unused_vars],
413           {error,[{22,erl_lint,{unsafe_var,'U',{'case',3}}}],
414            [{17,erl_lint,{unused_var,'Y'}},
415             {21,erl_lint,{unused_var,'U'}}]}},
416
417          {lc18,
418           <<"bin(Z) ->
419                  case bar of
420                      true ->
421                          U = 2;
422                      false ->
423                          true
424                  end,
425                  case bar of
426                      true ->
427                          X = 2;
428                      false ->
429                          X = 3
430                  end,
431                  case foo of
432                      true ->
433                          Y = 3;
434                      false ->
435                          4
436                  end,
437                  [B || <<U: % U unused
438                          U>> <- X, <<B:Y>> <- Z]. % U unsafe. Y unsafe.
439						% U shadowed. (X exported.)
440           ">>,
441           [warn_unused_vars],
442           {error,[{21,erl_lint,{unsafe_var,'U',{'case',2}}},
443                   {21,erl_lint,{unsafe_var,'Y',{'case',14}}}],
444            [{20,erl_lint,{unused_var,'U'}}
445            ]}},
446
447          {lc19,
448           <<"p({B,C}) ->
449                  <<A:B,A:C>> = <<17:32>>;
450              p(B) ->
451                  <<A:B>> = <<17:32>>. % A unused.
452           ">>,
453           [warn_unused_vars],
454           {warnings,[{4,erl_lint,{unused_var,'A'}}]}},
455
456          {lc20,
457           <<"c({I1,I2}) ->
458                  if
459                      <<I1:I2>> == <<>> ->
460                          foo
461                  end;
462              c([C1,C2]) -> % C1 unused.
463                  case foo of
464                      <<C2:C2,
465                        C3:C2>> -> % C3 unused.
466                          bar
467                  end.
468
469           ">>,
470           [warn_unused_vars],
471           {warnings,[{6,erl_lint,{unused_var,'C1'}},
472		      {7,sys_core_fold,no_clause_match},
473                      {9,erl_lint,{unused_var,'C3'}}]}},
474
475          {lc21,
476           <<"t() ->
477                  S = 8,
478                  case <<3:8>> of
479                      <<X:S>> ->
480                          X;
481                      <<S:X>> -> % X unbound
482                          foo
483                  end;
484              t() ->
485                  S = 8,
486                  case <<3:8>> of
487                      <<S:S>> ->
488                          S;
489                      <<Q:32>> -> % Q unused.
490                          foo
491                  end.
492           ">>,
493           [warn_unused_vars],
494           {error,[{6,erl_lint,{unbound_var,'X'}}],
495                  [{14,erl_lint,{unused_var,'Q'}}]}}
496
497          ],
498    [] = run(Config, Ts),
499    ok.
500
501
502%% Warnings for unused variables in records.
503unused_vars_warn_rec(Config) when is_list(Config) ->
504    Ts = [{rec1, % An example provided by Bjorn.
505           <<"-record(edge,
506                      {ltpr,
507                       ltsu,
508                       rtpr,
509                       rtsu
510                      }).
511
512              f1(#edge{ltpr = A, ltsu = A}) ->
513                  true;
514              f1({Q, Q}) ->
515                  true.
516
517              f2(Edge, Etab) ->
518                  case gb_trees:lookup(Edge, Etab) of
519                      {value,#edge{ltpr=Same,ltsu=Same}} -> ok;
520                      {value,_} -> error
521                  end.
522
523              bar(Edge, Etab) ->
524                  case gb_trees:lookup(Edge, Etab) of
525                      {Same,Same} -> ok;
526                      {value,#edge{ltpr=Same}} -> ok; % Same unused.
527                      {value,_} -> error
528                  end.
529           ">>,
530           [warn_unused_vars],
531           {warnings,[{22,erl_lint,{unused_var,'Same'}}]}},
532          {rec2,
533           <<"-record(r, {a,b}).
534              f(X, Y) -> #r{a=[K || K <- Y], b=[K || K <- Y]}.
535              g(X, Y) -> #r{a=lists:map(fun (K) -> K end, Y),
536                            b=lists:map(fun (K) -> K end, Y)}.
537              h(X, Y) -> #r{a=case Y of _ when is_list(Y) -> Y end,
538                            b=case Y of _ when is_list(Y) -> Y end}.
539              i(X, Y) -> #r{a=if is_list(Y) -> Y end, b=if is_list(Y) -> Y end}.
540             ">>,
541           [warn_unused_vars],
542           {warnings,[{2,erl_lint,{unused_var,'X'}},
543                      {3,erl_lint,{unused_var,'X'}},
544                      {5,erl_lint,{unused_var,'X'}},
545                      {7,erl_lint,{unused_var,'X'}}]}},
546          {rec3,
547           <<"-record(r, {a}).
548              t() -> X = 1, #r{a=foo, a=bar, a=qux}.
549             ">>,
550           [warn_unused_vars],
551           {error,[{2,erl_lint,{redefine_field,r,a}},
552                   {2,erl_lint,{redefine_field,r,a}}],
553                  [{2,erl_lint,{unused_var,'X'}}]}}],
554    [] = run(Config, Ts),
555    ok.
556
557%% Warnings for unused variables in funs.
558unused_vars_warn_fun(Config) when is_list(Config) ->
559    Ts = [{fun1,
560           <<"a({A,B}) -> % A unused.
561                  fun(A) -> B end; % A shadowed. A unused.
562              a([A,B]) ->
563                  fun(<<A:B>>, % A shadowed. A unused.
564                       <<Q:A>>) -> foo % Q unused.
565                  end;
566              a({A,B,C,D,E}) ->
567                  fun(E) when C == <<A:A>>, <<17:B>> == D -> % E shadowed. E unused.
568                          foo
569                  end,
570                  E;
571              a([A,B,C,D,E]) -> % E unused.
572                  fun() ->
573                          (C == <<A:A>>) and (<<17:B>> == D)
574                  end.
575           ">>,
576           [warn_unused_vars],
577           {warnings,[{1,erl_lint,{unused_var,'A'}},
578                  {2,erl_lint,{unused_var,'A'}},
579                  {2,erl_lint,{shadowed_var,'A','fun'}},
580                  {4,erl_lint,{unused_var,'A'}},
581                  {4,erl_lint,{shadowed_var,'A','fun'}},
582                  {5,erl_lint,{unused_var,'Q'}},
583                  {8,erl_lint,{unused_var,'E'}},
584                  {8,erl_lint,{shadowed_var,'E','fun'}},
585		  {8,sys_core_fold,useless_building},
586                  {12,erl_lint,{unused_var,'E'}}]}},
587
588          {fun2,
589           <<"u() ->
590                  case foo of
591                      true ->
592                          U = 2;
593                      false ->
594                          true
595                  end,
596                  fun(U) -> foo end, % U unused.
597                  U; % U unsafe.
598              u() ->
599                  case foo of
600                      true ->
601                          U = 2;
602                      false ->
603                          U = 3
604                  end,
605                  fun(U) -> foo end, % U shadowed. U unused.
606                  U;
607              u() ->
608                  case foo of
609                      true ->
610                          U = 2; % U unused.
611                      false ->
612                          U = 3 % U unused.
613                  end,
614                  fun(U) -> foo end. % U shadowed. U unused.
615           ">>,
616           [warn_unused_vars],
617           {error,[{9,erl_lint,{unsafe_var,'U',{'case',2}}}],
618              [{8,erl_lint,{unused_var,'U'}},
619               {17,erl_lint,{unused_var,'U'}},
620               {17,erl_lint,{shadowed_var,'U','fun'}},
621               {22,erl_lint,{unused_var,'U'}},
622               {24,erl_lint,{unused_var,'U'}},
623               {26,erl_lint,{unused_var,'U'}},
624               {26,erl_lint,{shadowed_var,'U','fun'}}]}},
625          {named_fun,
626           <<"u() ->
627                  fun U() -> foo end, % U unused.
628                  U; % U unbound.
629              u() ->
630                  case foo of
631                      true ->
632                          U = 2;
633                      false ->
634                          true
635                  end,
636                  fun U() -> foo end, % U unused.
637                  U; % U unsafe.
638              u() ->
639                  case foo of
640                      true ->
641                          U = 2;
642                      false ->
643                          U = 3
644                  end,
645                  fun U() -> foo end, % U shadowed. U unused.
646                  U;
647              u() ->
648                  case foo of
649                      true ->
650                          U = 2; % U unused.
651                      false ->
652                          U = 3 % U unused.
653                  end,
654                  fun U() -> foo end; % U shadowed. U unused.
655              u() ->
656                  fun U(U) -> foo end; % U shadowed. U unused.
657              u() ->
658                  fun U(1) -> U; U(U) -> foo end; % U shadowed. U unused.
659              u() ->
660                  fun _(N) -> N + 1 end.  % Cover handling of '_' name.
661           ">>,
662           [warn_unused_vars],
663           {error,[{3,erl_lint,{unbound_var,'U'}},
664                   {12,erl_lint,{unsafe_var,'U',{'case',5}}}],
665                  [{2,erl_lint,{unused_var,'U'}},
666                   {11,erl_lint,{unused_var,'U'}},
667                   {20,erl_lint,{unused_var,'U'}},
668                   {20,erl_lint,{shadowed_var,'U','named fun'}},
669                   {25,erl_lint,{unused_var,'U'}},
670                   {27,erl_lint,{unused_var,'U'}},
671                   {29,erl_lint,{unused_var,'U'}},
672                   {29,erl_lint,{shadowed_var,'U','named fun'}},
673                   {31,erl_lint,{unused_var,'U'}},
674                   {31,erl_lint,{unused_var,'U'}},
675                   {31,erl_lint,{shadowed_var,'U','fun'}},
676                   {33,erl_lint,{unused_var,'U'}},
677                   {33,erl_lint,{shadowed_var,'U','fun'}}]}}
678          ],
679    [] = run(Config, Ts),
680    ok.
681
682%% Bit syntax, binsize variable used in the same matching.
683unused_vars_OTP_4858(Config) when is_list(Config) ->
684    Ts = [{otp_4858,
685           <<"objs(<<Size:4/unit:8, B:Size/binary>>) ->
686                  B.
687
688              fel(<<Size:4/unit:8, B:BadSize/binary>>) -> % BadSize unbound.
689                  BadSize.                                % B, Size unused.
690
691              r9c_highlight() -> % B, Rest unused.
692                 <<Size, B:Size/binary,Rest/binary>> = <<2,\"AB\",3,\"CDE\">>.
693           ">>,
694           [warn_unused_vars],
695           {error,[{4,erl_lint,{unbound_var,'BadSize'}}],
696              [{4,erl_lint,{unused_var,'B'}},
697               {4,erl_lint,{unused_var,'Size'}},
698               {8,erl_lint,{unused_var,'B'}},
699               {8,erl_lint,{unused_var,'Rest'}}]}}
700         ],
701    [] = run(Config, Ts),
702    ok.
703
704unused_unsafe_vars_warn(Config) when is_list(Config) ->
705    Ts = [{unused_unsafe1,
706           <<"t1() ->
707                  UnusedVar1 = unused1,
708                  try
709                      UnusedVar2 = unused2
710                  catch
711                      _:_ ->
712                          ok
713                  end,
714                  ok.
715           ">>,
716           [warn_unused_vars],
717           {warnings,[{2,erl_lint,{unused_var,'UnusedVar1'}},
718                      {4,erl_lint,{unused_var,'UnusedVar2'}}]}},
719          {unused_unsafe2,
720           <<"t2() ->
721                  try
722                      X = 1
723                  catch
724                      _:_ -> ok
725                  end.
726           ">>,
727           [warn_unused_vars],
728           {warnings,[{3,erl_lint,{unused_var,'X'}}]}},
729          {unused_unsafe2,
730           <<"t3(X, Y) ->
731                  X andalso Y.
732           ">>,
733           [warn_unused_vars],
734           []},
735          {unused_unsafe4,
736           <<"t4() ->
737                  _ = (catch X = X = 1),
738                  _ = case ok of _ -> fun() -> ok end end,
739                  fun (X) -> X end.
740           ">>,
741           [warn_unused_vars],
742           []}],
743    run(Config, Ts),
744    ok.
745
746%% Warnings for exported variables.
747export_vars_warn(Config) when is_list(Config) ->
748    Ts = [{exp1,
749           <<"u() ->
750                  case foo of
751                      1 ->
752                          A = 1,
753                          B = 2,
754                          W = 3, % W unused.
755                          Z = 3; % Z unused.
756                      2 ->
757                          B = 2,
758                          Z = 4 % Z unused.
759                  end,
760                  case bar of
761                      true ->
762                          A = 17, % A unsafe.
763                          X = 3, % X unused.
764                          U = 2,
765                          U;
766                      false ->
767                          B = 19, % B exported.
768                          U = 3; % U unused.
769                      foo ->
770                          X = 3,
771                          X;
772                      bar ->
773                          X = 9, % X unused.
774                          U = 14 % U unused.
775                  end.
776           ">>,
777           [warn_unused_vars],
778           {error,[{14,erl_lint,{unsafe_var,'A',{'case',2}}}],
779                  [{6,erl_lint,{unused_var,'W'}},
780                   {7,erl_lint,{unused_var,'Z'}},
781                   {10,erl_lint,{unused_var,'Z'}},
782                   {15,erl_lint,{unused_var,'X'}},
783                   {19,erl_lint,{exported_var,'B',{'case',2}}},
784                   {20,erl_lint,{unused_var,'U'}},
785                   {25,erl_lint,{unused_var,'X'}},
786                   {26,erl_lint,{unused_var,'U'}}]}},
787
788          {exp2,
789           <<"bin(A) ->
790                  receive
791                      M ->
792                           X = M,
793                           Y = M,
794                           Z = M
795                  end,
796                  [B || <<B:X>> <- A], % X exported.
797                  Y = B, % Y exported. B unbound.
798                  [B || B <- Z]. % Z exported. B shadowed.
799           ">>,
800           [warn_export_vars],
801           {error,[{9,erl_lint,{unbound_var,'B'}}],
802                  [{8,erl_lint,{exported_var,'X',{'receive',2}}},
803                   {9,erl_lint,{exported_var,'Y',{'receive',2}}},
804                   {10,erl_lint,{exported_var,'Z',{'receive',2}}},
805                   {10,erl_lint,{shadowed_var,'B',generate}}]}},
806
807          {exp3,
808           <<"bin(A) ->
809                  receive
810                      M ->
811                           X = M,
812                           Y = M,
813                           Z = M
814                  end,
815                  [B || <<B:X>> <- A], % (X exported.)
816                  Y = B, % Y exported. B unbound.
817                  [B || B <- Z]. % (Z exported.) B shadowed.
818           ">>,
819           [],
820           {error,[{9,erl_lint,{unbound_var,'B'}}],
821                  [{9,erl_lint,{exported_var,'Y',{'receive',2}}},
822                   {10,erl_lint,{shadowed_var,'B',generate}}]}},
823
824          {exp4,
825           <<"t(X) ->
826                  if true -> Z = X end,
827                  case X of
828                      1 -> Z;
829                      2 -> X
830                  end,
831                  Z = X.
832           ">>,
833           [],
834           {warnings,[{7,erl_lint,{exported_var,'Z',{'if',2}}}]}}
835         ],
836    [] = run(Config, Ts),
837    ok.
838
839%% Shadowed variables are tested in other places, but here we test
840%% that the warning can be turned off.
841shadow_vars(Config) when is_list(Config) ->
842    Ts = [{shadow1,
843	   <<"bin(A) ->
844                  receive
845                      M ->
846                           X = M,
847                           Y = M,
848                           Z = M
849                  end,
850                  [B || <<B:X>> <- A],
851                  Y = B,
852                  [B || B <- Z]. % B shadowed.
853           ">>,
854	   [nowarn_shadow_vars],
855	   {error,[{9,erl_lint,{unbound_var,'B'}}],
856	    [{9,erl_lint,{exported_var,'Y',{'receive',2}}}]}},
857          {shadow2,
858           <<"t() ->
859                  _ = (catch MS = MS = 1), % MS used unsafe
860                  _ = case ok of _ -> fun() -> ok end end,
861                  fun (MS) -> MS end. % MS not shadowed here
862           ">>,
863           [],
864           []}],
865    [] = run(Config, Ts),
866    ok.
867
868%% Test that the 'warn_unused_import' option works.
869unused_import(Config) when is_list(Config) ->
870    Ts = [{imp1,
871	   <<"-import(lists, [map/2,foldl/3]).
872              t(L) ->
873                 map(fun(X) -> 2*X end, L).
874           ">>,
875	   [warn_unused_import],
876	   {warnings,[{1,erl_lint,{unused_import,{{foldl,3},lists}}}]}}],
877    [] = run(Config, Ts),
878    ok.
879
880%% Test warnings for unused functions.
881unused_function(Config) when is_list(Config) ->
882    Ts = [{func1,
883	   <<"-export([t/1]).
884              t(L) ->
885                 lists:map(fun(X) -> 2*X end, L).
886
887              fact(N) ->
888                fact_1(N, 1).
889
890              fact_1(1, P) -> P;
891              fact_1(N, P) -> fact_1(N-1, P*N).
892           ">>,
893	   {[]},				%Tuple indicates no 'export_all'.
894	   {warnings,[{5,erl_lint,{unused_function,{fact,1}}},
895		      {8,erl_lint,{unused_function,{fact_1,2}}}]}},
896
897	  %% Turn off warnings for unused functions.
898	  {func2,
899	   <<"-export([t/1]).
900              t(L) ->
901                 lists:map(fun(X) -> 2*X end, L).
902
903              b(X) ->
904                32*X.
905           ">>,
906	   {[nowarn_unused_function]},         %Tuple indicates no 'export_all'.
907	   []},
908
909	  %% Turn off warnings for unused functions using a -compile() directive.
910	  {func3,
911	   <<"-export([t/1]).
912              -compile(nowarn_unused_function).
913
914              t(L) ->
915                 lists:map(fun(X) -> 2*X end, L).
916
917              b(X) ->
918                32*X.
919           ">>,
920	   {[]},		     %Tuple indicates no 'export_all'.
921	   []}],
922
923    [] = run(Config, Ts),
924    ok.
925
926%% Test warnings for unused types
927unused_type(Config) when is_list(Config) ->
928    Ts = [{func1,
929           <<"-type foo() :: term().">>,
930           {[]},                                %Tuple indicates no export_all
931           {warnings,[{1,erl_lint,{unused_type,{foo,0}}}]}},
932
933           %% Turn off warnings for unused types.
934           {func2,
935           <<"-type foo() :: term().">>,
936           {[nowarn_unused_type]},              %Tuple indicates no export_all
937           []},
938
939           %% Turn off warnings for unused types using a -compile() directive.
940           {func3,
941           <<"-compile(nowarn_unused_type).
942              -type foo() :: term().">>,
943           {[]},                                %Tuple indicates no export_all
944           []}],
945
946    [] = run(Config, Ts),
947    ok.
948
949%% OTP-4671. Errors for unsafe variables.
950unsafe_vars(Config) when is_list(Config) ->
951    Ts = [{unsafe1,
952           <<"t() ->
953                 (X = true) orelse (Y = false),
954                  Y.
955           ">>,
956           [warn_unused_vars],
957           {error,[{3,erl_lint,{unsafe_var,'Y',{'orelse',2}}}],
958            [{2,erl_lint,{unused_var,'X'}}]}},
959          {unsafe2,
960           <<"t2() ->
961                  (X = true) orelse (Y = false),
962                  X.
963           ">>,
964           [warn_unused_vars],
965           {warnings,[{2,erl_lint,{unused_var,'Y'}}]}},
966          {unsafe3,
967           <<"t3() ->
968                  (X = true) andalso (Y = false),
969                  Y.
970           ">>,
971           [warn_unused_vars],
972           {error,[{3,erl_lint,{unsafe_var,'Y',{'andalso',2}}}],
973            [{2,erl_lint,{unused_var,'X'}}]}},
974          {unsafe4,
975           <<"t4() ->
976                  (X = true) andalso (true = X),
977                  X.
978           ">>,
979           [warn_unused_vars],
980           []},
981          {unsafe5,
982           <<"t5() ->
983                  Y = 3,
984                  (X = true) andalso (X = true),
985                  {X,Y}.
986           ">>,
987           [warn_unused_vars],
988           []},
989          {unsafe6,
990           <<"t6() ->
991                  X = true,
992                  (X = true) andalso (true = X),
993                  X.
994           ">>,
995           [warn_unused_vars],
996           []},
997          {unsafe7,
998           <<"t7() ->
999                  (if true -> X = 3; false -> true end)
1000                      andalso (X > 2),
1001                  X.
1002           ">>,
1003           [warn_unused_vars],
1004           {errors,[{3,erl_lint,{unsafe_var,'X',{'if',2}}},
1005                    {4,erl_lint,{unsafe_var,'X',{'if',2}}}],
1006            []}},
1007          {unsafe8,
1008           <<"t8(X) ->
1009                  case X of _ -> catch _Y = 1 end,
1010                  _Y."
1011           >>,
1012           [],
1013           {errors,[{3,erl_lint,{unsafe_var,'_Y',{'catch',2}}}],
1014            []}},
1015           {unsafe9,
1016           <<"t9(X) ->
1017                  case X of
1018                      1 ->
1019                          catch A = 1, % unsafe only here
1020                          B = 1,
1021                          C = 1,
1022                          D = 1;
1023                      2 ->
1024                          A = 2,
1025                          %% B not bound here
1026                          C = 2,
1027                          catch D = 2; % unsafe in two clauses
1028                      3 ->
1029                          A = 3,
1030                          B = 3,
1031                          C = 3,
1032                          catch D = 3; % unsafe in two clauses
1033                      4 ->
1034                          A = 4,
1035                          B = 4,
1036                          C = 4,
1037                          D = 4
1038                  end,
1039                  {A,B,C,D}."
1040           >>,
1041           [],
1042           {errors,[{24,erl_lint,{unsafe_var,'A',{'catch',4}}},
1043                    {24,erl_lint,{unsafe_var,'B',{'case',2}}},
1044                    {24,erl_lint,{unsafe_var,'D',{'case',2}}}],
1045            []}},
1046          {unsafe_comprehension,
1047           <<"foo() ->
1048                 case node() of
1049                     P when is_tuple(P) ->
1050                         P;
1051                     _ ->
1052                         ok
1053                 end,
1054                 Y = try
1055                         ok
1056                     catch _C:_R ->
1057                             [1 || _ <- []]
1058                     end,
1059                 case Y of
1060                     P ->
1061                         P
1062                 end.
1063           ">>,
1064           [],
1065           {errors,[{14,erl_lint,{unsafe_var,'P',{'case',2}}}],[]}}
1066         ],
1067    [] = run(Config, Ts),
1068    ok.
1069
1070%% OTP-4831, seq8202. No warn_unused_vars and unsafe variables.
1071unsafe_vars2(Config) when is_list(Config) ->
1072    Ts = [{unsafe2_1,
1073           <<"foo(State) ->
1074                  case State of
1075                      true ->
1076                          if
1077                              false -> ok;
1078                              true ->  State1=State
1079                          end
1080                  end,
1081                  State1. % unsafe
1082           ">>,
1083           [warn_unused_vars],
1084           {errors,[{9,erl_lint,{unsafe_var,'State1',{'if',4}}}],[]}},
1085          {unsafe2_2,
1086           <<"foo(State) ->
1087                  case State of
1088                      true ->
1089                          if
1090                              false -> ok;
1091                              true ->  State1=State
1092                          end
1093                  end,
1094                  State1. % unsafe
1095           ">>,
1096           [],
1097           {errors,[{9,erl_lint,{unsafe_var,'State1',{'if',4}}}],[]}}
1098         ],
1099    [] = run(Config, Ts),
1100    ok.
1101
1102%% Errors for unsafe variables in try/catch constructs.
1103unsafe_vars_try(Config) when is_list(Config) ->
1104    Ts = [{unsafe_try1,
1105	   <<"foo2() ->
1106                try self()
1107                catch
1108                  Class:Data -> Result={Class,Data}
1109                end,
1110                Result.
1111              foo3a() ->
1112                try self() of
1113                  R -> R
1114                catch
1115                  Class:Data -> Result={Class,Data}
1116                end,
1117                Result.
1118              foo3b() ->
1119                try self() of
1120                  Result -> ok
1121                catch
1122                  Class:Data -> {Class,Data}
1123                end,
1124                Result.
1125           ">>,
1126	   [],
1127	   {errors,[{6,erl_lint,{unsafe_var,'Result',{'try',2}}},
1128		    {13,erl_lint,{unsafe_var,'Result',{'try',8}}},
1129		    {20,erl_lint,{unsafe_var,'Result',{'try',15}}}],
1130	    []}},
1131	  {unsafe_try2,
1132	   <<"foo1a() ->
1133                Try =
1134                  try self()
1135                  catch
1136                    Class:Data -> Rc={Class,Data}
1137                  after
1138                    Ra=ok
1139                  end,
1140                {Try,Rc,Ra}.
1141              foo1b() ->
1142                Try =
1143                  try self() of
1144                    R -> R
1145                  catch
1146                    Class:Data -> Rc={Class,Data}
1147                  after
1148                    Ra=R
1149                  end,
1150                {Try,Rc,Ra}.
1151              foo2() ->
1152                Try =
1153                  try self() of
1154                    R -> Ro=R
1155                  catch
1156                    Class:Data -> {Class,Data}
1157                  after
1158                    Ra=R
1159                  end,
1160                {Try,Ro,Ra}.
1161              foo3() ->
1162                Try =
1163                  try self() of
1164                    R -> Ro=R
1165                  catch
1166                    Class:Data -> Rc={Class,Data}
1167                  after
1168                    Ra=R
1169                  end,
1170                {Try,R,Ro,Rc,Ra}.
1171           ">>,
1172	   [],
1173	   {errors,[{9,erl_lint,{unsafe_var,'Ra',{'try',3}}},
1174                    {9,erl_lint,{unsafe_var,'Rc',{'try',3}}},
1175		    {17,erl_lint,{unsafe_var,'R',{'try',12}}},
1176		    {19,erl_lint,{unsafe_var,'Ra',{'try',12}}},
1177		    {19,erl_lint,{unsafe_var,'Rc',{'try',12}}},
1178		    {27,erl_lint,{unsafe_var,'R',{'try',22}}},
1179		    {29,erl_lint,{unsafe_var,'Ra',{'try',22}}},
1180		    {29,erl_lint,{unsafe_var,'Ro',{'try',22}}},
1181		    {37,erl_lint,{unsafe_var,'R',{'try',32}}},
1182		    {39,erl_lint,{unsafe_var,'R',{'try',32}}},
1183		    {39,erl_lint,{unsafe_var,'Ra',{'try',32}}},
1184                    {39,erl_lint,{unsafe_var,'Rc',{'try',32}}},
1185                    {39,erl_lint,{unsafe_var,'Ro',{'try',32}}}],
1186	    []}},
1187	  {unsafe_try3,
1188	   <<"foo1(X) ->
1189                Try =
1190                  try R=self()
1191                  catch
1192                    Class:Data -> Rc={X,R,Class,Data}
1193                  end,
1194                {X,Try,Rc}.
1195	      foo2(X) ->
1196                Try =
1197                  try R=self() of
1198                    RR -> Ro={X,R,RR}
1199                  catch
1200                    Class:Data -> {X,R,RR,Ro,Class,Data}
1201                  end,
1202                {X,Try,R,RR,Ro,Class,Data}.
1203	      foo3(X) ->
1204                Try =
1205                  try R=self() of
1206                    RR -> {X,R,RR}
1207                  catch
1208                    Class:Data -> {X,R,RR,Class,Data}
1209                  after
1210                    Ra={X,R,RR,Class,Data}
1211                  end,
1212                {X,Try,R,RR,Ra,Class,Data}.
1213           ">>,
1214	   [],
1215	   {errors,[{5,erl_lint,{unsafe_var,'R',{'try',3}}},
1216		    {7,erl_lint,{unsafe_var,'Rc',{'try',3}}},
1217		    {11,erl_lint,{unsafe_var,'R',{'try',10}}},
1218		    {13,erl_lint,{unbound_var,'RR'}},
1219		    {13,erl_lint,{unbound_var,'Ro'}},
1220		    {13,erl_lint,{unsafe_var,'R',{'try',10}}},
1221		    {15,erl_lint,{unsafe_var,'Class',{'try',10}}},
1222		    {15,erl_lint,{unsafe_var,'Data',{'try',10}}},
1223		    {15,erl_lint,{unsafe_var,'R',{'try',10}}},
1224		    {15,erl_lint,{unsafe_var,'RR',{'try',10}}},
1225		    {15,erl_lint,{unsafe_var,'Ro',{'try',10}}},
1226		    {19,erl_lint,{unsafe_var,'R',{'try',18}}},
1227		    {21,erl_lint,{unbound_var,'RR'}},
1228		    {21,erl_lint,{unsafe_var,'R',{'try',18}}},
1229		    {23,erl_lint,{unsafe_var,'Class',{'try',18}}},
1230		    {23,erl_lint,{unsafe_var,'Data',{'try',18}}},
1231		    {23,erl_lint,{unsafe_var,'R',{'try',18}}},
1232		    {23,erl_lint,{unsafe_var,'RR',{'try',18}}},
1233		    {25,erl_lint,{unsafe_var,'Class',{'try',18}}},
1234                    {25,erl_lint,{unsafe_var,'Data',{'try',18}}},
1235		    {25,erl_lint,{unsafe_var,'R',{'try',18}}},
1236		    {25,erl_lint,{unsafe_var,'RR',{'try',18}}},
1237		    {25,erl_lint,{unsafe_var,'Ra',{'try',18}}}],
1238	    []}},
1239	  {unsafe_try4,
1240	   <<"foo1(X) ->
1241                Try =
1242                  try R=self() of
1243                    RR -> Ro={X,R,RR}
1244                  catch
1245                    Class:Data -> Rc={X,R,RR,Ro,Class,Data}
1246                  after
1247                    Ra={X,R,RR,Ro,Rc,Class,Data}
1248                  end,
1249                {X,Try,R,RR,Ro,Rc,Ra,Class,Data}.
1250           ">>,
1251	   [],
1252	   {errors,[{4,erl_lint,{unsafe_var,'R',{'try',3}}},
1253		    {6,erl_lint,{unbound_var,'RR'}},
1254		    {6,erl_lint,{unbound_var,'Ro'}},
1255		    {6,erl_lint,{unsafe_var,'R',{'try',3}}},
1256		    {8,erl_lint,{unsafe_var,'Class',{'try',3}}},
1257		    {8,erl_lint,{unsafe_var,'Data',{'try',3}}},
1258		    {8,erl_lint,{unsafe_var,'R',{'try',3}}},
1259		    {8,erl_lint,{unsafe_var,'RR',{'try',3}}},
1260		    {8,erl_lint,{unsafe_var,'Rc',{'try',3}}},
1261		    {8,erl_lint,{unsafe_var,'Ro',{'try',3}}},
1262		    {10,erl_lint,{unsafe_var,'Class',{'try',3}}},
1263                    {10,erl_lint,{unsafe_var,'Data',{'try',3}}},
1264		    {10,erl_lint,{unsafe_var,'R',{'try',3}}},
1265		    {10,erl_lint,{unsafe_var,'RR',{'try',3}}},
1266		    {10,erl_lint,{unsafe_var,'Ra',{'try',3}}},
1267		    {10,erl_lint,{unsafe_var,'Rc',{'try',3}}},
1268		    {10,erl_lint,{unsafe_var,'Ro',{'try',3}}}],
1269	    []}},
1270          {unsafe_try5,
1271           <<"bang() ->
1272                case 1 of
1273                  nil ->
1274                    Acc = 2;
1275                  _ ->
1276                    try
1277                      Acc = 3,
1278                      Acc
1279                    catch _:_ ->
1280                      ok
1281                    end
1282                end,
1283                Acc.
1284           ">>,
1285           [],
1286           {errors,[{13,erl_lint,{unsafe_var,'Acc',{'try',6}}}],[]}}],
1287        [] = run(Config, Ts),
1288    ok.
1289
1290%% Unsized binary fields are forbidden in patterns of bit string generators.
1291unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
1292    Ts = [{unsized_binary_in_bin_gen_pattern,
1293	   <<"t({bc,binary,Bin}) ->
1294		  << <<X,Tail/binary>> || <<X,Tail/binary>> <= Bin >>;
1295	      t({bc,bytes,Bin}) ->
1296		  << <<X,Tail/binary>> || <<X,Tail/bytes>> <= Bin >>;
1297	      t({bc,bits,Bin}) ->
1298		  << <<X,Tail/bits>> || <<X,Tail/bits>> <= Bin >>;
1299	      t({bc,bitstring,Bin}) ->
1300		  << <<X,Tail/bits>> || <<X,Tail/bitstring>> <= Bin >>;
1301	      t({lc,binary,Bin}) ->
1302		  [ {X,Tail} || <<X,Tail/binary>> <= Bin ];
1303	      t({lc,bytes,Bin}) ->
1304		  [ {X,Tail} || <<X,Tail/bytes>> <= Bin ];
1305	      t({lc,bits,Bin}) ->
1306		  [ {X,Tail} || <<X,Tail/bits>> <= Bin ];
1307	      t({lc,bitstring,Bin}) ->
1308		  [ {X,Tail} || <<X,Tail/bitstring>> <= Bin ].">>,
1309	   [],
1310	   {errors,
1311	    [{2,erl_lint,unsized_binary_in_bin_gen_pattern},
1312	     {4,erl_lint,unsized_binary_in_bin_gen_pattern},
1313	     {6,erl_lint,unsized_binary_in_bin_gen_pattern},
1314	     {8,erl_lint,unsized_binary_in_bin_gen_pattern},
1315	     {10,erl_lint,unsized_binary_in_bin_gen_pattern},
1316	     {12,erl_lint,unsized_binary_in_bin_gen_pattern},
1317	     {14,erl_lint,unsized_binary_in_bin_gen_pattern},
1318	     {16,erl_lint,unsized_binary_in_bin_gen_pattern}],
1319	     []}}],
1320    [] = run(Config, Ts),
1321    ok.
1322
1323%% OTP-4670. Guards, is_record in particular.
1324guard(Config) when is_list(Config) ->
1325    %% Well, these could be plain code...
1326    Ts = [{guard1,
1327           <<"-record(apa, {}).
1328              t(A) when atom(A) ->
1329                  atom;
1330              t(A) when binary(A) ->
1331                  binary;
1332              t(A) when constant(A) ->
1333                  constant;
1334              t(A) when float(A) ->
1335                  float;
1336              t(A) when function(A) ->
1337                  function;
1338              t(A) when integer(A) ->
1339                  integer;
1340              t(A) when is_atom(A) ->
1341                  is_atom;
1342              t(A) when is_binary(A) ->
1343                  is_binary;
1344              t(A) when is_constant(A) ->
1345                  is_constant;
1346              t(A) when is_float(A) ->
1347                  is_float;
1348              t(A) when is_function(A) ->
1349                  is_function;
1350              t(A) when is_integer(A) ->
1351                  is_integer;
1352              t(A) when is_list(A) ->
1353                  is_list;
1354              t(A) when is_number(A) ->
1355                  is_number;
1356              t(A) when is_pid(A) ->
1357                  is_pid;
1358              t(A) when is_port(A) ->
1359                  is_port;
1360              t(A) when is_record(A, apa) ->
1361                  is_record;
1362              t(A) when is_record(A, apa, 1) ->
1363                  is_record;
1364              t(A) when is_reference(A) ->
1365                  is_reference;
1366              t(A) when is_tuple(A) ->
1367                  is_tuple;
1368              t(A) when list(A) ->
1369                  list;
1370              t(A) when number(A) ->
1371                  number;
1372              t(A) when pid(A) ->
1373                  pid;
1374              t(A) when port(A) ->
1375                  port;
1376              t(A) when record(A, apa) ->
1377                  record;
1378              t(A) when reference(A) ->
1379                  reference;
1380              t(A) when tuple(A) ->
1381                  tuple.
1382           ">>,
1383           [nowarn_obsolete_guard],
1384           {errors,
1385	    [{6,erl_lint,illegal_guard_expr},{18,erl_lint,illegal_guard_expr}],
1386	    []}},
1387          {guard2,
1388           <<"-record(apa,{}).
1389              t1(A) when atom(A), atom(A) ->
1390                  atom;
1391              t1(A) when binary(A), binary(A) ->
1392                  binary;
1393              t1(A) when constant(A), constant(A) ->
1394                  constant;
1395              t1(A) when float(A), float(A) ->
1396                  float;
1397              t1(A) when function(A), function(A) ->
1398                  function;
1399              t1(A) when integer(A), integer(A) ->
1400                  integer;
1401              t1(A) when is_atom(A), is_atom(A) ->
1402                  is_atom;
1403              t1(A) when is_binary(A), is_binary(A) ->
1404                  is_binary;
1405              t1(A) when is_constant(A), is_constant(A) ->
1406                  is_constant;
1407              t1(A) when is_float(A), is_float(A) ->
1408                  is_float;
1409              t1(A) when is_function(A), is_function(A) ->
1410                  is_function;
1411              t1(A) when is_integer(A), is_integer(A) ->
1412                  is_integer;
1413              t1(A) when is_list(A), is_list(A) ->
1414                  is_list;
1415              t1(A) when is_number(A), is_number(A) ->
1416                  is_number;
1417              t1(A) when is_pid(A), is_pid(A) ->
1418                  is_pid;
1419              t1(A) when is_port(A), is_port(A) ->
1420                  is_port;
1421              t1(A) when is_record(A, apa), is_record(A, apa) ->
1422                  is_record;
1423              t1(A) when is_record(A, apa, 1), is_record(A, apa, 1) ->
1424                  is_record;
1425              t1(A) when is_reference(A), is_reference(A) ->
1426                  is_reference;
1427              t1(A) when is_tuple(A), is_tuple(A) ->
1428                  is_tuple;
1429              t1(A) when list(A), list(A) ->
1430                  list;
1431              t1(A) when number(A), number(A) ->
1432                  number;
1433              t1(A) when pid(A), pid(A) ->
1434                  pid;
1435              t1(A) when port(A), port(A) ->
1436                  port;
1437              t1(A) when record(A, apa), record(A, apa) ->
1438                  record;
1439              t1(A) when reference(A), reference(A) ->
1440                  reference;
1441              t1(A) when tuple(A), tuple(A) ->
1442                  tuple.
1443           ">>,
1444           [nowarn_obsolete_guard],
1445	   {errors,[{6,erl_lint,illegal_guard_expr},
1446		    {6,erl_lint,illegal_guard_expr},
1447		    {18,erl_lint,illegal_guard_expr},
1448		    {18,erl_lint,illegal_guard_expr}],
1449	    []}},
1450          {guard3,
1451           <<"-record(apa,{}).
1452              t2(A) when atom(A); atom(A) ->
1453                  atom;
1454              t2(A) when binary(A); binary(A) ->
1455                  binary;
1456              t2(A) when float(A); float(A) ->
1457                  float;
1458              t2(A) when function(A); function(A) ->
1459                  function;
1460              t2(A) when integer(A); integer(A) ->
1461                  integer;
1462              t2(A) when is_atom(A); is_atom(A) ->
1463                  is_atom;
1464              t2(A) when is_binary(A); is_binary(A) ->
1465                  is_binary;
1466              t2(A) when is_float(A); is_float(A) ->
1467                  is_float;
1468              t2(A) when is_function(A); is_function(A) ->
1469                  is_function;
1470              t2(A) when is_integer(A); is_integer(A) ->
1471                  is_integer;
1472              t2(A) when is_list(A); is_list(A) ->
1473                  is_list;
1474              t2(A) when is_number(A); is_number(A) ->
1475                  is_number;
1476              t2(A) when is_pid(A); is_pid(A) ->
1477                  is_pid;
1478              t2(A) when is_port(A); is_port(A) ->
1479                  is_port;
1480              t2(A) when is_record(A, apa); is_record(A, apa) ->
1481                  is_record;
1482              t2(A) when is_record(A, gurka, 1); is_record(A, gurka, 1) ->
1483                  is_record;
1484              t2(A) when is_reference(A); is_reference(A) ->
1485                  is_reference;
1486              t2(A) when is_tuple(A); is_tuple(A) ->
1487                  is_tuple;
1488              t2(A) when list(A); list(A) ->
1489                  list;
1490              t2(A) when number(A); number(A) ->
1491                  number;
1492              t2(A) when pid(A); pid(A) ->
1493                  pid;
1494              t2(A) when port(A); port(A) ->
1495                  port;
1496              t2(A) when record(A, apa); record(A, apa) ->
1497                  record;
1498              t2(A) when reference(A); reference(A) ->
1499                  reference;
1500              t2(A) when tuple(A); tuple(A) ->
1501                  tuple.
1502           ">>,
1503           [nowarn_obsolete_guard],
1504	   []},
1505          {guard4,
1506           <<"-record(apa, {}).
1507              t3(A) when float(A) or float(A) -> % coercing... (badarg)
1508                  float;
1509              t3(A) when is_atom(A) or is_atom(A) ->
1510                  is_atom;
1511              t3(A) when is_binary(A) or is_binary(A) ->
1512                  is_binary;
1513              t3(A) when is_float(A) or is_float(A) ->
1514                  is_float;
1515              t3(A) when is_function(A) or is_function(A) ->
1516                  is_function;
1517              t3(A) when is_integer(A) or is_integer(A) ->
1518                  is_integer;
1519              t3(A) when is_list(A) or is_list(A) ->
1520                  is_list;
1521              t3(A) when is_number(A) or is_number(A) ->
1522                  is_number;
1523              t3(A) when is_pid(A) or is_pid(A) ->
1524                  is_pid;
1525              t3(A) when is_port(A) or is_port(A) ->
1526                  is_port;
1527              t3(A) when is_record(A, apa) or is_record(A, apa) ->
1528                  is_record;
1529              t3(A) when is_record(A, apa, 1) or is_record(A, apa, 1) ->
1530                  is_record;
1531              t3(A) when is_reference(A) or is_reference(A) ->
1532                  is_reference;
1533              t3(A) when is_tuple(A) or is_tuple(A) ->
1534                  is_tuple.
1535           ">>,
1536           [nowarn_obsolete_guard],
1537           []}],
1538    [] = run(Config, Ts),
1539    Ts1 = [{guard5,
1540            <<"-record(apa, {}).
1541               t3(A) when record(A, {apa}) ->
1542                   foo;
1543               t3(A) when is_record(A, {apa}) ->
1544                   foo;
1545               t3(A) when erlang:is_record(A, {apa}) ->
1546                   foo;
1547               t3(A) when is_record(A, {apa}, 1) ->
1548                   foo;
1549               t3(A) when erlang:is_record(A, {apa}, 1) ->
1550                   foo;
1551               t3(A) when is_record(A, apa, []) ->
1552                   foo;
1553               t3(A) when erlang:is_record(A, apa, []) ->
1554                   foo;
1555               t3(A) when record(A, apa) ->
1556                   foo;
1557               t3(A) when is_record(A, apa) ->
1558                   foo;
1559               t3(A) when erlang:is_record(A, apa) ->
1560                   foo.
1561            ">>,
1562            [warn_unused_vars, nowarn_obsolete_guard],
1563            {errors,[{2,erl_lint,illegal_guard_expr},
1564		     {4,erl_lint,illegal_guard_expr},
1565		     {6,erl_lint,illegal_guard_expr},
1566		     {8,erl_lint,illegal_guard_expr},
1567		     {10,erl_lint,illegal_guard_expr},
1568		     {12,erl_lint,illegal_guard_expr},
1569		     {14,erl_lint,illegal_guard_expr}],
1570	     []}},
1571           {guard6,
1572            <<"-record(apa,{a=a,b=foo:bar()}).
1573              apa() ->
1574                 [X || X <- [], #apa{a = a} == {r,X,foo}];
1575              apa() ->
1576                 [X || X <- [], #apa{b = b} == {r,X,foo}];
1577              apa() ->
1578                 [X || X <- [], #ful{a = a} == {r,X,foo}].
1579            ">>,
1580            [],
1581            {errors,[{7,erl_lint,{undefined_record,ful}}],
1582             []}},
1583           {guard7,
1584            <<"-record(apa,{}).
1585               t() ->
1586               [X || X <- [1,#apa{},3], (3+is_record(X, apa)) or
1587                                        (is_record(X, apa)*2)].
1588            ">>,
1589            [],
1590            []},
1591	   {guard8,
1592	    <<"t(A) when erlang:is_foobar(A) -> ok;
1593	      t(A) when A ! ok -> ok;
1594	      t(A) when A ++ [x] -> ok."
1595	    >>,
1596	    [],
1597	    {errors,[{1,erl_lint,illegal_guard_expr},
1598		     {2,erl_lint,illegal_guard_expr},
1599		     {3,erl_lint,illegal_guard_expr}],[]}},
1600           {guard9,
1601            <<"t(X, Y) when erlang:'andalso'(X, Y) -> ok;
1602               t(X, Y) when erlang:'orelse'(X, Y) -> ok.
1603            ">>,
1604            [],
1605            {errors,[{1,erl_lint,illegal_guard_expr},
1606                     {2,erl_lint,illegal_guard_expr}],
1607             []}},
1608           {guard10,
1609            <<"is_port(_) -> false.
1610               t(P) when port(P) -> ok.
1611            ">>,
1612            [],
1613            {error,
1614	     [{2,erl_lint,{obsolete_guard_overridden,port}}],
1615	     [{2,erl_lint,{obsolete_guard,{port,1}}}]}}
1616	  ],
1617    [] = run(Config, Ts1),
1618    ok.
1619
1620%% OTP-4886. Calling is_record with given record name.
1621otp_4886(Config) when is_list(Config) ->
1622    Ts = [{otp_4886,
1623           <<"t() ->
1624                  X = {foo},
1625                  is_record(X, foo),
1626                  erlang:is_record(X, foo),
1627                  {erlang,is_record}(X, foo),
1628                  %% Note: is_record/3 does not verify that the record is defined,
1629                  %% so the following lines should give no errors.
1630                  is_record(X, foo, 1),
1631                  erlang:is_record(X, foo, 1),
1632                  {erlang,is_record}(X, foo, 1).
1633             ">>,
1634           [],
1635           {errors,[{3,erl_lint,{undefined_record,foo}},
1636                    {4,erl_lint,{undefined_record,foo}},
1637                    {5,erl_lint,{undefined_record,foo}}],
1638            []}}],
1639    [] = run(Config, Ts),
1640    ok.
1641
1642%% OTP-4988. Error when in-lining non-existent functions.
1643otp_4988(Config) when is_list(Config) ->
1644    Ts = [{otp_4988,
1645           <<"-compile({inline, [{f,3},{f,4},{f,2},{f,a},{1,foo}]}).
1646              -compile({inline, {g,1}}).
1647              -compile({inline, {g,12}}).
1648              -compile(inline).
1649              -compile({inline_size,100}).
1650
1651              f(A, B) ->
1652                  {g(A), B}.
1653
1654              g(A) ->
1655                  {A}.
1656             ">>,
1657           [],
1658           {errors,[{1,erl_lint,{bad_inline,{1,foo}}},
1659                    {1,erl_lint,{bad_inline,{f,3}}},
1660                    {1,erl_lint,{bad_inline,{f,4}}},
1661                    {1,erl_lint,{bad_inline,{f,a}}},
1662                    {3,erl_lint,{bad_inline,{g,12}}}],
1663            []}}],
1664    [] = run(Config, Ts),
1665    ok.
1666
1667%% OTP-5091. Patterns and the bit syntax: invalid warnings.
1668otp_5091(Config) when is_list(Config) ->
1669    Ts = [{otp_5091_1,
1670           <<"t() ->
1671                 [{Type, Value} || <<Type:16, _Len:16,
1672                                    Value:_Len/binary>> <- []].
1673             ">>,
1674           [],
1675           []},
1676          {otp_5091_2,
1677           <<"t() ->
1678                 %% This one has always been handled OK:
1679                 <<Type:16, _Len:16,
1680                      Value:_Len/binary>> = <<18:16, 9:16, \"123456789\">>,
1681                 {Type, Value}.
1682             ">>,
1683           [],
1684           []},
1685          {otp_5091_3,
1686           <<"t() ->
1687                 fun(<<Type:16, _Len:16, Value:_Len/binary>>) ->
1688                     {Type, Value}
1689                 end.
1690             ">>,
1691           [],
1692           []},
1693          {otp_5091_4,
1694           <<"t() ->
1695                 L = 8,
1696                 F = fun(<<A:L,B:A>>) -> B end,
1697                 F(<<16:8, 7:16>>).
1698             ">>,
1699           [],
1700           []},
1701          {otp_5091_5,
1702           <<"t() ->
1703                 L = 8,
1704                 F = fun(<<L: % L shadowed.
1705                            L,
1706                           B:
1707                            L>>) -> B end,
1708                 F(<<16:8, 7:16>>).
1709             ">>,
1710           [],
1711           {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}},
1712          {otp_5091_6,
1713           <<"t(A) ->
1714                 (fun(<<L:16,M:L,N:M>>) -> ok end)(A).
1715             ">>,
1716           [],
1717           {warnings,[{2,erl_lint,{unused_var,'N'}}]}},
1718          {otp_5091_7,
1719           <<"t() ->
1720                  U = 8,
1721                  (fun(<<U: % U shadowed.
1722                          U>>) -> U end)(<<32:8>>).
1723             ">>,
1724           [],
1725           {warnings,[{3,erl_lint,{shadowed_var,'U','fun'}}]}},
1726          {otp_5091_8,
1727           <<"t() ->
1728                  [X || <<A:8,
1729                          B:A>> <- [],
1730                        <<X:8>> <- [B]].
1731             ">>,
1732           [],
1733           []},
1734          {otp_5091_9,
1735           <<"t() ->
1736                  L = 8,
1737                  F = fun(<<L: % Shadow.
1738                           L,
1739                           L:
1740                           L,
1741                           L:
1742                           L
1743                           >>) ->
1744                              L
1745                      end,
1746                  F(<<16:8, 8:16, 32:8>>).
1747             ">>,
1748           [],
1749           {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}},
1750          {otp_5091_10,
1751           <<"t() ->
1752                L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B.
1753             ">>,
1754           [],
1755           []},
1756          {otp_5091_11,
1757           <<"t() ->
1758                fun(<<L:16,L:L,L:L>>) -> ok end.
1759             ">>,
1760           [],
1761           []},
1762          {otp_5091_12,
1763           <<"t([A,B]) ->
1764                 fun(<<A:B>>, % A shadowed and unused
1765                     <<Q:A>>) -> foo % Q unused. 'outer' A is used.
1766                 end.
1767             ">>,
1768           [],
1769           {warnings,[{2,erl_lint,{unused_var,'A'}},
1770                      {2,erl_lint,{shadowed_var,'A','fun'}},
1771                      {3,erl_lint,{unused_var,'Q'}}]}},
1772          {otp_5091_13,
1773           <<"t([A,B]) -> % A unused, B unused
1774                 fun({A,B}, % A shadowed, B unused, B shadowed
1775                     {Q,A}) -> foo % Q unused. 'inner' A is used
1776                 end.
1777             ">>,
1778           [],
1779           {warnings,[{1,erl_lint,{unused_var,'A'}},
1780                      {1,erl_lint,{unused_var,'B'}},
1781                      {2,erl_lint,{unused_var,'B'}},
1782                      {2,erl_lint,{shadowed_var,'A','fun'}},
1783                      {2,erl_lint,{shadowed_var,'B','fun'}},
1784                      {3,erl_lint,{unused_var,'Q'}}]}},
1785          {otp_5091_14,
1786           <<"t() ->
1787                 A = 4,
1788                 fun(<<A: % shadowed, unused
1789                       A>>) -> 2 end.
1790             ">>,
1791           [],
1792           {warnings,[{3,erl_lint,{unused_var,'A'}},
1793                      {3,erl_lint,{shadowed_var,'A','fun'}}]}},
1794          {otp_5091_15,
1795           <<"t() ->
1796                 A = 4, % unused
1797                 fun(<<A:8, % shadowed
1798                       16:A>>) -> 2 end.
1799             ">>,
1800           [],
1801           {warnings,[{2,erl_lint,{unused_var,'A'}},
1802                      {3,erl_lint,{shadowed_var,'A','fun'}}]}},
1803          {otp_5091_16,
1804           <<"t() ->
1805                 A = 4,
1806                 fun(<<8:A, %
1807                       A:8>>) -> 7 end. % shadowed, unused
1808             ">>,
1809           [],
1810           {warnings,[{4,erl_lint,{unused_var,'A'}},
1811                      {4,erl_lint,{shadowed_var,'A','fun'}}]}},
1812          {otp_5091_17,
1813           <<"t() ->
1814                 L = 16,
1815                 fun(<<L: % shadow
1816                       L>>, % 'outer' L
1817                     <<L: % shadow and match
1818                       L>>) -> % 'outer' L
1819                         a
1820                 end.
1821             ">>,
1822           [],
1823           {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}},
1824          {otp_5091_18,
1825           <<"t() ->
1826                 L = 4,      % L unused
1827                 fun({L,     % L shadowed
1828                      L},
1829                     {L,
1830                      L}) ->
1831                         a
1832                 end.
1833             ">>,
1834           [],
1835           {warnings,[{2,erl_lint,{unused_var,'L'}},
1836                      {3,erl_lint,{shadowed_var,'L','fun'}}]}},
1837          {otp_5091_19,
1838           <<"t() ->
1839                 L = 4,
1840                 [L || <<L: % shadowed
1841                         L,
1842                         L:
1843                         L>> <- []].
1844             ">>,
1845           [],
1846           {warnings,[{3,erl_lint,{shadowed_var,'L',generate}}]}},
1847          {otp_5091_20,
1848           <<"t() ->
1849                 L = 4, % L unused.
1850                 [1 || L <- []]. % L unused, L shadowed.
1851             ">>,
1852           [],
1853           {warnings,[{2,erl_lint,{unused_var,'L'}},
1854                      {3,erl_lint,{unused_var,'L'}},
1855                      {3,erl_lint,{shadowed_var,'L',generate}}]}},
1856          {otp_5091_21,
1857           <<"t() ->
1858                 L = 4,
1859                 [1 || L <- [L]]. % L shadowed. L unused.
1860             ">>,
1861           [],
1862           {warnings,[{3,erl_lint,{unused_var,'L'}},
1863                      {3,erl_lint,{shadowed_var,'L',generate}}]}},
1864          {otp_5091_22,
1865           <<"t() ->
1866                 L = 4, % unused
1867                 fun(L) -> L end. % shadowed
1868             ">>,
1869           [],
1870           {warnings,[{2,erl_lint,{unused_var,'L'}},
1871                      {3,erl_lint,{shadowed_var,'L','fun'}}]}},
1872          {otp_5091_23,
1873           <<"t([A,A]) -> a.">>, [], []},
1874          {otp_5091_24,
1875           <<"t({A,A}) -> a.">>, [], []},
1876          {otp_5091_25,
1877           <<"-record(r, {f1,f2}).
1878              t(#r{f1 = A, f2 = A}) -> a.">>, [], []}],
1879
1880    [] = run(Config, Ts),
1881    ok.
1882
1883%% OTP-5276. Check the 'deprecated' attributed.
1884otp_5276(Config) when is_list(Config) ->
1885    Ts = [{otp_5276_1,
1886          <<"-deprecated([{frutt,0,next_version}]).
1887             -deprecated([{does_not_exist,1}]).
1888             -deprecated('foo bar').
1889             -deprecated(module).
1890             -deprecated([{f,'_'}]).
1891             -deprecated([{t,0}]).
1892             -deprecated([{t,'_',eventually}]).
1893             -deprecated([{'_','_',never}]).
1894             -deprecated([{{badly,formed},1}]).
1895             -deprecated([{'_','_',next_major_release}]).
1896             -deprecated([{atom_to_list,1}]).
1897             -export([t/0]).
1898             frutt() -> ok.
1899             t() -> ok.
1900            ">>,
1901           {[]},
1902           {error,[{1,erl_lint,{bad_deprecated,{frutt,0}}},
1903                   {2,erl_lint,{bad_deprecated,{does_not_exist,1}}},
1904                   {3,erl_lint,{invalid_deprecated,'foo bar'}},
1905                   {5,erl_lint,{bad_deprecated,{f,'_'}}},
1906                   {8,erl_lint,{invalid_deprecated,{'_','_',never}}},
1907                   {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}},
1908		   {11,erl_lint,{bad_deprecated,{atom_to_list,1}}}],
1909            [{13,erl_lint,{unused_function,{frutt,0}}}]}}],
1910    [] = run(Config, Ts),
1911    ok.
1912
1913%% OTP-5917. Check the 'deprecated' attributed.
1914otp_5917(Config) when is_list(Config) ->
1915    Ts = [{otp_5917_1,
1916          <<"-export([t/0]).
1917
1918             -deprecated({t,0}).
1919
1920             t() ->
1921                 foo.
1922            ">>,
1923           {[]},
1924           []}],
1925    [] = run(Config, Ts),
1926    ok.
1927
1928%% OTP-6585. Check the deprecated guards list/1, pid/1, ....
1929otp_6585(Config) when is_list(Config) ->
1930    Ts = [{otp_6585_1,
1931          <<"-export([t/0]).
1932
1933             -record(r, {}).
1934
1935             f(A) when list(A) -> list;
1936             f(R) when record(R, r) -> rec;
1937             f(P) when pid(P) -> pid.
1938
1939             t() ->
1940                 f([]).
1941            ">>,
1942           [warn_obsolete_guard],
1943           {warnings,[{5,erl_lint,{obsolete_guard,{list,1}}},
1944                      {6,erl_lint,{obsolete_guard,{record,2}}},
1945                      {7,erl_lint,{obsolete_guard,{pid,1}}}]}}],
1946    [] = run(Config, Ts),
1947    ok.
1948
1949%% OTP-5338. Bad warning in record initialization.
1950otp_5338(Config) when is_list(Config) ->
1951    %% OTP-5878: variables like X are no longer allowed in initialisations
1952    Ts = [{otp_5338,
1953          <<"-record(c, {a = <<X:7/binary-unit:8>>}).
1954              t() ->
1955                  X = <<\"hejsans\">>,
1956                  #c{}.
1957            ">>,
1958           [],
1959           {error,[{1,erl_lint,{unbound_var,'X'}}],
1960                  [{3,erl_lint,{unused_var,'X'}}]}}],
1961    [] = run(Config, Ts),
1962    ok.
1963
1964%% OTP-5362. deprecated_function,
1965%% {nowarn_unused_funtion,FAs}, 'better' line numbers.
1966otp_5362(Config) when is_list(Config) ->
1967    Ts = [{otp_5362_1,
1968          <<"-include_lib(\"stdlib/include/qlc.hrl\").
1969
1970             -file(?FILE, 1000).
1971
1972             t() ->
1973                 qlc:q([X || X <- [],
1974                             begin A = 3, true end]).
1975            ">>,
1976           {[warn_unused_vars]},
1977           {warnings,[{1002,erl_lint,{unused_function,{t,0}}},
1978                      {1004,erl_lint,{unused_var,'A'}}]}},
1979
1980          {otp_5362_2,
1981          <<"-export([inline/0]).
1982
1983             -import(lists, [a/1,b/1]). % b/1 is not used
1984
1985             -compile([{inline,{inl,7}}]).    % undefined
1986             -compile([{inline,[{inl,17}]}]). % undefined
1987             -compile([{inline,{inl,1}}]).    % OK
1988
1989             foop() ->   % unused function
1990                 a([]),  % used import, OK
1991                 fipp(). % undefined
1992
1993             inline() ->
1994                 inl(foo).
1995
1996             inl(_) ->
1997                 true.
1998
1999             not_used() ->      % unused function
2000                 true.
2001
2002             -compile({nowarn_unused_function,[{and_not_used,2}]}). % unknown
2003             and_not_used(_) -> % unused function
2004                 foo.
2005
2006             -compile({nowarn_unused_function,{unused_function,2}}).
2007             unused_function(_, _) ->
2008                 ok.
2009           ">>,
2010          {[warn_unused_vars, warn_unused_import]},
2011           {error,[{5,erl_lint,{bad_inline,{inl,7}}},
2012                   {6,erl_lint,{bad_inline,{inl,17}}},
2013                   {11,erl_lint,{undefined_function,{fipp,0}}},
2014                   {22,erl_lint,{bad_nowarn_unused_function,{and_not_used,2}}}],
2015            [{3,erl_lint,{unused_import,{{b,1},lists}}},
2016             {9,erl_lint,{unused_function,{foop,0}}},
2017             {19,erl_lint,{unused_function,{not_used,0}}},
2018             {23,erl_lint,{unused_function,{and_not_used,1}}}]}},
2019
2020          {otp_5362_3,
2021           <<"-record(a, {x,
2022                          x}).
2023              -record(a, {x,
2024                          X}). % erl_parse
2025              -record(a, [x,
2026                          x]). % erl_parse
2027              -record(ok, {a,b}).
2028
2029              -record(r, {a = #ok{},
2030                          b = (#ok{})#ok.a}).
2031
2032              t() ->
2033                  {#a{},
2034                   #nix{},
2035                   #ok{nix = []},
2036                   #ok{Var = 4},
2037                   #r{}
2038                  }.
2039           ">>,
2040           {[nowarn_unused_function]},
2041           {errors2, [{4,erl_parse,"bad record field"},
2042                      {5,erl_parse,"bad record declaration"}],
2043                     [{2,erl_lint,{redefine_field,a,x}},
2044                      {14,erl_lint,{undefined_record,nix}},
2045                      {15,erl_lint,{undefined_field,ok,nix}},
2046                      {16,erl_lint,{field_name_is_variable,ok,'Var'}}]}},
2047
2048	  %% Nowarn_bif_clash has changed behaviour as local functions
2049	  %% nowdays supersede auto-imported BIFs, why nowarn_bif_clash in itself generates an error
2050	  %% (OTP-8579) /PaN
2051          {otp_5362_4,
2052           <<"-compile(nowarn_deprecated_function).
2053              -compile(nowarn_bif_clash).
2054              spawn(A) ->
2055                  erlang:now(),
2056                  spawn(A).
2057           ">>,
2058           {[nowarn_unused_function,
2059             warn_deprecated_function,
2060             warn_bif_clash]},
2061           {error,
2062            [{5,erl_lint,{call_to_redefined_old_bif,{spawn,1}}}],
2063            [{4,erl_lint,{deprecated,{erlang,now,0},
2064                          "Deprecated BIF. See the \"Time and Time Correction in Erlang\" "
2065                          "chapter of the ERTS User's Guide for more information."}}]}},
2066          {otp_5362_5,
2067           <<"-compile(nowarn_deprecated_function).
2068              -compile(nowarn_bif_clash).
2069              spawn(A) ->
2070                  erlang:now(),
2071                  spawn(A).
2072           ">>,
2073           {[nowarn_unused_function]},
2074	   {errors,
2075            [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}},
2076
2077          %% The special nowarn_X are not affected by general warn_X.
2078          {otp_5362_6,
2079           <<"-compile({nowarn_deprecated_function,{erlang,now,0}}).
2080              -compile({nowarn_bif_clash,{spawn,1}}).
2081              spawn(A) ->
2082                  erlang:now(),
2083                  spawn(A).
2084           ">>,
2085           {[nowarn_unused_function,
2086             warn_deprecated_function,
2087             warn_bif_clash]},
2088           {errors,
2089            [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}},
2090
2091          {otp_5362_7,
2092           <<"-export([spawn/1]).
2093              -compile({nowarn_deprecated_function,{erlang,now,0}}).
2094              -compile({nowarn_bif_clash,{spawn,1}}).
2095              -compile({nowarn_bif_clash,{spawn,2}}). % bad
2096              -compile([{nowarn_deprecated_function,
2097                                [{erlang,now,-1},{3,now,-1}]}, % 2 bad
2098                     {nowarn_deprecated_function, {{a,b,c},now,-1}}]). % bad
2099              spawn(A) ->
2100                  erlang:now(),
2101                  spawn(A).
2102           ">>,
2103           {[nowarn_unused_function]},
2104           {errors,[{3,erl_lint,disallowed_nowarn_bif_clash},
2105                    {4,erl_lint,disallowed_nowarn_bif_clash},
2106                    {4,erl_lint,{bad_nowarn_bif_clash,{spawn,2}}}],
2107            []}
2108           },
2109
2110          {otp_5362_8,
2111           <<"-export([spawn/1]).
2112              -compile(warn_deprecated_function).
2113              -compile(warn_bif_clash).
2114              spawn(A) ->
2115                  erlang:now(),
2116                  spawn(A).
2117           ">>,
2118           {[nowarn_unused_function,
2119             {nowarn_bif_clash,{spawn,1}}]}, % has no effect
2120           {warnings,
2121            [{5,erl_lint,{deprecated,{erlang,now,0},
2122                          "Deprecated BIF. See the \"Time and Time Correction in Erlang\" "
2123                          "chapter of the ERTS User's Guide for more information."}}]}},
2124
2125          {otp_5362_9,
2126           <<"-include_lib(\"stdlib/include/qlc.hrl\").
2127              -record(a, {x = qlc:q([{X,Y} || {X} <- [],{Y} <- [],X =:= Y])}).
2128              -export([t/0]).
2129              t() -> #a{}.
2130          ">>,
2131           {[]},
2132           []},
2133
2134          {otp_5362_10,
2135           <<"-compile({nowarn_deprecated_function,{erlang,now,0}}).
2136              -compile({nowarn_bif_clash,{spawn,1}}).
2137              -import(x,[spawn/1]).
2138              spin(A) ->
2139                  erlang:now(),
2140                  spawn(A).
2141           ">>,
2142           {[nowarn_unused_function,
2143             warn_deprecated_function,
2144             warn_bif_clash]},
2145           {errors,
2146            [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}},
2147
2148	  {call_deprecated_function,
2149	   <<"t(X) -> calendar:local_time_to_universal_time(X).">>,
2150	   [],
2151	   {warnings,
2152            [{1,erl_lint,{deprecated,{calendar,local_time_to_universal_time,1},
2153			  {calendar,local_time_to_universal_time_dst,1}, "a future release"}}]}},
2154
2155	  {call_removed_function,
2156	   <<"t(X) -> erlang:hash(X, 10000).">>,
2157	   [],
2158	   {warnings,
2159            [{1,erl_lint,{removed,{erlang,hash,2},{erlang,phash2,2},"20.0"}}]}},
2160
2161	  {nowarn_call_removed_function_1,
2162	   <<"t(X) -> erlang:hash(X, 10000).">>,
2163	   [{nowarn_removed,{erlang,hash,2}}],
2164	   []},
2165
2166	  {nowarn_call_removed_function_2,
2167	   <<"t(X) -> os_mon_mib:any_function_really(erlang:hash(X, 10000)).">>,
2168	   [nowarn_removed],
2169	   []},
2170
2171	  {call_removed_module,
2172	   <<"t(X) -> os_mon_mib:any_function_really(X).">>,
2173	   [],
2174           {warnings,[{1,erl_lint,
2175                       {removed,{os_mon_mib,any_function_really,1},
2176                        "was removed in 22.0"}}]}},
2177
2178	  {nowarn_call_removed_module,
2179	   <<"t(X) -> os_mon_mib:any_function_really(X).">>,
2180	   [{nowarn_removed,os_mon_mib}],
2181	   []}
2182
2183	 ],
2184
2185    [] = run(Config, Ts),
2186    ok.
2187
2188%% OTP-15456. All compiler options can now be given in the option list
2189%% (as opposed to only in files).
2190otp_15456(Config) when is_list(Config) ->
2191    Ts = [
2192          %% {nowarn_deprecated_function,[{M,F,A}]} can now be given
2193          %% in the option list as well as in an attribute.
2194          %% Wherever it occurs, it is not affected by
2195          %% warn_deprecated_function.
2196          {otp_15456_1,
2197           <<"-compile({nowarn_deprecated_function,{erlang,now,0}}).
2198              -export([foo/0]).
2199
2200              foo() ->
2201                  {erlang:now(), random:seed0(), random:seed(1, 2, 3),
2202                   random:uniform(), random:uniform(42)}.
2203           ">>,
2204           {[{nowarn_deprecated_function,{random,seed0,0}},
2205             {nowarn_deprecated_function,[{random,uniform,0},
2206                                          {random,uniform,1}]},
2207             %% There should be no warnings when attempting to
2208             %% turn of warnings for functions that are not
2209             %% deprecated or not used in the module.
2210             {nowarn_deprecated_function,{random,uniform_s,1}},
2211             {nowarn_deprecated_function,{erlang,abs,1}},
2212             warn_deprecated_function]},
2213           {warnings,[{5,erl_lint,
2214                       {deprecated,{random,seed,3},
2215                        "the 'random' module is deprecated; "
2216                        "use the 'rand' module instead"}}]}},
2217
2218          %% {nowarn_unused_function,[{M,F,A}]} can be given
2219          %% in the option list as well as in an attribute.
2220          %% It was incorrectly documented to only work when
2221          %% given in an attribute.
2222          {otp_15456_2,
2223           <<"-compile({nowarn_unused_function,foo/0}).
2224              foo() -> ok.
2225              bar() -> ok.
2226              foobar() -> ok.
2227              barf(_) -> ok.
2228              other() -> ok.
2229           ">>,
2230           {[{nowarn_unused_function,[{bar,0},{foobar,0}]},
2231             {nowarn_unused_function,{barf,1}},
2232             %% There should be no warnings when attempting to
2233             %% turn of warnings for unused functions that are not
2234             %% defined in the module.
2235             {nowarn_unused_function,{not_defined_in_module,1}},
2236             warn_unused_function]},
2237           {warnings,[{6,erl_lint,{unused_function,{other,0}}}]}
2238          }],
2239
2240    [] = run(Config, Ts),
2241    ok.
2242
2243%% OTP-5371. Aliases for bit syntax expressions are no longer allowed.
2244otp_5371(Config) when is_list(Config) ->
2245    Ts = [{otp_5371_1,
2246           <<"t(<<A:8>> = <<B:8>>) ->
2247                  {A,B}.
2248             ">>,
2249	   [],
2250	   {errors,[{1,erl_lint,illegal_bin_pattern}],[]}},
2251	  {otp_5371_2,
2252           <<"x([<<A:8>>] = [<<B:8>>]) ->
2253                  {A,B}.
2254              y({a,<<A:8>>} = {b,<<B:8>>}) ->
2255                  {A,B}.
2256             ">>,
2257	   [],
2258	   {errors,[{1,erl_lint,illegal_bin_pattern},
2259		    {3,erl_lint,illegal_bin_pattern}],[]}},
2260	  {otp_5371_3,
2261           <<"-record(foo, {a,b,c}).
2262              -record(bar, {x,y,z}).
2263              -record(buzz, {x,y}).
2264              a(#foo{a = <<X:8>>} = #bar{x = <<Y:8>>}) ->
2265                  {X,Y}.
2266              b(#foo{b = <<X:8>>} = #foo{b = <<Y:4,Z:4>>}) ->
2267                  {X,Y,Z}.
2268              c(#foo{a = <<X:8>>} = #buzz{x = <<Y:8>>}) ->
2269                  {X,Y}.
2270              d(#foo{a=x,b = <<X:8>>} = #buzz{y = <<Y:8>>}) ->
2271                  {X,Y}.
2272              e(#foo{a=x,b = <<X:8>>} = #buzz{x=glurf,y = <<Y:8>>}) ->
2273                  {X,Y}.
2274             ">>,
2275	   [],
2276	   {errors,[{4,erl_lint,illegal_bin_pattern},
2277		    {6,erl_lint,illegal_bin_pattern},
2278		    {8,erl_lint,illegal_bin_pattern},
2279		    {10,erl_lint,illegal_bin_pattern},
2280		    {12,erl_lint,illegal_bin_pattern}],[]}},
2281	  {otp_5371_4,
2282           <<"-record(foo, {a,b,c}).
2283              -record(bar, {x,y,z}).
2284              -record(buzz, {x,y}).
2285              a(#foo{a = <<X:8>>,b=x} = #foo{b = <<Y:8>>}) ->
2286                  {X,Y}.
2287              b(#foo{a = <<X:8>>} = #bar{y = <<Y:4,Z:4>>}) ->
2288                  {X,Y,Z}.
2289              c(#foo{a = <<X:8>>} = #buzz{y = <<Y:8>>}) ->
2290                  {X,Y}.
2291             ">>,
2292	   [],
2293	   {warnings,[{4,v3_core,nomatch},
2294		      {6,v3_core,nomatch},
2295		      {8,v3_core,nomatch}]}}
2296	 ],
2297    [] = run(Config, Ts),
2298    ok.
2299
2300%% OTP_7227. Some aliases for bit syntax expressions were still allowed.
2301otp_7227(Config) when is_list(Config) ->
2302    Ts = [{otp_7227_1,
2303           <<"t([<<A:8>> = {C,D} = <<B:8>>]) ->
2304                  {A,B,C,D}.
2305             ">>,
2306	   [],
2307	   {errors,[{1,erl_lint,illegal_bin_pattern}],[]}},
2308	  {otp_7227_2,
2309           <<"t([(<<A:8>> = {C,D}) = <<B:8>>]) ->
2310                  {A,B,C,D}.
2311             ">>,
2312	   [],
2313	   {errors,[{1,erl_lint,illegal_bin_pattern}],[]}},
2314	  {otp_7227_3,
2315           <<"t([(<<A:8>> = {C,D}) = (<<B:8>> = <<C:8>>)]) ->
2316                  {A,B,C,D}.
2317             ">>,
2318	   [],
2319	   {errors,[{1,erl_lint,illegal_bin_pattern},
2320		    {1,erl_lint,illegal_bin_pattern},
2321		    {1,erl_lint,illegal_bin_pattern}],[]}},
2322	  {otp_7227_4,
2323           <<"t(Val) ->
2324                  <<A:8>> = <<B:8>> = Val,
2325                  {A,B}.
2326             ">>,
2327	   [],
2328	   {errors,[{2,erl_lint,illegal_bin_pattern}],[]}},
2329	  {otp_7227_5,
2330           <<"t(Val) ->
2331                  <<A:8>> = X = <<B:8>> = Val,
2332                  {A,B,X}.
2333             ">>,
2334	   [],
2335	   {errors,[{2,erl_lint,illegal_bin_pattern}],[]}},
2336	  {otp_7227_6,
2337           <<"t(X, Y) ->
2338                  <<A:8>> = <<X:4,Y:4>>,
2339                  A.
2340             ">>,
2341	   [],
2342	   []},
2343	  {otp_7227_7,
2344           <<"t(Val) ->
2345                  (<<A:8>> = X) = (<<B:8>> = <<A:4,B:4>>) = Val,
2346                  {A,B,X}.
2347             ">>,
2348	   [],
2349	   {errors,[{2,erl_lint,illegal_bin_pattern},
2350		    {2,erl_lint,illegal_bin_pattern},
2351		    {2,erl_lint,illegal_bin_pattern}],[]}},
2352	  {otp_7227_8,
2353           <<"t(Val) ->
2354                  (<<A:8>> = X) = (Y = <<B:8>>) = Val,
2355                  {A,B,X,Y}.
2356             ">>,
2357	   [],
2358	   {errors,[{2,erl_lint,illegal_bin_pattern}],[]}},
2359	  {otp_7227_9,
2360           <<"t(Val) ->
2361                  (Z = <<A:8>> = X) = (Y = <<B:8>> = W) = Val,
2362                  {A,B,X,Y,Z,W}.
2363             ">>,
2364	   [],
2365	   {errors,[{2,erl_lint,illegal_bin_pattern}],[]}}
2366	 ],
2367    [] = run(Config, Ts),
2368    ok.
2369
2370%% OTP-5494. Warnings for functions exported more than once.
2371otp_5494(Config) when is_list(Config) ->
2372    Ts = [{otp_5494_1,
2373           <<"-export([t/0]).
2374              -export([t/0]).
2375              t() -> a.
2376             ">>,
2377           [],
2378           {warnings,[{2,erl_lint,{duplicated_export,{t,0}}}]}}],
2379    [] = run(Config, Ts),
2380    ok.
2381
2382%% OTP-5644. M:F/A in record initialization.
2383otp_5644(Config) when is_list(Config) ->
2384    %% This test is a no-op. Although {function,mfa,i,1} was
2385    %% transformed into {function,Line,i,1} by copy_expr, the module
2386    %% was never checked (Line is the line number).
2387    %% (OTP-5878: somewhat modified.)
2388    Ts = [{otp_5644,
2389          <<"-record(c, {a = fun ?MODULE:i/1(17)}).
2390              t() ->
2391                  #c{}.
2392
2393              i(X) ->
2394                  X.
2395            ">>,
2396           [],
2397           []}],
2398    [] = run(Config, Ts),
2399    ok.
2400
2401%% OTP-5878. Record declaration: forward references, introduced variables.
2402otp_5878(Config) when is_list(Config) ->
2403    Ts = [{otp_5878_10,
2404          <<"-record(rec1, {a = #rec2{}}).
2405             -record(rec2, {a = #rec1{}}).
2406             t() ->#rec1{}.
2407            ">>,
2408           [warn_unused_record],
2409           {error,[{1,erl_lint,{undefined_record,rec2}}],
2410                  [{2,erl_lint,{unused_record,rec2}}]}},
2411
2412          {otp_5878_20,
2413           <<"-record(r1, {a = begin A = 4, {A,B} end}). % B unbound
2414              -record(r2, {e = begin A = 3, #r1{} end}).
2415              t() -> #r2{}.
2416             ">>,
2417           [warn_unused_record],
2418           {error,[{1,erl_lint,{unbound_var,'B'}},
2419                   {1,erl_lint,{variable_in_record_def,'A'}},
2420                   {2,erl_lint,{variable_in_record_def,'A'}}],
2421            [{1,erl_lint,{unused_record,r1}}]}},
2422
2423          {otp_5878_30,
2424           <<"-record(r1, {t = case foo of _ -> 3 end}).
2425              -record(r2, {a = case foo of A -> A; _ -> 3 end}).
2426              -record(r3, {a = case foo of A -> A end}).
2427              -record(r4, {a = fun _AllowedFunName() -> allowed end}).
2428              t() -> {#r1{},#r2{},#r3{},#r4{}}.
2429             ">>,
2430           [warn_unused_record],
2431           {errors,[{2,erl_lint,{variable_in_record_def,'A'}},
2432                    {3,erl_lint,{variable_in_record_def,'A'}}],
2433            []}},
2434
2435          {otp_5878_40,
2436           <<"-record(r1, {foo = A}). % A unbound
2437              -record(r2, {a = fun(X) -> X end(3)}).
2438              -record(r3, {a = [X || X <- [1,2,3]]}).
2439              t() -> {#r1{},#r2{},#r3{}}.
2440             ">>,
2441           [warn_unused_record],
2442           {errors,[{1,erl_lint,{unbound_var,'A'}}],[]}},
2443
2444          {otp_5878_50,
2445           <<"-record(r1, {a = {A, % A unbound
2446                                A}}). % A unbound
2447              -record(r2, {a = begin case foo of
2448                                         A -> A
2449                                     end,
2450                                     A
2451                                end}).
2452              -record(r3, {a = fun(X) ->
2453                                       case foo of
2454                                           A -> A
2455                                       end
2456                               end
2457                          }).
2458              -record(r4, {a = case foo of
2459                                   foo ->
2460                                       case foo of
2461                                           A -> A
2462                                       end;
2463                                   _ ->
2464                                       bar
2465                               end}).
2466              t() -> {#r1{},#r2{},#r3{},#r4{}}.
2467             ">>,
2468           [warn_unused_record],
2469           {error,[{1,erl_lint,{unbound_var,'A'}},
2470                   {2,erl_lint,{unbound_var,'A'}},
2471                   {4,erl_lint,{variable_in_record_def,'A'}},
2472                   {17,erl_lint,{variable_in_record_def,'A'}}],
2473            [{8,erl_lint,{unused_var,'X'}}]}},
2474
2475          {otp_5878_60,
2476           <<"-record(r1, {a = fun(NotShadowing) -> NotShadowing end}).
2477              t() ->
2478                  NotShadowing = 17,
2479                  {#r1{}, NotShadowing}.
2480             ">>,
2481           [warn_unused_record],
2482           []},
2483
2484          {otp_5878_70,
2485           <<"-record(r1, {a = fun(<<X:8>>) -> X end,
2486                           b = case <<17:8>> of
2487                                   <<_:Y>> -> Y;
2488                                   <<Y:8>> ->
2489                                       Y
2490                               end}).
2491              t() -> #r1{}.
2492             ">>,
2493           [warn_unused_record],
2494           {errors,[{3,erl_lint,{unbound_var,'Y'}},
2495                    {4,erl_lint,{variable_in_record_def,'Y'}}],
2496            []}},
2497
2498          {otp_5878_80,
2499           <<"-record(r, {a = [X || {A,Y} <- [{1,2},V={3,4}],
2500                                    begin Z = [1,2,3], true end,
2501                                    X <- Z ++ [A,Y]]}).
2502              t() ->#r{}.
2503             ">>,
2504           [warn_unused_record],
2505           {warnings,[{1,erl_lint,{unused_var,'V'}}]}},
2506
2507          {otp_5878_90,
2508           <<"-record(r, {a = foo()}). % unused
2509
2510              t() -> ok.
2511             ">>,
2512           [warn_unused_record],
2513           {error,[{1,erl_lint,{undefined_function,{foo,0}}}],
2514            [{1,erl_lint,{unused_record,r}}]}}
2515
2516         ],
2517    [] = run(Config, Ts),
2518
2519    Abstr = <<"-module(lint_test, [A, B]).
2520            ">>,
2521    {errors,[{1,erl_lint,pmod_unsupported}],[]} =
2522        run_test2(Config, Abstr, [warn_unused_record]),
2523
2524    QLC1 = <<"-module(lint_test).
2525              -include_lib(\"stdlib/include/qlc.hrl\").
2526              -export([t/0]).
2527              -record(r1, {a = qlc:e(qlc:q([X || X <- [1,2,3]]))}).
2528              -record(r2, {a = qlc:q([X || X <- [1,2,3]])}).
2529              -record(r3, {a = qlc:q([X || {A,Y} <- [{1,2},V={3,4}],
2530                                           begin Z = [1,2,3], true end,
2531                                           X <- Z ++ [A,Y]])}).
2532              t() -> {#r1{},#r2{},#r3{}}.
2533             ">>,
2534    {error,[{8,qlc,{used_generator_variable,'A'}},
2535                  {8,qlc,{used_generator_variable,'Y'}},
2536                  {8,qlc,{used_generator_variable,'Z'}}],
2537           [{6,erl_lint,{unused_var,'V'}}]} =
2538        run_test2(Config, QLC1, [warn_unused_record]),
2539
2540    Ill1 = <<"-module(lint_test).
2541              -export([t/0]).
2542              -record(r, {a = true}).
2543              -record(r1, {a,b}).
2544              -record(r2, {a = #r1{a = true}}).
2545              -record(r3, {a = A}). % A is unbound
2546              -record(r4, {a = dict:new()}).
2547
2548              t() ->
2549                  case x() of
2550                      _ when (#r{})#r.a ->
2551                          a;
2552                      _ when (#r4{})#r.a -> % illegal
2553                          b;
2554                      _ when (#r3{q = 5})#r.a -> % no warning for unbound A
2555                          q;
2556                      _ when (#r{q = 5})#r.a ->
2557                          a;
2558                      _ when (((#r{a = #r2{}})#r.a)#r2.a)#r1.a ->
2559                          b;
2560                      _ when #r{a = dict:new()} -> % illegal
2561                          c;
2562                      _ when l() > 3 -> % illegal, does not use l/0...
2563                          d;
2564                      _ ->
2565                          w
2566                  end.
2567
2568              l() ->
2569                  foo.
2570
2571              x() ->
2572                  bar.
2573              ">>,
2574
2575    {errors,[{6,erl_lint,{unbound_var,'A'}},
2576                   {13,erl_lint,illegal_guard_expr},
2577                   {15,erl_lint,{undefined_field,r3,q}},
2578                   {17,erl_lint,{undefined_field,r,q}},
2579                   {21,erl_lint,illegal_guard_expr},
2580                   {23,erl_lint,{illegal_guard_local_call,{l,0}}}],
2581           []} =
2582        run_test2(Config, Ill1, [warn_unused_record]),
2583
2584    Ill2 = <<"-module(lint_test).
2585              -export([t/0]).
2586              t() ->
2587                  case x() of
2588                      _ when l()
2589                             or
2590                             l() ->
2591                          foo
2592                  end.
2593             ">>,
2594    {errors,[{4,erl_lint,{undefined_function,{x,0}}},
2595                   {5,erl_lint,illegal_guard_expr},
2596                   {7,erl_lint,illegal_guard_expr}],
2597           []} =
2598        run_test2(Config, Ill2, [warn_unused_record]),
2599
2600    Ill3 = <<"t() -> ok.">>,
2601    {errors,[{1,erl_lint,undefined_module}],[]} =
2602        run_test2(Config, Ill3, [warn_unused_record]),
2603
2604    Usage1 = <<"-module(lint_test).
2605                -export([t/0]).
2606                -record(u1, {a}).
2607                -record(u2, {a = #u1{}}).
2608                -record(u3, {a}). % unused
2609                -record(u4, {a = #u3{}}). % unused
2610
2611                t() ->
2612                    {#u2{}}.
2613               ">>,
2614    {warnings,[{5,erl_lint,{unused_record,u3}},
2615                     {6,erl_lint,{unused_record,u4}}]} =
2616        run_test2(Config, Usage1, [warn_unused_record]),
2617
2618    Usage2 = <<"-module(lint_test).
2619                -export([t/0]).
2620                -record(u1, {a}).
2621                -record(u2, {a = #u1{}}).
2622                -file(\"some_file.hrl\", 1).
2623                -record(u3, {a}). % unused, but on other file
2624                -record(u4, {a = #u3{}}). % -\"-
2625
2626                t() ->
2627                    {#u2{}}.
2628               ">>,
2629    [] = run_test2(Config, Usage2, [warn_unused_record]),
2630
2631    %% This a completely different story...
2632    %% The linter checks if qlc.hrl hasn't been included
2633    QLC2 = <<"-module(lint_test).
2634              -import(qlc, [q/2]).
2635              -export([t/0]).
2636
2637              t() ->
2638                  H1 = qlc:q([X || X <- [1,2]]),
2639                  H2 = qlc:q([X || X <- [1,2]], []),
2640                  H3 = q([X || X <- [1,2]], []),
2641                  {H1,H2,H3}.
2642             ">>,
2643    {warnings,[{6,erl_lint,{missing_qlc_hrl,1}},
2644                     {7,erl_lint,{missing_qlc_hrl,2}},
2645                     {8,erl_lint,{missing_qlc_hrl,2}}]} =
2646        run_test2(Config, QLC2, [warn_unused_record]),
2647
2648    %% Records that are used by types are not unused.
2649    %% (Thanks to Fredrik Thulin and Kostis Sagonas.)
2650    UsedByType = <<"-module(t).
2651                    -export([foo/1]).
2652                    -record(sipurl,  {host :: string()}).
2653                    -record(keylist, {list = [] :: [_]}).
2654                    -type sip_headers() :: #keylist{}.
2655                    -record(request, {uri :: #sipurl{}, header :: sip_headers()}).
2656
2657                    foo(#request{}) -> ok.
2658                  ">>,
2659    [] = run_test2(Config, UsedByType, [warn_unused_record]),
2660
2661    %% Abstract code generated by OTP 18. Note that the type info for
2662    %% record fields has been put in a separate form.
2663    OldAbstract = [{attribute,1,file,{"rec.erl",1}},
2664                   {attribute,1,module,rec},
2665                   {attribute,3,export,[{t,0}]},
2666                   {attribute,7,record,{r,[{record_field,7,{atom,7,f}}]}},
2667                   {attribute,7,type,
2668                    {{record,r},
2669                     [{typed_record_field,
2670                       {record_field,7,{atom,7,f}},
2671                       {type,7,union,[{atom,7,undefined},{type,7,atom,[]}]}}],
2672                     []}},
2673                   {function,9,t,0,[{clause,9,[],[],[{record,10,r,[]}]}]},
2674                   {eof,11}],
2675    {error,[{"rec.erl",[{7,erl_lint,old_abstract_code}]}],[]} =
2676        compile_forms(OldAbstract, [return, report]),
2677
2678    ok.
2679
2680%% OTP-6885. Binary fields in bit syntax matching is now only
2681%% allowed at the end.
2682otp_6885(Config) when is_list(Config) ->
2683    Ts = <<"-module(otp_6885).
2684            -export([t/1]).
2685            t(<<_/binary,I>>) -> I;
2686            t(<<X/binary,I:X>>) -> I;
2687	    t(<<B/binary,T/binary>>) -> {B,T}.
2688
2689            build(A, B) ->
2690               <<A/binary,B/binary>>.
2691
2692            foo(<<\"abc\"/binary>>) ->
2693               ok;
2694            foo(<<\"abc\":13/integer>>) ->
2695               ok;
2696            foo(<<\"abc\"/float>>) ->
2697               ok;
2698            foo(<<\"abc\":19>>) ->
2699               ok;
2700            foo(<<\"abc\"/utf8>>) ->
2701               ok;
2702            foo(<<\"abc\"/utf16>>) ->
2703               ok;
2704            foo(<<\"abc\"/utf32>>) ->
2705               ok.
2706
2707           ">>,
2708    {errors,[{3,erl_lint,unsized_binary_not_at_end},
2709		   {4,erl_lint,unsized_binary_not_at_end},
2710		   {5,erl_lint,unsized_binary_not_at_end},
2711		   {10,erl_lint,typed_literal_string},
2712		   {12,erl_lint,typed_literal_string},
2713		   {14,erl_lint,typed_literal_string},
2714		   {16,erl_lint,typed_literal_string}],
2715	   []} = run_test2(Config, Ts, []),
2716    ok.
2717
2718%% OTP-6885. Warnings for opaque types.
2719otp_10436(Config) when is_list(Config) ->
2720    Ts = <<"-module(otp_10436).
2721            -export_type([t1/0]).
2722            -opaque t1() :: {i, integer()}.
2723            -opaque t2() :: {a, atom()}.
2724         ">>,
2725    {warnings,[{4,erl_lint,{not_exported_opaque,{t2,0}}},
2726               {4,erl_lint,{unused_type,{t2,0}}}]} =
2727        run_test2(Config, Ts, []),
2728    Ts2 = <<"-module(otp_10436_2).
2729             -export_type([t1/0, t2/0]).
2730             -opaque t1() :: term().
2731             -opaque t2() :: any().
2732         ">>,
2733    {warnings,[{3,erl_lint,{underspecified_opaque,{t1,0}}},
2734               {4,erl_lint,{underspecified_opaque,{t2,0}}}]} =
2735        run_test2(Config, Ts2, []),
2736    ok.
2737
2738%% OTP-11254. M:F/A could crash the linter.
2739otp_11254(Config) when is_list(Config) ->
2740    Ts = <<"-module(p2).
2741            -export([manifest/2]).
2742            manifest(Module, Name) ->
2743              fun Module:Nine/1.
2744         ">>,
2745    {error,[{4,erl_lint,{unbound_var,'Nine'}}],
2746     [{3,erl_lint,{unused_var,'Name'}}]} =
2747        run_test2(Config, Ts, []),
2748    ok.
2749
2750%% OTP-11772. Reintroduce errors for redefined builtin types.
2751otp_11772(Config) when is_list(Config) ->
2752    Ts = <<"
2753            -module(newly).
2754
2755            -export([t/0]).
2756
2757            %% Built-in:
2758            -type node() :: node().
2759            -type mfa() :: tuple().
2760            -type gb_tree() :: mfa(). % Allowed since Erlang/OTP 17.0
2761            -type digraph() :: [_].   % Allowed since Erlang/OTP 17.0
2762
2763            -type t() :: mfa() | digraph() | gb_tree() | node().
2764
2765            -spec t() -> t().
2766
2767            t() ->
2768                1.
2769         ">>,
2770    {errors,[{7,erl_lint,{builtin_type,{node,0}}},
2771             {8,erl_lint,{builtin_type,{mfa,0}}}],
2772     []} = run_test2(Config, Ts, []),
2773    ok.
2774
2775%% OTP-11771. Do not allow redefinition of the types arity(_) &c..
2776otp_11771(Config) when is_list(Config) ->
2777    Ts = <<"
2778            -module(newly).
2779
2780            -export([t/0]).
2781
2782            %% No longer allowed in 17.0:
2783            -type arity() :: atom().
2784            -type bitstring() :: list().
2785            -type iodata() :: integer().
2786            -type boolean() :: iodata().
2787
2788            -type t() :: arity() | bitstring() | iodata() | boolean().
2789
2790            -spec t() -> t().
2791
2792            t() ->
2793                1.
2794         ">>,
2795    {errors,[{7,erl_lint,{builtin_type,{arity,0}}},
2796             {8,erl_lint,{builtin_type,{bitstring,0}}},
2797             {9,erl_lint,{builtin_type,{iodata,0}}},
2798             {10,erl_lint,{builtin_type,{boolean,0}}}],
2799     []} = run_test2(Config, Ts, []),
2800    ok.
2801
2802%% OTP-11872. The type map() undefined when exported.
2803otp_11872(Config) when is_list(Config) ->
2804    Ts = <<"
2805            -module(map).
2806
2807            -export([t/0]).
2808
2809            -export_type([map/0, product/0]).
2810
2811            -opaque map() :: dict().
2812
2813            -spec t() -> map().
2814
2815            t() ->
2816                1.
2817         ">>,
2818    {errors,[{6,erl_lint,{undefined_type,{product,0}}},
2819             {8,erl_lint,{builtin_type,{map,0}}}], []} =
2820        run_test2(Config, Ts, []),
2821    ok.
2822
2823%% OTP-7392. Warning for export_all.
2824export_all(Config) when is_list(Config) ->
2825    Ts = <<"-module(export_all_module).
2826            -compile([export_all]).
2827
2828            id(I) -> I.
2829           ">>,
2830    [] = run_test2(Config, Ts, [nowarn_export_all]),
2831    {warnings,[{2,erl_lint,export_all}]} =
2832	run_test2(Config, Ts, []),
2833    ok.
2834
2835%% Test warnings for functions that clash with BIFs.
2836bif_clash(Config) when is_list(Config) ->
2837    Ts = [{clash1,
2838           <<"t(X) ->
2839                  size(X).
2840
2841              %% No warning for the following calls, since they
2842              %% are unambigous.
2843              b(X) ->
2844                  erlang:size(X).
2845
2846              c(X) ->
2847                  ?MODULE:size(X).
2848
2849              size({N,_}) ->
2850                N.
2851             ">>,
2852           [],
2853	   {errors,[{2,erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}},
2854
2855	  %% Verify that warnings cannot be turned off in the old way.
2856	  {clash2,
2857           <<"-export([t/1,size/1]).
2858              t(X) ->
2859                  size(X).
2860
2861              size({N,_}) ->
2862                N.
2863
2864              %% My own abs/1 function works on lists too. From R14 this really works.
2865              abs([H|T]) when $a =< H, H =< $z -> [H-($a-$A)|abs(T)];
2866              abs([H|T]) -> [H|abs(T)];
2867              abs([]) -> [];
2868              abs(X) -> erlang:abs(X).
2869             ">>,
2870	   {[nowarn_unused_function,nowarn_bif_clash]},
2871	   {errors,[{erl_lint,disallowed_nowarn_bif_clash}],[]}},
2872	  %% As long as noone calls an overridden BIF, it's totally OK
2873	  {clash3,
2874           <<"-export([size/1]).
2875              size({N,_}) ->
2876                N;
2877              size(X) ->
2878                erlang:size(X).
2879             ">>,
2880	   [],
2881	   []},
2882	  %% But this is totally wrong - meaning of the program changed in R14, so this is an error
2883	  {clash4,
2884           <<"-export([size/1]).
2885              size({N,_}) ->
2886                N;
2887              size(X) ->
2888                size(X).
2889             ">>,
2890	   [],
2891	   {errors,[{5,erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}},
2892	  %% For a post R14 bif, its only a warning
2893	  {clash5,
2894           <<"-export([binary_part/2]).
2895              binary_part({B,_},{X,Y}) ->
2896                binary_part(B,{X,Y});
2897              binary_part(B,{X,Y}) ->
2898                binary:part(B,X,Y).
2899             ">>,
2900	   [],
2901	   {warnings,[{3,erl_lint,{call_to_redefined_bif,{binary_part,2}}}]}},
2902	  %% If you really mean to call yourself here, you can "unimport" size/1
2903	  {clash6,
2904           <<"-export([size/1]).
2905              -compile({no_auto_import,[size/1]}).
2906              size([]) ->
2907                0;
2908              size({N,_}) ->
2909                N;
2910              size([_|T]) ->
2911                1+size(T).
2912             ">>,
2913	   [],
2914	   []},
2915	  %% Same for the post R14 autoimport warning
2916	  {clash7,
2917           <<"-export([binary_part/2]).
2918              -compile({no_auto_import,[binary_part/2]}).
2919              binary_part({B,_},{X,Y}) ->
2920                binary_part(B,{X,Y});
2921              binary_part(B,{X,Y}) ->
2922                binary:part(B,X,Y).
2923             ">>,
2924	   [],
2925	   []},
2926          %% but this doesn't mean the local function is allowed in a guard...
2927	  {clash8,
2928           <<"-export([x/1]).
2929              -compile({no_auto_import,[binary_part/2]}).
2930              x(X) when binary_part(X,{1,2}) =:= <<1,2>> ->
2931                 hej.
2932              binary_part({B,_},{X,Y}) ->
2933                binary_part(B,{X,Y});
2934              binary_part(B,{X,Y}) ->
2935                binary:part(B,X,Y).
2936             ">>,
2937	   [],
2938	   {errors,[{3,erl_lint,{illegal_guard_local_call,{binary_part,2}}}],[]}},
2939          %% no_auto_import is not like nowarn_bif_clash, it actually removes the autoimport
2940	  {clash9,
2941           <<"-export([x/1]).
2942              -compile({no_auto_import,[binary_part/2]}).
2943              x(X) ->
2944                 binary_part(X,{1,2}) =:= <<1,2>>.
2945             ">>,
2946	   [],
2947	   {errors,[{4,erl_lint,{undefined_function,{binary_part,2}}}],[]}},
2948          %% but we could import it again...
2949	  {clash10,
2950           <<"-export([x/1]).
2951              -compile({no_auto_import,[binary_part/2]}).
2952              -import(erlang,[binary_part/2]).
2953              x(X) ->
2954                 binary_part(X,{1,2}) =:= <<1,2>>.
2955             ">>,
2956	   [],
2957	   []},
2958          %% and actually use it in a guard...
2959	  {clash11,
2960           <<"-export([x/1]).
2961              -compile({no_auto_import,[binary_part/2]}).
2962              -import(erlang,[binary_part/2]).
2963              x(X) when binary_part(X,{0,1}) =:= <<0>> ->
2964                 binary_part(X,{1,2}) =:= <<1,2>>.
2965             ">>,
2966	   [],
2967	   []},
2968          %% but for non-obvious historical reasons, imported functions cannot be used in
2969	  %% fun construction without the module name...
2970	  {clash12,
2971           <<"-export([x/1]).
2972              -compile({no_auto_import,[binary_part/2]}).
2973              -import(erlang,[binary_part/2]).
2974              x(X) when binary_part(X,{0,1}) =:= <<0>> ->
2975                 binary_part(X,{1,2}) =:= fun binary_part/2.
2976             ">>,
2977	   [],
2978	   {errors,[{5,erl_lint,{undefined_function,{binary_part,2}}}],[]}},
2979          %% Not from erlang and not from anywhere else
2980	  {clash13,
2981           <<"-export([x/1]).
2982              -compile({no_auto_import,[binary_part/2]}).
2983              -import(x,[binary_part/2]).
2984              x(X) ->
2985                 binary_part(X,{1,2}) =:= fun binary_part/2.
2986             ">>,
2987	   [],
2988	   {errors,[{5,erl_lint,{undefined_function,{binary_part,2}}}],[]}},
2989	  %% ...while real auto-import is OK.
2990	  {clash14,
2991           <<"-export([x/1]).
2992              x(X) when binary_part(X,{0,1}) =:= <<0>> ->
2993                 binary_part(X,{1,2}) =:= fun binary_part/2.
2994             ">>,
2995	   [],
2996	   []},
2997          %% Import directive clashing with old bif is an error, regardless of if it's called or not
2998	  {clash15,
2999           <<"-export([x/1]).
3000              -import(x,[abs/1]).
3001              x(X) ->
3002                 binary_part(X,{1,2}).
3003             ">>,
3004	   [],
3005	   {errors,[{2,erl_lint,{redefine_old_bif_import,{abs,1}}}],[]}},
3006	  %% For a new BIF, it's only a warning
3007	  {clash16,
3008           <<"-export([x/1]).
3009              -import(x,[binary_part/3]).
3010              x(X) ->
3011                 abs(X).
3012             ">>,
3013	   [],
3014	   {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}},
3015	  %% And, you cannot redefine already imported things that aren't auto-imported
3016	  {clash17,
3017           <<"-export([x/1]).
3018              -import(x,[binary_port/3]).
3019              -import(y,[binary_port/3]).
3020              x(X) ->
3021                 abs(X).
3022             ">>,
3023	   [],
3024	   {errors,[{3,erl_lint,{redefine_import,{{binary_port,3},x}}}],[]}},
3025	  %% Not with local functions either
3026	  {clash18,
3027           <<"-export([x/1]).
3028              -import(x,[binary_port/3]).
3029              binary_port(A,B,C) ->
3030                 binary_part(A,B,C).
3031              x(X) ->
3032                 abs(X).
3033             ">>,
3034	   [],
3035	   {errors,[{3,erl_lint,{define_import,{binary_port,3}}}],[]}},
3036	  %% Like clash8: Dont accept a guard if it's explicitly module-name called either
3037	  {clash19,
3038           <<"-export([binary_port/3]).
3039              -compile({no_auto_import,[binary_part/3]}).
3040              -import(x,[binary_part/3]).
3041              binary_port(A,B,C) when x:binary_part(A,B,C) ->
3042                 binary_part(A,B,C+1).
3043             ">>,
3044	   [],
3045	   {errors,[{4,erl_lint,illegal_guard_expr}],[]}},
3046	  %% Not with local functions either
3047	  {clash20,
3048           <<"-export([binary_port/3]).
3049              -import(x,[binary_part/3]).
3050              binary_port(A,B,C) ->
3051                 binary_part(A,B,C).
3052             ">>,
3053	   [warn_unused_import],
3054	   {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}},
3055	  %% Don't accept call to a guard BIF if there is a local definition
3056	  %% or an import with the same name. Note: is_record/2 is an
3057	  %% exception, since it is more of syntatic sugar than a real BIF.
3058	  {clash21,
3059           <<"-export([is_list/1]).
3060              -import(x, [is_tuple/1]).
3061              -record(r, {a,b}).
3062              x(T) when is_tuple(T) -> ok;
3063              x(T) when is_list(T) -> ok.
3064              y(T) when is_tuple(T) =:= true -> ok;
3065              y(T) when is_list(T) =:= true -> ok;
3066              y(T) when is_record(T, r, 3) -> ok;
3067              y(T) when is_record(T, r, 3) =:= true -> ok;
3068              y(T) when is_record(T, r) =:= true -> ok.
3069              is_list(_) ->
3070                ok.
3071              is_record(_, _) ->
3072                ok.
3073              is_record(_, _, _) ->
3074                ok.
3075             ">>,
3076	   [{no_auto_import,[{is_tuple,1}]}],
3077	   {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
3078		    {5,erl_lint,{illegal_guard_local_call,{is_list,1}}},
3079		    {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
3080		    {7,erl_lint,{illegal_guard_local_call,{is_list,1}}},
3081		    {8,erl_lint,{illegal_guard_local_call,{is_record,3}}},
3082		    {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}},
3083	  %% We can also suppress all auto imports at once
3084	  {clash22,
3085          <<"-export([size/1, binary_part/2]).
3086             -compile(no_auto_import).
3087             size([]) ->
3088               0;
3089             size({N,_}) ->
3090               N;
3091             size([_|T]) ->
3092               1+size(T).
3093             binary_part({B,_},{X,Y}) ->
3094               binary_part(B,{X,Y});
3095             binary_part(B,{X,Y}) ->
3096               binary:part(B,X,Y).
3097            ">>,
3098	   [],
3099	   []}
3100	 ],
3101
3102    [] = run(Config, Ts),
3103    ok.
3104
3105%% Basic tests with one behaviour.
3106behaviour_basic(Config) when is_list(Config) ->
3107    Ts = [{behaviour1,
3108           <<"-behaviour(application).
3109             ">>,
3110           [],
3111	   {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}},
3112		      {1,erl_lint,{undefined_behaviour_func,{stop,1},application}}]}},
3113
3114	  {behaviour2,
3115           <<"-behaviour(application).
3116              -export([stop/1]).
3117              stop(_) -> ok.
3118             ">>,
3119           [],
3120	   {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}]}},
3121
3122	  {behaviour3,
3123           <<"-behavior(application).  %% Test American spelling.
3124              -export([start/2,stop/1]).
3125              start(_, _) -> ok.
3126              stop(_) -> ok.
3127             ">>,
3128           [],
3129           []},
3130
3131          {behaviour4,
3132           <<"-behavior(application).  %% Test callbacks with export_all
3133              -compile([export_all, nowarn_export_all]).
3134              stop(_) -> ok.
3135             ">>,
3136           [],
3137           {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}]}}
3138	 ],
3139    [] = run(Config, Ts),
3140    ok.
3141
3142%% Basic tests with multiple behaviours.
3143behaviour_multiple(Config) when is_list(Config) ->
3144    Ts = [{behaviour1,
3145           <<"-behaviour(application).
3146              -behaviour(supervisor).
3147             ">>,
3148           [],
3149	   {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}},
3150		      {1,erl_lint,{undefined_behaviour_func,{stop,1},application}},
3151		      {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}}]}},
3152
3153	  {behaviour2,
3154           <<"-behaviour(application).
3155              -behaviour(supervisor).
3156              -export([start/2,stop/1,init/1]).
3157              start(_, _) -> ok.
3158              stop(_) -> ok.
3159              init(_) -> ok.
3160             ">>,
3161           [],
3162	   []},
3163
3164	  {american_behavior2,
3165           <<"-behavior(application).
3166              -behavior(supervisor).
3167              -export([start/2,stop/1,init/1]).
3168              start(_, _) -> ok.
3169              stop(_) -> ok.
3170              init(_) -> ok.
3171             ">>,
3172           [],
3173	   []},
3174
3175	  {behaviour3,
3176           <<"-behaviour(gen_server).
3177              -behaviour(supervisor).
3178              -export([handle_call/3,handle_cast/2,handle_info/2]).
3179              handle_call(_, _, _) -> ok.
3180              handle_cast(_, _) -> ok.
3181              handle_info(_, _) -> ok.
3182             ">>,
3183           [],
3184	   {warnings,[{1,erl_lint,{undefined_behaviour_func,{init,1},gen_server}},
3185		      {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}},
3186		      {2,
3187		       erl_lint,
3188		       {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}},
3189	  {american_behavior3,
3190           <<"-behavior(gen_server).
3191              -behavior(supervisor).
3192              -export([handle_call/3,handle_cast/2,handle_info/2]).
3193              handle_call(_, _, _) -> ok.
3194              handle_cast(_, _) -> ok.
3195              handle_info(_, _) -> ok.
3196             ">>,
3197           [],
3198	   {warnings,[{1,erl_lint,{undefined_behaviour_func,{init,1},gen_server}},
3199		      {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}},
3200		      {2,
3201		       erl_lint,
3202		       {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}},
3203
3204	  {behaviour4,
3205           <<"-behaviour(gen_server).
3206              -behaviour(gen_fsm).
3207              -behaviour(supervisor).
3208              -export([init/1,handle_call/3,handle_cast/2,
3209                       handle_info/2,handle_info/3,
3210                       handle_event/3,handle_sync_event/4,
3211                       code_change/3,code_change/4,
3212                       terminate/2,terminate/3,terminate/4]).
3213              init(_) -> ok.
3214              handle_call(_, _, _) -> ok.
3215              handle_event(_, _, _) -> ok.
3216              handle_sync_event(_, _, _, _) -> ok.
3217              handle_cast(_, _) -> ok.
3218              handle_info(_, _) -> ok.
3219              handle_info(_, _, _) -> ok.
3220              code_change(_, _, _) -> ok.
3221              code_change(_, _, _, _) -> ok.
3222              terminate(_, _) -> ok.
3223              terminate(_, _, _) -> ok.
3224              terminate(_, _, _, _) -> ok.
3225             ">>,
3226           [],
3227	   {warnings,[{2,
3228		       erl_lint,
3229		       {conflicting_behaviours,{init,1},gen_fsm,1,gen_server}},
3230		      {3,
3231		       erl_lint,
3232		       {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}}
3233	 ],
3234    [] = run(Config, Ts),
3235    ok.
3236
3237%% OTP-11861. behaviour_info() and -callback.
3238otp_11861(Conf) when is_list(Conf) ->
3239    CallbackFiles = [callback1, callback2, callback3,
3240                     bad_behaviour1, bad_behaviour2],
3241    lists:foreach(fun(M) ->
3242                          F = filename:join(?datadir, M),
3243                          Opts = [{outdir,?privdir}, return],
3244                          {ok, M, []} = compile:file(F, Opts)
3245                  end, CallbackFiles),
3246    CodePath = code:get_path(),
3247    true = code:add_path(?privdir),
3248    Ts = [{otp_11861_1,
3249           <<"
3250              -export([b1/1]).
3251              -behaviour(callback1).
3252              -behaviour(callback2).
3253
3254              -spec b1(atom()) -> integer().
3255              b1(A) when is_atom(A)->
3256                  3.
3257             ">>,
3258           [],
3259           %% b2/1 is optional in both modules
3260           {warnings,[{4,erl_lint,
3261                       {conflicting_behaviours,{b1,1},callback2,3,callback1}}]}},
3262          {otp_11861_2,
3263           <<"
3264              -export([b2/1]).
3265              -behaviour(callback1).
3266              -behaviour(callback2).
3267
3268              -spec b2(integer()) -> atom().
3269              b2(I) when is_integer(I)->
3270                  a.
3271             ">>,
3272           [],
3273           %% b2/1 is optional in callback2, but not in callback1
3274           {warnings,[{3,erl_lint,{undefined_behaviour_func,{b1,1},callback1}},
3275                      {4,erl_lint,
3276                       {conflicting_behaviours,{b2,1},callback2,3,callback1}}]}},
3277          {otp_11861_3,
3278           <<"
3279              -callback b(_) -> atom().
3280              -optional_callbacks({b1,1}). % non-existing and ignored
3281             ">>,
3282           [],
3283           []},
3284          {otp_11861_4,
3285           <<"
3286              -callback b(_) -> atom().
3287              -optional_callbacks([{b1,1}]). % non-existing
3288             ">>,
3289           [],
3290           %% No behaviour-info(), but callback.
3291           {errors,[{3,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}},
3292          {otp_11861_5,
3293           <<"
3294              -optional_callbacks([{b1,1}]). % non-existing
3295             ">>,
3296           [],
3297           %% No behaviour-info() and no callback: warning anyway
3298           {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}},
3299          {otp_11861_6,
3300           <<"
3301              -optional_callbacks([b1/1]). % non-existing
3302              behaviour_info(callbacks) -> [{b1,1}].
3303             ">>,
3304           [],
3305           %% behaviour-info() and no callback: warning anyway
3306           {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}}],[]}},
3307          {otp_11861_7,
3308           <<"
3309              -optional_callbacks([b1/1]). % non-existing
3310              -callback b(_) -> atom().
3311              behaviour_info(callbacks) -> [{b1,1}].
3312             ">>,
3313           [],
3314           %% behaviour-info() callback: warning
3315           {errors,[{2,erl_lint,{undefined_callback,{lint_test,b1,1}}},
3316                    {3,erl_lint,{behaviour_info,{lint_test,b,1}}}],
3317            []}},
3318          {otp_11861_8,
3319           <<"
3320              -callback b(_) -> atom().
3321              -optional_callbacks([b/1, {b, 1}]).
3322             ">>,
3323           [],
3324           {errors,[{3,erl_lint,{redefine_optional_callback,{b,1}}}],[]}},
3325          {otp_11861_9,
3326           <<"
3327              -behaviour(gen_server).
3328              -export([handle_call/3,handle_cast/2,handle_info/2,
3329                       code_change/3, init/1, terminate/2]).
3330              handle_call(_, _, _) -> ok.
3331              handle_cast(_, _) -> ok.
3332              handle_info(_, _) -> ok.
3333              code_change(_, _, _) -> ok.
3334              init(_) -> ok.
3335              terminate(_, _) -> ok.
3336             ">>,
3337           [],
3338           []},
3339          {otp_11861_9,
3340           <<"
3341              -behaviour(gen_server).
3342              -export([handle_call/3,handle_cast/2,handle_info/2,
3343                       code_change/3, init/1, terminate/2, format_status/2]).
3344              handle_call(_, _, _) -> ok.
3345              handle_cast(_, _) -> ok.
3346              handle_info(_, _) -> ok.
3347              code_change(_, _, _) -> ok.
3348              init(_) -> ok.
3349              terminate(_, _) -> ok.
3350              format_status(_, _) -> ok. % optional callback
3351             ">>,
3352           [],
3353           %% Nothing...
3354           []},
3355          {otp_11861_10,
3356           <<"
3357              -optional_callbacks([{b1,1,bad}]). % badly formed and ignored
3358              behaviour_info(callbacks) -> [{b1,1}].
3359             ">>,
3360           [],
3361           []},
3362          {otp_11861_11,
3363           <<"
3364              -behaviour(bad_behaviour1).
3365             ">>,
3366           [],
3367           {warnings,[{2,erl_lint,
3368                       {ill_defined_behaviour_callbacks,bad_behaviour1}}]}},
3369          {otp_11861_12,
3370           <<"
3371              -behaviour(non_existing_behaviour).
3372             ">>,
3373           [],
3374           {warnings,[{2,erl_lint,
3375                       {undefined_behaviour,non_existing_behaviour}}]}},
3376          {otp_11861_13,
3377           <<"
3378              -behaviour(bad_behaviour_none).
3379             ">>,
3380           [],
3381           {warnings,[{2,erl_lint,{undefined_behaviour,bad_behaviour_none}}]}},
3382          {otp_11861_14,
3383           <<"
3384              -callback b(_) -> atom().
3385             ">>,
3386           [],
3387           []},
3388          {otp_11861_15,
3389           <<"
3390              -optional_callbacks([{b1,1,bad}]). % badly formed
3391              -callback b(_) -> atom().
3392             ">>,
3393           [],
3394           []},
3395          {otp_11861_16,
3396           <<"
3397              -callback b(_) -> atom().
3398              -callback b(_) -> atom().
3399             ">>,
3400           [],
3401           {errors,[{3,erl_lint,{redefine_callback,{b,1}}}],[]}},
3402          {otp_11861_17,
3403           <<"
3404              -behaviour(bad_behaviour2).
3405             ">>,
3406           [],
3407           {warnings,[{2,erl_lint,{undefined_behaviour_callbacks,
3408                                   bad_behaviour2}}]}},
3409          {otp_11861_18,
3410           <<"
3411              -export([f1/1]).
3412              -behaviour(callback3).
3413              f1(_) -> ok.
3414             ">>,
3415           [],
3416           []}
3417	 ],
3418    [] = run(Conf, Ts),
3419    true = code:set_path(CodePath),
3420    ok.
3421
3422%% Test that the new utf8/utf16/utf32 types do not allow size or
3423%% unit specifiers.
3424otp_7550(Config) when is_list(Config) ->
3425    Ts = [{otp_7550,
3426           <<"f8(A) ->
3427                  <<A:8/utf8>>.
3428              g8(A) ->
3429                  <<A:8/utf8-unit:1>>.
3430              h8(A) ->
3431                  <<A/utf8-unit:1>>.
3432
3433              f16(A) ->
3434                  <<A:8/utf16>>.
3435              g16(A) ->
3436                  <<A:8/utf16-unit:1>>.
3437              h16(A) ->
3438                  <<A/utf16-unit:1>>.
3439
3440              f32(A) ->
3441                  <<A:8/utf32>>.
3442              g32(A) ->
3443                  <<A:8/utf32-unit:1>>.
3444              h32(A) ->
3445                  <<A/utf32-unit:1>>.
3446             ">>,
3447           [],
3448           {errors,[{2,erl_lint,utf_bittype_size_or_unit},
3449		    {4,erl_lint,utf_bittype_size_or_unit},
3450		    {6,erl_lint,utf_bittype_size_or_unit},
3451		    {9,erl_lint,utf_bittype_size_or_unit},
3452		    {11,erl_lint,utf_bittype_size_or_unit},
3453		    {13,erl_lint,utf_bittype_size_or_unit},
3454		    {16,erl_lint,utf_bittype_size_or_unit},
3455		    {18,erl_lint,utf_bittype_size_or_unit},
3456		    {20,erl_lint,utf_bittype_size_or_unit}
3457		   ],
3458            []}}],
3459    [] = run(Config, Ts),
3460    ok.
3461
3462
3463%% Bugfix: -opaque with invalid type.
3464otp_8051(Config) when is_list(Config) ->
3465    Ts = [{otp_8051,
3466           <<"-opaque foo() :: bar().
3467              -export_type([foo/0]).
3468             ">>,
3469           [],
3470           {errors,[{1,erl_lint,{undefined_type,{bar,0}}}],[]}}],
3471    [] = run(Config, Ts),
3472    ok.
3473
3474%% Check that format warnings are generated.
3475format_warn(Config) when is_list(Config) ->
3476    L1 = 14,
3477    L2 = 4,
3478    format_level(1, L1, Config),
3479    format_level(2, L1+L2, Config),
3480    format_level(3, L1+L2, Config),             %there is no level 3
3481    ok.
3482
3483format_level(Level, Count, Config) ->
3484    W = get_compilation_result(Config, "format",
3485                                     [{warn_format, Level}]),
3486    %% Pick out the 'format' warnings.
3487    FW = lists:filter(fun({_Line, erl_lint, {format_error, _}}) -> true;
3488                               (_) -> false
3489                            end,
3490                            W),
3491    case length(FW) of
3492              Count ->
3493                  ok;
3494              Other ->
3495                  io:format("Expected ~w warning(s); got ~w", [Count,Other]),
3496                  fail()
3497          end,
3498    ok.
3499
3500%% Test the -on_load(Name/0) directive.
3501
3502
3503on_load_successful(Config) when is_list(Config) ->
3504    Ts = [{on_load_1,
3505	   %% Exported on_load function.
3506	   <<"-export([do_on_load/0]).
3507             -on_load(do_on_load/0).
3508             do_on_load() -> ok.
3509             ">>,
3510	   {[]},				%Tuple indicates no 'export_all'.
3511	   []},
3512
3513	  {on_load_2,
3514	   %% Local on_load function.
3515	   <<"-on_load(do_on_load/0).
3516             do_on_load() -> ok.
3517             ">>,
3518	   {[]},				%Tuple indicates no 'export_all'.
3519	   []},
3520
3521	  {on_load_3,
3522	   %% Local on_load function, calling other local functions.
3523	   <<"-on_load(do_on_load/0).
3524             do_on_load() -> foo().
3525             foo() -> bar(5) + 42.
3526             bar(N) -> 2*N.
3527             ">>,
3528	   {[]},				%Tuple indicates no 'export_all'.
3529	   []}
3530	 ],
3531    [] = run(Config, Ts),
3532    ok.
3533
3534on_load_failing(Config) when is_list(Config) ->
3535    Ts = [{on_load_1,
3536	   %% Badly formed.
3537	   <<"-on_load(atom).
3538             ">>,
3539	   {[]},				%Tuple indicates no 'export_all'.
3540	   {errors,
3541	    [{1,erl_lint,{bad_on_load,atom}}],[]}},
3542
3543	  {on_load_2,
3544	   %% Badly formed.
3545	   <<"-on_load({42,0}).
3546             ">>,
3547	   {[]},				%Tuple indicates no 'export_all'.
3548	   {errors,
3549	    [{1,erl_lint,{bad_on_load,{42,0}}}],[]}},
3550
3551	  {on_load_3,
3552	   %% Multiple on_load attributes.
3553	   <<"-on_load(foo/0).
3554              -on_load(bar/0).
3555              foo() -> ok.
3556              bar() -> ok.
3557             ">>,
3558	   {[]},				%Tuple indicates no 'export_all'.
3559	   {errors,
3560	    [{2,erl_lint,multiple_on_loads}],[]}},
3561
3562	  {on_load_4,
3563	   %% Wrong arity.
3564	   <<"-on_load(foo/1).
3565              foo(_) -> ok.
3566             ">>,
3567	   {[]},				%Tuple indicates no 'export_all'.
3568	   {errors,
3569	    [{1,erl_lint,{bad_on_load_arity,{foo,1}}}],[]}},
3570
3571	  {on_load_5,
3572	   %% Non-existing function.
3573	   <<"-on_load(non_existing/0).
3574             ">>,
3575	   {[]},				%Tuple indicates no 'export_all'.
3576	   {errors,
3577	    [{1,erl_lint,{undefined_on_load,{non_existing,0}}}],[]}}
3578	 ],
3579    [] = run(Config, Ts),
3580    ok.
3581
3582%% Test that too many arguments is not accepted.
3583too_many_arguments(Config) when is_list(Config) ->
3584    Ts = [{too_many_1,
3585	   <<"f(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ok.">>,
3586	   [],
3587	   {errors,
3588	    [{1,erl_lint,{too_many_arguments,256}}],[]}}
3589	 ],
3590
3591    [] = run(Config, Ts),
3592    ok.
3593
3594
3595%% Test some basic errors to improve coverage.
3596basic_errors(Config) ->
3597    Ts = [{redefine_module,
3598	   <<"-module(redefine_module).">>,
3599	   [],
3600	   {errors,[{1,erl_lint,redefine_module}],[]}},
3601
3602	  {attr_after_function,
3603	   <<"f() -> ok.
3604               -attr(x).">>,
3605	   [],
3606	   {errors,[{2,erl_lint,{attribute,attr}}],[]}},
3607
3608	  {redefine_function,
3609	   <<"f() -> ok.
3610              f() -> ok.">>,
3611	   [],
3612	   {errors,[{2,erl_lint,{redefine_function,{f,0}}}],[]}},
3613
3614	  {redefine_record,
3615	   <<"-record(r, {a}).
3616              -record(r, {a}).
3617	      f(#r{}) -> ok.">>,
3618	   [],
3619	   {errors,[{2,erl_lint,{redefine_record,r}}],[]}},
3620
3621	  {illegal_record_info,
3622	   <<"f1() -> record_info(42, record).
3623	      f2() -> record_info(shoe_size, record).
3624              f3() -> fun record_info/2.">>,
3625	   [],
3626	   {errors,[{1,erl_lint,illegal_record_info},
3627		    {2,erl_lint,illegal_record_info},
3628                    {3,erl_lint,illegal_record_info}],[]}},
3629
3630	  {illegal_expr,
3631	   <<"f() -> a:b.">>,
3632	   [],
3633	   {errors,[{1,erl_lint,illegal_expr}],[]}},
3634
3635	  {illegal_pattern,
3636	   <<"f(A+B) -> ok.">>,
3637	   [],
3638	   {errors,[{1,erl_lint,illegal_pattern}],[]}}
3639	 ],
3640    [] = run(Config, Ts),
3641    ok.
3642
3643%% Test binary syntax errors
3644bin_syntax_errors(Config) ->
3645    Ts = [{bin_syntax_errors,
3646	   <<"t(<<X:bad_size>>) -> X;
3647	      t(<<_:(x ! y)/integer>>) -> ok;
3648              t(<<X:all/integer>>) -> X;
3649              t(<<X/bad_type>>) -> X;
3650	      t(<<X/unit:8>>) -> X;
3651	      t(<<X:7/float>>) -> X;
3652	      t(<< <<_:8>> >>) -> ok;
3653	      t(<<(x ! y):8/integer>>) -> ok;
3654              t(X) ->
3655                {<<X/binary-integer>>,<<X/signed-unsigned-integer>>,
3656                 <<X/little-big>>,<<X/unit:4-unit:8>>}.
3657	    ">>,
3658	   [],
3659	   {error,[{1,erl_lint,illegal_bitsize},
3660		   {2,erl_lint,illegal_bitsize},
3661		   {3,erl_lint,illegal_bitsize},
3662		   {4,erl_lint,{undefined_bittype,bad_type}},
3663		   {5,erl_lint,bittype_unit},
3664		   {7,erl_lint,illegal_pattern},
3665		   {8,erl_lint,illegal_pattern},
3666		   {10,erl_lint,{bittype_mismatch,integer,binary,"type"}},
3667		   {10,erl_lint,{bittype_mismatch,unsigned,signed,"sign"}},
3668		   {11,erl_lint,{bittype_mismatch,8,4,"unit"}},
3669		   {11,erl_lint,{bittype_mismatch,big,little,"endianness"}}
3670		  ],
3671	    [{6,erl_lint,{bad_bitsize,"float"}}]}}
3672	 ],
3673    [] = run(Config, Ts),
3674    ok.
3675
3676%% OTP-10342: No longer predefined types: array(), digraph(), and so on.
3677predef(Config) when is_list(Config) ->
3678    W = get_compilation_result(Config, "predef", []),
3679    [] = W,
3680    %% dict(), digraph() and so on were removed in Erlang/OTP 18.0.
3681    E2 = get_compilation_result(Config, "predef2", []),
3682    Tag = undefined_type,
3683    {[{7,erl_lint,{Tag,{array,0}}},
3684      {12,erl_lint,{Tag,{dict,0}}},
3685      {17,erl_lint,{Tag,{digraph,0}}},
3686      {27,erl_lint,{Tag,{gb_set,0}}},
3687      {32,erl_lint,{Tag,{gb_tree,0}}},
3688      {37,erl_lint,{Tag,{queue,0}}},
3689      {42,erl_lint,{Tag,{set,0}}},
3690      {47,erl_lint,{Tag,{tid,0}}}],[]} = E2,
3691    ok.
3692
3693maps(Config) ->
3694    Ts = [{illegal_map_construction,
3695           <<"t() ->
3696                  #{ a := b,
3697                     c => d,
3698                     e := f
3699                  }#{ a := b,
3700                      c => d,
3701                      e := f };
3702              t() when is_map(#{ a := b,
3703                                 c => d
3704                              }#{ a := b,
3705                                  c => d,
3706                                  e := f }) ->
3707                  ok.
3708            ">>,
3709           [],
3710           {errors,[{2,erl_lint,illegal_map_construction},
3711                    {4,erl_lint,illegal_map_construction},
3712                    {8,erl_lint,illegal_map_construction}],
3713            []}},
3714          {illegal_pattern,
3715           <<"t(#{ a := A,
3716                   c => d,
3717                   e := F,
3718                   g := 1 + 1,
3719                   h := _,
3720                   i := (_X = _Y),
3721                   j := (x ! y),
3722		   <<0:300>> := 33}) ->
3723                  {A,F}.
3724            ">>,
3725           [],
3726           {errors,[{2,erl_lint,illegal_pattern},
3727                    {7,erl_lint,illegal_pattern}],
3728            []}},
3729          {error_in_illegal_map_construction,
3730           <<"t() -> #{ a := X }.">>,
3731           [],
3732	   {errors,[{1,erl_lint,illegal_map_construction},
3733                    {1,erl_lint,{unbound_var,'X'}}],
3734            []}},
3735          {legal_map_pattern,
3736	   <<"
3737               -record(mapkey, {a=1,b=2}).
3738               t(M,K1) ->
3739                     #{ a := 1,
3740                        $a := 1, $z := 99,
3741                        #{a=>val} := 2,
3742                        K1 := 1337,
3743                        #mapkey{a = 10} := wat,
3744                        #{{a,val}=>val} := 2,
3745                        #{ \"hi\" => wazzup, hi => ho } := yep,
3746                        ok := 1.0,
3747                        [3+3] := nope,
3748                        1.0 := yep,
3749                        {3.0+3} := nope,
3750                        {yep} := yep
3751                      } = M.
3752	   ">>,
3753	   [],
3754	   []},
3755	  {legal_map_construction,
3756	   <<"t(V) -> #{ a => 1,
3757			#{a=>V} => 2,
3758			#{{a,V}=>V} => 2,
3759			#{ \"hi\" => wazzup, hi => ho } => yep,
3760			[try a catch _:_ -> b end] => nope,
3761			ok => 1.0,
3762			[3+3] => nope,
3763			1.0 => yep,
3764			{3.0+3} => nope,
3765			{yep} => yep,
3766			[case a of a -> a end] => nope
3767		      }.
3768	   ">>,
3769	   [],
3770	   []},
3771	   {errors_in_map_keys_pattern,
3772	   <<"t(#{ a := 2,
3773	           #{} := A,
3774	           #{ 3 => 33 } := hi,
3775	           #{ 3 := 33 } := hi,
3776	           #{ hi => 54, \"hello\" => 45 } := hi,
3777		   #{ V => 33 } := hi }) ->
3778	       A.
3779	   ">>,
3780	   [],
3781	   {errors,[{4,erl_lint,illegal_map_construction},
3782                    {6,erl_lint,illegal_map_key}],[]}},
3783          {unused_vars_with_empty_maps,
3784           <<"t(Foo, Bar, Baz) -> {#{},#{}}.">>,
3785           [warn_unused_variables],
3786           {warnings,[{1,erl_lint,{unused_var,'Bar'}},
3787                      {1,erl_lint,{unused_var,'Baz'}},
3788                      {1,erl_lint,{unused_var,'Foo'}}]}}],
3789    [] = run(Config, Ts),
3790    ok.
3791
3792maps_type(Config) when is_list(Config) ->
3793    Ts = [
3794	{maps_type1,
3795	 <<"
3796	-type m() :: #{a => integer()}.
3797	-spec t1(#{k=>term()}) -> {term(), map()}.
3798
3799	t1(#{k:=V}=M) -> {V,M}.
3800
3801	-spec t2(m()) -> integer().
3802
3803	t2(#{a:=V}) -> V.
3804	">>,
3805	[],
3806	[]},
3807	{maps_type2,
3808	 <<"
3809            %% Built-in var arity map type:
3810	    -type map() :: tuple().
3811	    -type a() :: map().
3812
3813	    -spec t(a()) -> a().
3814	    t(M) -> M.
3815	 ">>,
3816	 [],
3817	 {errors,[{3,erl_lint,{builtin_type,{map,0}}}],[]}}],
3818    [] = run(Config, Ts),
3819    ok.
3820
3821maps_parallel_match(Config) when is_list(Config) ->
3822    Ts = [{parallel_map_patterns_unbound1,
3823           <<"
3824           t(#{} = M) ->
3825               #{K := V} = #{k := K} = M,
3826               V.
3827           ">>,
3828           [],
3829           {errors,[{3,erl_lint,{unbound_var,'K'}}],[]}},
3830          {parallel_map_patterns_unbound2,
3831           <<"
3832           t(#{} = M) ->
3833               #{K1 := V1} =
3834               #{K2 := V2} =
3835               #{k1 := K1,k2 := K2} = M,
3836               [V1,V2].
3837           ">>,
3838           [],
3839           {errors,[{3,erl_lint,{unbound_var,'K1'}},
3840                    {3,erl_lint,{unbound_var,'K1'}},
3841                    {4,erl_lint,{unbound_var,'K2'}},
3842                    {4,erl_lint,{unbound_var,'K2'}}],[]}},
3843          {parallel_map_patterns_bound,
3844           <<"
3845           t(#{} = M,K1,K2) ->
3846               #{K1 := V1} =
3847               #{K2 := V2} =
3848               #{k1 := K1,k2 := K2} = M,
3849               [V1,V2].
3850           ">>,
3851           [],
3852           []},
3853          {parallel_map_patterns_literal,
3854           <<"
3855           t(#{} = M) ->
3856               #{k1 := V1} =
3857               #{k2 := V2} =
3858               #{k1 := V1,k2 := V2} = M,
3859               [V1,V2].
3860           ">>,
3861           [],
3862           []}],
3863    [] = run(Config, Ts),
3864    ok.
3865
3866%% OTP-11851: More atoms can be used as type names + bug fixes.
3867otp_11851(Config) when is_list(Config) ->
3868    Ts = [
3869	{otp_11851_1,
3870	 <<"-export([t/0]).
3871            -type range(A, B) :: A | B.
3872
3873            -type union(A) :: A.
3874
3875            -type product() :: integer().
3876
3877            -type tuple(A) :: A.
3878
3879            -type map(A) :: A.
3880
3881            -type record() :: a | b.
3882
3883            -type integer(A) :: A.
3884
3885            -type atom(A) :: A.
3886
3887            -type binary(A, B) :: A | B.
3888
3889            -type 'fun'() :: integer().
3890
3891            -type 'fun'(X) :: X.
3892
3893            -type 'fun'(X, Y) :: X | Y.
3894
3895            -type all() :: range(atom(), integer()) | union(pid()) | product()
3896                         | tuple(reference()) | map(function()) | record()
3897                         | integer(atom()) | atom(integer())
3898                         | binary(pid(), tuple()) | 'fun'(port())
3899                         | 'fun'() | 'fun'(<<>>, 'none').
3900
3901            -spec t() -> all().
3902
3903            t() ->
3904                a.
3905	">>,
3906	[],
3907	[]},
3908	{otp_11851_2,
3909	 <<"-export([a/1, b/1, t/0]).
3910
3911            -callback b(_) -> integer().
3912
3913            -callback ?MODULE:a(_) -> integer().
3914
3915            a(_) -> 3.
3916
3917            b(_) -> a.
3918
3919            t()-> a.
3920	">>,
3921	[],
3922	{errors,[{5,erl_lint,{bad_callback,{lint_test,a,1}}}],[]}},
3923	{otp_11851_3,
3924	 <<"-export([a/1]).
3925
3926            -spec a(_A) -> boolean() when
3927                  _ :: atom(),
3928                  _A :: integer().
3929
3930            a(_) -> true.
3931	">>,
3932	[],
3933	{errors,[{4,erl_parse,"bad type variable"}],[]}},
3934	{otp_11851_4,
3935	 <<"
3936            -spec a(_) -> ok.
3937            -spec a(_) -> ok.
3938
3939            -spec ?MODULE:a(_) -> ok.
3940            -spec ?MODULE:a(_) -> ok.
3941	">>,
3942	[],
3943         {errors,[{3,erl_lint,{redefine_spec,{a,1}}},
3944                  {5,erl_lint,{redefine_spec,{lint_test,a,1}}},
3945                  {6,erl_lint,{redefine_spec,{lint_test,a,1}}},
3946                  {6,erl_lint,{spec_fun_undefined,{a,1}}}],
3947          []}}
3948          ],
3949    [] = run(Config, Ts),
3950    ok.
3951
3952%% OTP-11879: The -spec f/a :: (As) -> B; syntax removed,
3953%% and is_subtype/2 deprecated.
3954otp_11879(_Config) ->
3955    Fs = [{attribute,0,file,{"file.erl",0}},
3956          {attribute,0,module,m},
3957          {attribute,1,spec,
3958           {{f,1},
3959            [{type,2,'fun',[{type,3,product,[{var,4,'V1'},
3960                                             {var,5,'V1'}]},
3961                            {type,6,integer,[]}]}]}},
3962          {attribute,20,callback,
3963           {{cb,21},
3964            [{type,22,'fun',[{type,23,product,[{var,24,'V1'},
3965                                               {var,25,'V1'}]},
3966                             {type,6,integer,[]}]}]}}],
3967    {error,[{"file.erl",
3968             [{1,erl_lint,{spec_fun_undefined,{f,1}}},
3969              {2,erl_lint,spec_wrong_arity},
3970              {22,erl_lint,callback_wrong_arity}]}],
3971     []} = compile_forms(Fs, [return,report]),
3972    ok.
3973
3974compile_forms(Terms, Opts) ->
3975    Forms = [erl_parse:anno_from_term(Term) || Term <- Terms],
3976    compile:forms(Forms, Opts).
3977
3978%% OTP-13230: -deprecated without -module.
3979otp_13230(Config) when is_list(Config) ->
3980    Abstr = <<"-deprecated([{frutt,0,next_version}]).">>,
3981    {errors,[{1,erl_lint,undefined_module},
3982             {1,erl_lint,{bad_deprecated,{frutt,0}}}],
3983     []} = run_test2(Config, Abstr, []),
3984    ok.
3985
3986record_errors(Config) when is_list(Config) ->
3987    Ts = [{rec1,
3988           <<"-record(r, {a,b}).
3989              b() -> #r{a=foo,b=42,a=bar}.
3990              u(R) -> R#r{a=1,b=2,a=2}.
3991             ">>,
3992           [],
3993           {errors,[{2,erl_lint,{redefine_field,r,a}},
3994		    {3,erl_lint,{redefine_field,r,a}}],[]}}],
3995    run(Config, Ts).
3996
3997otp_11879_cont(Config) ->
3998    Ts = [{constraint1,
3999           <<"-export([t/1]).
4000              -spec t(X) -> X when is_subtype(integer()).
4001              t(a) -> foo:bar().
4002             ">>,
4003           [],
4004           {errors,
4005            [{2,erl_parse,"unsupported constraint " ++ ["is_subtype"]}],
4006            []}},
4007          {constraint2,
4008           <<"-export([t/1]).
4009              -spec t(X) -> X when bad_atom(X, integer()).
4010              t(a) -> foo:bar().
4011             ">>,
4012           [],
4013           {errors,
4014            [{2,erl_parse,"unsupported constraint " ++ ["bad_atom"]}],
4015            []}},
4016          {constraint3,
4017           <<"-export([t/1]).
4018              -spec t(X) -> X when is_subtype(bad_variable, integer()).
4019              t(a) -> foo:bar().
4020             ">>,
4021           [],
4022           {errors,[{2,erl_parse,"bad type variable"}],[]}},
4023          {constraint4,
4024           <<"-export([t/1]).
4025              -spec t(X) -> X when is_subtype(atom(), integer()).
4026              t(a) -> foo:bar().
4027             ">>,
4028           [],
4029           {errors,[{2,erl_parse,"bad type variable"}],[]}},
4030          {constraint5,
4031           <<"-export([t/1]).
4032              -spec t(X) -> X when is_subtype(X, integer()).
4033              t(a) -> foo:bar().
4034             ">>,
4035           [],
4036           []},
4037          {constraint6,
4038           <<"-export([t/1]).
4039              -spec t(X) -> X when X :: integer().
4040              t(a) -> foo:bar().
4041             ">>,
4042           [],
4043           []}],
4044    run(Config, Ts).
4045
4046%% OTP-14285: We currently don't support non-latin1 module names.
4047
4048non_latin1_module(Config) ->
4049    do_non_latin1_module('юникод'),
4050    do_non_latin1_module(list_to_atom([256,$a,$b,$c])),
4051    do_non_latin1_module(list_to_atom([$a,$b,256,$c])),
4052
4053    "module names with non-latin1 characters are not supported" =
4054        format_error(non_latin1_module_unsupported),
4055    BadCallback =
4056        {bad_callback,{'кирилли́ческий атом','кирилли́ческий атом',0}},
4057    BadModule =
4058        {bad_module,{'кирилли́ческий атом','кирилли́ческий атом',0}},
4059    "explicit module not allowed for callback "
4060    "'кирилли́ческий атом':'кирилли́ческий атом'/0" =
4061        format_error(BadCallback),
4062    UndefBehav = {undefined_behaviour,'кирилли́ческий атом'},
4063    "behaviour 'кирилли́ческий атом' undefined" =
4064        format_error(UndefBehav),
4065    Ts = [{non_latin1_module,
4066           <<"
4067            %% Report uses of module names with non-Latin-1 characters.
4068
4069            -import('кирилли́ческий атом', []).
4070            -behaviour('кирилли́ческий атом').
4071            -behavior('кирилли́ческий атом').
4072
4073            -callback 'кирилли́ческий атом':'кирилли́ческий атом'() -> a.
4074
4075            %% erl_lint:gexpr/3 is not extended to check module name here:
4076            t1() when 'кирилли́ческий атом':'кирилли́ческий атом'(1) ->
4077                b.
4078
4079            t2() ->
4080                'кирилли́ческий атом':'кирилли́ческий атом'().
4081
4082            -spec 'кирилли́ческий атом':'кирилли́ческий атом'() -> atom().
4083
4084            -spec 'кирилли́ческий атом'(integer()) ->
4085              'кирилли́ческий атом':'кирилли́ческий атом'().
4086
4087            'кирилли́ческий атом'(1) ->
4088                'кирилли́ческий атом':f(),
4089                F = f,
4090                'кирилли́ческий атом':F()."/utf8>>,
4091           [],
4092           {error,
4093            [{4,erl_lint,non_latin1_module_unsupported},
4094             {5,erl_lint,non_latin1_module_unsupported},
4095             {6,erl_lint,non_latin1_module_unsupported},
4096             {8,erl_lint,non_latin1_module_unsupported},
4097             {8,erl_lint,BadCallback},
4098             {11,erl_lint,illegal_guard_expr},
4099             {15,erl_lint,non_latin1_module_unsupported},
4100             {17,erl_lint,non_latin1_module_unsupported},
4101             {17,erl_lint,BadModule},
4102             {20,erl_lint,non_latin1_module_unsupported},
4103             {23,erl_lint,non_latin1_module_unsupported},
4104             {25,erl_lint,non_latin1_module_unsupported}],
4105            [{5,erl_lint,UndefBehav},
4106             {6,erl_lint,UndefBehav}]}}],
4107    run(Config, Ts),
4108    ok.
4109
4110do_non_latin1_module(Mod) ->
4111    File = atom_to_list(Mod) ++ ".erl",
4112    L1 = erl_anno:new(1),
4113    Forms = [{attribute,L1,file,{File,1}},
4114             {attribute,L1,module,Mod},
4115             {eof,2}],
4116    error = compile:forms(Forms),
4117    {error,_,[]} = compile:forms(Forms, [return]),
4118    ok.
4119
4120
4121otp_14378(Config) ->
4122    Ts = [
4123          {otp_14378_1,
4124           <<"-export([t/0]).
4125              -compile({nowarn_deprecated_function,{erlang,now,1}}).
4126              t() ->
4127                 erlang:now().">>,
4128           [],
4129           {warnings,[{4,erl_lint,
4130                       {deprecated,{erlang,now,0},
4131                        "Deprecated BIF. See the \"Time and Time Correction"
4132                        " in Erlang\" chapter of the ERTS User's Guide"
4133                        " for more information."}}]}}],
4134    [] = run(Config, Ts),
4135    ok.
4136
4137%% OTP-14323: Check the dialyzer attribute.
4138otp_14323(Config) ->
4139    Ts = [
4140          {otp_14323_1,
4141           <<"-import(mod, [m/1]).
4142
4143              -export([f/0, g/0, h/0]).
4144
4145              -dialyzer({nowarn_function,module_info/0}). % undefined function
4146              -dialyzer({nowarn_function,record_info/2}). % undefined function
4147              -dialyzer({nowarn_function,m/1}). % undefined function
4148
4149              -dialyzer(nowarn_function). % unknown option
4150              -dialyzer(1). % badly formed
4151              -dialyzer(malformed). % unkonwn option
4152              -dialyzer({malformed,f/0}). % unkonwn option
4153              -dialyzer({nowarn_function,a/1}). % undefined function
4154              -dialyzer({nowarn_function,{a,-1}}). % badly formed
4155
4156              -dialyzer([no_return, no_match]).
4157              -dialyzer({nowarn_function, f/0}).
4158              -dialyzer(no_improper_lists).
4159              -dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).
4160              -dialyzer({no_improper_lists, g/0}).
4161              -dialyzer({[no_return, no_match], [g/0, h/0]}).
4162
4163              f() -> a.
4164              g() -> b.
4165              h() -> c.">>,
4166           [],
4167           {errors,[{5,erl_lint,{undefined_function,{module_info,0}}},
4168                    {6,erl_lint,{undefined_function,{record_info,2}}},
4169                    {7,erl_lint,{undefined_function,{m,1}}},
4170                    {9,erl_lint,{bad_dialyzer_option,nowarn_function}},
4171                    {10,erl_lint,{bad_dialyzer_attribute,1}},
4172                    {11,erl_lint,{bad_dialyzer_option,malformed}},
4173                    {12,erl_lint,{bad_dialyzer_option,malformed}},
4174                    {13,erl_lint,{undefined_function,{a,1}}},
4175                    {14,erl_lint,{bad_dialyzer_attribute,
4176                                  {nowarn_function,{a,-1}}}}],
4177            []}},
4178          {otp_14323_2,
4179           <<"-type t(_) :: atom().">>,
4180           [],
4181           {errors,[{1,erl_parse,"bad type variable"}],[]}}],
4182    [] = run(Config, Ts),
4183    ok.
4184
4185stacktrace_syntax(Config) ->
4186    Ts = [{guard,
4187           <<"t1() ->
4188                  try error(foo)
4189                  catch _:_:Stk when is_number(Stk) -> ok
4190                  end.
4191           ">>,
4192           [],
4193           {errors,[{3,erl_lint,{stacktrace_guard,'Stk'}}],[]}},
4194          {bound,
4195           <<"t1() ->
4196                  Stk = [],
4197                  try error(foo)
4198                  catch _:_:Stk -> ok
4199                  end.
4200           ">>,
4201           [],
4202           {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}}],[]}},
4203          {guard_and_bound,
4204           <<"t1() ->
4205                  Stk = [],
4206                  try error(foo)
4207                  catch _:_:Stk when is_integer(Stk) -> ok
4208                  end.
4209           ">>,
4210           [],
4211           {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}},
4212                    {4,erl_lint,{stacktrace_guard,'Stk'}}],[]}}
4213         ],
4214
4215    run(Config, Ts),
4216    ok.
4217
4218
4219%% Unicode atoms.
4220otp_14285(Config) ->
4221    %% A small sample of all the errors and warnings in module erl_lint.
4222    E1 = {redefine_function,{'кирилли́ческий атом',0}},
4223    E2 = {attribute,'кирилли́ческий атом'},
4224    E3 = {undefined_record,'кирилли́ческий атом'},
4225    E4 = {undefined_bittype,'кирилли́ческий атом'},
4226    "function 'кирилли́ческий атом'/0 already defined" = format_error(E1),
4227    "attribute 'кирилли́ческий атом' after function definitions" =
4228        format_error(E2),
4229    "record 'кирилли́ческий атом' undefined" = format_error(E3),
4230    "bit type 'кирилли́ческий атом' undefined" = format_error(E4),
4231    Ts = [{otp_14285_1,
4232           <<"'кирилли́ческий атом'() -> a.
4233              'кирилли́ческий атом'() -> a.
4234             "/utf8>>,
4235           [],
4236           {errors,
4237            [{2,erl_lint,E1}],
4238            []}},
4239         {otp_14285_2,
4240           <<"'кирилли́ческий атом'() -> a.
4241              -'кирилли́ческий атом'(a).
4242             "/utf8>>,
4243           [],
4244           {errors,
4245            [{2,erl_lint,E2}],
4246            []}},
4247         {otp_14285_3,
4248           <<"'кирилли́ческий атом'() -> #'кирилли́ческий атом'{}.
4249             "/utf8>>,
4250           [],
4251           {errors,
4252            [{1,erl_lint,E3}],
4253            []}},
4254         {otp_14285_4,
4255           <<"t() -> <<34/'кирилли́ческий атом'>>.
4256             "/utf8>>,
4257           [],
4258           {errors,
4259            [{1,erl_lint,E4}],
4260            []}}],
4261    run(Config, Ts),
4262    ok.
4263
4264external_funs(Config) when is_list(Config) ->
4265    Ts = [{external_funs_1,
4266           %% ERL-762: Unused variable warning not being emitted.
4267           <<"f() ->
4268                BugVar = process_info(self()),
4269                if true -> fun m:f/1 end.
4270              f(M, F) ->
4271                BugVar = process_info(self()),
4272                if true -> fun M:F/1 end.">>,
4273           [],
4274           {warnings,[{2,erl_lint,{unused_var,'BugVar'}},
4275                      {5,erl_lint,{unused_var,'BugVar'}}]}}],
4276    run(Config, Ts),
4277    ok.
4278
4279otp_15563(Config) when is_list(Config) ->
4280    Ts = [{otp_15563,
4281           <<"-type deep_list(A) :: [A | deep_list(A)].
4282              -spec lists:flatten(deep_list(A)) -> [A].
4283              -callback lists:concat([_]) -> string().
4284              -spec ?MODULE:foo() -> any().
4285              foo() -> a.
4286           ">>,
4287           [warn_unused_vars],
4288           {errors,[{2,erl_lint,{bad_module,{lists,flatten,1}}},
4289                    {3,erl_lint,{bad_callback,{lists,concat,1}}}],
4290            []}}],
4291    [] = run(Config, Ts),
4292    ok.
4293
4294format_error(E) ->
4295    lists:flatten(erl_lint:format_error(E)).
4296
4297run(Config, Tests) ->
4298    F = fun({N,P,Ws,E}, BadL) ->
4299                case catch run_test(Config, P, Ws) of
4300                    E ->
4301                        BadL;
4302                    Bad ->
4303                        io:format("~nTest ~p failed. Expected~n  ~p~n"
4304                                  "but got~n  ~p~n", [N, E, Bad]),
4305			fail()
4306                end
4307        end,
4308    lists:foldl(F, [], Tests).
4309
4310%% Compiles a test file and returns the list of warnings/errors.
4311
4312get_compilation_result(Conf, Filename, Warnings) ->
4313    DataDir = ?datadir,
4314    File = filename:join(DataDir, Filename),
4315    {ok,Bin} = file:read_file(File++".erl"),
4316    FileS = binary_to_list(Bin),
4317    {match,[{Start,Length}|_]} = re:run(FileS, "-module.*\\n"),
4318    Test = lists:nthtail(Start+Length, FileS),
4319    case run_test(Conf, Test, Warnings) of
4320        {warnings, Ws} -> Ws;
4321        {errors,Es,Ws} -> {Es,Ws};
4322        [] -> []
4323    end.
4324
4325%% Compiles a test module and returns the list of errors and warnings.
4326
4327run_test(Conf, Test0, Warnings0) ->
4328    Test = list_to_binary(["-module(lint_test). ", Test0]),
4329    run_test2(Conf, Test, Warnings0).
4330
4331run_test2(Conf, Test, Warnings0) ->
4332    Filename = "lint_test.erl",
4333    DataDir = ?privdir,
4334    File = filename:join(DataDir, Filename),
4335    Opts = case Warnings0 of
4336               {Warnings} ->		%Hairy trick to not add export_all.
4337                   [return|Warnings];
4338               Warnings ->
4339                   [export_all,return|Warnings]
4340           end,
4341    ok = file:write_file(File, Test),
4342
4343    %% We will use the 'binary' option so that the compiler will not
4344    %% compare the module name to the output file name. Also, there
4345    %% is no reason to produce an output file since we are only
4346    %% interested in the errors and warnings.
4347
4348    %% Print warnings, call erl_lint:format_error/1. (But note that
4349    %% the compiler will ignore failing calls to erl_lint:format_error/1.)
4350    compile:file(File, [binary,report|Opts]),
4351
4352    case compile:file(File, [binary|Opts]) of
4353        {ok, _M, Code, Ws} when is_binary(Code) ->
4354	    warnings(File, Ws);
4355        {error, [{File,Es}], []} ->
4356	    {errors, call_format_error(Es), []};
4357        {error, [{File,Es}], [{File,Ws}]} ->
4358	    {error, call_format_error(Es), call_format_error(Ws)};
4359        {error, [{File,Es1},{File,Es2}], []} ->
4360	    {errors2, Es1, Es2}
4361    end.
4362
4363warnings(File, Ws) ->
4364    case lists:append([W || {F, W} <- Ws, F =:= File]) of
4365        [] ->
4366	    [];
4367        L ->
4368	    {warnings, call_format_error(L)}
4369    end.
4370
4371call_format_error(L) ->
4372    %% Smoke test of format_error/1 to make sure that no crashes
4373    %% slip through.
4374    _ = [Mod:format_error(Term) || {_,Mod,Term} <- L],
4375    L.
4376
4377fail() ->
4378    ct:fail(failed).
4379