1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2004-2019. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(match_SUITE). 21 22-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 23 init_per_group/2,end_per_group/2, 24 pmatch/1,mixed/1,aliases/1,non_matching_aliases/1, 25 match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, 26 selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1, 27 coverage/1,grab_bag/1,literal_binary/1, 28 unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1, 29 tuple_size_in_try/1,match_boolean_list/1]). 30 31-include_lib("common_test/include/ct.hrl"). 32 33suite() -> [{ct_hooks,[ts_install_cth]}]. 34 35all() -> 36 [{group,p}]. 37 38groups() -> 39 [{p,[parallel], 40 [pmatch,mixed,aliases,non_matching_aliases, 41 match_in_call,untuplify, 42 shortcut_boolean,letify_guard,selectify,deselectify, 43 underscore,match_map,map_vars_used,coverage, 44 grab_bag,literal_binary,unary_op,eq_types, 45 match_after_return,match_right_tuple, 46 tuple_size_in_try,match_boolean_list]}]. 47 48 49init_per_suite(Config) -> 50 test_lib:recompile(?MODULE), 51 Config. 52 53end_per_suite(_Config) -> 54 ok. 55 56init_per_group(_GroupName, Config) -> 57 Config. 58 59end_per_group(_GroupName, Config) -> 60 Config. 61 62 63pmatch(Config) when is_list(Config) -> 64 ok = doit(1), 65 ok = doit(2), 66 {error,baz} = doit(3), 67 {error,foobar} = doit(4), 68 ok. 69 70%% Thanks to Tobias Lindahl (HiPE). 71-define(FOO(X), 72 case X of 73 1 -> foo; 74 2 -> bar; 75 3 -> baz; 76 4 -> foobar 77 end). 78 79doit(X) -> 80 case ?FOO(X) of 81 foo -> ok; 82 bar -> ok; 83 Other -> {error, Other} 84 end. 85 86mixed(Config) when is_list(Config) -> 87 glufs = mixit(1), 88 klafs = mixit(2), 89 fnurra = mixit(3), 90 usch = mixit(4), 91 {error,blurf} = mixit(5), 92 {error,87987987} = mixit(6), 93 {error,{a,b,c}} = mixit(7), 94 no_match = mixed_1(), 95 ok. 96 97mixit(X) -> 98 case case X of 99 1 -> a; 100 2 -> b; 101 3 -> 42; 102 4 -> 77; 103 4+1 -> blurf; 104 5+1 -> 87987987; 105 6+1 -> {a,b,c} 106 end of 107 a -> glufs; 108 b -> klafs; 109 42 -> fnurra; 110 77 -> usch; 111 Other -> {error,Other} 112 end. 113 114mixed_1() -> 115 case 0 of 116 0.0 -> 117 %% This clause must not match. 118 zero; 119 0.5 -> 120 half; 121 _ -> 122 no_match 123 end. 124 125aliases(Config) when is_list(Config) -> 126 %% Lists/strings. 127 ok = str_alias("abc"), 128 ok = str_alias("def"), 129 ok = str_alias("ghi"), 130 ok = str_alias("klm"), 131 ok = str_alias("qrs"), 132 ok = str_alias("xy"), 133 ok = str_alias(""), 134 ok = str_alias([]), 135 error = str_alias("blurf"), 136 137 %% Characters/integers. 138 ok = char_alias($v), 139 ok = char_alias(118), 140 ok = char_alias($w), 141 ok = char_alias(119), 142 ok = char_alias(42), 143 ok = char_alias(3.0), 144 error = char_alias($_), 145 error = char_alias(0), 146 147 {42,42,42} = three(42), 148 149 {1,42,99,1,42,99} = tuple_alias({1,42,99}), 150 {-10,20,-10,20,-10,20} = tuple_alias({-10,20}), 151 6 = tup_lit_alias({1,2,3}), 152 6 = tup_lit_alias_rev({1,2,3}), 153 154 {42,42,42,42} = multiple_aliases_1(42), 155 {7,7,7} = multiple_aliases_2(7), 156 {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}), 157 158 %% Lists/literals. 159 {a,b} = list_alias1([a,b]), 160 {a,b} = list_alias2([a,b]), 161 {a,b} = list_alias3([a,b]), 162 163 %% Multiple matches. 164 {'EXIT',{{badmatch,home},_}} = 165 (catch fun() -> 166 Rec = (42 = V) = home, 167 {Rec,V} 168 end()), 169 {home,home} = 170 fun() -> 171 Rec = (home = V) = home, 172 {Rec,V} 173 end(), 174 {'EXIT',{{badmatch,16},_}} = 175 (catch fun(B) -> 176 <<42:V>> = V = B 177 end(16)), 178 {'EXIT',{{badmatch,0},_}} = 179 (catch fun() -> 180 <<2:V>> = V = 0 181 end()), 182 {42,42} = 183 fun(E) -> 184 Rec = (42 = V) = id(E), 185 {Rec,V} 186 end(42), 187 188 ok. 189 190str_alias(V) -> 191 Res = str_alias_1(V), 192 Res = str_alias_2(V). 193 194str_alias_1([$a,$b,$c]="abc"="a"++[$b,$c]=[97,98,99]) -> ok; 195str_alias_1([$d|"ef"]="def") -> ok; 196str_alias_1([$g|"hi"]="g"++"hi"="gh"++"i"="ghi"++"") -> ok; 197str_alias_1("k"++"lm"=[$k|"lm"]) -> ok; 198str_alias_1([113,114,115]="qrs"=[$q,$r,$s]="q"++"r"++"s") -> ok; 199str_alias_1([$x,$y]="xy") -> ok; 200str_alias_1(""=[]) -> ok; 201str_alias_1(_) -> error. 202 203%% Make sure that different line numbers do not matter. 204 205str_alias_2([$a,$b,$c]= 206 "abc"= 207 "a"++[$b,$c 208 ]= 209 [97,98,99 210 ]) -> ok; 211str_alias_2([$d|"ef"]= 212 "def") -> ok; 213str_alias_2([$g|"hi"]= 214 "g"++"hi"= 215 "gh"++"i"= 216 "ghi"++"") -> ok; 217str_alias_2("k"++"lm"= 218 [$k|"lm" 219 ]) -> ok; 220str_alias_2([113,114,115]= 221 "qrs"=[$q,$r,$s 222 ]= 223 "q"++"r"++"s") -> ok; 224str_alias_2([$x,$y]= 225 "xy") -> ok; 226str_alias_2(""= 227 []) -> ok; 228str_alias_2(_) -> error. 229 230char_alias(V) -> 231 Res = char_alias_1(V), 232 Res = char_alias_2(V). 233 234char_alias_1(118=$v) -> ok; 235char_alias_1($w=119) -> ok; 236char_alias_1(42=42) -> ok; 237char_alias_1(3.0=3.0) -> ok; 238char_alias_1(_) -> error. 239 240char_alias_2(118= 241 $v) -> ok; 242char_alias_2($w= 243 119) -> ok; 244char_alias_2(42= 245 42) -> ok; 246char_alias_2(3.0= 247 3.0) -> ok; 248char_alias_2(_) -> error. 249 250three(V) -> 251 Res = three_1(V), 252 Res = three_2(V). 253 254three_1(A=B=C) -> 255 {A,B,C}. 256 257three_2(A= 258 B= 259 C) -> 260 {A,B,C}. 261 262tuple_alias({A,B,C}={X,Y,Z}) -> 263 {A,B,C,X,Y,Z}; 264tuple_alias({A,B}={C,D}={E,F}) -> 265 {A,B,C,D,E,F}. 266 267tup_lit_alias({A,B,C}={1,2,3}) -> 268 A+B+C. 269 270tup_lit_alias_rev({1,2,3}={A,B,C}) -> 271 A+B+C. 272 273multiple_aliases_1((A=B)=(C=D)) -> 274 {A,B,C,D}. 275 276multiple_aliases_2((A=B)=(A=C)) -> 277 {A,B,C}. 278 279multiple_aliases_3((A={_,_}=B)={_,_}=C) -> 280 {A,B,C}. 281 282list_alias1([a,b]=[X,Y]) -> 283 {X,Y}. 284 285list_alias2([X,Y]=[a,b]) -> 286 {X,Y}. 287 288list_alias3([X,b]=[a,Y]) -> 289 {X,Y}. 290 291non_matching_aliases(_Config) -> 292 none = mixed_aliases(<<42>>), 293 none = mixed_aliases([b]), 294 none = mixed_aliases([d]), 295 none = mixed_aliases({a,42}), 296 none = mixed_aliases(42), 297 none = mixed_aliases(<<6789:16>>), 298 none = mixed_aliases(#{key=>value}), 299 300 {'EXIT',{{badmatch,bar},_}} = (catch plus_plus_prefix()), 301 {'EXIT',{{badmatch,42},_}} = (catch nomatch_alias(42)), 302 {'EXIT',{{badmatch,job},_}} = (catch entirely()), 303 {'EXIT',{{badmatch,associates},_}} = (catch printer()), 304 {'EXIT',{{badmatch,borogoves},_}} = (catch tench()), 305 306 put(perch, 0), 307 {'EXIT',{{badmatch,{spine,42}},_}} = (catch perch(42)), 308 1 = erase(perch), 309 310 put(salmon, 0), 311 {'EXIT',{{badmatch,mimsy},_}} = (catch salmon()), 312 1 = erase(salmon), 313 314 put(shark, 0), 315 {'EXIT',{{badmatch,_},_}} = (catch shark()), 316 1 = erase(shark), 317 318 {'EXIT',{{badmatch,_},_}} = (catch radio(research)), 319 320 {'EXIT',{{case_clause,whatever},_}} = (catch pike1(whatever)), 321 {'EXIT',{{case_clause,whatever},_}} = (catch pike2(whatever)), 322 323 ok. 324 325mixed_aliases(<<X:8>> = x) -> {a,X}; 326mixed_aliases([b] = <<X:8>>) -> {b,X}; 327mixed_aliases(<<X:8>> = {a,X}) -> {c,X}; 328mixed_aliases([X] = <<X:8>>) -> {d,X}; 329mixed_aliases(<<X:16>> = X) -> {e,X}; 330mixed_aliases(X = <<X:16>>) -> {f,X}; 331mixed_aliases(<<X:16,_/binary>> = X) -> {g,X}; 332mixed_aliases(X = <<X:16,_/binary>>) -> {h,X}; 333mixed_aliases(X = #{key:=X}) -> {i,X}; 334mixed_aliases(#{key:=X} = X) -> {j,X}; 335mixed_aliases([X] = #{key:=X}) -> {k,X}; 336mixed_aliases(#{key:=X} = [X]) -> {l,X}; 337mixed_aliases({a,X} = #{key:=X}) -> {m,X}; 338mixed_aliases(#{key:=X} = {a,X}) -> {n,X}; 339mixed_aliases([] ++ (foo = [])) -> o; 340mixed_aliases(_) -> none. 341 342plus_plus_prefix() -> 343 [] ++ (foo = []) = bar. 344 345nomatch_alias(I) -> 346 {ok={A,B}} = id(I), 347 {A,B}. 348 349entirely() -> 350 0(((Voice = true) = cool) = job), 351 [receive _ -> Voice end || banking <- printer]. 352 353printer() -> 354 {[Indoor] = [] = associates}, 355 [ireland || Indoor <- Indoor]. 356 357tench() -> 358 E = begin 359 [A] = [] = borogoves, 360 A + 1 361 end, 362 E + 7 * A. 363 364perch(X) -> 365 begin 366 put(perch, get(perch)+1), 367 [A] = [] = {spine,X} 368 end. 369 370salmon() -> 371 {put(salmon, get(salmon)+1),#{key:=([A]=[])}=mimsy,exit(fail)}, 372 A + 10. 373 374shark() -> 375 (hello = there) = (catch shark(put(shark, get(shark)+1), a = b)). 376 377shark(_, _) -> 378 ok. 379 380radio(research) -> 381 (connection = proof) = 382 (catch erlang:trace_pattern(catch mechanisms + assist, 383 summary = mechanisms)). 384 385pike1(X) -> 386 case id([]) of 387 [] -> 388 case X of 389 [Var] = [] -> 390 ok 391 end 392 end, 393 Var. 394 395pike2(X) -> 396 case id([]) of 397 [] -> 398 case X of 399 [_] = [] -> 400 Var = 42 401 end 402 end, 403 Var. 404 405%% OTP-7018. 406 407match_in_call(Config) when is_list(Config) -> 408 mac_a(0), 409 mac_b(1), 410 mac_c(42), 411 mac_d(42), 412 mac_e({gurka,42}), 413 414 [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]), 415 {'EXIT',_} = (catch mac_lc([{1,1}])), 416 417 ok. 418 419mac_a(X) -> 420 id(_Gurka = {gurka,X}), 421 ok. 422 423mac_b(X) -> 424 id(Gurka = {gurka,X}), 425 gurka(Gurka, X), 426 ok. 427 428mac_c(X) -> 429 id(Gurka = Yxa = {gurka,X}), 430 id({Gurka,Yxa}), 431 ok. 432 433mac_d(X) -> 434 id({gurka,42} = {gurka,X}), 435 ok. 436 437mac_e(X) -> 438 id({gurka,42} = X), 439 ok. 440 441mac_lc(E) -> 442 Res = mac_lc1(E), 443 Res = mac_lc2(E). 444 445mac_lc1(E) -> 446 [{X,Y} || 447 {X,_} <- E, 448 (Y = X) =:= (Y = 1 + 1)]. 449 450mac_lc2(E) -> 451 [{X,Y} || 452 {X,_} <- E, 453 (Y = X) =:= (Y = 2)]. 454 455gurka({gurka,X}, X) -> ok. 456 457 458untuplify(Config) when is_list(Config) -> 459 %% We do this to cover sys_core_fold:unalias_pat/1. 460 {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias), 461 error = untuplify_1([1,2], {3,4}, 42), 462 463 %% Test that a previous bug in v3_codegen is gone. (The sinking of 464 %% stack frames into only the case arms that needed them was not always 465 %% safe.) 466 [33, -1, -33, 1] = untuplify_2(32, 65), 467 {33, 1, -33, -1} = untuplify_2(65, 32), 468 469 ok. 470 471untuplify_1(A, B, C) -> 472 case {A,B,C} of 473 {[X,Y],{Z,W},alias=Alias}=Top -> 474 {X,Y,Z,W,Alias,Top}; 475 [_,_]=CantMatch -> 476 CantMatch; 477 _ -> 478 error 479 end. 480 481untuplify_2(V1, V2) -> 482 {D1,D2,D3,D4} = 483 if V1 > V2 -> 484 %% The 1 value was overwritten by the value of V2-V1. 485 {V1-V2, 1, V2-V1, -1}; 486 true -> 487 {V2-V1, -1, V1-V2, 1} 488 end, 489 if 490 D2 > D4 -> 491 {D1, D2, D3, D4}; 492 true -> 493 [D1, D2, D3, D4] 494 end. 495 496%% Coverage of beam_dead:shortcut_boolean_label/4. 497shortcut_boolean(Config) when is_list(Config) -> 498 false = shortcut_boolean_1([0]), 499 true = shortcut_boolean_1({42}), 500 maybe = shortcut_boolean_1(self()), 501 {'EXIT',_} = (catch shortcut_boolean_1([a,b])), 502 {'EXIT',_} = (catch shortcut_boolean_1({a,b})), 503 ok. 504 505shortcut_boolean_1(X) -> 506 Outer = case not is_pid(X) of 507 true -> 508 V = case X of 509 [_] -> true; 510 {_} -> false 511 end, 512 not V; 513 false -> 514 maybe 515 end, 516 id(Outer). 517 518 519%% Test sys_core_fold:letify_guard/3. 520letify_guard(Config) when is_list(Config) -> 521 {-15,a} = letify_guard(-15, a), 522 5 = letify_guard(2, 3), 523 ok. 524 525letify_guard(A, B) -> 526 case {A,B} of 527 %% The tuple will be built in the guard... 528 Z when tuple_size(Z) =:= 2, element(1, Z) < 0 -> 529 %% ... and again here. 530 Z; 531 {X,Y} -> X+Y 532 end. 533 534%% Test combining of is_eq_exact instructions to select_val 535%% instructions in beam_dead and beam_peep. 536 537selectify(Config) when is_list(Config) -> 538 integer = sel_different_types({r,42}), 539 atom = sel_different_types({r,forty_two}), 540 float = sel_different_types({r,100.0}), 541 none = sel_different_types({r,18}), 542 {'EXIT',_} = (catch sel_different_types([a,b,c])), 543 544 integer = sel_same_value({r,42}), 545 error = sel_same_value({r,100}), 546 error = sel_same_value(a), 547 548 integer42 = sel_same_value2(42), 549 integer43 = sel_same_value2(43), 550 error = sel_same_value2(44), 551 552 ok. 553 554sel_different_types({r,_}=T) when element(2, T) =:= forty_two -> 555 atom; 556sel_different_types({r,_}=T) when element(2, T) =:= 42 -> 557 integer; 558sel_different_types({r,_}=T) when element(2, T) =:= 100.0 -> 559 float; 560sel_different_types({r,_}) -> 561 none. 562 563sel_same_value({r,V}) when V =:= 42 -> 564 integer; 565sel_same_value({r,V}) when V =:= 42 -> 566 integer42; 567sel_same_value(_) -> 568 error. 569 570sel_same_value2(V) when V =:= 42 -> 571 integer42; 572sel_same_value2(V) when V =:= 42; V =:= 43 -> 573 integer43; 574sel_same_value2(_) -> 575 error. 576 577%% Test deconstruction of select_val instructions to regular tests 578%% with zero or one values left. 579 580deselectify(Config) when is_list(Config) -> 581 one_or_other = desel_tuple_arity({1}), 582 two = desel_tuple_arity({1,1}), 583 one_or_other = desel_tuple_arity({1,1,1}), 584 585 one_or_other = dsel_integer(1), 586 two = dsel_integer(2), 587 one_or_other = dsel_integer(3), 588 589 one_or_other = dsel_integer_typecheck(1), 590 two = dsel_integer_typecheck(2), 591 one_or_other = dsel_integer_typecheck(3), 592 593 one_or_other = dsel_atom(one), 594 two = dsel_atom(two), 595 one_or_other = dsel_atom(three), 596 597 one_or_other = dsel_atom_typecheck(one), 598 two = dsel_atom_typecheck(two), 599 one_or_other = dsel_atom_typecheck(three), 600 601 %% Cover deconstruction of select_val instructions in 602 %% beam_peep. 603 604 stop = dsel_peek_0(stop), 605 ignore = dsel_peek_0(ignore), 606 Config = dsel_peek_0(Config), 607 608 stop = dsel_peek_1(stop, any), 609 Config = dsel_peek_1(ignore, Config), 610 other = dsel_peek_1(other, ignored), 611 612 0 = dsel_peek_2(0, any), 613 Config = dsel_peek_2(1, Config), 614 2 = dsel_peek_2(2, ignored), 615 616 true = dsel_peek_3(true), 617 false = dsel_peek_3(false), 618 {error,Config} = dsel_peek_3(Config), 619 620 ok. 621 622%% The following will be optimized by the sharing optimizations 623%% in beam_ssa_opt. 624 625desel_tuple_arity(Tuple) when is_tuple(Tuple) -> 626 case Tuple of 627 {_} -> one_or_other; 628 {_,_} -> two; 629 _ -> one_or_other 630 end. 631 632dsel_integer(Val) -> 633 case Val of 634 1 -> one_or_other; 635 2 -> two; 636 _ -> one_or_other 637 end. 638 639dsel_integer_typecheck(Val) when is_integer(Val) -> 640 case Val of 641 1 -> one_or_other; 642 2 -> two; 643 _ -> one_or_other 644 end. 645 646dsel_atom(Val) -> 647 case Val of 648 one -> one_or_other; 649 two -> two; 650 _ -> one_or_other 651 end. 652 653dsel_atom_typecheck(Val) when is_atom(Val) -> 654 case Val of 655 one -> one_or_other; 656 two -> two; 657 _ -> one_or_other 658 end. 659 660%% The following functions are carefully crafted so that the sharing 661%% optimizations in beam_ssa_opt can't be applied. After applying the 662%% beam_jump:eliminate_moves/1 optimization and beam_clean:clean_labels/1 663%% has unified labels, beam_peep is able to optimize these functions. 664 665dsel_peek_0(A0) -> 666 case id(A0) of 667 stop -> stop; 668 ignore -> ignore; 669 A -> A 670 end. 671 672dsel_peek_1(A0, B) -> 673 case id(A0) of 674 stop -> stop; 675 ignore -> B; 676 A -> A 677 end. 678 679dsel_peek_2(A0, B) -> 680 case id(A0) of 681 0 -> 0; 682 1 -> B; 683 A -> A 684 end. 685 686dsel_peek_3(A0) -> 687 case id(A0) of 688 true -> true; 689 false -> false; 690 Other -> {error,Other} 691 end. 692 693underscore(Config) when is_list(Config) -> 694 case Config of 695 [] -> 696 %% Assignment to _ at the end of a construct. 697 _ = length(Config); 698 [_|_] -> 699 %% Assignment to _ at the end of a construct. 700 _ = list_to_tuple(Config) 701 end, 702 _ = is_list(Config), 703 ok. 704 705-record(s, {map,t}). 706 707match_map(Config) when is_list(Config) -> 708 Map = #{key=>{x,y},ignore=>anything}, 709 #s{map=Map,t={x,y}} = do_match_map(#s{map=Map}), 710 {a,#{k:={a,b,c}}} = do_match_map_2(#{k=>{a,b,c}}), 711 ok. 712 713do_match_map(#s{map=#{key:=Val}}=S) -> 714 %% Would crash with a 'badarg' exception. 715 S#s{t=Val}. 716 717do_match_map_2(Map) -> 718 case {a,Map} of 719 {a,#{k:=_}}=Tuple -> 720 Tuple 721 end. 722 723map_vars_used(Config) when is_list(Config) -> 724 {some,value} = do_map_vars_used(a, b, #{{a,b}=>42,v=>{some,value}}), 725 ok. 726 727do_map_vars_used(X, Y, Map) -> 728 case {X,Y} of 729 T -> 730 %% core_lib:is_var_used/2 would not consider T used. 731 #{T:=42,v:=Val} = Map, 732 Val 733 end. 734 735-record(coverage_id, {bool=false,id}). 736coverage(Config) when is_list(Config) -> 737 %% Cover beam_dead. 738 ok = coverage_1(x, a), 739 ok = coverage_1(x, b), 740 741 %% Cover sys_pre_expand. 742 ok = coverage_3("abc"), 743 744 %% Cover beam_ssa_dead. 745 {expr,key} = coverage_4([literal,get], [[expr,key]]), 746 {expr,key} = coverage_4([expr,key], []), 747 748 a = coverage_5([8,8,8], #coverage_id{bool=true}), 749 b = coverage_5([], #coverage_id{bool=true}), 750 751 %% Cover beam_ssa_opt. 752 ok = coverage_6(), 753 754 ok. 755 756coverage_1(B, Tag) -> 757 case Tag of 758 a -> coverage_2(1, a, B); 759 b -> coverage_2(2, b, B) 760 end. 761 762coverage_2(1, a, x) -> ok; 763coverage_2(2, b, x) -> ok. 764 765coverage_3([$a]++[]++"bc") -> ok. 766 767%% Cover beam_ssa_dead:eval_type_test_1(is_nonempty_list, Arg). 768coverage_4([literal,get], [Expr]) -> 769 coverage_4(Expr, []); 770coverage_4([Expr,Key], []) -> 771 {Expr,Key}. 772 773%% Cover beam_ssa_dead:eval_type_test_1(is_tagged_tuple, Arg). 774coverage_5(Config, TermId) 775 when TermId =:= #coverage_id{bool=true}, 776 Config =:= [8,8,8] -> 777 a; 778coverage_5(_Config, #coverage_id{bool=true}) -> 779 b. 780 781coverage_6() -> 782 X = 17, 783 case 784 case id(1) > 0 of 785 true -> 786 17; 787 false -> 788 42 789 end 790 of 791 X -> 792 ok; 793 V -> 794 %% Cover beam_ssa_opt:make_literal/2. 795 error([error,X,V]) 796 end. 797 798grab_bag(_Config) -> 799 [_|T] = id([a,b,c]), 800 [b,c] = id(T), 801 802 T1 = fun() -> 803 [_|_] = x 804 end, 805 {'EXIT',_} = (catch T1()), 806 807 T2 = fun(A, B) -> 808 case {{element(1, A),element(2, B)}, 809 {element(2, A),element(2, B)}} of 810 {Same,Same} -> ok; 811 {{0,1},{up,X}} -> id(X); 812 {_,{X,_}} -> id(X) 813 end 814 end, 815 ok = T2({a,a,z,z}, {z,a,z}), 816 1 = T2({0,up}, {zzz,1}), 817 y = T2({x,y}, {a,z,z}), 818 819 %% OTP-5244. 820 L = [{stretch,0,0}, 821 {bad,[]}, 822 {bad,atom}, 823 {bad,0}, 824 {bad,16#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}, 825 {bad,16#555555555555555555555555555555555555555555555555555}], 826 ok = grab_bag_remove_failure(L, unit, 0), 827 828 {42,<<43,44>>} = grab_bag_single_valued(<<42,43,44>>), 829 empty_list = grab_bag_single_valued([]), 830 empty_tuple = grab_bag_single_valued({}), 831 832 ok. 833 834grab_bag_remove_failure([], _Unit, _MaxFailure) -> 835 ok; 836grab_bag_remove_failure([{bad,Bad}|_], _Unit, _MaxFailure) -> 837 Bad; 838grab_bag_remove_failure([{stretch,_,Mi}=Stretch | Specs], Unit, _MaxFailure) -> 839 {MinMax,NewMaxFailure} = id({min,1}), 840 case {MinMax,grab_bag_remove_failure(Specs, Unit, NewMaxFailure)} of 841 {min,{NewMaxFailure,Rest}} -> 842 {done,[{fixed,Mi} | Rest]}; 843 {min,_} when Specs =/= [] -> 844 grab_bag_remove_failure([Stretch|tl(Specs)], Unit, NewMaxFailure); 845 {min,_} -> 846 ok 847 end. 848 849%% Cover a line v3_kernel that places binary matching first. 850grab_bag_single_valued(<<H,T/bytes>>) -> {H,T}; 851grab_bag_single_valued([]) -> empty_list; 852grab_bag_single_valued({}) -> empty_tuple. 853 854 855%% Regression in 19.0, reported by Alexei Sholik 856literal_binary(_Config) -> 857 3 = literal_binary_match(bar, <<"y">>), 858 859 %% While we are at it, also test the remaining code paths 860 %% in literal_binary_match/2. 861 1 = literal_binary_match(bar, <<"x">>), 862 2 = literal_binary_match(foo, <<"x">>), 863 3 = literal_binary_match(foo, <<"y">>), 864 fail = literal_binary_match(bar, <<"z">>), 865 fail = literal_binary_match(foo, <<"z">>), 866 ok. 867 868literal_binary_match(bar, <<"x">>) -> 1; 869literal_binary_match(_, <<"x">>) -> 2; 870literal_binary_match(_, <<"y">>) -> 3; 871literal_binary_match(_, _) -> fail. 872 873unary_op(Config) -> 874 %% ERL-514. This test case only verifies that the code 875 %% calculates the correct result, not that the generated 876 %% code is optimial. 877 878 {non_associative,30} = unary_op_1('&'), 879 {non_associative,300} = unary_op_1('^'), 880 {non_associative,300} = unary_op_1('not'), 881 {non_associative,300} = unary_op_1('+'), 882 {non_associative,300} = unary_op_1('-'), 883 {non_associative,300} = unary_op_1('~~~'), 884 {non_associative,300} = unary_op_1('!'), 885 {non_associative,320} = unary_op_1('@'), 886 887 error = unary_op_1(Config), 888 error = unary_op_1(abc), 889 error = unary_op_1(42), 890 891 ok. 892 893unary_op_1(Vop@1) -> 894 %% If all optimizations are working as they should, there should 895 %% be no stack frame and all '=:=' tests should be coalesced into 896 %% a single select_val instruction. 897 898 case Vop@1 =:= '&' of 899 true -> 900 {non_associative,30}; 901 false -> 902 case 903 case Vop@1 =:= '^' of 904 true -> 905 true; 906 false -> 907 case Vop@1 =:= 'not' of 908 true -> 909 true; 910 false -> 911 case Vop@1 =:= '+' of 912 true -> 913 true; 914 false -> 915 case Vop@1 =:= '-' of 916 true -> 917 true; 918 false -> 919 case Vop@1 =:= '~~~' of 920 true -> 921 true; 922 false -> 923 Vop@1 =:= '!' 924 end 925 end 926 end 927 end 928 end 929 of 930 true -> 931 {non_associative,300}; 932 false -> 933 case Vop@1 =:= '@' of 934 true -> 935 {non_associative,320}; 936 false -> 937 error 938 end 939 end 940 end. 941 942eq_types(_Config) -> 943 Ref = make_ref(), 944 Ref = eq_types(Ref, any), 945 ok. 946 947eq_types(A, B) -> 948 %% {put_tuple2,{y,0},{list,[{x,0},{x,1}]}}. 949 Term0 = {A, B}, 950 Term = id(Term0), 951 952 %% {test,is_eq_exact,{f,3},[{y,0},{x,0}]}. 953 %% Here beam_validator must infer that {x,0} has the 954 %% same type as {y,0}. 955 Term = Term0, 956 957 %% {get_tuple_element,{x,0},0,{x,0}}. 958 {Ref22,_} = Term, 959 960 Ref22. 961 962match_after_return(Config) when is_list(Config) -> 963 %% The return type of the following call will never match the 'wont_happen' 964 %% clauses below, and the beam_ssa_type was clever enough to see that but 965 %% didn't remove the blocks, so it crashed when trying to extract A. 966 ok = case mar_test_tuple(erlang:unique_integer()) of 967 {gurka, never_matches, A} -> {wont_happen, A}; 968 _ -> ok 969 end. 970 971mar_test_tuple(I) -> {gurka, I}. 972 973match_right_tuple(Config) when is_list(Config) -> 974 %% The loader wrongly coalesced certain get_tuple_element sequences, fusing 975 %% the code below into a single i_get_tuple_element2 operating on {x,0} 976 %% even though the first one overwrites it. 977 %% 978 %% {get_tuple_element,{x,0},0,{x,0}}. 979 %% {get_tuple_element,{x,0},1,{x,1}}. 980 981 Inner = {id(wrong_element), id(ok)}, 982 Outer = {Inner, id(wrong_tuple)}, 983 ok = match_right_tuple_1(Outer). 984 985match_right_tuple_1(T) -> 986 {A, _} = T, 987 {_, B} = A, 988 %% The call ensures that A is in {x,0} and B is in {x,1} 989 id(force_succ_regs(A, B)). 990 991force_succ_regs(_A, B) -> B. 992 993tuple_size_in_try(Config) when is_list(Config) -> 994 %% The tuple_size optimization was applied outside of guards, causing 995 %% either the emulator or compiler to crash. 996 ok = tsit(gurka), 997 ok = tsit(gaffel). 998 999tsit(A) -> 1000 try 1001 id(ignored), 1002 1 = tuple_size(A), 1003 error 1004 catch 1005 _:_ -> ok 1006 end. 1007 1008match_boolean_list(Config) when is_list(Config) -> 1009 BoolList = [N rem 2 =:= 0 || N <- lists:seq(1, 8)], 1010 %% The compiler knows that all list elements are booleans, so it translates 1011 %% the expression below to a #b_br{} on the list head. 1012 %% 1013 %% This is fine, but since the value was only used in that branch, 1014 %% reserve_zregs/3 (pre_codegen) would place the variable in a z register, 1015 %% crashing the compiler in a later pass. 1016 ok = case BoolList of 1017 [true | _] -> error; 1018 [false | _] -> ok 1019 end. 1020 1021id(I) -> I. 1022