1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2005-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
21-module(bs_match_SUITE).
22-compile(nowarn_shadow_vars).
23
24-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
25	 init_per_group/2,end_per_group/2,
26	 init_per_testcase/2,end_per_testcase/2,
27	 size_shadow/1,int_float/1,otp_5269/1,null_fields/1,wiger/1,
28	 bin_tail/1,save_restore/1,
29	 partitioned_bs_match/1,function_clause/1,
30	 unit/1,shared_sub_bins/1,bin_and_float/1,
31	 dec_subidentifiers/1,skip_optional_tag/1,decode_integer/1,
32	 wfbm/1,degenerated_match/1,bs_sum/1,coverage/1,
33	 multiple_uses/1,zero_label/1,followed_by_catch/1,
34	 matching_meets_construction/1,simon/1,matching_and_andalso/1,
35	 otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1,
36	 match_string/1,zero_width/1,bad_size/1,haystack/1,
37	 cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1,
38	 no_partition/1,calling_a_binary/1,binary_in_map/1,
39	 match_string_opt/1,select_on_integer/1,
40	 map_and_binary/1,unsafe_branch_caching/1,
41	 bad_literals/1,good_literals/1,constant_propagation/1,
42	 parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
43         beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1,
44         bs_start_match2_defs/1]).
45
46-export([coverage_id/1,coverage_external_ignore/2]).
47
48-include_lib("common_test/include/ct.hrl").
49-include_lib("syntax_tools/include/merl.hrl").
50
51
52suite() ->
53    [{ct_hooks,[ts_install_cth]},
54     {timetrap,{minutes,1}}].
55
56all() ->
57    [{group,p}].
58
59groups() ->
60    [{p,[parallel],
61      [size_shadow,int_float,otp_5269,null_fields,wiger,
62       bin_tail,save_restore,
63       partitioned_bs_match,function_clause,unit,
64       shared_sub_bins,bin_and_float,dec_subidentifiers,
65       skip_optional_tag,decode_integer,wfbm,degenerated_match,bs_sum,
66       coverage,multiple_uses,zero_label,followed_by_catch,
67       matching_meets_construction,simon,
68       matching_and_andalso,otp_7188,otp_7233,otp_7240,
69       otp_7498,match_string,zero_width,bad_size,haystack,
70       cover_beam_bool,matched_out_size,follow_fail_branch,
71       no_partition,calling_a_binary,binary_in_map,
72       match_string_opt,select_on_integer,
73       map_and_binary,unsafe_branch_caching,
74       bad_literals,good_literals,constant_propagation,parse_xml,
75       get_payload,escape,num_slots_different,
76       beam_bsm,guard,is_ascii,non_opt_eq,erl_689,
77       bs_start_match2_defs]}].
78
79
80init_per_suite(Config) ->
81    test_lib:recompile(?MODULE),
82    Config.
83
84end_per_suite(_Config) ->
85    ok.
86
87init_per_group(_GroupName, Config) ->
88    Config.
89
90end_per_group(_GroupName, Config) ->
91    Config.
92
93
94init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
95    Config.
96
97end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
98    ok.
99
100size_shadow(Config) when is_list(Config) ->
101    %% Originally OTP-5270.
102    7 = size_shadow_1(),
103    7 = size_shadow_2(8),
104    7 = size_shadow_3(),
105    no = size_shadow_4(8),
106    Any = {any,term,goes},
107    {2577,Any,-175,whatever} =
108	(size_shadow_5(Any, 12))(<<2577:12>>, -175, whatever),
109    {7777,Any,42,whatever} =
110	(size_shadow_6(Any, 13))(42, <<7777:13>>, whatever),
111    {<<45>>,<<>>} = size_shadow_7({int,1}, <<1:16,45>>),
112    {'EXIT',{function_clause,_}} =
113	(catch size_shadow_7({int,42}, <<1:16,45>>)),
114    ok.
115
116size_shadow_1() ->
117    L = 8,
118    F = fun(<<L:L,B:L>>) -> B end,
119    F(<<16:8, 7:16>>).
120
121size_shadow_2(L) ->
122    F = fun(<<L:L,B:L>>) -> B end,
123    F(<<16:8, 7:16>>).
124
125size_shadow_3() ->
126    L = 8,
127    F = fun(<<L:L,B:L,L:L>>) -> B end,
128    F(<<16:8, 7:16,16:16>>).
129
130size_shadow_4(L) ->
131    F = fun(<<L:L,B:L,L:L>>) -> B;
132	   (_) -> no end,
133    F(<<16:8, 7:16,15:16>>).
134
135size_shadow_5(X, Y) ->
136    fun (<< A:Y >>, Y, B) -> fum(A, X, Y, B) end.
137
138size_shadow_6(X, Y) ->
139    fun (Y, << A:Y >>, B) -> fum(A, X, Y, B) end.
140
141fum(A, B, C, D) ->
142    {A,B,C,D}.
143
144size_shadow_7({int,N}, <<N:16,B:N/binary,T/binary>>) ->
145    {B,T}.
146
147
148int_float(Config) when is_list(Config) ->
149    %% OTP-5323
150    <<103133.0:64/float>> = <<103133:64/float>>,
151    <<103133:64/float>> = <<103133:64/float>>,
152
153    %% Coverage of error cases in sys_pre_expand:coerce_to_float/2.
154    case id(default) of
155	<<(1 bsl 1024):64/float>> ->
156	    ct:fail(should_not_match);
157	default ->
158	    ok
159    end.
160
161%% Stolen from erl_eval_SUITE and modified.
162%% OTP-5269. Bugs in the bit syntax.
163otp_5269(Config) when is_list(Config) ->
164    check(fun() -> L = 8,
165		   F = fun(<<A:L,B:A>>) -> B end,
166		   F(<<16:8, 7:16>>)
167                end,
168                7),
169    check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end,
170	  7),
171    check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end,
172	  32),
173    check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end,
174	  [32]),
175    check(fun() -> [X || <<A:8,
176			   B:A>> <- [<<16:8,19:16>>],
177			 <<X:8>> <- [<<B:8>>]] end,
178	  [19]),
179    check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end,
180	  28),
181    check(fun() ->
182		  <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
183		  {Size,B,Rest}
184	  end,
185	  {2,<<"AB">>,<<"CD">>}),
186    check(fun() -> X = 32,
187		   [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
188    %% "binsize variable"    ^
189	  [1,2]),
190    check(fun() ->
191		  (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) ->
192			   case A of
193			       B -> wrong;
194			       _ -> ok
195			   end
196		   end)(<<1,2,3,4>>) end,
197	  ok),
198    ok.
199
200null_fields(Config) when is_list(Config) ->
201    check(fun() ->
202		  W = id(0),
203		  F = fun(<<_:W>>) -> tail;
204			 (<<>>) -> empty
205		      end,
206		  F(<<>>)
207	  end, tail),
208    check(fun() ->
209		  F = fun(<<_/binary>>) -> tail;
210			 (<<>>) -> empty
211		      end,
212		  F(<<>>)
213	  end, tail),
214    ok.
215
216wiger(Config) when is_list(Config) ->
217    ok1 = wcheck(<<3>>),
218    ok2 = wcheck(<<1,2,3>>),
219    ok3 = wcheck(<<4>>),
220    {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
221    {error,<<>>} = wcheck(<<>>),
222    ok.
223
224wcheck(<<A>>) when A==3->
225    ok1;
226wcheck(<<_,_:2/binary>>) ->
227    ok2;
228wcheck(<<_>>) ->
229    ok3;
230wcheck(Other) ->
231    {error,Other}.
232
233bin_tail(Config) when is_list(Config) ->
234    S = <<"abcde">>,
235    $a = bin_tail_c(S, 0),
236    $c = bin_tail_c(S, 2),
237    $e = bin_tail_c(S, 4),
238    {'EXIT',_} = (catch bin_tail_c(S, 5)),
239    {'EXIT',_} = (catch bin_tail_c_var(S, 5)),
240
241    $a = bin_tail_d(S, 0),
242    $b = bin_tail_d(S, 8),
243    $d = bin_tail_d(S, 3*8),
244    {'EXIT',_} = (catch bin_tail_d_dead(S, 1)),
245    {'EXIT',_} = (catch bin_tail_d_dead(S, 9)),
246    {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)),
247    {'EXIT',_} = (catch bin_tail_d_var(S, 1)),
248
249    ok = bin_tail_e(<<2:2,0:1,1:5>>),
250    ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
251    error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
252    error = bin_tail_e(<<>>),
253    ok.
254
255bin_tail_c(Bin, Offset) ->
256    Res = bin_tail_c_dead(Bin, Offset),
257    <<_:Offset/binary,_,Tail/binary>> = Bin,
258    {Res,Tail} = bin_tail_c_var(Bin, Offset),
259    Res.
260
261bin_tail_c_dead(Bin, Offset) ->
262    <<_:Offset/binary,C,_/binary>> = Bin,
263    C.
264
265bin_tail_c_var(Bin, Offset) ->
266    <<_:Offset/binary,C,Tail/binary>> = Bin,
267    {C,Tail}.
268
269
270bin_tail_d(Bin, BitOffset) ->
271    Res = bin_tail_d_dead(Bin, BitOffset),
272    <<_:BitOffset,_:8,Tail/binary>> = Bin,
273    {Res,Tail} = bin_tail_d_var(Bin, BitOffset),
274    Res.
275
276bin_tail_d_dead(Bin, BitOffset) ->
277    <<_:BitOffset,C,_/binary>> = Bin,
278    C.
279
280bin_tail_d_var(Bin, BitOffset) ->
281    <<_:BitOffset,C,Tail/binary>> = Bin,
282    {C,Tail}.
283
284bin_tail_e(Bin) ->
285    case bin_tail_e_dead(Bin) of
286	ok ->
287	    <<_,Tail/binary>> = Bin,
288	    Tail = bin_tail_e_var(Bin),
289	    ok;
290	error ->
291	    bin_tail_e_var(Bin)
292    end.
293
294bin_tail_e_dead(Bin) ->
295    case Bin of
296	%% The binary is aligned at the end; neither the bs_skip_bits2 nor
297	%% bs_test_tail2 instructions are needed.
298	<<2:2,_:1,1:5,_/binary>> -> ok;
299	_ -> error
300    end.
301
302bin_tail_e_var(Bin) ->
303    case Bin of
304	%% The binary is aligned at the end; neither the bs_skip_bits2 nor
305	%% bs_test_tail2 instructions are needed.
306	<<2:2,_:1,1:5,Tail/binary>> -> Tail;
307	_ -> error
308    end.
309
310save_restore(Config) when is_list(Config) ->
311    0 = save_restore_1(<<0:2,42:6>>),
312    {1,3456} = save_restore_1(<<1:2,3456:14>>),
313    {2,7981234} = save_restore_1(<<2:2,7981234:30>>),
314    {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>),
315
316    A = <<" x">>,
317    B = <<".x">>,
318    C = <<"-x">>,
319
320    {" ",<<"x">>} = lll(A),
321    {" ",<<"x">>} = mmm(A),
322    {" ",<<"x">>} = nnn(A),
323    {" ",<<"x">>} = ooo(A),
324
325    {".",<<"x">>} = lll(B),
326    {".",<<"x">>} = mmm(B),
327    {".",<<"x">>} = nnn(B),
328    {".",<<"x">>} = ooo(B),
329
330    {"-",<<"x">>} = lll(C),
331    {"-",<<"x">>} = mmm(C),
332    {"-",<<"x">>} = nnn(C),
333    {"-",<<"x">>} = ooo(C),
334
335    a = multiple_matches(<<777:16>>, <<777:16>>),
336    b = multiple_matches(<<777:16>>, <<999:16>>),
337    c = multiple_matches(<<777:16>>, <<57:8>>),
338    d = multiple_matches(<<17:8>>, <<1111:16>>),
339
340    Bin = <<-1:64>>,
341    case bad_float_unpack_match(Bin) of
342	-1 -> ok;
343	_Other -> ct:fail(bad_return_value_probably_NaN)
344    end.
345
346save_restore_1(Bin) ->
347    case Bin of
348	<<0:2,_:6>> -> 0;
349	<<1:2,A:14>> -> {1,A};
350	<<2:2,A:30>> -> {2,A};
351	<<A:64>> -> {3,A}
352    end.
353
354lll(<<Char,         Tail/binary>>) -> {[Char],Tail}.
355
356mmm(<<$.,$.,$.,     Tail/binary>>) -> Tail;
357mmm(<<$\s,$-,$\s,   Tail/binary>>) -> Tail;
358mmm(<<Char,         Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
359
360nnn(<<"...",        Tail/binary>>) -> Tail;
361nnn(<<" - ",        Tail/binary>>) -> Tail;
362nnn(<<Char,         Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
363
364ooo(<<" - ",        Tail/binary>>) -> Tail;
365ooo(<<Char,         Tail/binary>>) -> {[Char],Tail}.
366
367multiple_matches(<<Y:16>>, <<Y:16>>) -> a;
368multiple_matches(<<_:16>>, <<_:16>>) -> b;
369multiple_matches(<<_:16>>, <<_:8>>) -> c;
370multiple_matches(<<_:8>>, <<_:16>>) -> d.
371
372bad_float_unpack_match(<<F:64/float>>) -> F;
373bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
374
375
376partitioned_bs_match(Config) when is_list(Config) ->
377    <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>),
378    error = partitioned_bs_match(10, <<7,8,15,13>>),
379    error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}),
380    ok = partitioned_bs_match(0, <<>>),
381    fc(partitioned_bs_match, [-1,blurf],
382	     catch partitioned_bs_match(-1, blurf)),
383    fc(partitioned_bs_match, [-1,<<1,2,3>>],
384	     catch partitioned_bs_match(-1, <<1,2,3>>)),
385    {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>),
386    {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>),
387
388    fc(partitioned_bs_match_2, [4,<<0:17>>],
389	     catch partitioned_bs_match_2(4, <<0:17>>)),
390
391    anything = partitioned_bs_match_3(anything, <<42>>),
392    ok = partitioned_bs_match_3(1, 2),
393
394    ok.
395
396partitioned_bs_match(_, <<42:8,T/binary>>) ->
397    T;
398partitioned_bs_match(N, _) when N > 0 ->
399    error;
400partitioned_bs_match(_, <<>>) ->
401    ok.
402
403partitioned_bs_match_2(1, <<B:8,T/binary>>) ->
404    {B,T};
405partitioned_bs_match_2(Len, <<_:8,T/binary>>) ->
406    {Len,T}.
407
408partitioned_bs_match_3(Var, <<_>>) -> Var;
409partitioned_bs_match_3(1, 2) -> ok.
410
411function_clause(Config) when is_list(Config)  ->
412    ok = function_clause_1(<<0,7,0,7,42>>),
413    fc(function_clause_1, [<<0,1,2,3>>],
414       catch function_clause_1(<<0,1,2,3>>)),
415    fc(function_clause_1, [<<0,1,2,3>>],
416       catch function_clause_1(<<0,7,0,1,2,3>>)),
417
418    ok = function_clause_2(<<0,7,0,7,42>>),
419    ok = function_clause_2(<<255>>),
420    ok = function_clause_2(<<13:4>>),
421    fc(function_clause_2, [<<0,1,2,3>>],
422       catch function_clause_2(<<0,1,2,3>>)),
423    fc(function_clause_2, [<<0,1,2,3>>],
424       catch function_clause_2(<<0,7,0,1,2,3>>)),
425
426    ok.
427
428function_clause_1(<<0:8,7:8,T/binary>>) ->
429    function_clause_1(T);
430function_clause_1(<<_:8>>) ->
431    ok.
432
433function_clause_2(<<0:8,7:8,T/binary>>) ->
434    function_clause_2(T);
435function_clause_2(<<_:8>>) ->
436    ok;
437function_clause_2(<<_:4>>) ->
438    ok.
439
440unit(Config) when is_list(Config) ->
441    42 = peek1(<<42>>),
442    43 = peek1(<<43,1,2>>),
443    43 = peek1(<<43,1,2,(-1):1>>),
444    43 = peek1(<<43,1,2,(-1):2>>),
445    43 = peek1(<<43,1,2,(-1):7>>),
446
447    99 = peek8(<<99>>),
448    100 = peek8(<<100,101>>),
449    fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)),
450
451    37484 = peek16(<<37484:16>>),
452    37489 = peek16(<<37489:16,5566:16>>),
453    fc(peek16, [<<8>>], catch peek16(<<8>>)),
454    fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)),
455    fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)),
456
457    127 = peek7(<<127:7>>),
458    100 = peek7(<<100:7,19:7>>),
459    fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)),
460    ok.
461
462peek1(<<B:8,_/bitstring>>) -> B.
463
464peek7(<<B:7,_/binary-unit:7>>) -> B.
465
466peek8(<<B:8,_/binary>>) -> B.
467
468peek16(<<B:16,_/binary-unit:16>>) -> B.
469
470shared_sub_bins(Config) when is_list(Config) ->
471    {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
472    ok.
473
474sum(<<B,T/binary>>, Acc, Sum) ->
475    sum(T, [T|Acc], Sum+B);
476sum(<<>>, Last, Sum) -> {Sum,Last}.
477
478
479bin_and_float(Config) when is_list(Config) ->
480    14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0),
481    ok.
482
483bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X),
484							      is_float(Y),
485							      is_float(Z) ->
486    bin_and_float(T, Sum+X*X+Y*Y+Z*Z);
487bin_and_float(<<>>, Sum) -> Sum.
488
489dec_subidentifiers(Config) when is_list(Config) ->
490    {[],<<1,2,3>>} =
491	do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2),
492    {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2),
493    {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0),
494    ok.
495
496do_dec_subidentifiers(Buffer, Av, Al, Len) ->
497    Res = dec_subidentifiers(Buffer, Av, Al, Len),
498    Res = dec_subidentifiers2(Buffer, Av, Al, Len),
499    Res = dec_subidentifiers4(Buffer, Av, Al, Len),
500    Res = dec_subidentifiers3(Buffer, Av, Al, Len).
501
502dec_subidentifiers(Buffer, _Av, Al, 0) ->
503    {lists:reverse(Al),Buffer};
504dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
505    dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1);
506dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) ->
507    dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
508
509dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) ->
510    {lists:reverse(Al),Buffer};
511dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
512    dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1);
513dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) ->
514    dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
515
516dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) ->
517    {lists:reverse(Al),Buffer};
518dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
519    dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1);
520dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) ->
521    dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
522
523dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 ->
524    dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1);
525dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 ->
526    dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1);
527dec_subidentifiers4(Buffer, _Av, Al, 0) ->
528    {lists:reverse(Al),Buffer}.
529
530
531skip_optional_tag(Config) when is_list(Config) ->
532    {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>),
533    {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>),
534    {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>),
535    missing = skip_optional_tag(<<2:3>>, blurf),
536    ok.
537
538skip_optional_tag(<<>>, Binary) ->
539    {ok,Binary};
540skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) ->
541    skip_optional_tag(RestTag, Rest);
542skip_optional_tag(_, _) -> missing.
543
544decode_integer(_Config) ->
545    {10795,<<43>>,whatever} = decode_integer(1, <<42,43>>, whatever),
546    {-28909,<<19>>,whatever} = decode_integer(1, <<143,19>>, whatever),
547    ok.
548
549decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) when B1 == 0 ->
550    Bin = <<_Skip:Len/unit:8, Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>,
551    Size = byte_size(Bin),
552    <<Int:Size/unit:8>> = Bin,
553    {Int,Buffer2,RemovedBytes};
554decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes)  ->
555    Bin = <<_Skip:Len/unit:8,Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>,
556    Size = byte_size(Bin),
557    <<N:Size/unit:8>> = <<B2,Bs/binary>>,
558    Int = N - (1 bsl (8 * size(Bin) -1)),
559    {Int,Buffer2,RemovedBytes}.
560
561-define(DATELEN, 16).
562
563wfbm(Config) when is_list(Config) ->
564    %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski,
565    %% with modifications.
566    {nomatch,0} = check_for_dot_or_space(<<" ">>),
567    {nomatch,0} = check_for_dot_or_space(<<" abc">>),
568    {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>),
569    {nomatch,0} = check_for_dot_or_space(<<".gurka">>),
570    {nomatch,1} = check_for_dot_or_space(<<"g.urka">>),
571
572    nomatch = get_tail(<<>>),
573    {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>),
574    {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>),
575    nomatch = get_tail(<<"200y.2007.10.23.blurf ">>),
576    {'EXIT',_} = (catch get_tail({no,binary,at,all})),
577    {'EXIT',_} = (catch get_tail(no_binary)),
578    ok.
579
580check_for_dot_or_space(Bin) ->
581    check_for_dot_or_space(Bin, 0).
582
583check_for_dot_or_space(<<$\s, _/binary>>, 0) ->
584    {nomatch,0};
585check_for_dot_or_space(Bin, Len) ->
586    case Bin of
587        <<Front:Len/binary, $\s, _/binary>> ->
588            {ok,Front};
589        <<_:Len/binary, $., _/binary>> ->
590            {nomatch,Len};
591	_ ->
592            check_for_dot_or_space(Bin, Len+1)
593    end.
594
595get_tail(<<>>) ->
596    nomatch;
597get_tail(Bin) ->
598    <<Front:?DATELEN/binary, Tail/binary>> = Bin,
599    case Front of
600        <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> ->
601	    case check_for_dot_or_space(Tail) of
602                {ok,Match} ->
603                    {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>};
604                {nomatch,Skip} -> {skip,?DATELEN + Skip}
605            end;
606        _ -> nomatch
607    end.
608
609degenerated_match(Config) when is_list(Config) ->
610    error = degenerated_match_1(<<>>),
611    1 = degenerated_match_1(<<1:1>>),
612    2 = degenerated_match_1(<<42,43>>),
613
614    error = degenerated_match_2(<<>>),
615    no_split = degenerated_match_2(<<1,2>>),
616    {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>),
617
618    ok.
619
620degenerated_match_1(<<>>) -> error;
621degenerated_match_1(Bin) -> byte_size(Bin).
622
623degenerated_match_2(<<>>) -> error;
624degenerated_match_2(Bin) ->
625    case byte_size(Bin) > 4 of
626	true ->
627	    split_binary(Bin, 4);
628	false ->
629	    no_split
630    end.
631
632bs_sum(Config) when is_list(Config) ->
633    0 = bs_sum_1([]),
634    0 = bs_sum_1(<<>>),
635    42 = bs_sum_1([42]),
636    1 = bs_sum_1(<<1>>),
637    10 = bs_sum_1([1,2,3,4]),
638    15 = bs_sum_1(<<1,2,3,4,5>>),
639    21 = bs_sum_1([1,2,3|<<4,5,6>>]),
640    15 = bs_sum_1([1,2,3|{4,5}]),
641    6 = bs_sum_1([1,2,3|zero]),
642    6 = bs_sum_1([1,2,3|0]),
643    7 = bs_sum_1([1,2,3|one]),
644
645    fc(catch bs_sum_1({too,big,tuple})),
646    fc(catch bs_sum_1([1,2,3|{too,big,tuple}])),
647
648    [] = sneaky_alias(<<>>),
649    [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)),
650    fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))),
651    fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))),
652    ok.
653
654bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T);
655bs_sum_1([H|T]) -> H+bs_sum_1(T);
656bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B;
657bs_sum_1(0) -> 0;
658bs_sum_1(zero=_Zero) -> 0;
659bs_sum_1(one) -> 1;
660bs_sum_1([]) -> 0;
661bs_sum_1(<<>>) -> 0.
662
663sneaky_alias(<<>>=L) -> binary_to_list(L);
664sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)].
665
666coverage(Config) when is_list(Config) ->
667    0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>),
668    6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>),
669    fc(catch coverage_fold(fun(B, A) ->
670					 A+B
671				 end, 0, [a,b,c])),
672
673    {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
674    {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
675    {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
676	coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
677
678    [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
679
680    {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
681
682    [42] = coverage_apply(<<42>>, [coverage_id]),
683    42 = coverage_external(<<42>>),
684
685    do_coverage_bin_to_term_list([]),
686    do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
687    fc(coverage_bin_to_term_list, [<<0,0,0,7>>],
688	     catch do_coverage_bin_to_term_list_1(<<7:32>>)),
689
690    <<>> = coverage_per_key(<<4:32>>),
691    <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
692
693    binary = coverage_bitstring(<<>>),
694    binary = coverage_bitstring(<<7>>),
695    bitstring = coverage_bitstring(<<7:4>>),
696    other = coverage_bitstring([a]),
697    ok.
698
699coverage_fold(Fun, Acc, <<H,T/binary>>) ->
700    IdFun = fun id/1,
701    coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T);
702coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc.
703
704coverage_build(Acc0, <<H,T/binary>>, float) ->
705    Float = id(<<H:64/float>>),
706    Acc = <<Acc0/binary,Float/binary>>,
707    coverage_build(Acc, T, float);
708coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
709    Str = id(<<H:(id(4)),(H-1):4,"abc">>),
710    Acc = id(<<Acc0/bitstring,Str/bitstring>>),
711    Tuple = setelement(2, setelement(3, Tuple0, 43), 42),
712    if
713	byte_size(Acc) > 0 ->
714	    coverage_build(Acc, T, Tuple)
715    end;
716coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}.
717
718coverage_bc(<<H,T/binary>>, Acc) ->
719    B = << <<C:8>> || C <- [H] >>,
720    coverage_bc(T, [B|Acc]);
721coverage_bc(<<>>, Acc) -> Acc.
722
723coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x ->
724    setelement(H, Tuple, T1).
725
726coverage_apply(<<H,T/binary>>, [F|Fs]) ->
727    [?MODULE:F(H)|coverage_apply(T, Fs)];
728coverage_apply(<<>>, []) -> [].
729
730coverage_external(<<H,T/binary>>) ->
731    ?MODULE:coverage_external_ignore(T, T),
732    H.
733
734coverage_external_ignore(_, _) ->
735    ok.
736
737coverage_id(I) -> id(I).
738
739do_coverage_bin_to_term_list(L) ->
740    Bin = << <<(begin BinTerm = term_to_binary(Term),
741		      <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> ||
742	      Term <- L >>,
743    L = do_coverage_bin_to_term_list_1(Bin),
744    L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>),
745    L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>).
746
747do_coverage_bin_to_term_list_1(Bin) ->
748    Res = coverage_bin_to_term_list(Bin),
749    Res = coverage_bin_to_term_list(Bin, []),
750    Res = coverage_bin_to_term_list_catch(Bin),
751    Res = coverage_bin_to_term_list_catch(Bin, []).
752
753coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
754    try binary_to_term(BinTerm) of
755	Term -> [Term|coverage_bin_to_term_list(T)]
756    catch
757	error:badarg -> coverage_bin_to_term_list(T)
758    end;
759coverage_bin_to_term_list(<<>>) -> [].
760
761coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
762    try binary_to_term(BinTerm) of
763	Term -> coverage_bin_to_term_list(T, [Term|Acc])
764    catch
765	error:badarg -> coverage_bin_to_term_list(T, Acc)
766    end;
767coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc).
768
769coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
770    case catch binary_to_term(BinTerm) of
771	{'EXIT',_} -> coverage_bin_to_term_list_catch(T);
772	Term -> [Term|coverage_bin_to_term_list_catch(T)]
773    end;
774coverage_bin_to_term_list_catch(<<>>) -> [].
775
776coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
777    case catch binary_to_term(BinTerm) of
778	{'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc);
779	Term -> coverage_bin_to_term_list_catch(T, [Term|Acc])
780    end;
781coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc).
782
783coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
784    true = (byte_size(B) =:= BinSize),
785    Bin.
786
787coverage_bitstring(Bin) when is_binary(Bin) -> binary;
788coverage_bitstring(<<_/bitstring>>) -> bitstring;
789coverage_bitstring(_) -> other.
790
791multiple_uses(Config) when is_list(Config) ->
792    {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
793    true = multiple_uses_2(<<0,0,197,18>>),
794    <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1),
795
796    ok = first_after(<<>>, 42),
797    <<1>> = first_after(<<1,2,3>>, 0),
798    <<2>> = first_after(<<1,2,3>>, 1),
799
800    ok.
801
802multiple_uses_1(<<X:16,Tail/binary>>) ->
803    %% NOT OPTIMIZED: sub binary is matched or used in more than one place
804    {Y,Z} = multiple_uses_match(Tail),
805    {X,Y,Z,Tail}.
806
807multiple_uses_2(<<_:16,Tail/binary>>) ->
808    %% NOT OPTIMIZED: sub binary is matched or used in more than one place
809    multiple_uses_cmp(Tail, Tail).
810
811multiple_uses_3(<<_:16,Tail/binary>>, Fun) ->
812    %% NOT OPTIMIZED: sub binary is used or returned
813    Fun(Tail).
814
815multiple_uses_match(<<Y:16,Z:16>>) ->
816    {Y,Z}.
817
818multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true;
819multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false.
820
821first_after(Data, Offset) ->
822    case byte_size(Data) > Offset of
823	false ->
824	    {_First, _Rest} = {ok, ok},
825	    ok;
826	true ->
827	    <<_:Offset/binary, Rest/binary>> = Data,
828	    %% 'Rest' saved in y(0) before the call.
829            {First, _} = match_first(Data, Rest),
830            %% When beam_bsm sees the code, the following line
831            %% which uses y(0) has been optimized away.
832	    {First, Rest} = {First, Rest},
833	    First
834    end.
835
836match_first(_, <<First:1/binary, Rest/binary>>) ->
837    {First, Rest}.
838
839zero_label(Config) when is_list(Config) ->
840    <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>),
841    <<"CE">> = read_pols(<<"noFACE">>),
842    ok.
843
844read_pols(Data) ->
845    <<PolygonType:4/binary,Rest/binary>> = Data,
846    %% Intentional warning.
847    (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>),
848    Rest.
849
850followed_by_catch(Config) when is_list(Config) ->
851    ok = handle(<<0,1,2,3,4,5>>).
852
853-record(rec,{field}).
854handle(<<>>) ->  ok;
855handle(Msg) ->
856    <<_DataLen:16, Rest/binary>> = Msg,
857    case catch fooX:func() of
858	[X] ->
859	    X#rec.field;
860	_ ->
861	    ok
862    end,
863    handle(Rest).
864
865matching_meets_construction(Config) when is_list(Config) ->
866    Bin = id(<<"abc">>),
867    Len = id(2),
868    Tail0 = id(<<1,2,3,4,5>>),
869    <<_:Len/binary,Tail/binary>> = Tail0,
870    Res = <<Tail/binary,Bin/binary>>,
871    <<3,4,5,"abc">> = Res,
872    {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)),
873    {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)),
874    <<"Bbc">> = matching_meets_construction_3(<<"Abc">>),
875
876    <<1,2>> = encode_octet_string(<<1,2,3>>, 2),
877    ok.
878
879matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>.
880
881matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>.
882
883matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>.
884
885encode_octet_string(<<OctetString/binary>>, Len) ->
886    <<OctetString:Len/binary-unit:8>>.
887
888simon(Config) when is_list(Config) ->
889    one = simon(blurf, <<>>),
890    two = simon(0, <<42>>),
891    fc(simon, [17,<<1>>], catch simon(17, <<1>>)),
892    fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)),
893
894    one = simon2(blurf, <<9>>),
895    two = simon2(0, <<9,1>>),
896    fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)),
897    ok.
898
899simon(_, <<>>) -> one;
900simon(0, <<_>>) -> two.
901
902simon2(_, <<9>>) -> one;
903simon2(0, <<_:16>>) -> two.
904
905
906%% OTP-7113: Crash in v3_codegen.
907matching_and_andalso(Config) when is_list(Config) ->
908    ok = matching_and_andalso_1(<<1,2,3>>, 3),
909    {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)),
910    {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
911    {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
912
913    {"abc",<<"xyz">>} = matching_and_andalso_23("abc", <<"-xyz">>),
914    {"abc",<<"">>} = matching_and_andalso_23("abc", <<($a-1)>>),
915    {"abc",<<"">>} = matching_and_andalso_23("abc", <<($z+1)>>),
916    {"abc",<<"">>} = matching_and_andalso_23("abc", <<($A-1)>>),
917    {"abc",<<"">>} = matching_and_andalso_23("abc", <<($Z+1)>>),
918    error = matching_and_andalso_23([], <<>>),
919    error = matching_and_andalso_23([], <<$A>>),
920    error = matching_and_andalso_23([], <<$Z>>),
921    error = matching_and_andalso_23([], <<$a>>),
922    error = matching_and_andalso_23([], <<$z>>),
923    ok.
924
925matching_and_andalso_1(<<Bitmap/binary>>, K)
926  when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K ->
927    ok.
928
929matching_and_andalso_23(Datetime, Bin) ->
930    Res = matching_and_andalso_2(Datetime, Bin),
931    Res = matching_and_andalso_3(Datetime, Bin),
932    Res.
933
934matching_and_andalso_2(Datetime, <<H,T/binary>>)
935  when not ((H >= $a) andalso (H =< $z)) andalso
936       not ((H >= $A) andalso (H =< $Z)) ->
937    {Datetime,T};
938matching_and_andalso_2(_, _) -> error.
939
940%% Contrived example to ensure we cover the handling of 'call' instructions
941%% in v3_codegen:bsm_rename_ctx/4.
942matching_and_andalso_3(Datetime, <<H,T/binary>>)
943  when not ((abs(H) >= $a) andalso (abs(H) =< $z)) andalso
944       not ((abs(H) >= $A) andalso (abs(H) =< $Z)) ->
945    {Datetime,T};
946matching_and_andalso_3(_, _) -> error.
947
948%% Thanks to Tomas Stejskal.
949otp_7188(Config) when is_list(Config) ->
950    MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0,
951	   0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76,
952	   97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,
953	   101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
954	   0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115,
955	   116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
956	   32,32,12>>,
957    {ok,{"ID3v1",
958	       [{title,<<68,117,154,105,232,107,121>>},
959		{artist,<<"Daniel Landa">>},
960		{album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3).
961
962parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
963		     Artist:30/binary, Album:30/binary,
964		     _Year:4/binary, _Comment:28/binary,
965		     0:8, Track:8, _Genre:8>>) ->
966    {ok,
967     {"ID3v1.1",
968      [{track, Track}, {title, trim(Title)},
969       {artist, trim(Artist)}, {album, trim(Album)}]}};
970parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
971		     Artist:30/binary, Album:30/binary,
972		     _Year:4/binary, _Comment:30/binary,
973		     _Genre:8>>) ->
974    {ok,
975     {"ID3v1",
976      [{title, trim(Title)},
977       {artist, trim(Artist)},
978       {album, trim(Album)}]}};
979parse_v1_or_v11_tag(_) ->
980    error.
981
982trim(Bin) ->
983    list_to_binary(trim_blanks(binary_to_list(Bin))).
984
985trim_blanks(L) ->
986    lists:reverse(skip_blanks_and_zero(lists:reverse(L))).
987
988skip_blanks_and_zero([$\s|T]) ->
989    skip_blanks_and_zero(T);
990skip_blanks_and_zero([0|T]) ->
991    skip_blanks_and_zero(T);
992skip_blanks_and_zero(L) ->
993    L.
994
995%% OTP-7233. Record and binary matching optimizations clashed.
996%% Thanks to Vladimir Klebansky.
997
998-record(rec_otp_7233, {key, val}).
999
1000otp_7233(Config) when is_list(Config) ->
1001    otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}),
1002    [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format),
1003    erase(io_format),
1004    otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}),
1005    undefined = get(io_format),
1006    ok.
1007
1008otp_7233_1(Rec) ->
1009    <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key,
1010    case K of
1011	<<"XX">> ->
1012	    Value = Rec#rec_otp_7233.val,
1013	    case lists:keyfind("xxxxxxxx", 1, Value) of
1014		false ->
1015		    ok;
1016		T ->
1017		    put(io_format, [Rec#rec_otp_7233.key,T])
1018	    end;
1019	_ -> ok
1020    end.
1021
1022
1023otp_7240(Config) when is_list(Config) ->
1024    a = otp_7240_a(0, <<>>),
1025    b = otp_7240_a(1, 2),
1026
1027    a = otp_7240_b(anything, <<>>),
1028    b = otp_7240_b(1, {x,y}),
1029
1030    a = otp_7240_c(anything, <<>>),
1031    b = otp_7240_c(1, <<2>>),
1032
1033    a = otp_7240_d(anything, <<>>),
1034    b = otp_7240_d(again, <<2>>),
1035
1036    a = otp_7240_e(anything, <<>>),
1037    b = otp_7240_e(1, 41),
1038
1039    a = otp_7240_f(anything, <<>>),
1040    b = otp_7240_f(1, {}),
1041
1042    ok.
1043
1044otp_7240_a(_, <<>>) -> a;
1045otp_7240_a(1, 2) -> b.
1046
1047otp_7240_b(_, <<>>) -> a;
1048otp_7240_b(1, {_,_}) -> b.
1049
1050otp_7240_c(_, <<>>) -> a;
1051otp_7240_c(1, <<2>>) -> b.
1052
1053otp_7240_d(_, <<>>) -> a;
1054otp_7240_d(_, <<2>>) -> b.
1055
1056otp_7240_e(_, <<>>) -> a;
1057otp_7240_e(1, B) when B < 42 -> b.
1058
1059otp_7240_f(_, <<>>) -> a;
1060otp_7240_f(1, B) when is_tuple(B) -> b.
1061
1062otp_7498(Config) when is_list(Config) ->
1063    <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0),
1064    <<2,3>> = otp_7498_foo(<<1,2,3>>, 1),
1065    <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2),
1066
1067    <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0),
1068    <<2,3>> = otp_7498_bar(<<1,2,3>>, 1),
1069    <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2),
1070    <<>> = otp_7498_bar(<<>>, 2),
1071    <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3),
1072
1073    ok.
1074
1075otp_7498_foo(Bin, 0) ->
1076   otp_7498_foo(Bin, 42);
1077otp_7498_foo(<<_A, Rest/bitstring>>, 1) ->
1078   otp_7498_foo(Rest, 43);
1079otp_7498_foo(Bin, _I)  ->
1080   Bin.
1081
1082otp_7498_bar(Bin, 0) ->
1083   otp_7498_bar(Bin, 42);
1084otp_7498_bar(<<_A, Rest/bitstring>>, 1) ->
1085   otp_7498_bar(Rest, 43);
1086otp_7498_bar(<<>>, 2) ->
1087   otp_7498_bar(<<>>, 44);
1088otp_7498_bar(Bin, _I)  ->
1089   Bin.
1090
1091
1092match_string(Config) when is_list(Config) ->
1093    %% To make sure that native endian really is handled correctly
1094    %% (i.e. that the compiler does not attempt to use bs_match_string/4
1095    %% instructions for native segments), running this test is not enough.
1096    %% Either examine the generated for do_match_string_native/1 or
1097    %% check the coverage for the v3_kernel module.
1098    case erlang:system_info(endian) of
1099	little ->
1100	    do_match_string_native(<<$a,0,$b,0>>);
1101	big ->
1102	    do_match_string_native(<<0,$a,0,$b>>)
1103    end,
1104
1105    do_match_string_big(<<0,$a,0,$b>>),
1106    do_match_string_little(<<$a,0,$b,0>>),
1107
1108    do_match_string_big_signed(<<255,255>>),
1109    do_match_string_little_signed(<<255,255>>),
1110
1111    plain = no_match_string_opt(<<"abc">>),
1112    strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>),
1113
1114    ok.
1115
1116do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok.
1117
1118do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok.
1119
1120do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok.
1121
1122do_match_string_big_signed(<<(-1):16/signed>>) -> ok.
1123
1124do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok.
1125
1126no_match_string_opt(<<"abc">>) -> plain;
1127no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange.
1128
1129
1130%% OTP-7591: A zero-width segment in matching would crash the compiler.
1131
1132zero_width(Config) when is_list(Config) ->
1133    <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>,
1134    2 = Len,
1135    Str = <<"hi">>,
1136
1137    %% Match sure that values that cannot fit in a segment will not match.
1138    case id(<<0:8>>) of
1139	<<256:8>> -> ct:fail(should_not_match);
1140	_ -> ok
1141    end,
1142    ok.
1143
1144
1145%% OTP_7650: A invalid size for binary segments could crash the compiler.
1146bad_size(Config) when is_list(Config) ->
1147    Tuple = {a,b,c},
1148    {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
1149    Binary = <<1,2,3>>,
1150    {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
1151    ok.
1152
1153haystack(Config) when is_list(Config) ->
1154    <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>),
1155    [<<0:10/unit:8>>,
1156	   <<0:20/unit:8>>] = haystack_2(<<1:8192>>),
1157    ok.
1158
1159%% Used to crash the compiler.
1160haystack_1(Haystack) ->
1161    Subs = [10],
1162    [begin
1163	 <<B:Y/binary>> = Haystack,
1164	 B
1165     end || Y <- Subs],
1166    Haystack.
1167
1168%% There would be an incorrect badmatch exception.
1169haystack_2(Haystack) ->
1170    Subs = [{687,10},{369,20}],
1171    [begin
1172	 <<_:X/binary,B:Y/binary,_/binary>> = Haystack,
1173	 B
1174     end || {X,Y} <- Subs ].
1175
1176fc({'EXIT',{function_clause,_}}) -> ok;
1177fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok.
1178
1179fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok;
1180fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity,_}|_]}})
1181  when length(Args) =:= Arity ->
1182    true = test_server:is_native(?MODULE);
1183fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}})
1184  when ?MODULE =:= bs_match_inline_SUITE ->
1185    Args = tuple_to_list(ActualArgs).
1186
1187%% Cover the clause handling bs_context to binary in
1188%% beam_block:initialized_regs/2.
1189cover_beam_bool(Config) when is_list(Config) ->
1190    ok = do_cover_beam_bool(<<>>, 3),
1191    <<19>> = do_cover_beam_bool(<<19>>, 2),
1192    <<42>> = do_cover_beam_bool(<<42>>, 1),
1193    <<17>> = do_cover_beam_bool(<<13,17>>, 0),
1194    ok.
1195
1196do_cover_beam_bool(Bin, X) when X > 0 ->
1197    if
1198	X =:= 1; X =:= 2 ->
1199	    Bin;
1200	true ->
1201	    ok
1202    end;
1203do_cover_beam_bool(<<_,Bin/binary>>, X) ->
1204    do_cover_beam_bool(Bin, X+1).
1205
1206matched_out_size(Config) when is_list(Config) ->
1207    {253,16#DEADBEEF} = mos_int(<<8,253,16#DEADBEEF:32>>),
1208    {6,16#BEEFDEAD} = mos_int(<<3,6:3,16#BEEFDEAD:32>>),
1209    {53,16#CAFEDEADBEEFCAFE} = mos_int(<<16,53:16,16#CAFEDEADBEEFCAFE:64>>),
1210    {23,16#CAFEDEADBEEFCAFE} = mos_int(<<5,23:5,16#CAFEDEADBEEFCAFE:64>>),
1211
1212    {<<1,2,3>>,4} = mos_bin(<<3,1,2,3,4,3>>),
1213    {<<1,2,3,7>>,19,42} = mos_bin(<<4,1,2,3,7,19,4,42>>),
1214    <<1,2,3,7>> = mos_bin(<<4,1,2,3,7,"abcdefghij">>),
1215
1216    ok.
1217
1218mos_int(<<L,I:L,X:32>>) ->
1219    {I,X};
1220mos_int(<<L,I:L,X:64>>) ->
1221    {I,X}.
1222
1223mos_bin(<<L,Bin:L/binary,X:8,L>>) ->
1224    L = byte_size(Bin),
1225    {Bin,X};
1226mos_bin(<<L,Bin:L/binary,X:8,L,Y:8>>) ->
1227    L = byte_size(Bin),
1228    {Bin,X,Y};
1229mos_bin(<<L,Bin:L/binary,"abcdefghij">>) ->
1230    L = byte_size(Bin),
1231    Bin.
1232
1233follow_fail_branch(_) ->
1234    42 = ffb_1(<<0,1>>, <<0>>),
1235    8 = ffb_1(<<0,1>>, [a]),
1236    42 = ffb_2(<<0,1>>, <<0>>, 17),
1237    8 = ffb_2(<<0,1>>, [a], 0),
1238    ok.
1239
1240ffb_1(<<_,T/bitstring>>, List) ->
1241    case List of
1242	<<_>> ->
1243	    42;
1244	[_|_] ->
1245	    %% The fail branch of the bs_start_match2 instruction
1246	    %% pointing to here would be ignored, making the compiler
1247	    %% incorrectly assume that the delayed sub-binary
1248	    %% optimization was safe.
1249	    bit_size(T)
1250    end.
1251
1252ffb_2(<<_,T/bitstring>>, List, A) ->
1253    case List of
1254	<<_>> when A =:= 17 -> 42;
1255	[_|_] -> bit_size(T)
1256    end.
1257
1258no_partition(_) ->
1259    one = no_partition_1(<<"string">>, a1),
1260    {two,<<"string">>} = no_partition_1(<<"string">>, a2),
1261    {two,<<>>} = no_partition_1(<<>>, a2),
1262    {two,a} = no_partition_1(a, a2),
1263    three = no_partition_1(undefined, a3),
1264    {four,a,[]} = no_partition_1([a], a4),
1265    {five,a,b} = no_partition_1({a,b}, a5),
1266
1267    one = no_partition_2(<<"string">>, a1),
1268    two = no_partition_2(<<"string">>, a2),
1269    two = no_partition_2(<<>>, a2),
1270    two = no_partition_2(a, a2),
1271    three = no_partition_2(undefined, a3),
1272    four = no_partition_2(42, a4),
1273    five = no_partition_2([], a5),
1274    six = no_partition_2(42.0, a6),
1275    ok.
1276
1277no_partition_1(<<"string">>, a1) ->
1278    one;
1279no_partition_1(V, a2) ->
1280    {two,V};
1281no_partition_1(undefined, a3) ->
1282    three;
1283no_partition_1([H|T], a4) ->
1284    {four,H,T};
1285no_partition_1({A,B}, a5) ->
1286    {five,A,B}.
1287
1288no_partition_2(<<"string">>, a1) ->
1289    one;
1290no_partition_2(_, a2) ->
1291    two;
1292no_partition_2(undefined, a3) ->
1293    three;
1294no_partition_2(42, a4) ->
1295    four;
1296no_partition_2([], a5) ->
1297    five;
1298no_partition_2(42.0, a6) ->
1299    six.
1300
1301calling_a_binary(Config) when is_list(Config) ->
1302    [] = call_binary(<<>>, []),
1303    {'EXIT',{badarg,_}} = (catch call_binary(<<1>>, [])),
1304    {'EXIT',{badarg,_}} = (catch call_binary(<<1,2,3>>, [])),
1305    ok.
1306
1307call_binary(<<>>, Acc) ->
1308    Acc;
1309call_binary(<<H,T/bits>>, Acc) ->
1310    T(<<Acc/binary,H>>).
1311
1312binary_in_map(Config) when is_list(Config) ->
1313    ok = match_binary_in_map(#{key => <<42:8>>}),
1314    {'EXIT',{{badmatch,#{key := 1}},_}} =
1315	(catch match_binary_in_map(#{key => 1})),
1316    {'EXIT',{{badmatch,#{key := <<1023:16>>}},_}} =
1317	(catch match_binary_in_map(#{key => <<1023:16>>})),
1318    {'EXIT',{{badmatch,#{key := <<1:8>>}},_}} =
1319	(catch match_binary_in_map(#{key => <<1:8>>})),
1320    {'EXIT',{{badmatch,not_a_map},_}} =
1321	(catch match_binary_in_map(not_a_map)),
1322    ok.
1323
1324match_binary_in_map(Map) ->
1325    case 8 of
1326	N ->
1327	    #{key := <<42:N>>} = Map,
1328	    ok
1329    end.
1330
1331match_string_opt(Config) when is_list(Config) ->
1332    {x,<<1,2,3>>,{<<1>>,{v,<<1,2,3>>}}} =
1333	do_match_string_opt({<<1>>,{v,<<1,2,3>>}}),
1334    ok.
1335
1336do_match_string_opt({<<1>>,{v,V}}=T) ->
1337    {x,V,T}.
1338
1339select_on_integer(Config) when is_list(Config) ->
1340    42 = do_select_on_integer(<<42>>),
1341    <<"abc">> = do_select_on_integer(<<128,"abc">>),
1342
1343    {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)),
1344    {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)),
1345    {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)),
1346    ok.
1347
1348%% The ASN.1 compiler frequently generates code like this.
1349do_select_on_integer(<<0:1,I:7>>) ->
1350    I;
1351do_select_on_integer(<<1:1,_:7,Bin/binary>>) ->
1352    Bin.
1353
1354%% If 'bin_opt_info' was given the warning would lack filename
1355%% and line number.
1356
1357map_and_binary(_Config) ->
1358    {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>),
1359    Map1 = #{time => "noon"},
1360    {ok,Map1} = do_map_and_binary(Map1),
1361    Map2 = #{hour => 8, min => 42},
1362    {8,42,Map2} = do_map_and_binary(Map2),
1363    ok.
1364
1365do_map_and_binary(<<Hour:2/bytes, $:, Min:2/bytes, Rest/binary>>) ->
1366    {Hour, Min, Rest};
1367do_map_and_binary(#{time := _} = T) ->
1368    {ok, T};
1369do_map_and_binary(#{hour := Hour, min := Min} = T) ->
1370    {Hour, Min, T}.
1371
1372%% Unsafe caching of branch outcomes in beam_bsm would cause the
1373%% delayed creation of sub-binaries optimization to be applied even
1374%% when it was unsafe.
1375
1376unsafe_branch_caching(_Config) ->
1377    <<>> = do_unsafe_branch_caching(<<42,1>>),
1378    <<>> = do_unsafe_branch_caching(<<42,2>>),
1379    <<>> = do_unsafe_branch_caching(<<42,3>>),
1380    <<17,18>> = do_unsafe_branch_caching(<<42,3,17,18>>),
1381    <<>> = do_unsafe_branch_caching(<<1,3,42,2>>),
1382
1383    ok.
1384
1385do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) ->
1386    <<C1/integer, B1/binary>> = Bin,
1387    case C1 of
1388	X when X =:= 1 orelse X =:= 2 ->
1389	    Bin2 = <<>>;
1390	_ ->
1391	    Bin2 = B1
1392    end,
1393    case Code of
1394	1 -> do_unsafe_branch_caching(Bin2);
1395	_ -> Bin2
1396    end.
1397
1398bad_literals(_Config) ->
1399    Mod = list_to_atom(?MODULE_STRING ++ "_" ++
1400			   atom_to_list(?FUNCTION_NAME)),
1401    S = [signed_lit_match(V, Sz) || V <- lists:seq(-8, 8),
1402				    Sz <- [0,1,2,3]] ++
1403	[unsigned_lit_match(V, Sz) || V <- lists:seq(-2, 8),
1404				      Sz <- [0,1,2]] ++
1405	[unicode_match(V) ||
1406	    V <- [-100,-1,0,1,2|lists:seq(16#10FFFC, 16#110004)]],
1407    Code = ?Q(["-module('@Mod@').\n"
1408	       "-export([f/0]).\n"
1409	       "f() ->\n"
1410	       "_@S,\n"
1411	       "ok.\n"]),
1412    merl:print(Code),
1413    Opts = test_lib:opt_opts(?MODULE),
1414    {ok,_} = merl:compile_and_load(Code, Opts),
1415    Mod:f(),
1416
1417    {'EXIT',<<42>>} = (catch bad_literals_1()),
1418
1419    Sz = id(8),
1420    {'EXIT',{{badmatch,_},_}} = (catch <<-1:Sz>> = <<-1>>),
1421    ok.
1422
1423bad_literals_1() ->
1424    BadSz = bad,
1425    case case <<42>> of
1426	     <<42:BadSz>> -> ok;
1427	     Val -> exit(Val)
1428	 end of
1429	ok -> ok;
1430	error -> error
1431    end.
1432
1433signed_lit_match(V, Sz) ->
1434    case <<V:Sz>> of
1435	<<V:Sz/signed>> ->
1436	    ?Q("<<_@V@:_@Sz@/signed>> = <<_@V@:_@Sz@>>");
1437	_ ->
1438	    ?Q(["case <<_@V@:_@Sz@>> of\n",
1439		" <<_@V@:_@Sz@/signed>> ->\n",
1440		"  ct:fail(should_not_match);\n",
1441		" _ ->\n",
1442		"  ok\n",
1443		"end\n"])
1444    end.
1445
1446unsigned_lit_match(V, Sz) ->
1447    case <<V:Sz>> of
1448	<<V:Sz/unsigned>> ->
1449	    ?Q("<<_@V@:_@Sz@>> = <<_@V@:_@Sz@>>");
1450	_ ->
1451	    ?Q(["case <<_@V@:_@Sz@>> of\n",
1452		" <<_@V@:_@Sz@/unsigned>> ->\n",
1453		"  ct:fail(should_not_match);\n",
1454		" _ ->\n",
1455		"  ok\n",
1456		"end\n"])
1457    end.
1458
1459unicode_match(V) ->
1460    try <<V/utf8>> of
1461	<<V/utf8>> ->
1462	    ?Q(["<<_@V@/utf8>> = <<_@V@/utf8>>,\n",
1463		"<<_@V@/utf16>> = <<_@V@/utf16>>,\n",
1464		"<<_@V@/utf32>> = <<_@V@/utf32>>\n"])
1465    catch
1466	error:badarg ->
1467	    ?Q(["case <<_@V@:32>> of\n",
1468		" <<_@V@/utf32>> ->\n",
1469		"  ct:fail(should_not_match);\n",
1470		" _ ->\n",
1471		"  ok\n",
1472		"end\n"])
1473    end.
1474
1475%% Test a few legal but rare cases.
1476
1477good_literals(_Config) ->
1478    Sz = id(64),
1479
1480    %% Variable size.
1481    <<42:Sz>> = id(<<42:Sz>>),
1482    <<42.0:Sz/float>> = id(<<42:Sz/float>>),
1483
1484    %% unit > 1
1485    <<16#cafebeef:4/unit:8>> = id(<<16#cafebeef:32>>),
1486    ok.
1487
1488constant_propagation(_Config) ->
1489    <<5>> = constant_propagation_a(a, <<5>>),
1490    {'EXIT',{{case_clause,b},_}} = (catch constant_propagation_a(b, <<5>>)),
1491    258 = constant_propagation_b(<<1,2>>),
1492    F = constant_propagation_c(),
1493    259 = F(<<1,3>>),
1494    ok.
1495
1496constant_propagation_a(X, Y) ->
1497    case X of
1498	a -> Y2 = 8
1499    end,
1500    <<5:Y2>> = Y.
1501
1502constant_propagation_b(B) ->
1503    Sz = 16,
1504    <<X:Sz/integer>> = B,
1505    X.
1506
1507constant_propagation_c() ->
1508    Size = 16,
1509    fun(Bin) ->
1510	    <<X:Size/integer>> = Bin,
1511	    X
1512    end.
1513
1514parse_xml(_Config) ->
1515    <<"<?xmlX">> = do_parse_xml(<<"<?xmlX">>),
1516    <<" ">> = do_parse_xml(<<"<?xml ">>),
1517    ok.
1518
1519do_parse_xml(<<"<?xml"/utf8,Rest/binary>> = Bytes) ->
1520    %% Delayed sub-binary creation is not safe. A buggy (development)
1521    %% version of check_liveness_everywhere() in beam_utils would turn
1522    %% on the optimization.
1523    Rest1 = case is_next_char_whitespace(Rest) of
1524		false ->
1525		    Bytes;
1526		true ->
1527		    id(Rest)
1528	    end,
1529    id(Rest1).
1530
1531is_next_char_whitespace(<<C/utf8,_/binary>>) ->
1532    C =:= $\s.
1533
1534-record(ext_header,
1535        {this_hdr = 17,
1536         ext_hdr_opts}).
1537
1538get_payload(_Config) ->
1539    <<3445:48>> = do_get_payload(#ext_header{ext_hdr_opts = <<3445:48>>}),
1540    {'EXIT',_} = (catch do_get_payload(#ext_header{})),
1541    ok.
1542
1543do_get_payload(ExtHdr) ->
1544    _ = ExtHdr#ext_header.this_hdr,
1545    ExtHdrOptions = ExtHdr#ext_header.ext_hdr_opts,
1546    <<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts,
1547    ExtHdrOptions.
1548
1549escape(_Config) ->
1550    0 = escape(<<>>, 0),
1551    1 = escape(<<128>>, 0),
1552    2 = escape(<<128,255>>, 0),
1553    42 = escape(<<42>>, 0),
1554    50 = escape(<<42,8>>, 0),
1555    ok.
1556
1557escape(<<Byte, Rest/bits>>, Pos) when Byte >= 127 ->
1558    escape(Rest, Pos + 1);
1559escape(<<Byte, Rest/bits>>, Pos) ->
1560    escape(Rest, Pos + Byte);
1561escape(<<_Rest/bits>>, Pos) ->
1562    Pos.
1563
1564%% ERL-490
1565num_slots_different(_Config) ->
1566    Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>},
1567          {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>},
1568          {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>},
1569          {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>},
1570          {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>},
1571          {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>},
1572          {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}],
1573    _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts],
1574
1575    {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)),
1576    {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)),
1577    {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)),
1578    {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)),
1579    ok.
1580
1581
1582lgettext(<<"de">>, <<"default">>, <<"Remove">>) ->
1583    {ok, <<"a">>};
1584lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) ->
1585    {ok, <<"a">>};
1586lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) ->
1587    {ok, <<"a">>};
1588lgettext(<<"de">>, <<"default">>, <<"Results">>) ->
1589    {ok, <<"Ergebnisse">>};
1590lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) ->
1591    {ok, <<"a">>};
1592lgettext(<<"de">>, <<"navigation">>, <<"Results">>) ->
1593    {ok, <<"Ergebnisse">>};
1594lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) ->
1595    {ok, <<"Ressourcen">>}.
1596
1597%% Test more code in beam_bsm.
1598beam_bsm(_Config) ->
1599    true = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [1,0,1,1]),
1600    false = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [0]),
1601
1602    true = bsm_validate_scheme(<<>>),
1603    true = bsm_validate_scheme(<<5,10>>),
1604    false = bsm_validate_scheme(<<5,10,11,12>>),
1605    true = bsm_validate_scheme([]),
1606    true = bsm_validate_scheme([5,10]),
1607    false = bsm_validate_scheme([5,6,7]),
1608
1609    <<1,2,3>> = bsm_must_save_and_not_save(<<1,2,3>>, []),
1610    D = fun(N) -> 2*N end,
1611    [2,4|<<3>>] = bsm_must_save_and_not_save(<<1,2,3>>, [D,D]),
1612
1613    ok.
1614
1615check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) ->
1616    check_bitstring_list(T1, T2);
1617check_bitstring_list(<<>>, []) ->
1618    true;
1619check_bitstring_list(_, _) ->
1620    false.
1621
1622bsm_validate_scheme([]) -> true;
1623bsm_validate_scheme([H|T]) ->
1624    case bsm_is_scheme(H) of
1625        true -> bsm_validate_scheme(T);
1626        false -> false
1627    end;
1628bsm_validate_scheme(<<>>) -> true;
1629bsm_validate_scheme(<<H, Rest/binary>>) ->
1630    case bsm_is_scheme(H) of
1631        true -> bsm_validate_scheme(Rest);
1632        false -> false
1633    end.
1634
1635bsm_is_scheme(Int) ->
1636    Int rem 5 =:= 0.
1637
1638%% NOT OPTIMIZED: different control paths use different positions in the binary
1639bsm_must_save_and_not_save(Bin, []) ->
1640    Bin;
1641bsm_must_save_and_not_save(<<H,T/binary>>, [F|Fs]) ->
1642    [F(H)|bsm_must_save_and_not_save(T, Fs)];
1643bsm_must_save_and_not_save(<<>>, []) ->
1644    [].
1645
1646guard(_Config) ->
1647    _Tuple = id({a,b}),
1648    ok = guard_1(<<1,2,3>>, {1,2,3}),
1649    ok = guard_2(<<42>>, #{}),
1650    ok.
1651
1652%% Cover handling of #k_put{} in v3_codegen:bsm_rename_ctx/4.
1653guard_1(<<A,B,C>>, Tuple) when Tuple =:= {A,B,C} ->
1654    ok.
1655
1656%% Cover handling of #k_call{} in v3_codegen:bsm_rename_ctx/4.
1657guard_2(<<_>>, Healing) when Healing#{[] => Healing} =:= #{[] => #{}} ->
1658    ok.
1659
1660is_ascii(_Config) ->
1661    true = do_is_ascii(<<>>),
1662    true = do_is_ascii(<<"string">>),
1663    false = do_is_ascii(<<1024/utf8>>),
1664    {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<$A,0:3>>)),
1665    {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<16#80,0:3>>)),
1666    ok.
1667
1668do_is_ascii(<<>>) ->
1669    true;
1670do_is_ascii(<<C,_/binary>>) when C >= 16#80 ->
1671    %% This clause must fail to match if the size of the argument in
1672    %% bits is not divisible by 8. Beware of unsafe optimizations.
1673    false;
1674do_is_ascii(<<_, T/binary>>) ->
1675    do_is_ascii(T).
1676
1677non_opt_eq(_Config) ->
1678    true = non_opt_eq([], <<>>),
1679    true = non_opt_eq([$a], <<$a>>),
1680    false = non_opt_eq([$a], <<$b>>),
1681    ok.
1682
1683%% An example from the Efficiency Guide. It used to be not optimized,
1684%% but now it can be optimized.
1685
1686non_opt_eq([H|T1], <<H,T2/binary>>) ->
1687    non_opt_eq(T1, T2);
1688non_opt_eq([_|_], <<_,_/binary>>) ->
1689    false;
1690non_opt_eq([], <<>>) ->
1691    true.
1692
1693%% ERL-689
1694
1695erl_689(_Config) ->
1696    {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE),
1697    {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE),
1698    {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>),
1699    {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>),
1700    ok.
1701
1702do_erl_689_1(Arg1, Arg2) ->
1703    Res = do_erl_689_1a(Arg1, Arg2),
1704    Res = do_erl_689_1b(Arg1, Arg2).
1705
1706do_erl_689_2(Arg1, Arg2) ->
1707    Res = do_erl_689_2a(Arg1, Arg2),
1708    Res = do_erl_689_2b(Arg1, Arg2).
1709
1710do_erl_689_1a(<<Length, Data/binary>>, _) ->
1711    case {Data, Length} of
1712        {_, 0} ->
1713            %% bs_context_to_binary would incorrectly set Data to the original
1714            %% binary (before matching in the function head).
1715            {{0, 0, 0}, Data};
1716        {<<Y:16/little, M, D, Rest/binary>>, 4} ->
1717            {{Y, M, D}, Rest}
1718    end.
1719
1720do_erl_689_1b(<<Length, Data/binary>>, _) ->
1721    case {Data, Length} of
1722        {_, 0} ->
1723            %% bs_context_to_binary would incorrectly set Data to the original
1724            %% binary (before matching in the function head).
1725            id(0),
1726            {{0, 0, 0}, Data};
1727        {<<Y:16/little, M, D, Rest/binary>>, 4} ->
1728            id(1),
1729            {{Y, M, D}, Rest}
1730    end.
1731
1732do_erl_689_2a(_, <<Length, Data/binary>>) ->
1733    case {Length, Data} of
1734        {0, _} ->
1735            %% bs_context_to_binary would incorrectly set Data to the original
1736            %% binary (before matching in the function head).
1737            {{0, 0, 0}, Data};
1738        {4, <<Y:16/little, M, D, Rest/binary>>} ->
1739            {{Y, M, D}, Rest}
1740    end.
1741
1742do_erl_689_2b(_, <<Length, Data/binary>>) ->
1743    case {Length, Data} of
1744        {0, _} ->
1745            %% bs_context_to_binary would incorrectly set Data to the original
1746            %% binary (before matching in the function head).
1747            id(0),
1748            {{0, 0, 0}, Data};
1749        {4, <<Y:16/little, M, D, Rest/binary>>} ->
1750            id(1),
1751            {{Y, M, D}, Rest}
1752    end.
1753
1754%% ERL-753
1755
1756bs_start_match2_defs(_Config) ->
1757    {<<"http://127.0.0.1:1234/vsaas/hello">>} = api_url(<<"hello">>, dummy),
1758    {"https://127.0.0.1:4321/vsaas/hello"} = api_url({https, "hello"}, dummy).
1759
1760api_url(URL, Auth) ->
1761    Header = [],
1762    case URL of
1763        <<_/binary>> -> {<<"http://127.0.0.1:1234/vsaas/",URL/binary>>};
1764        {https, [_|_] = URL1} -> {"https://127.0.0.1:4321/vsaas/"++URL1}
1765    end.
1766
1767check(F, R) ->
1768    R = F().
1769
1770id(I) -> I.
1771