1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1999-2013. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: -module(erl_lint_SUITE). 20: 21: %-define(debug, true). 22: 23: -ifdef(debug). 24: -define(line, put(line, ?LINE), ). 25: -define(config(X,Y), foo). 26: -define(datadir, "erl_lint_SUITE_data"). 27: -define(privdir, "erl_lint_SUITE_priv"). 28: -define(t, test_server). 29: -else. 30: -include_lib("test_server/include/test_server.hrl"). 31: -define(datadir, ?config(data_dir, Conf)). 32: -define(privdir, ?config(priv_dir, Conf)). 33: -endif. 34: 35: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 36: init_per_group/2,end_per_group/2, 37: init_per_testcase/2, end_per_testcase/2]). 38: 39: -export([ 40: unused_vars_warn_basic/1, 41: unused_vars_warn_lc/1, 42: unused_vars_warn_rec/1, 43: unused_vars_warn_fun/1, 44: unused_vars_OTP_4858/1, 45: export_vars_warn/1, 46: shadow_vars/1, 47: unused_import/1, 48: unused_function/1, 49: unsafe_vars/1,unsafe_vars2/1, 50: unsafe_vars_try/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: export_all/1, 55: bif_clash/1, 56: behaviour_basic/1, behaviour_multiple/1, 57: otp_7550/1, 58: otp_8051/1, 59: format_warn/1, 60: on_load_successful/1, on_load_failing/1, 61: too_many_arguments/1, 62: basic_errors/1,bin_syntax_errors/1 63: ]). 64: 65: % Default timetrap timeout (set in init_per_testcase). 66: -define(default_timeout, ?t:minutes(1)). 67: 68: init_per_testcase(_Case, Config) -> 69: ?line Dog = ?t:timetrap(?default_timeout), 70: [{watchdog, Dog} | Config]. 71: 72: end_per_testcase(_Case, _Config) -> 73: Dog = ?config(watchdog, _Config), 74: test_server:timetrap_cancel(Dog), 75: ok. 76: 77: suite() -> [{ct_hooks,[ts_install_cth]}]. 78: 79: all() -> 80: [{group, unused_vars_warn}, export_vars_warn, 81: shadow_vars, unused_import, unused_function, 82: unsafe_vars, unsafe_vars2, unsafe_vars_try, guard, 83: otp_4886, otp_4988, otp_5091, otp_5276, otp_5338, 84: otp_5362, otp_5371, otp_7227, otp_5494, otp_5644, 85: otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, otp_11254,export_all, 86: bif_clash, behaviour_basic, behaviour_multiple, 87: otp_7550, otp_8051, format_warn, {group, on_load}, 88: too_many_arguments, basic_errors, bin_syntax_errors]. 89: 90: groups() -> 91: [{unused_vars_warn, [], 92: [unused_vars_warn_basic, unused_vars_warn_lc, 93: unused_vars_warn_rec, unused_vars_warn_fun, 94: unused_vars_OTP_4858]}, 95: {on_load, [], [on_load_successful, on_load_failing]}]. 96: 97: init_per_suite(Config) -> 98: Config. 99: 100: end_per_suite(_Config) -> 101: ok. 102: 103: init_per_group(_GroupName, Config) -> 104: Config. 105: 106: end_per_group(_GroupName, Config) -> 107: Config. 108: 109: 110: 111: unused_vars_warn_basic(doc) -> 112: "Warnings for unused variables in some simple cases."; 113: unused_vars_warn_basic(suite) -> []; 114: unused_vars_warn_basic(Config) when is_list(Config) -> 115: Ts = [{basic1, 116: <<"f(F) -> % F unused. 117: ok. 118: 119: f(F, F) -> 120: ok. 121: 122: g(_X) -> 123: y. 124: 125: h(P) -> 126: P. 127: 128: x(N) -> 129: case a:b() of 130: [N|Y] -> % Y unused. 131: ok 132: end. 133: 134: y(N, L) -> 135: lists:map(fun(T) -> T*N end, L). 136: 137: z(N, L) -> % N unused 138: lists:map(fun(N, T) -> T*N end, L). % N shadowed. 139: 140: 141: c(A) -> 142: case A of 143: 1 -> B = []; % B unused. 144: 2 -> B = []; % B unused. 145: 3 -> B = f, B 146: end. 147: ">>, 148: [warn_unused_vars], 149: {warnings,[{1,erl_lint,{unused_var,'F'}}, 150: {15,erl_lint,{unused_var,'Y'}}, 151: {22,erl_lint,{unused_var,'N'}}, 152: {23,erl_lint,{shadowed_var,'N','fun'}}, 153: {28,erl_lint,{unused_var,'B'}}, 154: {29,erl_lint,{unused_var,'B'}}]}}, 155: {basic2, 156: <<"-record(r, {x,y}). 157: f({X,Y}) -> {Z=X,Z=Y}; 158: f([H|T]) -> [Z=H|Z=T]; 159: f(#r{x=X,y=Y}) -> #r{x=A=X,y=A=Y}. 160: g({M, F}) -> (Z=M):(Z=F)(); 161: g({M, F, Arg}) -> (Z=M):F(Z=Arg). 162: h(X, Y) -> (Z=X) + (Z=Y).">>, 163: [warn_unused_vars], []}], 164: ?line [] = run(Config, Ts), 165: ok. 166: 167: unused_vars_warn_lc(doc) -> 168: "Warnings for unused variables in list comprehensions."; 169: unused_vars_warn_lc(suite) -> []; 170: unused_vars_warn_lc(Config) when is_list(Config) -> 171: Ts = [{lc1, 172: <<"bin([X]) -> 173: [A || <<A:X>> <- []]; % X used, not shadowed. 174: bin({X}) -> 175: [X || <<X:X>> <- []]; % X used, and shadowed. 176: bin({X,Y,Z}) -> 177: [{A,B} || <<A:X>> <- Z, <<B:Y>> <- Z]; 178: bin([X,Y,Z]) -> % Y unused. 179: [C || <<V:X>> <- Z, <<B:V>> <- Z, <<C:B>> <- Z]. 180: ">>, 181: [warn_unused_vars], 182: {warnings, [{4,erl_lint,{shadowed_var,'X',generate}}, 183: {7,erl_lint,{unused_var,'Y'}}]}}, 184: 185: {lc2, 186: <<"bin([X]) -> 187: [A || <<A:X>> <- []]; % X used, not shadowed. 188: bin({X}) -> 189: [X || <<X:X>> <- []]; % X used, and shadowed. 190: bin({X,Y,Z}) -> 191: [{A,B} || <<A:X>> <- Z, <<B:Y>> <- Z]; 192: bin([X,Y,Z]) -> % Y unused. 193: [C || <<V:X>> <- Z, <<B:V>> <- Z, <<C:B>> <- Z]. 194: ">>, 195: [warn_unused_vars], 196: {warnings,[{4,erl_lint,{shadowed_var,'X',generate}}, 197: {7,erl_lint,{unused_var,'Y'}}]}}, 198: 199: {lc3, 200: <<"a([A]) -> 201: B = foo, 202: [{C,B} || {C,_} <- A]; 203: a({A}) -> 204: B = foo, 205: [C || {C,_} <- [B,A]]; 206: a({A,A}) -> 207: B = foo, 208: [C || {C,_} <- B, B < A]. 209: ">>, 210: [warn_unused_vars], 211: []}, 212: 213: {lc4, 214: <<"b(A) -> 215: B = foo, % B unused. 216: [C || {C,_} <- A]. 217: ">>, 218: [warn_unused_vars], 219: {warnings,[{2,erl_lint,{unused_var,'B'}}]}}, 220: 221: {lc5, 222: <<"c(A) -> 223: B = foo, 224: [C || {C,_} <- A], 225: B. 226: ">>, 227: [warn_unused_vars], 228: []}, 229: 230: {lc6, 231: <<"d(A) -> 232: B = foo, 233: [{A,B} || {Id,_} <- A]. % Id unused. 234: ">>, 235: [warn_unused_vars], 236: {warnings,[{3,erl_lint,{unused_var,'Id'}}]}}, 237: 238: {lc7, 239: <<"e(A) -> 240: B = foo, % B unused. 241: [B || B <- A]. % B shadowed. 242: ">>, 243: [warn_unused_vars], 244: {warnings,[{2,erl_lint,{unused_var,'B'}}, 245: {3,erl_lint,{shadowed_var,'B',generate}}]}}, 246: 247: {lc8, 248: <<"f(A) -> 249: B = foo, 250: [B || B <- A], % B shadowed. 251: B. 252: ">>, 253: [warn_unused_vars], 254: {warnings,[{3,erl_lint,{shadowed_var,'B',generate}}]}}, 255: 256: {lc9, 257: <<"g(A) -> 258: B = foo, % B unused. 259: [A || B <- A]. % B shadowed, B unused. 260: ">>, 261: [warn_unused_vars], 262: {warnings,[{2,erl_lint,{unused_var,'B'}}, 263: {3,erl_lint,{unused_var,'B'}}, 264: {3,erl_lint,{shadowed_var,'B',generate}}]}}, 265: 266: {lc10, 267: <<"h(A) -> 268: B = foo, 269: [A || B <- A], % B shadowed, B unused. 270: B. 271: ">>, 272: [warn_unused_vars], 273: {warnings,[{3,erl_lint,{unused_var,'B'}}, 274: {3,erl_lint,{shadowed_var,'B',generate}}]}}, 275: 276: {lc11, 277: <<"i(X) -> 278: [Z || Z <- X, % Z unused. 279: Z = X <- [foo]]. % X and Z shadowed. X unused! 280: ">>, 281: [warn_unused_vars], 282: {warnings,[{2,erl_lint,{unused_var,'Z'}}, 283: {3,erl_lint,{unused_var,'X'}}, 284: {3,erl_lint,{shadowed_var,'X',generate}}, 285: {3,erl_lint,{shadowed_var,'Z',generate}}]}}, 286: 287: {lc12, 288: <<"j({X}) -> 289: [Z || Z <- X, % Z unused. 290: Z <- X = [[1,2,3]], % Z shadowed. Z unused. 291: Z <- X, % Z shadowed. Z unused. 292: Z <- X]; % Z shadowed. 293: j(X) -> 294: [foo || X <- X, % X shadowed. 295: X <- % X shadowed. X unused. 296: X = 297: Y = [[1,2,3]], % Y unused. 298: X <- [], % X shadowed. 299: X <- X]. % X shadowed. X unused. 300: ">>, 301: [warn_unused_vars], 302: {warnings,[{2,erl_lint,{unused_var,'Z'}}, 303: {3,erl_lint,{unused_var,'Z'}}, 304: {3,erl_lint,{shadowed_var,'Z',generate}}, 305: {4,erl_lint,{unused_var,'Z'}}, 306: {4,erl_lint,{shadowed_var,'Z',generate}}, 307: {5,erl_lint,{shadowed_var,'Z',generate}}, 308: {7,erl_lint,{shadowed_var,'X',generate}}, 309: {8,erl_lint,{unused_var,'X'}}, 310: {8,erl_lint,{shadowed_var,'X',generate}}, 311: {10,erl_lint,{unused_var,'Y'}}, 312: {11,erl_lint,{shadowed_var,'X',generate}}, 313: {12,erl_lint,{unused_var,'X'}}, 314: {12,erl_lint,{shadowed_var,'X',generate}}]}}, 315: 316: {lc13, 317: <<"k(X) -> 318: [Z || Z <- Y = X]; % Y unused. 319: k(X) -> 320: [Z || Z <- X = Y = X]; % Y unused! 321: k(X) -> 322: [Z || Z <- begin X = Y = X, Y end]; 323: k(X) -> 324: [{Y,W} || W <- Y = X]; % Y unbound 325: k(X) -> 326: [Z || Z <- (Y = X), % Y unused. 327: Y > X]; % Y unbound. 328: k(X) -> 329: [Y || Y = X > 3, Z = X]; % Z unused. 330: k(X) -> 331: [Z || Y = X > 3, Z = X]. % Y unused. 332: ">>, 333: [warn_unused_vars], 334: {error,[{8,erl_lint,{unbound_var,'Y'}}, 335: {11,erl_lint,{unbound_var,'Y'}}], 336: [{2,erl_lint,{unused_var,'Y'}}, 337: {4,erl_lint,{unused_var,'Y'}}, 338: {8,erl_lint,{unused_var,'Y'}}, 339: {10,erl_lint,{unused_var,'Y'}}, 340: {13,erl_lint,{unused_var,'Z'}}, 341: {15,erl_lint,{unused_var,'Y'}}]}}, 342: 343: {lc14, 344: <<"lc2() -> 345: Z = [[1],[2],[3]], 346: [X || Z <- Z, % Z shadowed. 347: X <- Z]. 348: ">>, 349: [warn_unused_vars], 350: {warnings,[{3,erl_lint,{shadowed_var,'Z',generate}}]}}, 351: 352: {lc15, 353: <<"lc3() -> 354: Z = [1,2,3], 355: [X || X <- Z, 356: Z <- Z]. % Z shadowed. Z unused. 357: ">>, 358: [warn_unused_vars], 359: {warnings,[{4,erl_lint,{unused_var,'Z'}}, 360: {4,erl_lint,{shadowed_var,'Z',generate}}]}}, 361: 362: {lc16, 363: <<"bin(Z) -> 364: case bar of 365: true -> 366: U = 2; 367: false -> 368: true 369: end, 370: case bar of 371: true -> 372: X = 2; 373: false -> 374: X = 3 375: end, 376: case foo of 377: true -> 378: Y = 3; % Y unused. 379: false -> 380: 4 381: end, 382: case foo of 383: 1 -> 384: U; % U unsafe. 385: 2 -> 386: [Z || <<U:X>> <- Z]; % (X exported.) U unused. 387: 3 -> 388: [Z || <<U:X>> <- Z], % (X exported.) U unused. 389: U % U unsafe. 390: end. 391: ">>, 392: [warn_unused_vars], 393: {error,[{22,erl_lint,{unsafe_var,'U',{'case',2}}}, 394: {27,erl_lint,{unsafe_var,'U',{'case',2}}}], 395: [{16,erl_lint,{unused_var,'Y'}}, 396: % {24,erl_lint,{exported_var,'X',{'case',8}}}, 397: {24,erl_lint,{unused_var,'U'}}, 398: % {26,erl_lint,{exported_var,'X',{'case',8}}}, 399: {26,erl_lint,{unused_var,'U'}}]}}, 400: 401: {lc17, 402: <<"bin(Z) -> 403: %% This used to pass erl_lint... 404: case bar of 405: true -> 406: U = 2; 407: false -> 408: true 409: end, 410: case bar of 411: true -> 412: X = 2; 413: false -> 414: X = 3 415: end, 416: case foo of 417: true -> 418: Y = 3; % Y unused. 419: false -> 420: 4 421: end, 422: [Z || <<U:X>> <- Z], % (X exported.) U unused. 423: U. % U unsafe. 424: ">>, 425: [warn_unused_vars], 426: {error,[{22,erl_lint,{unsafe_var,'U',{'case',3}}}], 427: [{17,erl_lint,{unused_var,'Y'}}, 428: % {21,erl_lint,{exported_var,'X',{'case',9}}}, 429: {21,erl_lint,{unused_var,'U'}}]}}, 430: 431: {lc18, 432: <<"bin(Z) -> 433: case bar of 434: true -> 435: U = 2; 436: false -> 437: true 438: end, 439: case bar of 440: true -> 441: X = 2; 442: false -> 443: X = 3 444: end, 445: case foo of 446: true -> 447: Y = 3; 448: false -> 449: 4 450: end, 451: [B || <<U: % U unused 452: U>> <- X, <<B:Y>> <- Z]. % U unsafe. Y unsafe. 453: % U shadowed. (X exported.) 454: ">>, 455: [warn_unused_vars], 456: {error,[{21,erl_lint,{unsafe_var,'U',{'case',2}}}, 457: {21,erl_lint,{unsafe_var,'Y',{'case',14}}}], 458: [{20,erl_lint,{unused_var,'U'}} 459: % ,{21,erl_lint,{exported_var,'X',{'case',8}}} 460: % ,{21,erl_lint,{shadowed_var,'U',generate}} 461: ]}}, 462: 463: {lc19, 464: <<"p({B,C}) -> 465: <<A:B,A:C>> = <<17:32>>; 466: p(B) -> 467: <<A:B>> = <<17:32>>. % A unused. 468: ">>, 469: [warn_unused_vars], 470: {warnings,[{4,erl_lint,{unused_var,'A'}}]}}, 471: 472: {lc20, 473: <<"c({I1,I2}) -> 474: if 475: <<I1:I2>> == <<>> -> 476: foo 477: end; 478: c([C1,C2]) -> % C1 unused. 479: case foo of 480: <<C2:C2, 481: C3:C2>> -> % C3 unused. 482: bar 483: end. 484: 485: ">>, 486: [warn_unused_vars], 487: {warnings,[{6,erl_lint,{unused_var,'C1'}}, 488: {7,sys_core_fold,no_clause_match}, 489: {9,erl_lint,{unused_var,'C3'}}]}}, 490: 491: {lc21, 492: <<"t() -> 493: S = 8, 494: case <<3:8>> of 495: <<X:S>> -> 496: X; 497: <<S:X>> -> % X unbound 498: foo 499: end; 500: t() -> 501: S = 8, 502: case <<3:8>> of 503: <<S:S>> -> 504: S; 505: <<Q:32>> -> % Q unused. 506: foo 507: end. 508: ">>, 509: [warn_unused_vars], 510: {error,[{6,erl_lint,{unbound_var,'X'}}], 511: [{14,erl_lint,{unused_var,'Q'}}]}} 512: 513: ], 514: ?line [] = run(Config, Ts), 515: ok. 516: 517: 518: unused_vars_warn_rec(doc) -> 519: "Warnings for unused variables in records."; 520: unused_vars_warn_rec(suite) -> []; 521: unused_vars_warn_rec(Config) when is_list(Config) -> 522: Ts = [{rec1, % An example provided by Bjorn. 523: <<"-record(edge, 524: {ltpr, 525: ltsu, 526: rtpr, 527: rtsu 528: }). 529: 530: f1(#edge{ltpr = A, ltsu = A}) -> 531: true; 532: f1({Q, Q}) -> 533: true. 534: 535: f2(Edge, Etab) -> 536: case gb_trees:lookup(Edge, Etab) of 537: {value,#edge{ltpr=Same,ltsu=Same}} -> ok; 538: {value,_} -> error 539: end. 540: 541: bar(Edge, Etab) -> 542: case gb_trees:lookup(Edge, Etab) of 543: {Same,Same} -> ok; 544: {value,#edge{ltpr=Same}} -> ok; % Same unused. 545: {value,_} -> error 546: end. 547: ">>, 548: [warn_unused_vars], 549: {warnings,[{22,erl_lint,{unused_var,'Same'}}]}}, 550: {rec2, 551: <<"-record(r, {a,b}). 552: f(X, Y) -> #r{a=[K || K <- Y], b=[K || K <- Y]}. 553: g(X, Y) -> #r{a=lists:map(fun (K) -> K end, Y), 554: b=lists:map(fun (K) -> K end, Y)}. 555: h(X, Y) -> #r{a=case Y of _ when is_list(Y) -> Y end, 556: b=case Y of _ when is_list(Y) -> Y end}. 557: i(X, Y) -> #r{a=if is_list(Y) -> Y end, b=if is_list(Y) -> Y end}. 558: ">>, 559: [warn_unused_vars], 560: {warnings,[{2,erl_lint,{unused_var,'X'}}, 561: {3,erl_lint,{unused_var,'X'}}, 562: {5,erl_lint,{unused_var,'X'}}, 563: {7,erl_lint,{unused_var,'X'}}]}}, 564: {rec3, 565: <<"-record(r, {a}). 566: t() -> X = 1, #r{a=foo, a=bar, a=qux}. 567: ">>, 568: [warn_unused_vars], 569: {error,[{2,erl_lint,{redefine_field,r,a}}, 570: {2,erl_lint,{redefine_field,r,a}}], 571: [{2,erl_lint,{unused_var,'X'}}]}}], 572: ?line [] = run(Config, Ts), 573: ok. 574: 575: unused_vars_warn_fun(doc) -> 576: "Warnings for unused variables in records."; 577: unused_vars_warn_fun(suite) -> []; 578: unused_vars_warn_fun(Config) when is_list(Config) -> 579: Ts = [{fun1, 580: <<"a({A,B}) -> % A unused. 581: fun(A) -> B end; % A shadowed. A unused. 582: a([A,B]) -> 583: fun(<<A:B>>, % A shadowed. A unused. 584: <<Q:A>>) -> foo % Q unused. 585: end; 586: a({A,B,C,D,E}) -> 587: fun(E) when C == <<A:A>>, <<17:B>> == D -> % E shadowed. E unused. 588: foo 589: end, 590: E; 591: a([A,B,C,D,E]) -> % E unused. 592: fun() -> 593: (C == <<A:A>>) and (<<17:B>> == D) 594: end. 595: ">>, 596: [warn_unused_vars], 597: {warnings,[{1,erl_lint,{unused_var,'A'}}, 598: {2,erl_lint,{unused_var,'A'}}, 599: {2,erl_lint,{shadowed_var,'A','fun'}}, 600: {4,erl_lint,{unused_var,'A'}}, 601: {4,erl_lint,{shadowed_var,'A','fun'}}, 602: {5,erl_lint,{unused_var,'Q'}}, 603: {8,erl_lint,{unused_var,'E'}}, 604: {8,erl_lint,{shadowed_var,'E','fun'}}, 605: {8,sys_core_fold,useless_building}, 606: {12,erl_lint,{unused_var,'E'}}]}}, 607: 608: {fun2, 609: <<"u() -> 610: case foo of 611: true -> 612: U = 2; 613: false -> 614: true 615: end, 616: fun(U) -> foo end, % U unused. 617: U; % U unsafe. 618: u() -> 619: case foo of 620: true -> 621: U = 2; 622: false -> 623: U = 3 624: end, 625: fun(U) -> foo end, % U shadowed. U unused. 626: U; 627: u() -> 628: case foo of 629: true -> 630: U = 2; % U unused. 631: false -> 632: U = 3 % U unused. 633: end, 634: fun(U) -> foo end. % U shadowed. U unused. 635: ">>, 636: [warn_unused_vars], 637: {error,[{9,erl_lint,{unsafe_var,'U',{'case',2}}}], 638: [{8,erl_lint,{unused_var,'U'}}, 639: {17,erl_lint,{unused_var,'U'}}, 640: {17,erl_lint,{shadowed_var,'U','fun'}}, 641: {22,erl_lint,{unused_var,'U'}}, 642: {24,erl_lint,{unused_var,'U'}}, 643: {26,erl_lint,{unused_var,'U'}}, 644: {26,erl_lint,{shadowed_var,'U','fun'}}]}} 645: ], 646: ?line [] = run(Config, Ts), 647: ok. 648: 649: unused_vars_OTP_4858(doc) -> 650: "Bit syntax, binsize variable used in the same matching."; 651: unused_vars_OTP_4858(suite) -> []; 652: unused_vars_OTP_4858(Config) when is_list(Config) -> 653: Ts = [{otp_4858, 654: <<"objs(<<Size:4/unit:8, B:Size/binary>>) -> 655: B. 656: 657: fel(<<Size:4/unit:8, B:BadSize/binary>>) -> % BadSize unbound. 658: BadSize. % B, Size unused. 659: 660: r9c_highlight() -> % B, Rest unused. 661: <<Size, B:Size/binary,Rest/binary>> = <<2,\"AB\",3,\"CDE\">>. 662: ">>, 663: [warn_unused_vars], 664: {error,[{4,erl_lint,{unbound_var,'BadSize'}}], 665: [{4,erl_lint,{unused_var,'B'}}, 666: {4,erl_lint,{unused_var,'Size'}}, 667: {8,erl_lint,{unused_var,'B'}}, 668: {8,erl_lint,{unused_var,'Rest'}}]}} 669: ], 670: ?line [] = run(Config, Ts), 671: ok. 672: 673: export_vars_warn(doc) -> 674: "Warnings for exported variables"; 675: export_vars_warn(suite) -> []; 676: export_vars_warn(Config) when is_list(Config) -> 677: Ts = [{exp1, 678: <<"u() -> 679: case foo of 680: 1 -> 681: A = 1, 682: B = 2, 683: W = 3, % W unused. 684: Z = 3; % Z unused. 685: 2 -> 686: B = 2, 687: Z = 4 % Z unused. 688: end, 689: case bar of 690: true -> 691: A = 17, % A unsafe. 692: X = 3, % X unused. 693: U = 2, 694: U; 695: false -> 696: B = 19, % B exported. 697: U = 3; % U unused. 698: foo -> 699: X = 3, 700: X; 701: bar -> 702: X = 9, % X unused. 703: U = 14 % U unused. 704: end. 705: ">>, 706: [warn_unused_vars], 707: {error,[{14,erl_lint,{unsafe_var,'A',{'case',2}}}], 708: [{6,erl_lint,{unused_var,'W'}}, 709: {7,erl_lint,{unused_var,'Z'}}, 710: {10,erl_lint,{unused_var,'Z'}}, 711: {15,erl_lint,{unused_var,'X'}}, 712: {19,erl_lint,{exported_var,'B',{'case',2}}}, 713: {20,erl_lint,{unused_var,'U'}}, 714: {25,erl_lint,{unused_var,'X'}}, 715: {26,erl_lint,{unused_var,'U'}}]}}, 716: 717: {exp2, 718: <<"bin(A) -> 719: receive 720: M -> 721: X = M, 722: Y = M, 723: Z = M 724: end, 725: [B || <<B:X>> <- A], % X exported. 726: Y = B, % Y exported. B unbound. 727: [B || B <- Z]. % Z exported. B shadowed. 728: ">>, 729: [warn_export_vars], 730: {error,[{9,erl_lint,{unbound_var,'B'}}], 731: [{8,erl_lint,{exported_var,'X',{'receive',2}}}, 732: {9,erl_lint,{exported_var,'Y',{'receive',2}}}, 733: {10,erl_lint,{exported_var,'Z',{'receive',2}}}, 734: {10,erl_lint,{shadowed_var,'B',generate}}]}}, 735: 736: {exp3, 737: <<"bin(A) -> 738: receive 739: M -> 740: X = M, 741: Y = M, 742: Z = M 743: end, 744: [B || <<B:X>> <- A], % (X exported.) 745: Y = B, % Y exported. B unbound. 746: [B || B <- Z]. % (Z exported.) B shadowed. 747: ">>, 748: [], 749: {error,[{9,erl_lint,{unbound_var,'B'}}], 750: [{9,erl_lint,{exported_var,'Y',{'receive',2}}}, 751: {10,erl_lint,{shadowed_var,'B',generate}}]}} 752: ], 753: ?line [] = run(Config, Ts), 754: ok. 755: 756: shadow_vars(doc) -> 757: "Shadowed variables are tested in other places, but here we test " 758: "that the warning can be turned off."; 759: shadow_vars(suite) -> []; 760: shadow_vars(Config) when is_list(Config) -> 761: Ts = [{shadow1, 762: <<"bin(A) -> 763: receive 764: M -> 765: X = M, 766: Y = M, 767: Z = M 768: end, 769: [B || <<B:X>> <- A], 770: Y = B, 771: [B || B <- Z]. % B shadowed. 772: ">>, 773: [nowarn_shadow_vars], 774: {error,[{9,erl_lint,{unbound_var,'B'}}], 775: [{9,erl_lint,{exported_var,'Y',{'receive',2}}}]}}], 776: 777: ?line [] = run(Config, Ts), 778: ok. 779: 780: unused_import(doc) -> 781: "Test that the 'warn_unused_import' option works."; 782: unused_import(suite) -> []; 783: unused_import(Config) when is_list(Config) -> 784: Ts = [{imp1, 785: <<"-import(lists, [map/2,foldl/3]). 786: t(L) -> 787: map(fun(X) -> 2*X end, L). 788: ">>, 789: [warn_unused_import], 790: {warnings,[{1,erl_lint,{unused_import,{{foldl,3},lists}}}]}}], 791: ?line [] = run(Config, Ts), 792: ok. 793: 794: unused_function(doc) -> 795: "Test warnings for unused functions."; 796: unused_function(suite) -> []; 797: unused_function(Config) when is_list(Config) -> 798: Ts = [{func1, 799: <<"-export([t/1]). 800: t(L) -> 801: lists:map(fun(X) -> 2*X end, L). 802: 803: fact(N) -> 804: fact_1(N, 1). 805: 806: fact_1(1, P) -> P; 807: fact_1(N, P) -> fact_1(N-1, P*N). 808: ">>, 809: {[]}, %Tuple indicates no 'export_all'. 810: {warnings,[{5,erl_lint,{unused_function,{fact,1}}}, 811: {8,erl_lint,{unused_function,{fact_1,2}}}]}}, 812: 813: %% Turn off warnings for unused functions. 814: {func2, 815: <<"-export([t/1]). 816: t(L) -> 817: lists:map(fun(X) -> 2*X end, L). 818: 819: b(X) -> 820: 32*X. 821: ">>, 822: {[nowarn_unused_function]}, %Tuple indicates no 'export_all'. 823: []}, 824: 825: %% Turn off warnings for unused functions using a -compile() directive. 826: {func3, 827: <<"-export([t/1]). 828: -compile(nowarn_unused_function). 829: 830: t(L) -> 831: lists:map(fun(X) -> 2*X end, L). 832: 833: b(X) -> 834: 32*X. 835: ">>, 836: {[]}, %Tuple indicates no 'export_all'. 837: []}], 838: 839: ?line [] = run(Config, Ts), 840: ok. 841: 842: unsafe_vars(doc) -> 843: "OTP-4671. Errors for unsafe variables"; 844: unsafe_vars(suite) -> []; 845: unsafe_vars(Config) when is_list(Config) -> 846: Ts = [{unsafe1, 847: <<"t() -> 848: (X = true) orelse (Y = false), 849: Y. 850: ">>, 851: [warn_unused_vars], 852: {error,[{3,erl_lint,{unsafe_var,'Y',{'orelse',2}}}], 853: [{2,erl_lint,{unused_var,'X'}}]}}, 854: {unsafe2, 855: <<"t2() -> 856: (X = true) orelse (Y = false), 857: X. 858: ">>, 859: [warn_unused_vars], 860: {warnings,[{2,erl_lint,{unused_var,'Y'}}]}}, 861: {unsafe3, 862: <<"t3() -> 863: (X = true) andalso (Y = false), 864: Y. 865: ">>, 866: [warn_unused_vars], 867: {error,[{3,erl_lint,{unsafe_var,'Y',{'andalso',2}}}], 868: [{2,erl_lint,{unused_var,'X'}}]}}, 869: {unsafe4, 870: <<"t4() -> 871: (X = true) andalso (true = X), 872: X. 873: ">>, 874: [warn_unused_vars], 875: []}, 876: {unsafe5, 877: <<"t5() -> 878: Y = 3, 879: (X = true) andalso (X = true), 880: {X,Y}. 881: ">>, 882: [warn_unused_vars], 883: []}, 884: {unsafe6, 885: <<"t6() -> 886: X = true, 887: (X = true) andalso (true = X), 888: X. 889: ">>, 890: [warn_unused_vars], 891: []}, 892: {unsafe7, 893: <<"t7() -> 894: (if true -> X = 3; false -> true end) 895: andalso (X > 2), 896: X. 897: ">>, 898: [warn_unused_vars], 899: {errors,[{3,erl_lint,{unsafe_var,'X',{'if',2}}}, 900: {4,erl_lint,{unsafe_var,'X',{'if',2}}}], 901: []}} 902: ], 903: ?line [] = run(Config, Ts), 904: ok. 905: 906: unsafe_vars2(doc) -> 907: "OTP-4831, seq8202. No warn_unused_vars and unsafe variables"; 908: unsafe_vars2(suite) -> []; 909: unsafe_vars2(Config) when is_list(Config) -> 910: Ts = [{unsafe2_1, 911: <<"foo(State) -> 912: case State of 913: true -> 914: if 915: false -> ok; 916: true -> State1=State 917: end 918: end, 919: State1. % unsafe 920: ">>, 921: [warn_unused_vars], 922: {errors,[{9,erl_lint,{unsafe_var,'State1',{'if',4}}}],[]}}, 923: {unsafe2_2, 924: <<"foo(State) -> 925: case State of 926: true -> 927: if 928: false -> ok; 929: true -> State1=State 930: end 931: end, 932: State1. % unsafe 933: ">>, 934: [], 935: {errors,[{9,erl_lint,{unsafe_var,'State1',{'if',4}}}],[]}} 936: ], 937: ?line [] = run(Config, Ts), 938: ok. 939: 940: unsafe_vars_try(doc) -> 941: "Errors for unsafe variables in try/catch constructs."; 942: unsafe_vars_try(suite) -> []; 943: unsafe_vars_try(Config) when is_list(Config) -> 944: Ts = [{unsafe_try1, 945: <<"foo2() -> 946: try self() 947: catch 948: Class:Data -> Result={Class,Data} 949: end, 950: Result. 951: foo3a() -> 952: try self() of 953: R -> R 954: catch 955: Class:Data -> Result={Class,Data} 956: end, 957: Result. 958: foo3b() -> 959: try self() of 960: Result -> ok 961: catch 962: Class:Data -> {Class,Data} 963: end, 964: Result. 965: ">>, 966: [], 967: {errors,[{6,erl_lint,{unsafe_var,'Result',{'try',2}}}, 968: {13,erl_lint,{unsafe_var,'Result',{'try',8}}}, 969: {20,erl_lint,{unsafe_var,'Result',{'try',15}}}], 970: []}}, 971: {unsafe_try2, 972: <<"foo1a() -> 973: Try = 974: try self() 975: catch 976: Class:Data -> Rc={Class,Data} 977: after 978: Ra=ok 979: end, 980: {Try,Rc,Ra}. 981: foo1b() -> 982: Try = 983: try self() of 984: R -> R 985: catch 986: Class:Data -> Rc={Class,Data} 987: after 988: Ra=R 989: end, 990: {Try,Rc,Ra}. 991: foo2() -> 992: Try = 993: try self() of 994: R -> Ro=R 995: catch 996: Class:Data -> {Class,Data} 997: after 998: Ra=R 999: end, 1000: {Try,Ro,Ra}. 1001: foo3() -> 1002: Try = 1003: try self() of 1004: R -> Ro=R 1005: catch 1006: Class:Data -> Rc={Class,Data} 1007: after 1008: Ra=R 1009: end, 1010: {Try,R,Ro,Rc,Ra}. 1011: ">>, 1012: [], 1013: {errors,[{9,erl_lint,{unsafe_var,'Ra',{'try',3}}}, 1014: {9,erl_lint,{unsafe_var,'Rc',{'try',3}}}, 1015: {17,erl_lint,{unsafe_var,'R',{'try',12}}}, 1016: {19,erl_lint,{unsafe_var,'Ra',{'try',12}}}, 1017: {19,erl_lint,{unsafe_var,'Rc',{'try',12}}}, 1018: {27,erl_lint,{unsafe_var,'R',{'try',22}}}, 1019: {29,erl_lint,{unsafe_var,'Ra',{'try',22}}}, 1020: {29,erl_lint,{unsafe_var,'Ro',{'try',22}}}, 1021: {37,erl_lint,{unsafe_var,'R',{'try',32}}}, 1022: {39,erl_lint,{unsafe_var,'R',{'try',32}}}, 1023: {39,erl_lint,{unsafe_var,'Ra',{'try',32}}}, 1024: {39,erl_lint,{unsafe_var,'Rc',{'try',32}}}, 1025: {39,erl_lint,{unsafe_var,'Ro',{'try',32}}}], 1026: []}}, 1027: {unsafe_try3, 1028: <<"foo1(X) -> 1029: Try = 1030: try R=self() 1031: catch 1032: Class:Data -> Rc={X,R,Class,Data} 1033: end, 1034: {X,Try,Rc}. 1035: foo2(X) -> 1036: Try = 1037: try R=self() of 1038: RR -> Ro={X,R,RR} 1039: catch 1040: Class:Data -> {X,R,RR,Ro,Class,Data} 1041: end, 1042: {X,Try,R,RR,Ro,Class,Data}. 1043: foo3(X) -> 1044: Try = 1045: try R=self() of 1046: RR -> {X,R,RR} 1047: catch 1048: Class:Data -> {X,R,RR,Class,Data} 1049: after 1050: Ra={X,R,RR,Class,Data} 1051: end, 1052: {X,Try,R,RR,Ra,Class,Data}. 1053: ">>, 1054: [], 1055: {errors,[{5,erl_lint,{unsafe_var,'R',{'try',3}}}, 1056: {7,erl_lint,{unsafe_var,'Rc',{'try',3}}}, 1057: {11,erl_lint,{unsafe_var,'R',{'try',10}}}, 1058: {13,erl_lint,{unbound_var,'RR'}}, 1059: {13,erl_lint,{unbound_var,'Ro'}}, 1060: {13,erl_lint,{unsafe_var,'R',{'try',10}}}, 1061: {15,erl_lint,{unsafe_var,'Class',{'try',10}}}, 1062: {15,erl_lint,{unsafe_var,'Data',{'try',10}}}, 1063: {15,erl_lint,{unsafe_var,'R',{'try',10}}}, 1064: {15,erl_lint,{unsafe_var,'RR',{'try',10}}}, 1065: {15,erl_lint,{unsafe_var,'Ro',{'try',10}}}, 1066: {19,erl_lint,{unsafe_var,'R',{'try',18}}}, 1067: {21,erl_lint,{unbound_var,'RR'}}, 1068: {21,erl_lint,{unsafe_var,'R',{'try',18}}}, 1069: {23,erl_lint,{unsafe_var,'Class',{'try',18}}}, 1070: {23,erl_lint,{unsafe_var,'Data',{'try',18}}}, 1071: {23,erl_lint,{unsafe_var,'R',{'try',18}}}, 1072: {23,erl_lint,{unsafe_var,'RR',{'try',18}}}, 1073: {25,erl_lint,{unsafe_var,'Class',{'try',18}}}, 1074: {25,erl_lint,{unsafe_var,'Data',{'try',18}}}, 1075: {25,erl_lint,{unsafe_var,'R',{'try',18}}}, 1076: {25,erl_lint,{unsafe_var,'RR',{'try',18}}}, 1077: {25,erl_lint,{unsafe_var,'Ra',{'try',18}}}], 1078: []}}, 1079: {unsafe_try4, 1080: <<"foo1(X) -> 1081: Try = 1082: try R=self() of 1083: RR -> Ro={X,R,RR} 1084: catch 1085: Class:Data -> Rc={X,R,RR,Ro,Class,Data} 1086: after 1087: Ra={X,R,RR,Ro,Rc,Class,Data} 1088: end, 1089: {X,Try,R,RR,Ro,Rc,Ra,Class,Data}. 1090: ">>, 1091: [], 1092: {errors,[{4,erl_lint,{unsafe_var,'R',{'try',3}}}, 1093: {6,erl_lint,{unbound_var,'RR'}}, 1094: {6,erl_lint,{unbound_var,'Ro'}}, 1095: {6,erl_lint,{unsafe_var,'R',{'try',3}}}, 1096: {8,erl_lint,{unsafe_var,'Class',{'try',3}}}, 1097: {8,erl_lint,{unsafe_var,'Data',{'try',3}}}, 1098: {8,erl_lint,{unsafe_var,'R',{'try',3}}}, 1099: {8,erl_lint,{unsafe_var,'RR',{'try',3}}}, 1100: {8,erl_lint,{unsafe_var,'Rc',{'try',3}}}, 1101: {8,erl_lint,{unsafe_var,'Ro',{'try',3}}}, 1102: {10,erl_lint,{unsafe_var,'Class',{'try',3}}}, 1103: {10,erl_lint,{unsafe_var,'Data',{'try',3}}}, 1104: {10,erl_lint,{unsafe_var,'R',{'try',3}}}, 1105: {10,erl_lint,{unsafe_var,'RR',{'try',3}}}, 1106: {10,erl_lint,{unsafe_var,'Ra',{'try',3}}}, 1107: {10,erl_lint,{unsafe_var,'Rc',{'try',3}}}, 1108: {10,erl_lint,{unsafe_var,'Ro',{'try',3}}}], 1109: []}}, 1110: {unsafe_try5, 1111: <<"bang() -> 1112: case 1 of 1113: nil -> 1114: Acc = 2; 1115: _ -> 1116: try 1117: Acc = 3, 1118: Acc 1119: catch _:_ -> 1120: ok 1121: end 1122: end, 1123: Acc. 1124: ">>, 1125: [], 1126: {errors,[{13,erl_lint,{unsafe_var,'Acc',{'try',6}}}],[]}}], 1127: ?line [] = run(Config, Ts), 1128: ok. 1129: 1130: guard(doc) -> 1131: "OTP-4670. Guards, is_record in particular."; 1132: guard(suite) -> []; 1133: guard(Config) when is_list(Config) -> 1134: %% Well, these could be plain code... 1135: Ts = [{guard1, 1136: <<"-record(apa, {}). 1137: t(A) when atom(A) -> 1138: atom; 1139: t(A) when binary(A) -> 1140: binary; 1141: t(A) when constant(A) -> 1142: constant; 1143: t(A) when float(A) -> 1144: float; 1145: t(A) when function(A) -> 1146: function; 1147: t(A) when integer(A) -> 1148: integer; 1149: t(A) when is_atom(A) -> 1150: is_atom; 1151: t(A) when is_binary(A) -> 1152: is_binary; 1153: t(A) when is_constant(A) -> 1154: is_constant; 1155: t(A) when is_float(A) -> 1156: is_float; 1157: t(A) when is_function(A) -> 1158: is_function; 1159: t(A) when is_integer(A) -> 1160: is_integer; 1161: t(A) when is_list(A) -> 1162: is_list; 1163: t(A) when is_number(A) -> 1164: is_number; 1165: t(A) when is_pid(A) -> 1166: is_pid; 1167: t(A) when is_port(A) -> 1168: is_port; 1169: t(A) when is_record(A, apa) -> 1170: is_record; 1171: t(A) when is_record(A, apa, 1) -> 1172: is_record; 1173: t(A) when is_reference(A) -> 1174: is_reference; 1175: t(A) when is_tuple(A) -> 1176: is_tuple; 1177: t(A) when list(A) -> 1178: list; 1179: t(A) when number(A) -> 1180: number; 1181: t(A) when pid(A) -> 1182: pid; 1183: t(A) when port(A) -> 1184: port; 1185: t(A) when record(A, apa) -> 1186: record; 1187: t(A) when reference(A) -> 1188: reference; 1189: t(A) when tuple(A) -> 1190: tuple. 1191: ">>, 1192: [nowarn_obsolete_guard], 1193: {error, 1194: [{6,erl_lint,illegal_guard_expr},{18,erl_lint,illegal_guard_expr}], 1195: [{18,erl_lint,{removed,{erlang,is_constant,1}, 1196: "Removed in R13B"}}]}}, 1197: {guard2, 1198: <<"-record(apa,{}). 1199: t1(A) when atom(A), atom(A) -> 1200: atom; 1201: t1(A) when binary(A), binary(A) -> 1202: binary; 1203: t1(A) when constant(A), constant(A) -> 1204: constant; 1205: t1(A) when float(A), float(A) -> 1206: float; 1207: t1(A) when function(A), function(A) -> 1208: function; 1209: t1(A) when integer(A), integer(A) -> 1210: integer; 1211: t1(A) when is_atom(A), is_atom(A) -> 1212: is_atom; 1213: t1(A) when is_binary(A), is_binary(A) -> 1214: is_binary; 1215: t1(A) when is_constant(A), is_constant(A) -> 1216: is_constant; 1217: t1(A) when is_float(A), is_float(A) -> 1218: is_float; 1219: t1(A) when is_function(A), is_function(A) -> 1220: is_function; 1221: t1(A) when is_integer(A), is_integer(A) -> 1222: is_integer; 1223: t1(A) when is_list(A), is_list(A) -> 1224: is_list; 1225: t1(A) when is_number(A), is_number(A) -> 1226: is_number; 1227: t1(A) when is_pid(A), is_pid(A) -> 1228: is_pid; 1229: t1(A) when is_port(A), is_port(A) -> 1230: is_port; 1231: t1(A) when is_record(A, apa), is_record(A, apa) -> 1232: is_record; 1233: t1(A) when is_record(A, apa, 1), is_record(A, apa, 1) -> 1234: is_record; 1235: t1(A) when is_reference(A), is_reference(A) -> 1236: is_reference; 1237: t1(A) when is_tuple(A), is_tuple(A) -> 1238: is_tuple; 1239: t1(A) when list(A), list(A) -> 1240: list; 1241: t1(A) when number(A), number(A) -> 1242: number; 1243: t1(A) when pid(A), pid(A) -> 1244: pid; 1245: t1(A) when port(A), port(A) -> 1246: port; 1247: t1(A) when record(A, apa), record(A, apa) -> 1248: record; 1249: t1(A) when reference(A), reference(A) -> 1250: reference; 1251: t1(A) when tuple(A), tuple(A) -> 1252: tuple. 1253: ">>, 1254: [nowarn_obsolete_guard], 1255: {error,[{6,erl_lint,illegal_guard_expr}, 1256: {6,erl_lint,illegal_guard_expr}, 1257: {18,erl_lint,illegal_guard_expr}, 1258: {18,erl_lint,illegal_guard_expr}], 1259: [{18,erl_lint,{removed,{erlang,is_constant,1}, 1260: "Removed in R13B"}}, 1261: {18,erl_lint,{removed,{erlang,is_constant,1}, 1262: "Removed in R13B"}}]}}, 1263: {guard3, 1264: <<"-record(apa,{}). 1265: t2(A) when atom(A); atom(A) -> 1266: atom; 1267: t2(A) when binary(A); binary(A) -> 1268: binary; 1269: t2(A) when float(A); float(A) -> 1270: float; 1271: t2(A) when function(A); function(A) -> 1272: function; 1273: t2(A) when integer(A); integer(A) -> 1274: integer; 1275: t2(A) when is_atom(A); is_atom(A) -> 1276: is_atom; 1277: t2(A) when is_binary(A); is_binary(A) -> 1278: is_binary; 1279: t2(A) when is_float(A); is_float(A) -> 1280: is_float; 1281: t2(A) when is_function(A); is_function(A) -> 1282: is_function; 1283: t2(A) when is_integer(A); is_integer(A) -> 1284: is_integer; 1285: t2(A) when is_list(A); is_list(A) -> 1286: is_list; 1287: t2(A) when is_number(A); is_number(A) -> 1288: is_number; 1289: t2(A) when is_pid(A); is_pid(A) -> 1290: is_pid; 1291: t2(A) when is_port(A); is_port(A) -> 1292: is_port; 1293: t2(A) when is_record(A, apa); is_record(A, apa) -> 1294: is_record; 1295: t2(A) when is_record(A, gurka, 1); is_record(A, gurka, 1) -> 1296: is_record; 1297: t2(A) when is_reference(A); is_reference(A) -> 1298: is_reference; 1299: t2(A) when is_tuple(A); is_tuple(A) -> 1300: is_tuple; 1301: t2(A) when list(A); list(A) -> 1302: list; 1303: t2(A) when number(A); number(A) -> 1304: number; 1305: t2(A) when pid(A); pid(A) -> 1306: pid; 1307: t2(A) when port(A); port(A) -> 1308: port; 1309: t2(A) when record(A, apa); record(A, apa) -> 1310: record; 1311: t2(A) when reference(A); reference(A) -> 1312: reference; 1313: t2(A) when tuple(A); tuple(A) -> 1314: tuple. 1315: ">>, 1316: [nowarn_obsolete_guard], 1317: []}, 1318: {guard4, 1319: <<"-record(apa, {}). 1320: t3(A) when float(A) or float(A) -> % coercing... (badarg) 1321: float; 1322: t3(A) when is_atom(A) or is_atom(A) -> 1323: is_atom; 1324: t3(A) when is_binary(A) or is_binary(A) -> 1325: is_binary; 1326: t3(A) when is_float(A) or is_float(A) -> 1327: is_float; 1328: t3(A) when is_function(A) or is_function(A) -> 1329: is_function; 1330: t3(A) when is_integer(A) or is_integer(A) -> 1331: is_integer; 1332: t3(A) when is_list(A) or is_list(A) -> 1333: is_list; 1334: t3(A) when is_number(A) or is_number(A) -> 1335: is_number; 1336: t3(A) when is_pid(A) or is_pid(A) -> 1337: is_pid; 1338: t3(A) when is_port(A) or is_port(A) -> 1339: is_port; 1340: t3(A) when is_record(A, apa) or is_record(A, apa) -> 1341: is_record; 1342: t3(A) when is_record(A, apa, 1) or is_record(A, apa, 1) -> 1343: is_record; 1344: t3(A) when is_reference(A) or is_reference(A) -> 1345: is_reference; 1346: t3(A) when is_tuple(A) or is_tuple(A) -> 1347: is_tuple. 1348: ">>, 1349: [nowarn_obsolete_guard], 1350: []}], 1351: ?line [] = run(Config, Ts), 1352: Ts1 = [{guard5, 1353: <<"-record(apa, {}). 1354: t3(A) when record(A, {apa}) -> 1355: foo; 1356: t3(A) when is_record(A, {apa}) -> 1357: foo; 1358: t3(A) when erlang:is_record(A, {apa}) -> 1359: foo; 1360: t3(A) when is_record(A, {apa}, 1) -> 1361: foo; 1362: t3(A) when erlang:is_record(A, {apa}, 1) -> 1363: foo; 1364: t3(A) when is_record(A, apa, []) -> 1365: foo; 1366: t3(A) when erlang:is_record(A, apa, []) -> 1367: foo; 1368: t3(A) when record(A, apa) -> 1369: foo; 1370: t3(A) when is_record(A, apa) -> 1371: foo; 1372: t3(A) when erlang:is_record(A, apa) -> 1373: foo. 1374: ">>, 1375: [warn_unused_vars, nowarn_obsolete_guard], 1376: {errors,[{2,erl_lint,illegal_guard_expr}, 1377: {4,erl_lint,illegal_guard_expr}, 1378: {6,erl_lint,illegal_guard_expr}, 1379: {8,erl_lint,illegal_guard_expr}, 1380: {10,erl_lint,illegal_guard_expr}, 1381: {12,erl_lint,illegal_guard_expr}, 1382: {14,erl_lint,illegal_guard_expr}], 1383: []}}, 1384: {guard6, 1385: <<"-record(apa,{a=a,b=foo:bar()}). 1386: apa() -> 1387: [X || X <- [], #apa{a = a} == {r,X,foo}]; 1388: apa() -> 1389: [X || X <- [], #apa{b = b} == {r,X,foo}]; 1390: apa() -> 1391: [X || X <- [], #ful{a = a} == {r,X,foo}]. 1392: ">>, 1393: [], 1394: {errors,[{7,erl_lint,{undefined_record,ful}}], 1395: []}}, 1396: {guard7, 1397: <<"-record(apa,{}). 1398: t() -> 1399: [X || X <- [1,#apa{},3], (3+is_record(X, apa)) or 1400: (is_record(X, apa)*2)]. 1401: ">>, 1402: [], 1403: []}, 1404: {guard8, 1405: <<"t(A) when erlang:is_foobar(A) -> ok; 1406: t(A) when A ! ok -> ok; 1407: t(A) when A ++ [x] -> ok." 1408: >>, 1409: [], 1410: {errors,[{1,erl_lint,illegal_guard_expr}, 1411: {2,erl_lint,illegal_guard_expr}, 1412: {3,erl_lint,illegal_guard_expr}],[]}} 1413: ], 1414: ?line [] = run(Config, Ts1), 1415: ok. 1416: 1417: otp_4886(doc) -> 1418: "OTP-4886. Calling is_record with given record name."; 1419: otp_4886(suite) -> []; 1420: otp_4886(Config) when is_list(Config) -> 1421: Ts = [{otp_4886, 1422: <<"t() -> 1423: X = {foo}, 1424: is_record(X, foo), 1425: erlang:is_record(X, foo), 1426: {erlang,is_record}(X, foo), 1427: %% Note: is_record/3 does not verify that the record is defined, 1428: %% so the following lines should give no errors. 1429: is_record(X, foo, 1), 1430: erlang:is_record(X, foo, 1), 1431: {erlang,is_record}(X, foo, 1). 1432: ">>, 1433: [], 1434: {errors,[{3,erl_lint,{undefined_record,foo}}, 1435: {4,erl_lint,{undefined_record,foo}}, 1436: {5,erl_lint,{undefined_record,foo}}], 1437: []}}], 1438: ?line [] = run(Config, Ts), 1439: ok. 1440: 1441: otp_4988(doc) -> 1442: "OTP-4988. Error when in-lining non-existent functions."; 1443: otp_4988(suite) -> []; 1444: otp_4988(Config) when is_list(Config) -> 1445: Ts = [{otp_4988, 1446: <<"-compile({inline, [{f,3},{f,4},{f,2},{f,a},{1,foo}]}). 1447: -compile({inline, {g,1}}). 1448: -compile({inline, {g,12}}). 1449: -compile(inline). 1450: -compile({inline_size,100}). 1451: 1452: f(A, B) -> 1453: {g(A), B}. 1454: 1455: g(A) -> 1456: {A}. 1457: ">>, 1458: [], 1459: {errors,[{1,erl_lint,{bad_inline,{1,foo}}}, 1460: {1,erl_lint,{bad_inline,{f,3}}}, 1461: {1,erl_lint,{bad_inline,{f,4}}}, 1462: {1,erl_lint,{bad_inline,{f,a}}}, 1463: {3,erl_lint,{bad_inline,{g,12}}}], 1464: []}}], 1465: ?line [] = run(Config, Ts), 1466: ok. 1467: 1468: otp_5091(doc) -> 1469: "OTP-5091. Patterns and the bit syntax: invalid warnings."; 1470: otp_5091(suite) -> []; 1471: otp_5091(Config) when is_list(Config) -> 1472: Ts = [{otp_5091_1, 1473: <<"t() -> 1474: [{Type, Value} || <<Type:16, _Len:16, 1475: Value:_Len/binary>> <- []]. 1476: ">>, 1477: [], 1478: []}, 1479: {otp_5091_2, 1480: <<"t() -> 1481: %% This one has always been handled OK: 1482: <<Type:16, _Len:16, 1483: Value:_Len/binary>> = <<18:16, 9:16, \"123456789\">>, 1484: {Type, Value}. 1485: ">>, 1486: [], 1487: []}, 1488: {otp_5091_3, 1489: <<"t() -> 1490: fun(<<Type:16, _Len:16, Value:_Len/binary>>) -> 1491: {Type, Value} 1492: end. 1493: ">>, 1494: [], 1495: []}, 1496: {otp_5091_4, 1497: <<"t() -> 1498: L = 8, 1499: F = fun(<<A:L,B:A>>) -> B end, 1500: F(<<16:8, 7:16>>). 1501: ">>, 1502: [], 1503: []}, 1504: {otp_5091_5, 1505: <<"t() -> 1506: L = 8, 1507: F = fun(<<L: % L shadowed. 1508: L, 1509: B: 1510: L>>) -> B end, 1511: F(<<16:8, 7:16>>). 1512: ">>, 1513: [], 1514: {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}}, 1515: {otp_5091_6, 1516: <<"t(A) -> 1517: (fun(<<L:16,M:L,N:M>>) -> ok end)(A). 1518: ">>, 1519: [], 1520: {warnings,[{2,erl_lint,{unused_var,'N'}}]}}, 1521: {otp_5091_7, 1522: <<"t() -> 1523: U = 8, 1524: (fun(<<U: % U shadowed. 1525: U>>) -> U end)(<<32:8>>). 1526: ">>, 1527: [], 1528: {warnings,[{3,erl_lint,{shadowed_var,'U','fun'}}]}}, 1529: {otp_5091_8, 1530: <<"t() -> 1531: [X || <<A:8, 1532: B:A>> <- [], 1533: <<X:8>> <- [B]]. 1534: ">>, 1535: [], 1536: []}, 1537: {otp_5091_9, 1538: <<"t() -> 1539: L = 8, 1540: F = fun(<<L: % Shadow. 1541: L, 1542: L: 1543: L, 1544: L: 1545: L 1546: >>) -> 1547: L 1548: end, 1549: F(<<16:8, 8:16, 32:8>>). 1550: ">>, 1551: [], 1552: {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}}, 1553: {otp_5091_10, 1554: <<"t() -> 1555: L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B. 1556: ">>, 1557: [], 1558: []}, 1559: {otp_5091_11, 1560: <<"t() -> 1561: fun(<<L:16,L:L,L:L>>) -> ok end. 1562: ">>, 1563: [], 1564: []}, 1565: {otp_5091_12, 1566: <<"t([A,B]) -> 1567: fun(<<A:B>>, % A shadowed and unused 1568: <<Q:A>>) -> foo % Q unused. 'outer' A is used. 1569: end. 1570: ">>, 1571: [], 1572: {warnings,[{2,erl_lint,{unused_var,'A'}}, 1573: {2,erl_lint,{shadowed_var,'A','fun'}}, 1574: {3,erl_lint,{unused_var,'Q'}}]}}, 1575: {otp_5091_13, 1576: <<"t([A,B]) -> % A unused, B unused 1577: fun({A,B}, % A shadowed, B unused, B shadowed 1578: {Q,A}) -> foo % Q unused. 'inner' A is used 1579: end. 1580: ">>, 1581: [], 1582: {warnings,[{1,erl_lint,{unused_var,'A'}}, 1583: {1,erl_lint,{unused_var,'B'}}, 1584: {2,erl_lint,{unused_var,'B'}}, 1585: {2,erl_lint,{shadowed_var,'A','fun'}}, 1586: {2,erl_lint,{shadowed_var,'B','fun'}}, 1587: {3,erl_lint,{unused_var,'Q'}}]}}, 1588: {otp_5091_14, 1589: <<"t() -> 1590: A = 4, 1591: fun(<<A: % shadowed, unused 1592: A>>) -> 2 end. 1593: ">>, 1594: [], 1595: {warnings,[{3,erl_lint,{unused_var,'A'}}, 1596: {3,erl_lint,{shadowed_var,'A','fun'}}]}}, 1597: {otp_5091_15, 1598: <<"t() -> 1599: A = 4, % unused 1600: fun(<<A:8, % shadowed 1601: 16:A>>) -> 2 end. 1602: ">>, 1603: [], 1604: {warnings,[{2,erl_lint,{unused_var,'A'}}, 1605: {3,erl_lint,{shadowed_var,'A','fun'}}]}}, 1606: {otp_5091_16, 1607: <<"t() -> 1608: A = 4, 1609: fun(<<8:A, % 1610: A:8>>) -> 7 end. % shadowed, unused 1611: ">>, 1612: [], 1613: {warnings,[{4,erl_lint,{unused_var,'A'}}, 1614: {4,erl_lint,{shadowed_var,'A','fun'}}]}}, 1615: {otp_5091_17, 1616: <<"t() -> 1617: L = 16, 1618: fun(<<L: % shadow 1619: L>>, % 'outer' L 1620: <<L: % shadow and match 1621: L>>) -> % 'outer' L 1622: a 1623: end. 1624: ">>, 1625: [], 1626: {warnings,[{3,erl_lint,{shadowed_var,'L','fun'}}]}}, 1627: {otp_5091_18, 1628: <<"t() -> 1629: L = 4, % L unused 1630: fun({L, % L shadowed 1631: L}, 1632: {L, 1633: L}) -> 1634: a 1635: end. 1636: ">>, 1637: [], 1638: {warnings,[{2,erl_lint,{unused_var,'L'}}, 1639: {3,erl_lint,{shadowed_var,'L','fun'}}]}}, 1640: {otp_5091_19, 1641: <<"t() -> 1642: L = 4, 1643: [L || <<L: % shadowed 1644: L, 1645: L: 1646: L>> <- []]. 1647: ">>, 1648: [], 1649: {warnings,[{3,erl_lint,{shadowed_var,'L',generate}}]}}, 1650: {otp_5091_20, 1651: <<"t() -> 1652: L = 4, % L unused. 1653: [1 || L <- []]. % L unused, L shadowed. 1654: ">>, 1655: [], 1656: {warnings,[{2,erl_lint,{unused_var,'L'}}, 1657: {3,erl_lint,{unused_var,'L'}}, 1658: {3,erl_lint,{shadowed_var,'L',generate}}]}}, 1659: {otp_5091_21, 1660: <<"t() -> 1661: L = 4, 1662: [1 || L <- [L]]. % L shadowed. L unused. 1663: ">>, 1664: [], 1665: {warnings,[{3,erl_lint,{unused_var,'L'}}, 1666: {3,erl_lint,{shadowed_var,'L',generate}}]}}, 1667: {otp_5091_22, 1668: <<"t() -> 1669: L = 4, % unused 1670: fun(L) -> L end. % shadowed 1671: ">>, 1672: [], 1673: {warnings,[{2,erl_lint,{unused_var,'L'}}, 1674: {3,erl_lint,{shadowed_var,'L','fun'}}]}}, 1675: {otp_5091_23, 1676: <<"t([A,A]) -> a.">>, [], []}, 1677: {otp_5091_24, 1678: <<"t({A,A}) -> a.">>, [], []}, 1679: {otp_5091_25, 1680: <<"-record(r, {f1,f2}). 1681: t(#r{f1 = A, f2 = A}) -> a.">>, [], []}], 1682: 1683: ?line [] = run(Config, Ts), 1684: ok. 1685: 1686: otp_5276(doc) -> 1687: "OTP-5276. Check the 'deprecated' attributed."; 1688: otp_5276(suite) -> []; 1689: otp_5276(Config) when is_list(Config) -> 1690: Ts = [{otp_5276_1, 1691: <<"-deprecated([{frutt,0,next_version}]). 1692: -deprecated([{does_not_exist,1}]). 1693: -deprecated('foo bar'). 1694: -deprecated(module). 1695: -deprecated([{f,'_'}]). 1696: -deprecated([{t,0}]). 1697: -deprecated([{t,'_',eventually}]). 1698: -deprecated([{'_','_',never}]). 1699: -deprecated([{{badly,formed},1}]). 1700: -deprecated([{'_','_',next_major_release}]). 1701: -deprecated([{atom_to_list,1}]). 1702: -export([t/0]). 1703: frutt() -> ok. 1704: t() -> ok. 1705: ">>, 1706: {[]}, 1707: {error,[{1,erl_lint,{bad_deprecated,{frutt,0}}}, 1708: {2,erl_lint,{bad_deprecated,{does_not_exist,1}}}, 1709: {3,erl_lint,{invalid_deprecated,'foo bar'}}, 1710: {5,erl_lint,{bad_deprecated,{f,'_'}}}, 1711: {8,erl_lint,{invalid_deprecated,{'_','_',never}}}, 1712: {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}}, 1713: {11,erl_lint,{bad_deprecated,{atom_to_list,1}}}], 1714: [{13,erl_lint,{unused_function,{frutt,0}}}]}}], 1715: ?line [] = run(Config, Ts), 1716: ok. 1717: 1718: otp_5917(doc) -> 1719: "OTP-5917. Check the 'deprecated' attributed."; 1720: otp_5917(suite) -> []; 1721: otp_5917(Config) when is_list(Config) -> 1722: Ts = [{otp_5917_1, 1723: <<"-compile(export_all). 1724: 1725: -deprecated({t,0}). 1726: 1727: t() -> 1728: foo. 1729: ">>, 1730: {[]}, 1731: []}], 1732: ?line [] = run(Config, Ts), 1733: ok. 1734: 1735: otp_6585(doc) -> 1736: "OTP-6585. Check the deprecated guards list/1, pid/1, ...."; 1737: otp_6585(suite) -> []; 1738: otp_6585(Config) when is_list(Config) -> 1739: Ts = [{otp_6585_1, 1740: <<"-compile(export_all). 1741: 1742: -record(r, {}). 1743: 1744: f(A) when list(A) -> list; 1745: f(R) when record(R, r) -> rec; 1746: f(P) when pid(P) -> pid. 1747: 1748: t() -> 1749: f([]). 1750: ">>, 1751: [warn_obsolete_guard], 1752: {warnings,[{5,erl_lint,{obsolete_guard,{list,1}}}, 1753: {6,erl_lint,{obsolete_guard,{record,2}}}, 1754: {7,erl_lint,{obsolete_guard,{pid,1}}}]}}], 1755: ?line [] = run(Config, Ts), 1756: ok. 1757: 1758: otp_5338(doc) -> 1759: "OTP-5338. Bad warning in record initialization."; 1760: otp_5338(suite) -> []; 1761: otp_5338(Config) when is_list(Config) -> 1762: %% OTP-5878: variables like X are no longer allowed in initialisations 1763: Ts = [{otp_5338, 1764: <<"-record(c, {a = <<X:7/binary-unit:8>>}). 1765: t() -> 1766: X = <<\"hejsans\">>, 1767: #c{}. 1768: ">>, 1769: [], 1770: {error,[{1,erl_lint,{unbound_var,'X'}}], 1771: [{3,erl_lint,{unused_var,'X'}}]}}], 1772: ?line [] = run(Config, Ts), 1773: ok. 1774: 1775: otp_5362(doc) -> 1776: "OTP-5362. deprecated_function, " 1777: "{nowarn_unused_funtion,FAs}, 'better' line numbers."; 1778: otp_5362(suite) -> []; 1779: otp_5362(Config) when is_list(Config) -> 1780: Ts = [{otp_5362_1, 1781: <<"-include_lib(\"stdlib/include/qlc.hrl\"). 1782: 1783: -file(?FILE, 1000). 1784: 1785: t() -> 1786: qlc:q([X || X <- [], 1787: begin A = 3, true end]). 1788: ">>, 1789: {[warn_unused_vars]}, 1790: {warnings,[{1002,erl_lint,{unused_function,{t,0}}}, 1791: {1004,erl_lint,{unused_var,'A'}}]}}, 1792: 1793: {otp_5362_2, 1794: <<"-export([inline/0]). 1795: 1796: -import(lists, [a/1,b/1]). % b/1 is not used 1797: 1798: -compile([{inline,{inl,7}}]). % undefined 1799: -compile([{inline,[{inl,17}]}]). % undefined 1800: -compile([{inline,{inl,1}}]). % OK 1801: 1802: foop() -> % unused function 1803: a([]), % used import, OK 1804: fipp(). % undefined 1805: 1806: inline() -> 1807: inl(foo). 1808: 1809: inl(_) -> 1810: true. 1811: 1812: not_used() -> % unused function 1813: true. 1814: 1815: -compile({nowarn_unused_function,[{and_not_used,2}]}). % unknown 1816: and_not_used(_) -> % unused function 1817: foo. 1818: 1819: -compile({nowarn_unused_function,{unused_function,2}}). 1820: unused_function(_, _) -> 1821: ok. 1822: ">>, 1823: {[warn_unused_vars, warn_unused_import]}, 1824: {error,[{5,erl_lint,{bad_inline,{inl,7}}}, 1825: {6,erl_lint,{bad_inline,{inl,17}}}, 1826: {11,erl_lint,{undefined_function,{fipp,0}}}, 1827: {22,erl_lint,{bad_nowarn_unused_function,{and_not_used,2}}}], 1828: [{3,erl_lint,{unused_import,{{b,1},lists}}}, 1829: {9,erl_lint,{unused_function,{foop,0}}}, 1830: {19,erl_lint,{unused_function,{not_used,0}}}, 1831: {23,erl_lint,{unused_function,{and_not_used,1}}}]}}, 1832: 1833: {otp_5362_3, 1834: <<"-record(a, {x, 1835: x}). 1836: -record(a, {x, 1837: X}). % erl_parse 1838: -record(a, [x, 1839: x]). % erl_parse 1840: -record(ok, {a,b}). 1841: 1842: -record(r, {a = #ok{}, 1843: b = (#ok{})#ok.a}). 1844: 1845: t() -> 1846: {#a{}, 1847: #nix{}, 1848: #ok{nix = []}, 1849: #ok{Var = 4}, 1850: #r{} 1851: }. 1852: ">>, 1853: {[nowarn_unused_function]}, 1854: {errors2, [{4,erl_parse,"bad record field"}, 1855: {5,erl_parse,"bad record declaration"}], 1856: [{2,erl_lint,{redefine_field,a,x}}, 1857: {14,erl_lint,{undefined_record,nix}}, 1858: {15,erl_lint,{undefined_field,ok,nix}}, 1859: {16,erl_lint,{field_name_is_variable,ok,'Var'}}]}}, 1860: 1861: %% Nowarn_bif_clash has changed behaviour as local functions 1862: %% nowdays supersede auto-imported BIFs, why nowarn_bif_clash in itself generates an error 1863: %% (OTP-8579) /PaN 1864: {otp_5362_4, 1865: <<"-compile(nowarn_deprecated_function). 1866: -compile(nowarn_bif_clash). 1867: spawn(A) -> 1868: erlang:hash(A, 3000), 1869: spawn(A). 1870: ">>, 1871: {[nowarn_unused_function, 1872: warn_deprecated_function, 1873: warn_bif_clash]}, 1874: {error, 1875: [{5,erl_lint,{call_to_redefined_old_bif,{spawn,1}}}], 1876: [{4,erl_lint,{deprecated,{erlang,hash,2},{erlang,phash2,2}, 1877: "in a future release"}}]}}, 1878: 1879: {otp_5362_5, 1880: <<"-compile(nowarn_deprecated_function). 1881: -compile(nowarn_bif_clash). 1882: spawn(A) -> 1883: erlang:hash(A, 3000), 1884: spawn(A). 1885: ">>, 1886: {[nowarn_unused_function]}, 1887: {errors, 1888: [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}}, 1889: 1890: %% The special nowarn_X are not affected by general warn_X. 1891: {otp_5362_6, 1892: <<"-compile({nowarn_deprecated_function,{erlang,hash,2}}). 1893: -compile({nowarn_bif_clash,{spawn,1}}). 1894: spawn(A) -> 1895: erlang:hash(A, 3000), 1896: spawn(A). 1897: ">>, 1898: {[nowarn_unused_function, 1899: warn_deprecated_function, 1900: warn_bif_clash]}, 1901: {errors, 1902: [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}}, 1903: 1904: {otp_5362_7, 1905: <<"-export([spawn/1]). 1906: -compile({nowarn_deprecated_function,{erlang,hash,2}}). 1907: -compile({nowarn_bif_clash,{spawn,1}}). 1908: -compile({nowarn_bif_clash,{spawn,2}}). % bad 1909: -compile([{nowarn_deprecated_function, 1910: [{erlang,hash,-1},{3,hash,-1}]}, % 2 bad 1911: {nowarn_deprecated_function, {{a,b,c},hash,-1}}]). % bad 1912: spawn(A) -> 1913: erlang:hash(A, 3000), 1914: spawn(A). 1915: ">>, 1916: {[nowarn_unused_function]}, 1917: {error,[{3,erl_lint,disallowed_nowarn_bif_clash}, 1918: {4,erl_lint,disallowed_nowarn_bif_clash}, 1919: {4,erl_lint,{bad_nowarn_bif_clash,{spawn,2}}}], 1920: [{5,erl_lint,{bad_nowarn_deprecated_function,{3,hash,-1}}}, 1921: {5,erl_lint,{bad_nowarn_deprecated_function,{erlang,hash,-1}}}, 1922: {5,erl_lint,{bad_nowarn_deprecated_function,{{a,b,c},hash,-1}}}]} 1923: }, 1924: 1925: {otp_5362_8, 1926: <<"-export([spawn/1]). 1927: -compile(warn_deprecated_function). 1928: -compile(warn_bif_clash). 1929: spawn(A) -> 1930: erlang:hash(A, 3000), 1931: spawn(A). 1932: ">>, 1933: {[nowarn_unused_function, 1934: {nowarn_bif_clash,{spawn,1}}]}, % has no effect 1935: {warnings, 1936: [{5,erl_lint,{deprecated,{erlang,hash,2},{erlang,phash2,2}, 1937: "in a future release"}}]}}, 1938: 1939: {otp_5362_9, 1940: <<"-include_lib(\"stdlib/include/qlc.hrl\"). 1941: -record(a, {x = qlc:q([{X,Y} || {X} <- [],{Y} <- [],X =:= Y])}). 1942: -export([t/0]). 1943: t() -> #a{}. 1944: ">>, 1945: {[]}, 1946: []}, 1947: 1948: {otp_5362_10, 1949: <<"-compile({nowarn_deprecated_function,{erlang,hash,2}}). 1950: -compile({nowarn_bif_clash,{spawn,1}}). 1951: -import(x,[spawn/1]). 1952: spin(A) -> 1953: erlang:hash(A, 3000), 1954: spawn(A). 1955: ">>, 1956: {[nowarn_unused_function, 1957: warn_deprecated_function, 1958: warn_bif_clash]}, 1959: {errors, 1960: [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}}, 1961: 1962: {call_deprecated_function, 1963: <<"t(X) -> erlang:hash(X, 2000).">>, 1964: [], 1965: {warnings, 1966: [{1,erl_lint,{deprecated,{erlang,hash,2}, 1967: {erlang,phash2,2},"in a future release"}}]}}, 1968: 1969: {call_removed_function, 1970: <<"t(X) -> regexp:match(X).">>, 1971: [], 1972: {warnings, 1973: [{1,erl_lint,{removed,{regexp,match,1}, 1974: "removed in R15; use the re module instead"}}]}} 1975: 1976: ], 1977: 1978: ?line [] = run(Config, Ts), 1979: ok. 1980: 1981: otp_5371(doc) -> 1982: "OTP-5371. Aliases for bit syntax expressions are no longer allowed."; 1983: otp_5371(suite) -> []; 1984: otp_5371(Config) when is_list(Config) -> 1985: Ts = [{otp_5371_1, 1986: <<"t(<<A:8>> = <<B:8>>) -> 1987: {A,B}. 1988: ">>, 1989: [], 1990: {errors,[{1,erl_lint,illegal_bin_pattern}],[]}}, 1991: {otp_5371_2, 1992: <<"x([<<A:8>>] = [<<B:8>>]) -> 1993: {A,B}. 1994: y({a,<<A:8>>} = {b,<<B:8>>}) -> 1995: {A,B}. 1996: ">>, 1997: [], 1998: {errors,[{1,erl_lint,illegal_bin_pattern}, 1999: {3,erl_lint,illegal_bin_pattern}],[]}}, 2000: {otp_5371_3, 2001: <<"-record(foo, {a,b,c}). 2002: -record(bar, {x,y,z}). 2003: -record(buzz, {x,y}). 2004: a(#foo{a = <<X:8>>} = #bar{x = <<Y:8>>}) -> 2005: {X,Y}. 2006: b(#foo{b = <<X:8>>} = #foo{b = <<Y:4,Z:4>>}) -> 2007: {X,Y,Z}. 2008: c(#foo{a = <<X:8>>} = #buzz{x = <<Y:8>>}) -> 2009: {X,Y}. 2010: d(#foo{a=x,b = <<X:8>>} = #buzz{y = <<Y:8>>}) -> 2011: {X,Y}. 2012: e(#foo{a=x,b = <<X:8>>} = #buzz{x=glurf,y = <<Y:8>>}) -> 2013: {X,Y}. 2014: ">>, 2015: [], 2016: {errors,[{4,erl_lint,illegal_bin_pattern}, 2017: {6,erl_lint,illegal_bin_pattern}, 2018: {8,erl_lint,illegal_bin_pattern}, 2019: {10,erl_lint,illegal_bin_pattern}, 2020: {12,erl_lint,illegal_bin_pattern}],[]}}, 2021: {otp_5371_4, 2022: <<"-record(foo, {a,b,c}). 2023: -record(bar, {x,y,z}). 2024: -record(buzz, {x,y}). 2025: a(#foo{a = <<X:8>>,b=x} = #foo{b = <<Y:8>>}) -> 2026: {X,Y}. 2027: b(#foo{a = <<X:8>>} = #bar{y = <<Y:4,Z:4>>}) -> 2028: {X,Y,Z}. 2029: c(#foo{a = <<X:8>>} = #buzz{y = <<Y:8>>}) -> 2030: {X,Y}. 2031: ">>, 2032: [], 2033: {warnings,[{4,v3_core,nomatch}, 2034: {6,v3_core,nomatch}, 2035: {8,v3_core,nomatch}]}} 2036: ], 2037: ?line [] = run(Config, Ts), 2038: ok. 2039: 2040: otp_7227(doc) -> "OTP_7227. Some aliases for bit syntax expressions were still allowed."; 2041: otp_7227(Config) when is_list(Config) -> 2042: Ts = [{otp_7227_1, 2043: <<"t([<<A:8>> = {C,D} = <<B:8>>]) -> 2044: {A,B,C,D}. 2045: ">>, 2046: [], 2047: {errors,[{1,erl_lint,illegal_bin_pattern}],[]}}, 2048: {otp_7227_2, 2049: <<"t([(<<A:8>> = {C,D}) = <<B:8>>]) -> 2050: {A,B,C,D}. 2051: ">>, 2052: [], 2053: {errors,[{1,erl_lint,illegal_bin_pattern}],[]}}, 2054: {otp_7227_3, 2055: <<"t([(<<A:8>> = {C,D}) = (<<B:8>> = <<C:8>>)]) -> 2056: {A,B,C,D}. 2057: ">>, 2058: [], 2059: {errors,[{1,erl_lint,illegal_bin_pattern}, 2060: {1,erl_lint,illegal_bin_pattern}, 2061: {1,erl_lint,illegal_bin_pattern}],[]}}, 2062: {otp_7227_4, 2063: <<"t(Val) -> 2064: <<A:8>> = <<B:8>> = Val, 2065: {A,B}. 2066: ">>, 2067: [], 2068: {errors,[{2,erl_lint,illegal_bin_pattern}],[]}}, 2069: {otp_7227_5, 2070: <<"t(Val) -> 2071: <<A:8>> = X = <<B:8>> = Val, 2072: {A,B,X}. 2073: ">>, 2074: [], 2075: {errors,[{2,erl_lint,illegal_bin_pattern}],[]}}, 2076: {otp_7227_6, 2077: <<"t(X, Y) -> 2078: <<A:8>> = <<X:4,Y:4>>, 2079: A. 2080: ">>, 2081: [], 2082: []}, 2083: {otp_7227_7, 2084: <<"t(Val) -> 2085: (<<A:8>> = X) = (<<B:8>> = <<A:4,B:4>>) = Val, 2086: {A,B,X}. 2087: ">>, 2088: [], 2089: {errors,[{2,erl_lint,illegal_bin_pattern}, 2090: {2,erl_lint,illegal_bin_pattern}, 2091: {2,erl_lint,illegal_bin_pattern}],[]}}, 2092: {otp_7227_8, 2093: <<"t(Val) -> 2094: (<<A:8>> = X) = (Y = <<B:8>>) = Val, 2095: {A,B,X,Y}. 2096: ">>, 2097: [], 2098: {errors,[{2,erl_lint,illegal_bin_pattern}],[]}}, 2099: {otp_7227_9, 2100: <<"t(Val) -> 2101: (Z = <<A:8>> = X) = (Y = <<B:8>> = W) = Val, 2102: {A,B,X,Y,Z,W}. 2103: ">>, 2104: [], 2105: {errors,[{2,erl_lint,illegal_bin_pattern}],[]}} 2106: ], 2107: ?line [] = run(Config, Ts), 2108: ok. 2109: 2110: otp_5494(doc) -> 2111: "OTP-5494. Warnings for functions exported more than once."; 2112: otp_5494(suite) -> []; 2113: otp_5494(Config) when is_list(Config) -> 2114: Ts = [{otp_5494_1, 2115: <<"-export([t/0]). 2116: -export([t/0]). 2117: t() -> a. 2118: ">>, 2119: [], 2120: {warnings,[{2,erl_lint,{duplicated_export,{t,0}}}]}}], 2121: ?line [] = run(Config, Ts), 2122: ok. 2123: 2124: otp_5644(doc) -> 2125: "OTP-5644. M:F/A in record initialization."; 2126: otp_5644(suite) -> []; 2127: otp_5644(Config) when is_list(Config) -> 2128: %% This test is a no-op. Although {function,mfa,i,1} was 2129: %% transformed into {function,Line,i,1} by copy_expr, the module 2130: %% was never checked (Line is the line number). 2131: %% (OTP-5878: somewhat modified.) 2132: Ts = [{otp_5644, 2133: <<"-record(c, {a = fun ?MODULE:i/1(17)}). 2134: t() -> 2135: #c{}. 2136: 2137: i(X) -> 2138: X. 2139: ">>, 2140: [], 2141: []}], 2142: ?line [] = run(Config, Ts), 2143: ok. 2144: 2145: otp_5878(doc) -> 2146: "OTP-5878. Record declaration: forward references, introduced variables."; 2147: otp_5878(suite) -> []; 2148: otp_5878(Config) when is_list(Config) -> 2149: Ts = [{otp_5878_10, 2150: <<"-record(rec1, {a = #rec2{}}). 2151: -record(rec2, {a = #rec1{}}). 2152: t() ->#rec1{}. 2153: ">>, 2154: [warn_unused_record], 2155: {error,[{1,erl_lint,{undefined_record,rec2}}], 2156: [{2,erl_lint,{unused_record,rec2}}]}}, 2157: 2158: {otp_5878_20, 2159: <<"-record(r1, {a = begin A = 4, {A,B} end}). % B unbound 2160: -record(r2, {e = begin A = 3, #r1{} end}). 2161: t() -> #r2{}. 2162: ">>, 2163: [warn_unused_record], 2164: {error,[{1,erl_lint,{unbound_var,'B'}}, 2165: {1,erl_lint,{variable_in_record_def,'A'}}, 2166: {2,erl_lint,{variable_in_record_def,'A'}}], 2167: [{1,erl_lint,{unused_record,r1}}]}}, 2168: 2169: {otp_5878_30, 2170: <<"-record(r1, {t = case foo of _ -> 3 end}). 2171: -record(r2, {a = case foo of A -> A; _ -> 3 end}). 2172: -record(r3, {a = case foo of A -> A end}). 2173: t() -> {#r1{},#r2{},#r3{}}. 2174: ">>, 2175: [warn_unused_record], 2176: {errors,[{2,erl_lint,{variable_in_record_def,'A'}}, 2177: {3,erl_lint,{variable_in_record_def,'A'}}], 2178: []}}, 2179: 2180: {otp_5878_40, 2181: <<"-record(r1, {foo = A}). % A unbound 2182: -record(r2, {a = fun(X) -> X end(3)}). 2183: -record(r3, {a = [X || X <- [1,2,3]]}). 2184: t() -> {#r1{},#r2{},#r3{}}. 2185: ">>, 2186: [warn_unused_record], 2187: {errors,[{1,erl_lint,{unbound_var,'A'}}],[]}}, 2188: 2189: {otp_5878_50, 2190: <<"-record(r1, {a = {A, % A unbound 2191: A}}). % A unbound 2192: -record(r2, {a = begin case foo of 2193: A -> A 2194: end, 2195: A 2196: end}). 2197: -record(r3, {a = fun(X) -> 2198: case foo of 2199: A -> A 2200: end 2201: end 2202: }). 2203: -record(r4, {a = case foo of 2204: foo -> 2205: case foo of 2206: A -> A 2207: end; 2208: _ -> 2209: bar 2210: end}). 2211: t() -> {#r1{},#r2{},#r3{},#r4{}}. 2212: ">>, 2213: [warn_unused_record], 2214: {error,[{1,erl_lint,{unbound_var,'A'}}, 2215: {2,erl_lint,{unbound_var,'A'}}, 2216: {4,erl_lint,{variable_in_record_def,'A'}}, 2217: {17,erl_lint,{variable_in_record_def,'A'}}], 2218: [{8,erl_lint,{unused_var,'X'}}]}}, 2219: 2220: {otp_5878_60, 2221: <<"-record(r1, {a = fun(NotShadowing) -> NotShadowing end}). 2222: t() -> 2223: NotShadowing = 17, 2224: {#r1{}, NotShadowing}. 2225: ">>, 2226: [warn_unused_record], 2227: []}, 2228: 2229: {otp_5878_70, 2230: <<"-record(r1, {a = fun(<<X:8>>) -> X end, 2231: b = case <<17:8>> of 2232: <<_:Y>> -> Y; 2233: <<Y:8>> -> 2234: Y 2235: end}). 2236: t() -> #r1{}. 2237: ">>, 2238: [warn_unused_record], 2239: {errors,[{3,erl_lint,{unbound_var,'Y'}}, 2240: {4,erl_lint,{variable_in_record_def,'Y'}}], 2241: []}}, 2242: 2243: {otp_5878_80, 2244: <<"-record(r, {a = [X || {A,Y} <- [{1,2},V={3,4}], 2245: begin Z = [1,2,3], true end, 2246: X <- Z ++ [A,Y]]}). 2247: t() ->#r{}. 2248: ">>, 2249: [warn_unused_record], 2250: {warnings,[{1,erl_lint,{unused_var,'V'}}]}}, 2251: 2252: {otp_5878_90, 2253: <<"-record(r, {a = foo()}). % unused 2254: 2255: t() -> ok. 2256: ">>, 2257: [warn_unused_record], 2258: {error,[{1,erl_lint,{undefined_function,{foo,0}}}], 2259: [{1,erl_lint,{unused_record,r}}]}} 2260: 2261: ], 2262: ?line [] = run(Config, Ts), 2263: 2264: Abstr = <<"-module(lint_test, [A, B]). 2265: ">>, 2266: {errors,[{1,erl_lint,pmod_unsupported}],[]} = 2267: run_test2(Config, Abstr, [warn_unused_record]), 2268: 2269: QLC1 = <<"-module(lint_test). 2270: -include_lib(\"stdlib/include/qlc.hrl\"). 2271: -export([t/0]). 2272: -record(r1, {a = qlc:e(qlc:q([X || X <- [1,2,3]]))}). 2273: -record(r2, {a = qlc:q([X || X <- [1,2,3]])}). 2274: -record(r3, {a = qlc:q([X || {A,Y} <- [{1,2},V={3,4}], 2275: begin Z = [1,2,3], true end, 2276: X <- Z ++ [A,Y]])}). 2277: t() -> {#r1{},#r2{},#r3{}}. 2278: ">>, 2279: ?line {error,[{8,qlc,{used_generator_variable,'A'}}, 2280: {8,qlc,{used_generator_variable,'Y'}}, 2281: {8,qlc,{used_generator_variable,'Z'}}], 2282: [{6,erl_lint,{unused_var,'V'}}]} = 2283: run_test2(Config, QLC1, [warn_unused_record]), 2284: 2285: Ill1 = <<"-module(lint_test). 2286: -export([t/0]). 2287: -record(r, {a = true}). 2288: -record(r1, {a,b}). 2289: -record(r2, {a = #r1{a = true}}). 2290: -record(r3, {a = A}). % A is unbound 2291: -record(r4, {a = dict:new()}). 2292: 2293: t() -> 2294: case x() of 2295: _ when (#r{})#r.a -> 2296: a; 2297: _ when (#r4{})#r.a -> % illegal 2298: b; 2299: _ when (#r3{q = 5})#r.a -> % no warning for unbound A 2300: q; 2301: _ when (#r{q = 5})#r.a -> 2302: a; 2303: _ when (((#r{a = #r2{}})#r.a)#r2.a)#r1.a -> 2304: b; 2305: _ when #r{a = dict:new()} -> % illegal 2306: c; 2307: _ when l() > 3 -> % illegal, does not use l/0... 2308: d; 2309: _ -> 2310: w 2311: end. 2312: 2313: l() -> 2314: foo. 2315: 2316: x() -> 2317: bar. 2318: ">>, 2319: 2320: ?line {errors,[{6,erl_lint,{unbound_var,'A'}}, 2321: {13,erl_lint,illegal_guard_expr}, 2322: {15,erl_lint,{undefined_field,r3,q}}, 2323: {17,erl_lint,{undefined_field,r,q}}, 2324: {21,erl_lint,illegal_guard_expr}, 2325: {23,erl_lint,{illegal_guard_local_call,{l,0}}}], 2326: []} = 2327: run_test2(Config, Ill1, [warn_unused_record]), 2328: 2329: Ill2 = <<"-module(lint_test). 2330: -export([t/0]). 2331: t() -> 2332: case x() of 2333: _ when l() 2334: or 2335: l() -> 2336: foo 2337: end. 2338: ">>, 2339: ?line {errors,[{4,erl_lint,{undefined_function,{x,0}}}, 2340: {5,erl_lint,illegal_guard_expr}, 2341: {7,erl_lint,illegal_guard_expr}], 2342: []} = 2343: run_test2(Config, Ill2, [warn_unused_record]), 2344: 2345: Ill3 = <<"t() -> ok.">>, 2346: ?line {errors,[{1,erl_lint,undefined_module}],[]} = 2347: run_test2(Config, Ill3, [warn_unused_record]), 2348: 2349: Usage1 = <<"-module(lint_test). 2350: -export([t/0]). 2351: -record(u1, {a}). 2352: -record(u2, {a = #u1{}}). 2353: -record(u3, {a}). % unused 2354: -record(u4, {a = #u3{}}). % unused 2355: 2356: t() -> 2357: {#u2{}}. 2358: ">>, 2359: ?line {warnings,[{5,erl_lint,{unused_record,u3}}, 2360: {6,erl_lint,{unused_record,u4}}]} = 2361: run_test2(Config, Usage1, [warn_unused_record]), 2362: 2363: Usage2 = <<"-module(lint_test). 2364: -export([t/0]). 2365: -record(u1, {a}). 2366: -record(u2, {a = #u1{}}). 2367: -file(\"some_file.hrl\", 1). 2368: -record(u3, {a}). % unused, but on other file 2369: -record(u4, {a = #u3{}}). % -\"- 2370: 2371: t() -> 2372: {#u2{}}. 2373: ">>, 2374: ?line [] = run_test2(Config, Usage2, [warn_unused_record]), 2375: 2376: %% This a completely different story... 2377: %% The linter checks if qlc.hrl hasn't been included 2378: QLC2 = <<"-module(lint_test). 2379: -import(qlc, [q/2]). 2380: -export([t/0]). 2381: 2382: t() -> 2383: H1 = qlc:q([X || X <- [1,2]]), 2384: H2 = qlc:q([X || X <- [1,2]], []), 2385: H3 = q([X || X <- [1,2]], []), 2386: {H1,H2,H3}. 2387: ">>, 2388: ?line {warnings,[{6,erl_lint,{missing_qlc_hrl,1}}, 2389: {7,erl_lint,{missing_qlc_hrl,2}}, 2390: {8,erl_lint,{missing_qlc_hrl,2}}]} = 2391: run_test2(Config, QLC2, [warn_unused_record]), 2392: 2393: %% Records that are used by types are not unused. 2394: %% (Thanks to Fredrik Thulin and Kostis Sagonas.) 2395: UsedByType = <<"-module(t). 2396: -export([foo/1]). 2397: -record(sipurl, {host :: string()}). 2398: -record(keylist, {list = [] :: [_]}). 2399: -type sip_headers() :: #keylist{}. 2400: -record(request, {uri :: #sipurl{}, header :: sip_headers()}). 2401: 2402: foo(#request{}) -> ok. 2403: ">>, 2404: ?line [] = run_test2(Config, UsedByType, [warn_unused_record]), 2405: 2406: ok. 2407: 2408: otp_6885(doc) -> 2409: "OTP-6885. Binary fields in bit syntax matching is now only allowed at the end."; 2410: otp_6885(suite) -> []; 2411: otp_6885(Config) when is_list(Config) -> 2412: Ts = <<"-module(otp_6885). 2413: -export([t/1]). 2414: t(<<_/binary,I>>) -> I; 2415: t(<<X/binary,I:X>>) -> I; 2416: t(<<B/binary,T/binary>>) -> {B,T}. 2417: 2418: build(A, B) -> 2419: <<A/binary,B/binary>>. 2420: 2421: foo(<<\"abc\"/binary>>) -> 2422: ok; 2423: foo(<<\"abc\":13/integer>>) -> 2424: ok; 2425: foo(<<\"abc\"/float>>) -> 2426: ok; 2427: foo(<<\"abc\":19>>) -> 2428: ok; 2429: foo(<<\"abc\"/utf8>>) -> 2430: ok; 2431: foo(<<\"abc\"/utf16>>) -> 2432: ok; 2433: foo(<<\"abc\"/utf32>>) -> 2434: ok. 2435: 2436: ">>, 2437: ?line {errors,[{3,erl_lint,unsized_binary_not_at_end}, 2438: {4,erl_lint,unsized_binary_not_at_end}, 2439: {5,erl_lint,unsized_binary_not_at_end}, 2440: {10,erl_lint,typed_literal_string}, 2441: {12,erl_lint,typed_literal_string}, 2442: {14,erl_lint,typed_literal_string}, 2443: {16,erl_lint,typed_literal_string}], 2444: []} = run_test2(Config, Ts, []), 2445: ok. 2446: 2447: otp_10436(doc) -> 2448: "OTP-6885. Warnings for opaque types."; 2449: otp_10436(suite) -> []; 2450: otp_10436(Config) when is_list(Config) -> 2451: Ts = <<"-module(otp_10436). 2452: -export_type([t1/0]). 2453: -opaque t1() :: {i, integer()}. 2454: -opaque t2() :: {a, atom()}. 2455: ">>, 2456: {warnings,[{4,erl_lint,{not_exported_opaque,{t2,0}}}, 2457: {4,erl_lint,{unused_type,{t2,0}}}]} = 2458: run_test2(Config, Ts, []), 2459: Ts2 = <<"-module(otp_10436_2). 2460: -export_type([t1/0, t2/0]). 2461: -opaque t1() :: term(). 2462: -opaque t2() :: any(). 2463: ">>, 2464: {warnings,[{3,erl_lint,{underspecified_opaque,{t1,0}}}, 2465: {4,erl_lint,{underspecified_opaque,{t2,0}}}]} = 2466: run_test2(Config, Ts2, []), 2467: ok. 2468: 2469: otp_11254(doc) -> 2470: "OTP-11254. Warnings for opaque types."; 2471: otp_11254(suite) -> []; 2472: otp_11254(Config) when is_list(Config) -> 2473: Ts = <<"-module(p2). 2474: -export([manifest/2]). 2475: manifest(Module, Name) -> 2476: fun Module:Nine/1. 2477: ">>, 2478: {error,[{4,erl_lint,{unbound_var,'Nine'}}], 2479: [{3,erl_lint,{unused_var,'Name'}}]} = 2480: run_test2(Config, Ts, []), 2481: ok. 2482: 2483: export_all(doc) -> 2484: "OTP-7392. Warning for export_all."; 2485: export_all(Config) when is_list(Config) -> 2486: Ts = <<"-module(export_all_module). 2487: -compile([export_all]). 2488: 2489: id(I) -> I. 2490: ">>, 2491: ?line [] = run_test2(Config, Ts, []), 2492: ?line {warnings,[{2,erl_lint,export_all}]} = 2493: run_test2(Config, Ts, [warn_export_all]), 2494: ok. 2495: 2496: bif_clash(doc) -> 2497: "Test warnings for functions that clash with BIFs."; 2498: bif_clash(suite) -> []; 2499: bif_clash(Config) when is_list(Config) -> 2500: Ts = [{clash1, 2501: <<"t(X) -> 2502: size(X). 2503: 2504: %% No warning for the following calls, since they 2505: %% are unambigous. 2506: b(X) -> 2507: erlang:size(X). 2508: 2509: c(X) -> 2510: ?MODULE:size(X). 2511: 2512: size({N,_}) -> 2513: N. 2514: ">>, 2515: [], 2516: {errors,[{2,erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}}, 2517: 2518: %% Verify that warnings can not be turned off in the old way. 2519: {clash2, 2520: <<"-export([t/1,size/1]). 2521: t(X) -> 2522: size(X). 2523: 2524: size({N,_}) -> 2525: N. 2526: 2527: %% My own abs/1 function works on lists too. From R14 this really works. 2528: abs([H|T]) when $a =< H, H =< $z -> [H-($a-$A)|abs(T)]; 2529: abs([H|T]) -> [H|abs(T)]; 2530: abs([]) -> []; 2531: abs(X) -> erlang:abs(X). 2532: ">>, 2533: {[nowarn_unused_function,nowarn_bif_clash]}, 2534: {errors,[{erl_lint,disallowed_nowarn_bif_clash}],[]}}, 2535: %% As long as noone calls an overridden BIF, it's totally OK 2536: {clash3, 2537: <<"-export([size/1]). 2538: size({N,_}) -> 2539: N; 2540: size(X) -> 2541: erlang:size(X). 2542: ">>, 2543: [], 2544: []}, 2545: %% But this is totally wrong - meaning of the program changed in R14, so this is an error 2546: {clash4, 2547: <<"-export([size/1]). 2548: size({N,_}) -> 2549: N; 2550: size(X) -> 2551: size(X). 2552: ">>, 2553: [], 2554: {errors,[{5,erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}}, 2555: %% For a post R14 bif, its only a warning 2556: {clash5, 2557: <<"-export([binary_part/2]). 2558: binary_part({B,_},{X,Y}) -> 2559: binary_part(B,{X,Y}); 2560: binary_part(B,{X,Y}) -> 2561: binary:part(B,X,Y). 2562: ">>, 2563: [], 2564: {warnings,[{3,erl_lint,{call_to_redefined_bif,{binary_part,2}}}]}}, 2565: %% If you really mean to call yourself here, you can "unimport" size/1 2566: {clash6, 2567: <<"-export([size/1]). 2568: -compile({no_auto_import,[size/1]}). 2569: size([]) -> 2570: 0; 2571: size({N,_}) -> 2572: N; 2573: size([_|T]) -> 2574: 1+size(T). 2575: ">>, 2576: [], 2577: []}, 2578: %% Same for the post R14 autoimport warning 2579: {clash7, 2580: <<"-export([binary_part/2]). 2581: -compile({no_auto_import,[binary_part/2]}). 2582: binary_part({B,_},{X,Y}) -> 2583: binary_part(B,{X,Y}); 2584: binary_part(B,{X,Y}) -> 2585: binary:part(B,X,Y). 2586: ">>, 2587: [], 2588: []}, 2589: %% but this doesn't mean the local function is allowed in a guard... 2590: {clash8, 2591: <<"-export([x/1]). 2592: -compile({no_auto_import,[binary_part/2]}). 2593: x(X) when binary_part(X,{1,2}) =:= <<1,2>> -> 2594: hej. 2595: binary_part({B,_},{X,Y}) -> 2596: binary_part(B,{X,Y}); 2597: binary_part(B,{X,Y}) -> 2598: binary:part(B,X,Y). 2599: ">>, 2600: [], 2601: {errors,[{3,erl_lint,{illegal_guard_local_call,{binary_part,2}}}],[]}}, 2602: %% no_auto_import is not like nowarn_bif_clash, it actually removes the autoimport 2603: {clash9, 2604: <<"-export([x/1]). 2605: -compile({no_auto_import,[binary_part/2]}). 2606: x(X) -> 2607: binary_part(X,{1,2}) =:= <<1,2>>. 2608: ">>, 2609: [], 2610: {errors,[{4,erl_lint,{undefined_function,{binary_part,2}}}],[]}}, 2611: %% but we could import it again... 2612: {clash10, 2613: <<"-export([x/1]). 2614: -compile({no_auto_import,[binary_part/2]}). 2615: -import(erlang,[binary_part/2]). 2616: x(X) -> 2617: binary_part(X,{1,2}) =:= <<1,2>>. 2618: ">>, 2619: [], 2620: []}, 2621: %% and actually use it in a guard... 2622: {clash11, 2623: <<"-export([x/1]). 2624: -compile({no_auto_import,[binary_part/2]}). 2625: -import(erlang,[binary_part/2]). 2626: x(X) when binary_part(X,{0,1}) =:= <<0>> -> 2627: binary_part(X,{1,2}) =:= <<1,2>>. 2628: ">>, 2629: [], 2630: []}, 2631: %% but for non-obvious historical reasons, imported functions cannot be used in 2632: %% fun construction without the module name... 2633: {clash12, 2634: <<"-export([x/1]). 2635: -compile({no_auto_import,[binary_part/2]}). 2636: -import(erlang,[binary_part/2]). 2637: x(X) when binary_part(X,{0,1}) =:= <<0>> -> 2638: binary_part(X,{1,2}) =:= fun binary_part/2. 2639: ">>, 2640: [], 2641: {errors,[{5,erl_lint,{undefined_function,{binary_part,2}}}],[]}}, 2642: %% Not from erlang and not from anywhere else 2643: {clash13, 2644: <<"-export([x/1]). 2645: -compile({no_auto_import,[binary_part/2]}). 2646: -import(x,[binary_part/2]). 2647: x(X) -> 2648: binary_part(X,{1,2}) =:= fun binary_part/2. 2649: ">>, 2650: [], 2651: {errors,[{5,erl_lint,{undefined_function,{binary_part,2}}}],[]}}, 2652: %% ...while real auto-import is OK. 2653: {clash14, 2654: <<"-export([x/1]). 2655: x(X) when binary_part(X,{0,1}) =:= <<0>> -> 2656: binary_part(X,{1,2}) =:= fun binary_part/2. 2657: ">>, 2658: [], 2659: []}, 2660: %% Import directive clashing with old bif is an error, regardless of if it's called or not 2661: {clash15, 2662: <<"-export([x/1]). 2663: -import(x,[abs/1]). 2664: x(X) -> 2665: binary_part(X,{1,2}). 2666: ">>, 2667: [], 2668: {errors,[{2,erl_lint,{redefine_old_bif_import,{abs,1}}}],[]}}, 2669: %% For a new BIF, it's only a warning 2670: {clash16, 2671: <<"-export([x/1]). 2672: -import(x,[binary_part/3]). 2673: x(X) -> 2674: abs(X). 2675: ">>, 2676: [], 2677: {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, 2678: %% And, you cannot redefine already imported things that aren't auto-imported 2679: {clash17, 2680: <<"-export([x/1]). 2681: -import(x,[binary_port/3]). 2682: -import(y,[binary_port/3]). 2683: x(X) -> 2684: abs(X). 2685: ">>, 2686: [], 2687: {errors,[{3,erl_lint,{redefine_import,{{binary_port,3},x}}}],[]}}, 2688: %% Not with local functions either 2689: {clash18, 2690: <<"-export([x/1]). 2691: -import(x,[binary_port/3]). 2692: binary_port(A,B,C) -> 2693: binary_part(A,B,C). 2694: x(X) -> 2695: abs(X). 2696: ">>, 2697: [], 2698: {errors,[{3,erl_lint,{define_import,{binary_port,3}}}],[]}}, 2699: %% Like clash8: Dont accept a guard if it's explicitly module-name called either 2700: {clash19, 2701: <<"-export([binary_port/3]). 2702: -compile({no_auto_import,[binary_part/3]}). 2703: -import(x,[binary_part/3]). 2704: binary_port(A,B,C) when x:binary_part(A,B,C) -> 2705: binary_part(A,B,C+1). 2706: ">>, 2707: [], 2708: {errors,[{4,erl_lint,illegal_guard_expr}],[]}}, 2709: %% Not with local functions either 2710: {clash20, 2711: <<"-export([binary_port/3]). 2712: -import(x,[binary_part/3]). 2713: binary_port(A,B,C) -> 2714: binary_part(A,B,C). 2715: ">>, 2716: [warn_unused_import], 2717: {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, 2718: %% Don't accept call to a guard BIF if there is a local definition 2719: %% or an import with the same name. Note: is_record/2 is an 2720: %% exception, since it is more of syntatic sugar than a real BIF. 2721: {clash21, 2722: <<"-export([is_list/1]). 2723: -import(x, [is_tuple/1]). 2724: -record(r, {a,b}). 2725: x(T) when is_tuple(T) -> ok; 2726: x(T) when is_list(T) -> ok. 2727: y(T) when is_tuple(T) =:= true -> ok; 2728: y(T) when is_list(T) =:= true -> ok; 2729: y(T) when is_record(T, r, 3) -> ok; 2730: y(T) when is_record(T, r, 3) =:= true -> ok; 2731: y(T) when is_record(T, r) =:= true -> ok. 2732: is_list(_) -> 2733: ok. 2734: is_record(_, _) -> 2735: ok. 2736: is_record(_, _, _) -> 2737: ok. 2738: ">>, 2739: [{no_auto_import,[{is_tuple,1}]}], 2740: {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, 2741: {5,erl_lint,{illegal_guard_local_call,{is_list,1}}}, 2742: {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, 2743: {7,erl_lint,{illegal_guard_local_call,{is_list,1}}}, 2744: {8,erl_lint,{illegal_guard_local_call,{is_record,3}}}, 2745: {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}} 2746: ], 2747: 2748: ?line [] = run(Config, Ts), 2749: ok. 2750: 2751: behaviour_basic(doc) -> 2752: "Basic tests with one behaviour."; 2753: behaviour_basic(suite) -> []; 2754: behaviour_basic(Config) when is_list(Config) -> 2755: Ts = [{behaviour1, 2756: <<"-behaviour(application). 2757: ">>, 2758: [], 2759: {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}, 2760: {1,erl_lint,{undefined_behaviour_func,{stop,1},application}}]}}, 2761: 2762: {behaviour2, 2763: <<"-behaviour(application). 2764: -export([stop/1]). 2765: stop(_) -> ok. 2766: ">>, 2767: [], 2768: {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}]}}, 2769: 2770: {behaviour3, 2771: <<"-behavior(application). %% Test American spelling. 2772: -export([start/2,stop/1]). 2773: start(_, _) -> ok. 2774: stop(_) -> ok. 2775: ">>, 2776: [], 2777: []} 2778: ], 2779: ?line [] = run(Config, Ts), 2780: ok. 2781: 2782: behaviour_multiple(doc) -> 2783: "Basic tests with multiple behaviours."; 2784: behaviour_multiple(suite) -> []; 2785: behaviour_multiple(Config) when is_list(Config) -> 2786: Ts = [{behaviour1, 2787: <<"-behaviour(application). 2788: -behaviour(supervisor). 2789: ">>, 2790: [], 2791: {warnings,[{1,erl_lint,{undefined_behaviour_func,{start,2},application}}, 2792: {1,erl_lint,{undefined_behaviour_func,{stop,1},application}}, 2793: {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}}]}}, 2794: 2795: {behaviour2, 2796: <<"-behaviour(application). 2797: -behaviour(supervisor). 2798: -export([start/2,stop/1,init/1]). 2799: start(_, _) -> ok. 2800: stop(_) -> ok. 2801: init(_) -> ok. 2802: ">>, 2803: [], 2804: []}, 2805: 2806: {american_behavior2, 2807: <<"-behavior(application). 2808: -behavior(supervisor). 2809: -export([start/2,stop/1,init/1]). 2810: start(_, _) -> ok. 2811: stop(_) -> ok. 2812: init(_) -> ok. 2813: ">>, 2814: [], 2815: []}, 2816: 2817: {behaviour3, 2818: <<"-behaviour(gen_server). 2819: -behaviour(supervisor). 2820: -export([handle_call/3,handle_cast/2,handle_info/2]). 2821: handle_call(_, _, _) -> ok. 2822: handle_cast(_, _) -> ok. 2823: handle_info(_, _) -> ok. 2824: ">>, 2825: [], 2826: {warnings,[{1,erl_lint, 2827: {undefined_behaviour_func,{code_change,3},gen_server}}, 2828: {1,erl_lint,{undefined_behaviour_func,{init,1},gen_server}}, 2829: {1,erl_lint,{undefined_behaviour_func,{terminate,2},gen_server}}, 2830: {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}}, 2831: {2, 2832: erl_lint, 2833: {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}}, 2834: {american_behavior3, 2835: <<"-behavior(gen_server). 2836: -behavior(supervisor). 2837: -export([handle_call/3,handle_cast/2,handle_info/2]). 2838: handle_call(_, _, _) -> ok. 2839: handle_cast(_, _) -> ok. 2840: handle_info(_, _) -> ok. 2841: ">>, 2842: [], 2843: {warnings,[{1,erl_lint, 2844: {undefined_behaviour_func,{code_change,3},gen_server}}, 2845: {1,erl_lint,{undefined_behaviour_func,{init,1},gen_server}}, 2846: {1,erl_lint,{undefined_behaviour_func,{terminate,2},gen_server}}, 2847: {2,erl_lint,{undefined_behaviour_func,{init,1},supervisor}}, 2848: {2, 2849: erl_lint, 2850: {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}}, 2851: 2852: {behaviour4, 2853: <<"-behaviour(gen_server). 2854: -behaviour(gen_fsm). 2855: -behaviour(supervisor). 2856: -export([init/1,handle_call/3,handle_cast/2, 2857: handle_info/2,handle_info/3, 2858: handle_event/3,handle_sync_event/4, 2859: code_change/3,code_change/4, 2860: terminate/2,terminate/3,terminate/4]). 2861: init(_) -> ok. 2862: handle_call(_, _, _) -> ok. 2863: handle_event(_, _, _) -> ok. 2864: handle_sync_event(_, _, _, _) -> ok. 2865: handle_cast(_, _) -> ok. 2866: handle_info(_, _) -> ok. 2867: handle_info(_, _, _) -> ok. 2868: code_change(_, _, _) -> ok. 2869: code_change(_, _, _, _) -> ok. 2870: terminate(_, _) -> ok. 2871: terminate(_, _, _) -> ok. 2872: terminate(_, _, _, _) -> ok. 2873: ">>, 2874: [], 2875: {warnings,[{2, 2876: erl_lint, 2877: {conflicting_behaviours,{init,1},gen_fsm,1,gen_server}}, 2878: {3, 2879: erl_lint, 2880: {conflicting_behaviours,{init,1},supervisor,1,gen_server}}]}} 2881: ], 2882: ?line [] = run(Config, Ts), 2883: ok. 2884: 2885: otp_7550(doc) -> 2886: "Test that the new utf8/utf16/utf32 types do not allow size or unit specifiers."; 2887: otp_7550(Config) when is_list(Config) -> 2888: Ts = [{otp_7550, 2889: <<"f8(A) -> 2890: <<A:8/utf8>>. 2891: g8(A) -> 2892: <<A:8/utf8-unit:1>>. 2893: h8(A) -> 2894: <<A/utf8-unit:1>>. 2895: 2896: f16(A) -> 2897: <<A:8/utf16>>. 2898: g16(A) -> 2899: <<A:8/utf16-unit:1>>. 2900: h16(A) -> 2901: <<A/utf16-unit:1>>. 2902: 2903: f32(A) -> 2904: <<A:8/utf32>>. 2905: g32(A) -> 2906: <<A:8/utf32-unit:1>>. 2907: h32(A) -> 2908: <<A/utf32-unit:1>>. 2909: ">>, 2910: [], 2911: {errors,[{2,erl_lint,utf_bittype_size_or_unit}, 2912: {4,erl_lint,utf_bittype_size_or_unit}, 2913: {6,erl_lint,utf_bittype_size_or_unit}, 2914: {9,erl_lint,utf_bittype_size_or_unit}, 2915: {11,erl_lint,utf_bittype_size_or_unit}, 2916: {13,erl_lint,utf_bittype_size_or_unit}, 2917: {16,erl_lint,utf_bittype_size_or_unit}, 2918: {18,erl_lint,utf_bittype_size_or_unit}, 2919: {20,erl_lint,utf_bittype_size_or_unit} 2920: ], 2921: []}}], 2922: ?line [] = run(Config, Ts), 2923: ok. 2924: 2925: 2926: otp_8051(doc) -> 2927: "Bugfix: -opaque with invalid type."; 2928: otp_8051(Config) when is_list(Config) -> 2929: Ts = [{otp_8051, 2930: <<"-opaque foo() :: bar(). 2931: -export_type([foo/0]). 2932: ">>, 2933: [], 2934: {errors,[{1,erl_lint,{undefined_type,{bar,0}}}],[]}}], 2935: ?line [] = run(Config, Ts), 2936: ok. 2937: 2938: format_warn(doc) -> 2939: "Check that format warnings are generated."; 2940: format_warn(suite) -> []; 2941: format_warn(Config) when is_list(Config) -> 2942: L1 = 14, 2943: L2 = 4, 2944: format_level(1, L1, Config), 2945: format_level(2, L1+L2, Config), 2946: format_level(3, L1+L2, Config), %there is no level 3 2947: ok. 2948: 2949: format_level(Level, Count, Config) -> 2950: ?line W = get_compilation_warnings(Config, "format", 2951: [{warn_format, Level}]), 2952: %% Pick out the 'format' warnings. 2953: ?line FW = lists:filter(fun({_Line, erl_lint, {format_error, _}}) -> true; 2954: (_) -> false 2955: end, 2956: W), 2957: ?line case length(FW) of 2958: Count -> 2959: ok; 2960: Other -> 2961: ?t:format("Expected ~w warning(s); got ~w", [Count,Other]), 2962: fail() 2963: end, 2964: ok. 2965: 2966: %% Test the -on_load(Name/0) directive. 2967: 2968: 2969: on_load_successful(Config) when is_list(Config) -> 2970: Ts = [{on_load_1, 2971: %% Exported on_load function. 2972: <<"-export([do_on_load/0]). 2973: -on_load(do_on_load/0). 2974: do_on_load() -> ok. 2975: ">>, 2976: {[]}, %Tuple indicates no 'export_all'. 2977: []}, 2978: 2979: {on_load_2, 2980: %% Local on_load function. 2981: <<"-on_load(do_on_load/0). 2982: do_on_load() -> ok. 2983: ">>, 2984: {[]}, %Tuple indicates no 'export_all'. 2985: []}, 2986: 2987: {on_load_3, 2988: %% Local on_load function, calling other local functions. 2989: <<"-on_load(do_on_load/0). 2990: do_on_load() -> foo(). 2991: foo() -> bar(5) + 42. 2992: bar(N) -> 2*N. 2993: ">>, 2994: {[]}, %Tuple indicates no 'export_all'. 2995: []} 2996: ], 2997: ?line [] = run(Config, Ts), 2998: ok. 2999: 3000: on_load_failing(Config) when is_list(Config) -> 3001: Ts = [{on_load_1, 3002: %% Badly formed. 3003: <<"-on_load(atom). 3004: ">>, 3005: {[]}, %Tuple indicates no 'export_all'. 3006: {errors, 3007: [{1,erl_lint,{bad_on_load,atom}}],[]}}, 3008: 3009: {on_load_2, 3010: %% Badly formed. 3011: <<"-on_load({42,0}). 3012: ">>, 3013: {[]}, %Tuple indicates no 'export_all'. 3014: {errors, 3015: [{1,erl_lint,{bad_on_load,{42,0}}}],[]}}, 3016: 3017: {on_load_3, 3018: %% Multiple on_load attributes. 3019: <<"-on_load(foo/0). 3020: -on_load(bar/0). 3021: foo() -> ok. 3022: bar() -> ok. 3023: ">>, 3024: {[]}, %Tuple indicates no 'export_all'. 3025: {errors, 3026: [{2,erl_lint,multiple_on_loads}],[]}}, 3027: 3028: {on_load_4, 3029: %% Wrong arity. 3030: <<"-on_load(foo/1). 3031: foo(_) -> ok. 3032: ">>, 3033: {[]}, %Tuple indicates no 'export_all'. 3034: {errors, 3035: [{1,erl_lint,{bad_on_load_arity,{foo,1}}}],[]}}, 3036: 3037: {on_load_5, 3038: %% Non-existing function. 3039: <<"-on_load(non_existing/0). 3040: ">>, 3041: {[]}, %Tuple indicates no 'export_all'. 3042: {errors, 3043: [{1,erl_lint,{undefined_on_load,{non_existing,0}}}],[]}} 3044: ], 3045: ?line [] = run(Config, Ts), 3046: ok. 3047: 3048: too_many_arguments(doc) -> 3049: "Test that too many arguments is not accepted."; 3050: too_many_arguments(suite) -> []; 3051: too_many_arguments(Config) when is_list(Config) -> 3052: Ts = [{too_many_1, 3053: <<"f(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ok.">>, 3054: [], 3055: {errors, 3056: [{1,erl_lint,{too_many_arguments,256}}],[]}} 3057: ], 3058: 3059: ?line [] = run(Config, Ts), 3060: ok. 3061: 3062: 3063: %% Test some basic errors to improve coverage. 3064: basic_errors(Config) -> 3065: Ts = [{redefine_module, 3066: <<"-module(redefine_module).">>, 3067: [], 3068: {errors,[{1,erl_lint,redefine_module}],[]}}, 3069: 3070: {attr_after_function, 3071: <<"f() -> ok. 3072: -attr(x).">>, 3073: [], 3074: {errors,[{2,erl_lint,{attribute,attr}}],[]}}, 3075: 3076: {redefine_function, 3077: <<"f() -> ok. 3078: f() -> ok.">>, 3079: [], 3080: {errors,[{2,erl_lint,{redefine_function,{f,0}}}],[]}}, 3081: 3082: {redefine_record, 3083: <<"-record(r, {a}). 3084: -record(r, {a}). 3085: f(#r{}) -> ok.">>, 3086: [], 3087: {errors,[{2,erl_lint,{redefine_record,r}}],[]}}, 3088: 3089: {illegal_record_info, 3090: <<"f1() -> record_info(42, record). 3091: f2() -> record_info(shoe_size, record).">>, 3092: [], 3093: {errors,[{1,erl_lint,illegal_record_info}, 3094: {2,erl_lint,illegal_record_info}],[]}}, 3095: 3096: {illegal_expr, 3097: <<"f() -> a:b.">>, 3098: [], 3099: {errors,[{1,erl_lint,illegal_expr}],[]}}, 3100: 3101: {illegal_pattern, 3102: <<"f(A+B) -> ok.">>, 3103: [], 3104: {errors,[{1,erl_lint,illegal_pattern}],[]}} 3105: ], 3106: [] = run(Config, Ts), 3107: ok. 3108: 3109: %% Test binary syntax errors 3110: bin_syntax_errors(Config) -> 3111: Ts = [{bin_syntax_errors, 3112: <<"t(<<X:bad_size>>) -> X; 3113: t(<<_:(x ! y)/integer>>) -> ok; 3114: t(<<X:all/integer>>) -> X; 3115: t(<<X/bad_type>>) -> X; 3116: t(<<X/unit:8>>) -> X; 3117: t(<<X:7/float>>) -> X; 3118: t(<< <<_:8>> >>) -> ok; 3119: t(<<(x ! y):8/integer>>) -> ok. 3120: ">>, 3121: [], 3122: {error,[{1,erl_lint,illegal_bitsize}, 3123: {2,erl_lint,illegal_bitsize}, 3124: {3,erl_lint,illegal_bitsize}, 3125: {4,erl_lint,{undefined_bittype,bad_type}}, 3126: {5,erl_lint,bittype_unit}, 3127: {7,erl_lint,illegal_pattern}, 3128: {8,erl_lint,illegal_pattern}], 3129: [{6,erl_lint,{bad_bitsize,"float"}}]}} 3130: ], 3131: [] = run(Config, Ts), 3132: ok. 3133: 3134: run(Config, Tests) -> 3135: F = fun({N,P,Ws,E}, BadL) -> 3136: case catch run_test(Config, P, Ws) of 3137: E -> 3138: BadL; 3139: Bad -> 3140: ?t:format("~nTest ~p failed. Expected~n ~p~n" 3141: "but got~n ~p~n", [N, E, Bad]), 3142: fail() 3143: end 3144: end, 3145: lists:foldl(F, [], Tests). 3146: 3147: %% Compiles a test file and returns the list of warnings. 3148: 3149: get_compilation_warnings(Conf, Filename, Warnings) -> 3150: ?line DataDir = ?datadir, 3151: ?line File = filename:join(DataDir, Filename), 3152: {ok,Bin} = file:read_file(File++".erl"), 3153: FileS = binary_to_list(Bin), 3154: {match,[{Start,Length}|_]} = re:run(FileS, "-module.*\\n"), 3155: Test = lists:nthtail(Start+Length, FileS), 3156: {warnings, Ws} = run_test(Conf, Test, Warnings), 3157: Ws. 3158: 3159: %% Compiles a test module and returns the list of errors and warnings. 3160: 3161: run_test(Conf, Test0, Warnings0) -> 3162: Test = list_to_binary(["-module(lint_test). ", Test0]), 3163: run_test2(Conf, Test, Warnings0). 3164: 3165: run_test2(Conf, Test, Warnings0) -> 3166: Filename = "lint_test.erl", 3167: DataDir = ?privdir, 3168: File = filename:join(DataDir, Filename), 3169: Opts = case Warnings0 of 3170: {Warnings} -> %Hairy trick to not add export_all. 3171: [return|Warnings]; 3172: Warnings -> 3173: [export_all,return|Warnings] 3174: end, 3175: ok = file:write_file(File, Test), 3176: 3177: %% We will use the 'binary' option so that the compiler will not 3178: %% compare the module name to the output file name. Also, there 3179: %% is no reason to produce an output file since we are only 3180: %% interested in the errors and warnings. 3181: 3182: %% Print warnings, call erl_lint:format_error/1. 3183: compile:file(File, [binary,report|Opts]), 3184: 3185: case compile:file(File, [binary|Opts]) of 3186: {ok, _M, Code, Ws} when is_binary(Code) -> warnings(File, Ws); 3187: {error, [{File,Es}], []} -> {errors, Es, []}; 3188: {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws}; 3189: {error, [{File,Es1},{File,Es2}], []} -> {errors2, Es1, Es2} 3190: end. 3191: 3192: warnings(File, Ws) -> 3193: case lists:append([W || {F, W} <- Ws, F =:= File]) of 3194: [] -> []; 3195: L -> {warnings, L} 3196: end. 3197: 3198: fail() -> 3199: io:format("failed~n"), 3200: ?t:fail().