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