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