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