1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2003-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(warnings_SUITE). 21 22%%-define(STANDALONE, true). 23 24-ifdef(STANDALONE). 25-define(line, put(line, ?LINE), ). 26-define(config(X,Y), foo). 27-define(privdir, "warnings_SUITE_priv"). 28-define(t, test_server). 29-else. 30-include_lib("common_test/include/ct.hrl"). 31-define(datadir, proplists:get_value(data_dir, Conf)). 32-define(privdir, proplists:get_value(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([pattern/1,pattern2/1,pattern3/1,pattern4/1, 40 guard/1,bad_arith/1,bool_cases/1,bad_apply/1, 41 files/1,effect/1,bin_opt_info/1,bin_construction/1, 42 comprehensions/1,maps/1,maps_bin_opt_info/1, 43 redundant_boolean_clauses/1, 44 latin1_fallback/1,underscore/1,no_warnings/1, 45 bit_syntax/1,inlining/1,tuple_calls/1]). 46 47init_per_testcase(_Case, Config) -> 48 Config. 49 50end_per_testcase(_Case, _Config) -> 51 ok. 52 53suite() -> 54 [{ct_hooks,[ts_install_cth]}, 55 {timetrap,{minutes,2}}]. 56 57all() -> 58 [{group,p}]. 59 60groups() -> 61 [{p,test_lib:parallel(), 62 [pattern,pattern2,pattern3,pattern4,guard, 63 bad_arith,bool_cases,bad_apply,files,effect, 64 bin_opt_info,bin_construction,comprehensions,maps, 65 maps_bin_opt_info, 66 redundant_boolean_clauses,latin1_fallback, 67 underscore,no_warnings,bit_syntax,inlining, 68 tuple_calls]}]. 69 70init_per_suite(Config) -> 71 test_lib:recompile(?MODULE), 72 Config. 73 74end_per_suite(_Config) -> 75 ok. 76 77init_per_group(_GroupName, Config) -> 78 Config. 79 80end_per_group(_GroupName, Config) -> 81 Config. 82 83 84pattern(Config) when is_list(Config) -> 85 %% Test warnings generated by v3_core. 86 Ts = [{pattern, 87 <<"%% Just a comment here. 88 f(a={glurf,2}=A) -> A. 89 90 g(A) -> 91 case A of 92 a=[_|_] -> error; 93 Other -> true 94 end. 95 96 foo(X) -> 97 a = {nisse,b} = X. 98 ">>, 99 [warn_unused_vars], 100 {warnings, 101 [{2,v3_core,nomatch}, 102 {6,v3_core,nomatch}, 103 {11,v3_core,nomatch} ] }}], 104 [] = run(Config, Ts), 105 ok. 106 107pattern2(Config) when is_list(Config) -> 108 %% Test warnings generated by sys_core_fold. 109 %% If we disable Core Erlang optimizations, we expect that 110 %% v3_kernel should generate some of the warnings. 111 Source = <<"f(A) -> ok; 112 f(B) -> error. 113 t(A, B, C) -> 114 case {A,B,C} of 115 {a,B} -> ok; 116 {_,B} -> ok 117 end. 118 ">>, 119 120 %% Test warnings from sys_core_fold. 121 Ts = [{pattern2, 122 Source, 123 [nowarn_unused_vars], 124 {warnings,[{2,sys_core_fold,{nomatch_shadow,1}}, 125 {4,sys_core_fold,no_clause_match}, 126 {5,sys_core_fold,nomatch_clause_type}, 127 {6,sys_core_fold,nomatch_clause_type}]}}], 128 [] = run(Config, Ts), 129 130 %% Disable Core Erlang optimizations. v3_kernel should produce 131 %% a warning for the clause that didn't match. 132 Ts2 = [{pattern2, 133 Source, 134 [nowarn_unused_vars,no_copt], 135 {warnings, 136 [{2,v3_kernel,{nomatch_shadow,1}}]}}], 137 [] = run(Config, Ts2), 138 ok. 139 140pattern3(Config) when is_list(Config) -> 141 %% Test warnings generated by the pattern matching compiler 142 %% in v3_kernel. 143 144 Ts = [{pattern3, 145 <<" 146 f({A,_}) -> {ok,A}; 147 f([_|_]=B) -> {ok,B}; 148 f({urk,nisse}) -> urka_glurka. 149 ">>, 150 [nowarn_unused_vars], 151 {warnings, 152 [{4,v3_kernel,{nomatch_shadow,2}}]}}], 153 [] = run(Config, Ts), 154 155 ok. 156 157pattern4(Config) when is_list(Config) -> 158 %% Test warnings for clauses that cannot possibly match. 159 160 Ts = [{pattern4, 161 <<" 162 t() -> 163 case true of 164 false -> a; 165 true -> b 166 end. 167 168 fi() -> 169 case true of 170 false -> a; 171 false -> b 172 end, 173 case true of 174 true -> a; 175 true -> b; 176 X -> X 177 end, 178 case boolean of 179 true -> a; 180 false -> b 181 end. 182 int() -> 183 case 42 of 184 [a|b] -> no; 185 <<1>> -> no; 186 <<X>> -> no; 187 17 -> no; 188 [] -> no; 189 a -> no; 190 {a,b,c} -> no 191 end. 192 tuple() -> 193 case {x,y,z} of 194 \"xyz\" -> no; 195 [a|b] -> no; 196 <<1>> -> no; 197 <<X>> -> no; 198 17 -> no; 199 [] -> no; 200 a -> no; 201 {a,b,c} -> no; 202 {x,y} -> no 203 end. 204 ">>, 205 [nowarn_unused_vars], 206 {warnings, 207 [{9,sys_core_fold,no_clause_match}, 208 {11,sys_core_fold,nomatch_shadow}, 209 {15,sys_core_fold,nomatch_shadow}, 210 {18,sys_core_fold,no_clause_match}, 211 {23,sys_core_fold,no_clause_match}, 212 {33,sys_core_fold,no_clause_match} 213 ]}}], 214 [] = run(Config, Ts), 215 216 ok. 217 218guard(Config) when is_list(Config) -> 219 %% Test warnings for false guards. 220 221 Ts = [{guard, 222 <<" 223 t(A, B) when element(x, dum) -> ok. 224 225 tt(A, B) when 1 == 2 -> ok. 226 227 ttt() when element(x, dum) -> ok. 228 229 t4(T, F) when element({F}, T) -> ok. 230 t5(T, F) when element([F], T) -> ok. 231 t6(Pos, F) when element(Pos, [F]) -> ok. 232 t7(Pos) when element(Pos, []) -> ok. 233 ">>, 234 [nowarn_unused_vars], 235 {warnings, 236 [{2,sys_core_fold,no_clause_match}, 237 {2,sys_core_fold,nomatch_guard}, 238 {2,sys_core_fold,{eval_failure,badarg}}, 239 {4,sys_core_fold,no_clause_match}, 240 {4,sys_core_fold,nomatch_guard}, 241 {6,sys_core_fold,no_clause_match}, 242 {6,sys_core_fold,nomatch_guard}, 243 {6,sys_core_fold,{eval_failure,badarg}}, 244 {8,sys_core_fold,no_clause_match}, 245 {8,sys_core_fold,nomatch_guard}, 246 {8,sys_core_fold,{eval_failure,badarg}}, 247 {9,sys_core_fold,no_clause_match}, 248 {9,sys_core_fold,nomatch_guard}, 249 {9,sys_core_fold,{eval_failure,badarg}}, 250 {10,sys_core_fold,no_clause_match}, 251 {10,sys_core_fold,nomatch_guard}, 252 {10,sys_core_fold,{eval_failure,badarg}}, 253 {11,sys_core_fold,no_clause_match}, 254 {11,sys_core_fold,nomatch_guard}, 255 {11,sys_core_fold,{eval_failure,badarg}} 256 ]}}], 257 [] = run(Config, Ts), 258 259 ok. 260 261bad_arith(Config) when is_list(Config) -> 262 Ts = [{bad_arith, 263 <<"f() -> 264 if 265 a + 3 > 3 -> ok; 266 true -> error 267 end. 268 269 g(A) -> 270 if 271 is_integer(A), a + 3 > 3 -> ok; 272 a + 3 > 42, is_integer(A) -> ok; 273 true -> error 274 end. 275 276 h(A) -> 277 a + 3 + A. 278 ">>, 279 [], 280 {warnings, 281 [{3,sys_core_fold,nomatch_guard}, 282 {3,sys_core_fold,{eval_failure,badarith}}, 283 {9,sys_core_fold,nomatch_guard}, 284 {9,sys_core_fold,{eval_failure,badarith}}, 285 {10,sys_core_fold,nomatch_guard}, 286 {10,sys_core_fold,{eval_failure,badarith}}, 287 {15,sys_core_fold,{eval_failure,badarith}} 288 ] }}], 289 [] = run(Config, Ts), 290 ok. 291 292bool_cases(Config) when is_list(Config) -> 293 Ts = [{bool_cases, 294 <<" 295 f(A, B) -> 296 case A > B of 297 true -> true; 298 false -> false; 299 Other -> {error,not_bool} 300 end. 301 302 g(A, B) -> 303 case A =/= B of 304 false -> false; 305 true -> true; 306 Other -> {error,not_bool} 307 end. 308 309 h(Bool) -> 310 case not Bool of 311 maybe -> strange; 312 false -> ok; 313 true -> error 314 end. 315 ">>, 316 [nowarn_unused_vars], 317 {warnings, 318 [{6,sys_core_fold,nomatch_shadow}, 319 {13,sys_core_fold,nomatch_shadow}, 320 {18,sys_core_fold,nomatch_clause_type} ]} }], 321 [] = run(Config, Ts), 322 ok. 323 324bad_apply(Config) when is_list(Config) -> 325 Ts = [{bad_apply, 326 <<" 327 t(1) -> 42:42(); 328 t(2) -> erlang:42(); 329 t(3) -> 42:start(); 330 t(4) -> []:start(); 331 t(5) -> erlang:[](). 332 ">>, 333 [], 334 {warnings, 335 [{2,v3_kernel,bad_call}, 336 {3,v3_kernel,bad_call}, 337 {4,v3_kernel,bad_call}, 338 {5,v3_kernel,bad_call}, 339 {6,v3_kernel,bad_call}]}}], 340 [] = run(Config, Ts), 341 342 %% Also verify that the generated code generates the correct error. 343 try erlang:42() of 344 _ -> ct:fail(should_fail) 345 catch 346 error:badarg -> ok 347 end, 348 ok. 349 350files(Config) when is_list(Config) -> 351 Ts = [{files_1, 352 <<" 353 -file(\"file1\", 14). 354 355 t1() -> 356 1/0. 357 358 -file(\"file2\", 7). 359 360 t2() -> 361 1/0. 362 ">>, 363 [], 364 {warnings, 365 [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]}, 366 {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}], 367 368 [] = run(Config, Ts), 369 ok. 370 371%% Test warnings for term construction and BIF calls in effect context. 372effect(Config) when is_list(Config) -> 373 Ts = [{effect, 374 <<" 375 t(X) -> 376 case X of 377 warn_lc -> 378 [is_integer(Z) || Z <- [1,2,3]]; 379 warn_lc_2 -> 380 [{error,Z} || Z <- [1,2,3]]; 381 warn_lc_3 -> 382 [{error,abs(Z)} || Z <- [1,2,3]]; 383 no_warn_lc -> 384 [put(last_integer, Z) || Z <- [1,2,3]]; %no warning 385 unused_tuple_literal -> 386 {a,b,c}; 387 unused_list_literal -> 388 [1,2,3,4]; 389 unused_integer -> 390 42; 391 unused_arith -> 392 X*X; 393 nested -> 394 [{ok,node(),?MODULE:foo(),self(),[time(),date()],time()}, 395 is_integer(X)]; 396 unused_bit_syntax -> 397 <<X:8>>; 398 unused_fun -> 399 fun() -> {ok,X} end; 400 unused_named_fun -> 401 fun F(0) -> 1; 402 F(N) -> N*F(N-1) 403 end; 404 unused_atom -> 405 ignore; %no warning 406 unused_nil -> 407 []; %no warning 408 comp_op -> 409 X =:= 2; 410 cookie -> 411 erlang:get_cookie(); 412 result_ignore -> 413 _ = list_to_integer(X); 414 warn_lc_4 -> 415 %% No warning because of assignment to _. 416 [_ = abs(Z) || Z <- [1,2,3]] 417 end, 418 ok. 419 420 %% No warnings should be generated in the following functions. 421 m1(X, Sz) -> 422 if 423 Sz =:= 0 -> X = 0; 424 true -> ok 425 end, 426 ok. 427 428 m2(X, Sz) -> 429 if 430 Sz =:= 0 -> X = {a,Sz}; 431 true -> ok 432 end, 433 ok. 434 435 m3(X, Sz) -> 436 if 437 Sz =:= 0 -> X = [a,Sz]; 438 true -> ok 439 end, 440 ok. 441 442 m4(X, Sz, Var) -> 443 if 444 Sz =:= 0 -> X = Var; 445 true -> ok 446 end, 447 ok. 448 449 m5(X, Sz) -> 450 if 451 Sz =:= 0 -> X = {a,b,c}; 452 true -> ok 453 end, 454 ok. 455 456 m6(X, Sz) -> 457 if 458 Sz =:= 0 -> X = {a,Sz,[1,2,3]}; 459 true -> ok 460 end, 461 ok. 462 463 m7(X, Sz) -> 464 if 465 Sz =:= 0 -> X = {a,Sz,[1,2,3],abs(Sz)}; 466 true -> ok 467 end, 468 ok. 469 470 m8(A, B) -> 471 case {A,B} of 472 V -> V 473 end, 474 ok. 475 476 m9(Bs) -> 477 [{B,ok} = {B,foo:bar(B)} || B <- Bs], 478 ok. 479 480 m10(ConfigTableSize) -> 481 case ConfigTableSize of 482 apa -> 483 CurrentConfig = {id(camel_phase3),id(sms)}, 484 case CurrentConfig of 485 {apa, bepa} -> ok; 486 _ -> ok 487 end 488 end, 489 ok. 490 491 id(I) -> I. 492 ">>, 493 [], 494 {warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, 495 {7,sys_core_fold,useless_building}, 496 {9,sys_core_fold,result_ignored}, 497 {9,sys_core_fold,useless_building}, 498 {13,sys_core_fold,useless_building}, 499 {15,sys_core_fold,useless_building}, 500 {17,sys_core_fold,useless_building}, 501 {19,sys_core_fold,result_ignored}, 502 {21,sys_core_fold,useless_building}, 503 {21,sys_core_fold,{no_effect,{erlang,date,0}}}, 504 {21,sys_core_fold,{no_effect,{erlang,node,0}}}, 505 {21,sys_core_fold,{no_effect,{erlang,self,0}}}, 506 {21,sys_core_fold,{no_effect,{erlang,time,0}}}, 507 {22,sys_core_fold,useless_building}, 508 {22,sys_core_fold,{no_effect,{erlang,is_integer,1}}}, 509 {24,sys_core_fold,useless_building}, 510 {26,sys_core_fold,useless_building}, 511 {28,sys_core_fold,useless_building}, 512 {36,sys_core_fold,{no_effect,{erlang,'=:=',2}}}, 513 {38,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}], 514 [] = run(Config, Ts), 515 ok. 516 517bin_opt_info(Config) when is_list(Config) -> 518 Code = <<" 519 t1(Bin) -> 520 case Bin of 521 _ when byte_size(Bin) > 20 -> erlang:error(too_long); 522 <<_,T/binary>> -> t1(T); 523 <<>> -> ok 524 end. 525 526 t2(<<_,T/bytes>>) -> 527 split_binary(T, 4). 528 ">>, 529 Ts1 = [{bsm1, 530 Code, 531 [bin_opt_info], 532 {warnings, 533 [{4,sys_core_bsm,orig_bin_var_used_in_guard}, 534 {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}}, 535 {9,beam_bsm,{no_bin_opt, 536 {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}], 537 [] = run(Config, Ts1), 538 539 %% For coverage: don't give the bin_opt_info option. 540 Ts2 = [{bsm2, 541 Code, 542 [], 543 []}], 544 [] = run(Config, Ts2), 545 ok. 546 547bin_construction(Config) when is_list(Config) -> 548 Ts = [{bin_construction, 549 <<" 550 t() -> 551 Bin = <<1,2,3>>, 552 <<Bin:4/binary>>. 553 554 x() -> 555 Bin = <<1,2,3,7:4>>, 556 <<Bin/binary>>. 557 ">>, 558 [], 559 {warnings,[{4,sys_core_fold,embedded_binary_size}, 560 {8,sys_core_fold,{embedded_unit,8,28}}]}}], 561 [] = run(Config, Ts), 562 563 ok. 564 565comprehensions(Config) when is_list(Config) -> 566 Ts = [{tautologic_guards, 567 <<" 568 f() -> [ true || true ]. 569 g() -> << <<1>> || true >>. 570 ">>, 571 [], []}], 572 run(Config, Ts), 573 ok. 574 575maps(Config) when is_list(Config) -> 576 Ts = [{bad_map, 577 <<" 578 t() -> 579 case maybe_map of 580 #{} -> ok; 581 not_map -> error 582 end. 583 x() -> 584 case true of 585 #{} -> error; 586 true -> ok 587 end. 588 ">>, 589 [], 590 {warnings,[{3,sys_core_fold,no_clause_match}, 591 {9,sys_core_fold,nomatch_clause_type}]}}, 592 {bad_map_src1, 593 <<" 594 t() -> 595 M = {a,[]}, 596 {'EXIT',{badarg,_}} = (catch(M#{ a => 1 })), 597 ok. 598 ">>, 599 [], 600 {warnings,[{4,sys_core_fold,{eval_failure,badmap}}]}}, 601 {bad_map_src2, 602 <<" 603 t() -> 604 M = id({a,[]}), 605 {'EXIT',{badarg,_}} = (catch(M#{ a => 1})), 606 ok. 607 id(I) -> I. 608 ">>, 609 [inline], 610 []}, 611 {bad_map_src3, 612 <<" 613 t() -> 614 {'EXIT',{badarg,_}} = (catch <<>>#{ a := 1}), 615 ok. 616 ">>, 617 [], 618 {warnings,[{3,v3_core,badmap}]}}, 619 {ok_map_literal_key, 620 <<" 621 t() -> 622 V = id(1), 623 M = id(#{ <<$h,$i>> => V }), 624 V = case M of 625 #{ <<0:257>> := Val } -> Val; 626 #{ <<$h,$i>> := Val } -> Val 627 end, 628 ok. 629 id(I) -> I. 630 ">>, 631 [], 632 []}, 633 {repeated_keys1, 634 <<" 635 foo1() -> 636 #{a=>1, 637 b=> 2, 638 a=>3}. 639 640 bar1(M) -> 641 M#{a=>1, b=> 2, a:=3}. 642 643 baz1(M) -> 644 M#{a=>1, b=> 2, a:=3}. 645 646 foo2() -> 647 #{\"a\"=>1, \"b\"=> 2, \"a\"=>3}. 648 649 bar2(M) -> 650 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. 651 652 baz2(M) -> 653 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. 654 655 foo3() -> 656 #{\"a\"=>1, 657 \"b\"=> 2, 658 \"a\"=>3}. 659 660 bar3(M) -> 661 M#{\"a\"=>1, \"b\"=> 2, \"a\":=3}. 662 663 baz3(M) -> 664 M#{<<\"a\">>=>1, <<\"b\">>=> 2, <<\"a\">>:=3}. 665 ">>, 666 [], 667 {warnings,[{3,v3_core,{map_key_repeated,a}}, 668 {8,v3_core,{map_key_repeated,a}}, 669 {11,v3_core,{map_key_repeated,a}}, 670 {14,v3_core,{map_key_repeated,"a"}}, 671 {17,v3_core,{map_key_repeated,"a"}}, 672 {20,v3_core,{map_key_repeated,"a"}}, 673 {23,v3_core,{map_key_repeated,"a"}}, 674 {28,v3_core,{map_key_repeated,"a"}}, 675 {31,v3_core,{map_key_repeated,<<"a">>}}]}}, 676 {repeated_keys2, 677 <<" 678 foo4(K) -> 679 #{\"a\"=>1, K => 1, \"b\"=> 2, \"a\"=>3, K=>2}. 680 681 bar4(M,K) -> 682 M#{a=>1, K =>1, b=> 2, a:=3, K=>2}. 683 684 baz4(M,K) -> 685 M#{<<\"a\">>=>1, 686 K => 1, <<\"b\">>=> 2, 687 <<\"a\">>:=3, K=>2}. 688 689 foo5(K) -> 690 #{{\"a\",1}=>1, K => 1, \"b\"=> 2, {\"a\",1}=>3, K=>2}. 691 692 bar5(M,K) -> 693 M#{{\"a\",<<\"b\">>}=>1, K =>1, 694 \"b\"=> 2, {\"a\",<<\"b\">>}:=3, K=>2}. 695 696 baz5(M,K) -> 697 M#{{<<\"a\">>,1}=>1, K => 1, 698 <<\"b\">>=> 2, {<<\"a\">>,1}:=3,K=>2}. 699 700 foo6(K) -> 701 #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2, #{\"a\"=>1}=>3, K=>2}. 702 703 bar6(M,K) -> 704 M#{#{\"a\"=><<\"b\">>}=>1, K =>1, 705 \"b\"=> 2, #{\"a\"=><<\"b\">>}:=3, K=>2}. 706 707 baz6(M,K) -> 708 M#{#{<<\"a\">>=>1}=>1, 709 K => 1, 710 <<\"b\">>=> 2, 711 #{<<\"a\">>=>1}:=3,K=>2}. 712 713 foo7(K) -> 714 M1 = #{#{\"a\"=>1}=>1, K => 1, \"b\"=> 2}, 715 M1#{#{\"a\"=>1}=>3, K=>2}. 716 717 bar7(M,K) -> 718 M1 = M#{#{\"a\"=><<\"b\">>}=>1, K =>1, \"b\"=> 2}, 719 M1#{#{\"a\"=><<\"b\">>}:=3, K=>2}. 720 721 baz7(M,K) -> 722 M1 = M#{#{<<\"a\">>=>1}=>1, 723 K => 1, 724 <<\"b\">>=> 2}, 725 M1#{#{<<\"a\">>=>1}:=3,K=>2}. 726 ">>, 727 [], 728 {warnings,[{3,v3_core,{map_key_repeated,"a"}}, 729 {6,v3_core,{map_key_repeated,a}}, 730 {9,v3_core,{map_key_repeated,<<"a">>}}, 731 {14,v3_core,{map_key_repeated,{"a",1}}}, 732 {17,v3_core,{map_key_repeated,{"a",<<"b">>}}}, 733 {21,v3_core,{map_key_repeated,{<<"a">>,1}}}, 734 {25,v3_core,{map_key_repeated,#{"a" => 1}}}, 735 {28,v3_core,{map_key_repeated,#{"a" => <<"b">>}}}, 736 {32,v3_core,{map_key_repeated,#{<<"a">> => 1}}}]}} 737 ], 738 run(Config, Ts), 739 ok. 740 741maps_bin_opt_info(Config) when is_list(Config) -> 742 Ts = [{map_bsm, 743 <<" 744 t1(<<0:8,7:8,T/binary>>,#{val := I}=M) -> 745 t1(T, M#{val := I+1}); 746 t1(<<_:8>>,M) -> 747 M. 748 ">>, 749 [bin_opt_info], 750 {warnings,[{2,beam_bsm,bin_opt}]}}], 751 [] = run(Config, Ts), 752 ok. 753 754redundant_boolean_clauses(Config) when is_list(Config) -> 755 Ts = [{redundant_boolean_clauses, 756 <<" 757 t(X) -> 758 case X == 0 of 759 false -> no; 760 false -> no; 761 true -> yes 762 end. 763 ">>, 764 [], 765 {warnings,[{5,sys_core_fold,nomatch_shadow}]}}], 766 run(Config, Ts), 767 ok. 768 769latin1_fallback(Conf) when is_list(Conf) -> 770 DataDir = ?privdir, 771 IncFile = filename:join(DataDir, "include_me.hrl"), 772 file:write_file(IncFile, <<"%% ",246," in include file\n">>), 773 Ts1 = [{latin1_fallback1, 774 %% Test that the compiler fall backs to latin-1 with 775 %% a warning if a file has no encoding and does not 776 %% contain correct UTF-8 sequences. 777 <<"%% Bj",246,"rn 778 t(_) -> \"",246,"\"; 779 t(x) -> ok. 780 ">>, 781 [], 782 {warnings,[{1,compile,reparsing_invalid_unicode}, 783 {3,sys_core_fold,{nomatch_shadow,2}}]}}], 784 [] = run(Conf, Ts1), 785 786 Ts2 = [{latin1_fallback2, 787 %% Test that the compiler fall backs to latin-1 with 788 %% a warning if a file has no encoding and does not 789 %% contain correct UTF-8 sequences. 790 <<" 791 792 -include(\"include_me.hrl\"). 793 ">>, 794 [], 795 {warnings,[{1,compile,reparsing_invalid_unicode}]} 796 }], 797 [] = run(Conf, Ts2), 798 799 Ts3 = [{latin1_fallback3, 800 %% Test that the compiler fall backs to latin-1 with 801 %% a warning if a file has no encoding and does not 802 %% contain correct UTF-8 sequences. 803 <<"-ifdef(NOTDEFINED). 804 t(_) -> \"",246,"\"; 805 t(x) -> ok. 806 -endif. 807 ">>, 808 [], 809 {warnings,[{2,compile,reparsing_invalid_unicode}]}}], 810 [] = run(Conf, Ts3), 811 812 ok. 813 814underscore(Config) when is_list(Config) -> 815 S0 = <<"f(A) -> 816 _VAR1 = <<A>>, 817 _VAR2 = {ok,A}, 818 _VAR3 = [A], 819 ok. 820 g(A) -> 821 _VAR1 = A/0, 822 _VAR2 = date(), 823 ok. 824 h() -> 825 _VAR1 = fun() -> ok end, 826 ok. 827 i(A) -> 828 _VAR1 = #{A=>42}, 829 ok. 830 ">>, 831 Ts0 = [{underscore0, 832 S0, 833 [], 834 {warnings,[{2,sys_core_fold,useless_building}, 835 {3,sys_core_fold,useless_building}, 836 {4,sys_core_fold,useless_building}, 837 {7,sys_core_fold,result_ignored}, 838 {8,sys_core_fold,{no_effect,{erlang,date,0}}}, 839 {11,sys_core_fold,useless_building}, 840 {14,sys_core_fold,useless_building} 841 ]}}], 842 [] = run(Config, Ts0), 843 844 %% Replace all "_VAR<digit>" variables with a plain underscore. 845 %% Now there should be no warnings. 846 S1 = re:replace(S0, "_VAR\\d+", "_", [global]), 847 io:format("~s\n", [S1]), 848 Ts1 = [{underscore1,S1,[],[]}], 849 [] = run(Config, Ts1), 850 851 ok. 852 853no_warnings(Config) when is_list(Config) -> 854 Ts = [{no_warnings, 855 <<"-record(r, {s=ordsets:new(),a,b}). 856 857 a() -> 858 R = #r{}, %No warning expected. 859 {R#r.a,R#r.b}. 860 861 b(X) -> 862 T = true, 863 Var = [X], %No warning expected. 864 case T of 865 false -> Var; 866 true -> [] 867 end. 868 869 c() -> 870 R0 = {r,\"abc\",undefined,os:timestamp()}, %No warning. 871 case R0 of 872 {r,V1,_V2,V3} -> {r,V1,\"def\",V3} 873 end. 874 875 d(In0, Bool) -> 876 {In1,Int} = case id(Bool) of 877 false -> {In0,0} 878 end, 879 [In1,Int]. 880 881 id(I) -> I. 882 ">>, 883 [], 884 []}], 885 run(Config, Ts), 886 ok. 887 888bit_syntax(Config) -> 889 Ts = [{?FUNCTION_NAME, 890 <<"a(<<-1>>) -> ok; 891 a(<<1023>>) -> ok; 892 a(<<777/signed>>) -> ok; 893 a(<<a/binary>>) -> ok; 894 a(<<a/integer>>) -> ok; 895 a(<<a/float>>) -> ok; 896 a(<<a/utf8>>) -> ok; 897 a(<<a/utf16>>) -> ok; 898 a(<<a/utf32>>) -> ok; 899 a(<<a/utf32>>) -> ok. 900 b(Bin) -> Sz = bad, <<42:Sz>> = Bin. 901 c(Sz, Bin) -> 902 case Bin of 903 <<-42:Sz/unsigned>> -> ok; 904 <<42:Sz/float>> -> ok; 905 <<42:Sz/binary>> -> ok 906 end. 907 ">>, 908 [], 909 {warnings,[{1,sys_core_fold,no_clause_match}, 910 {1,sys_core_fold,{nomatch_bit_syntax_unsigned,-1}}, 911 {2,sys_core_fold,{nomatch_bit_syntax_truncated, 912 unsigned,1023,8}}, 913 {3,sys_core_fold,{nomatch_bit_syntax_truncated, 914 signed,777,8}}, 915 {4,sys_core_fold,{nomatch_bit_syntax_type,a,binary}}, 916 {5,sys_core_fold,{nomatch_bit_syntax_type,a,integer}}, 917 {6,sys_core_fold,{nomatch_bit_syntax_type,a,float}}, 918 {7,sys_core_fold,{nomatch_bit_syntax_type,a,utf8}}, 919 {8,sys_core_fold,{nomatch_bit_syntax_type,a,utf16}}, 920 {9,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, 921 {10,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, 922 {11,sys_core_fold,no_clause_match}, 923 {11,sys_core_fold,{nomatch_bit_syntax_size,bad}}, 924 {14,sys_core_fold,{nomatch_bit_syntax_unsigned,-42}}, 925 {16,sys_core_fold,{nomatch_bit_syntax_type,42,binary}} 926 ]} 927 }], 928 run(Config, Ts), 929 ok. 930 931inlining(Config) -> 932 %% Make sure that no spurious warnings are generated 933 %% when inlining. 934 Ts = [{inlining_1, 935 <<"-compile(inline). 936 compute1(X) -> add(X, 0). 937 add(1, 0) -> 1; 938 add(1, Y) -> 1 + Y; 939 add(X, Y) -> X + Y. 940 ">>, 941 [], 942 []}, 943 {inlining_2, 944 <<"-compile({inline,[add/2]}). 945 compute1(X) -> add(X, 0). 946 add(1, 0) -> 1; 947 add(1, Y) -> 1 + Y; 948 add(X, Y) -> X + Y. 949 ">>, 950 [], 951 []} 952 ], 953 run(Config, Ts), 954 ok. 955 956tuple_calls(Config) -> 957 %% Make sure that no spurious warnings are generated. 958 Ts = [{inlining_1, 959 <<"-compile(tuple_calls). 960 dispatch(X) -> 961 (list_to_atom(\"prefix_\" ++ 962 atom_to_list(suffix))):doit(X). 963 ">>, 964 [], 965 []} 966 ], 967 run(Config, Ts), 968 ok. 969 970%%% 971%%% End of test cases. 972%%% 973 974run(Config, Tests) -> 975 F = fun({N,P,Ws,E}, BadL) -> 976 case catch run_test(Config, P, Ws) of 977 E -> 978 BadL; 979 Bad -> 980 io:format("~nTest ~p failed. Expected~n ~p~n" 981 "but got~n ~p~n", [N, E, Bad]), 982 fail() 983 end 984 end, 985 lists:foldl(F, [], Tests). 986 987 988%% Compiles a test module and returns the list of errors and warnings. 989 990run_test(Conf, Test0, Warnings) -> 991 Module = "warnings_"++test_lib:uniq(), 992 Filename = Module ++ ".erl", 993 DataDir = ?privdir, 994 Test = ["-module(", Module, "). ", Test0], 995 File = filename:join(DataDir, Filename), 996 Opts = [binary,export_all,return|Warnings], 997 ok = file:write_file(File, Test), 998 999 %% Compile once just to print all warnings. 1000 compile:file(File, [binary,export_all,report|Warnings]), 1001 1002 %% Test result of compilation. 1003 Res = case compile:file(File, Opts) of 1004 {ok, _M, Bin, []} when is_binary(Bin) -> 1005 []; 1006 {ok, _M, Bin, Ws0} when is_binary(Bin) -> 1007 %% We are not interested in warnings from 1008 %% erl_lint here. 1009 WsL = [{F,[W || {_,Mod,_}=W <- Ws, 1010 Mod =/= erl_lint]} || 1011 {F,Ws} <- Ws0], 1012 case WsL of 1013 [{_File,Ws}] -> {warnings, Ws}; 1014 _ -> list_to_tuple([warnings, WsL]) 1015 end 1016 end, 1017 file:delete(File), 1018 Res. 1019 1020fail() -> 1021 ct:fail(failed). 1022