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