1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2001-2020. 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(guard_SUITE). 21 22-include_lib("syntax_tools/include/merl.hrl"). 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 misc/1,const_cond/1,basic_not/1,complex_not/1,nested_nots/1, 27 semicolon/1,complex_semicolon/1,comma/1, 28 or_guard/1,more_or_guards/1, 29 complex_or_guards/1,and_guard/1, 30 xor_guard/1,more_xor_guards/1, 31 old_guard_tests/1,complex_guard/1, 32 build_in_guard/1,gbif/1, 33 t_is_boolean/1,is_function_2/1, 34 tricky/1,rel_ops/1,rel_op_combinations/1, 35 generated_combinations/1,literal_type_tests/1, 36 basic_andalso_orelse/1,traverse_dcd/1, 37 check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, 38 bad_constants/1,bad_guards/1, 39 guard_in_catch/1,beam_bool_SUITE/1, 40 repeated_type_tests/1,use_after_branch/1]). 41 42suite() -> [{ct_hooks,[ts_install_cth]}]. 43 44all() -> 45 slow_group() ++ [{group,p}]. 46 47groups() -> 48 [{p,[parallel], 49 [misc,const_cond,basic_not,complex_not,nested_nots, 50 semicolon,complex_semicolon,comma,or_guard, 51 more_or_guards,complex_or_guards,and_guard,xor_guard, 52 more_xor_guards,build_in_guard, 53 old_guard_tests,complex_guard,gbif, 54 t_is_boolean,is_function_2,tricky, 55 rel_ops,rel_op_combinations, 56 basic_andalso_orelse,traverse_dcd, 57 check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, 58 bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE, 59 repeated_type_tests,use_after_branch]}, 60 {slow,[],[literal_type_tests,generated_combinations]}]. 61 62init_per_suite(Config) -> 63 test_lib:recompile(?MODULE), 64 Config. 65 66end_per_suite(_Config) -> 67 ok. 68 69init_per_group(_GroupName, Config) -> 70 Config. 71 72end_per_group(_GroupName, Config) -> 73 Config. 74 75slow_group() -> 76 case ?MODULE of 77 guard_SUITE -> 78 %% Canononical module name. Run slow cases. 79 [{group,slow}]; 80 _ -> 81 %% Cloned module. Don't run. 82 [] 83 end. 84 85misc(Config) when is_list(Config) -> 86 42 = case id(42) of 87 X when -X -> ok; 88 X -> X 89 end, 90 {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]), 91 none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]), 92 none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]), 93 none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]), 94 95 {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf), 96 {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf), 97 {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf), 98 error = get_data({o,false,raw}, 42, buf), 99 {ok,buf,<<>>} = get_data({o,true,0}, 0, buf), 100 {ok,buf,<<>>} = get_data({o,true,0}, 42, buf), 101 {ok,buf,<<>>} = get_data({o,false,0}, 0, buf), 102 error = get_data({o,false,0}, 42, buf), 103 104 relief = misc_2(0), 105 error = misc_2(1), 106 error = misc_2(true), 107 108 if 109 is_integer(Config) =/= true -> 110 ok 111 end, 112 113 true = misc_3(1, 0), 114 true = misc_3(0, 0), 115 false = misc_3(0, 2), 116 117 %% Abuse of boolean values. 118 119 Zero = id(0), 120 One = id(1), 121 ok = if (Zero == 0) > false -> ok end, 122 ok = if (Zero == 0) =:= (One == 1) -> ok end, 123 ok = if (Zero == 0) =:= (One == 1) -> ok end, 124 ok = if is_atom(Zero > One) -> ok end, 125 error = if abs(Zero > One) -> ok; true -> error end, 126 ok = if is_integer(Zero) >= is_integer(One) -> ok end, 127 128 ok. 129 130misc_1([{W},{X},{Y},{Z}]) -> 131 if 132 X > Y andalso abs(Z) =:= 2 -> 133 id(W); 134 true -> 135 none 136 end. 137 138misc_2(0) -> relief; 139misc_2(Adapter = 1) when Adapter -> franklin; 140misc_2(_) -> error. 141 142misc_3(LenUp, LenDw) -> 143 if 144 %% Cover handling of #k_alt{}. 145 LenUp >= 1 orelse ((LenDw >= 2) xor true) -> true; 146 true -> false 147 end. 148 149get_data({o,Active,Raw}, BytesToRead, Buffer) 150 when Raw =:= raw; Raw =:= 0 -> 151 if 152 Active =/= false orelse BytesToRead =:= 0 -> 153 {ok,Buffer,<<>>}; 154 true -> 155 error 156 end. 157 158const_cond(Config) when is_list(Config) -> 159 ok = const_cond({}, 0), 160 ok = const_cond({a}, 1), 161 error = const_cond({a,b}, 3), 162 error = const_cond({a}, 0), 163 error = const_cond({a,b}, 1), 164 ok. 165 166const_cond(T, Sz) -> 167 case T of 168 _X when false -> never; 169 _X when is_tuple(T), eq == eq, tuple_size(T) == Sz -> ok; 170 _X when is_tuple(T), eq == leq, tuple_size(T) =< Sz -> ok; 171 _X -> error 172 end. 173 174basic_not(Config) when is_list(Config) -> 175 True = id(true), 176 False = id(false), 177 Glurf = id(glurf), 178 A = id(5), 179 B = id(37.5), 180 C = id(-1), 181 D = id(5), 182 ATuple = {False,True,Glurf}, 183 184 check(fun() -> if not false -> ok; true -> error end end, ok), 185 check(fun() -> if not true -> ok; true -> error end end, error), 186 check(fun() -> if not False -> ok; true -> error end end, ok), 187 check(fun() -> if not True -> ok; true -> error end end, error), 188 189 check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), 190 check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), 191 check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), 192 193 check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; 194 not (7 == 453) -> ne; true -> eq end end, le), 195 check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; 196 not (7 == -8) -> ne; true -> eq end end, ge), 197 check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; 198 not (7 == 7) -> ne; true -> eq end end, le), 199 200 check(fun() -> if not (A > B) -> le; not (A < B) -> ge; 201 not (A == B) -> ne; true -> eq end end, le), 202 check(fun() -> if not (A > C) -> le; not (A < C) -> ge; 203 not (A == C) -> ne; true -> eq end end, ge), 204 check(fun() -> if not (A > D) -> le; not (A < D) -> ge; 205 not (A == D) -> ne; true -> eq end end, le), 206 207 check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), 208 check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), 209 check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), 210 211 check(fun() -> if not glurf -> ok; true -> error end end, error), 212 check(fun() -> if not Glurf -> ok; true -> error end end, error), 213 214 check(fun() -> if not (not true) -> broken end end, broken), 215 216 check(fun() -> if not (True xor True) -> ok end end, ok), 217 check(fun() -> if not (True xor False) -> ok; 218 true -> error end end, error), 219 220 check(fun() -> if not (True =:= true) -> ok; true -> error end end, error), 221 check(fun() -> if not (False =:= true) -> ok; true -> error end end, ok), 222 check(fun() -> if not (Glurf =:= true) -> ok; true -> error end end, ok), 223 224 ok. 225 226complex_not(Config) when is_list(Config) -> 227 ATuple = id({false,true,gurka}), 228 check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), 229 check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), 230 231 check(fun() -> if not(element(3, ATuple) == gurka) -> ok; 232 true -> error end end, error), 233 check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; 234 true -> error end end, ok), 235 236 check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; 237 true -> error end end, ok), 238 check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; 239 true -> error end end, error), 240 241 check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; 242 true -> error end end, error), 243 244 %% orelse 245 check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; 246 true -> error end end, error), 247 248 %% complex_not_1/4 249 ok = complex_not_1(1, 1, 1, a), 250 error = complex_not_1(1, 1, 1, []), 251 error = complex_not_1(1, 1, 3, a), 252 error = complex_not_1(1, 1, 3, []), 253 error = complex_not_1(1, 2, 1, a), 254 error = complex_not_1(1, 2, 1, []), 255 error = complex_not_1(1, 2, 3, a), 256 error = complex_not_1(1, 2, 3, []), 257 258 %% complex_not_2/4 259 ok = complex_not_2(1, 2, 0, x), 260 error = complex_not_2(1, 2, 0, []), 261 error = complex_not_2(1, 2, 3, x), 262 error = complex_not_2(1, 2, 3, []), 263 error = complex_not_2(1, 1, 0, x), 264 error = complex_not_2(1, 1, 0, []), 265 error = complex_not_2(1, 1, 3, x), 266 error = complex_not_2(1, 1, 3, []), 267 268 ok. 269 270complex_not_1(A, B, C, D) -> 271 Res = complex_not_1a(A, B, C, D), 272 Res = complex_not_1b(A, B, C, D). 273 274complex_not_1a(A, B, C, D) 275 when (not (A < B)) andalso (not (B < C)) andalso (not is_list(D)) -> 276 ok; 277complex_not_1a(_, _, _, _) -> 278 error. 279 280complex_not_1b(A, B, C, D) 281 when (not (A < B)) and (not (B < C)) and (not is_list(D)) -> 282 ok; 283complex_not_1b(_, _, _, _) -> 284 error. 285 286complex_not_2(A, B, C, D) -> 287 Res = complex_not_2a(A, B, C, D), 288 Res = complex_not_2b(A, B, C, D). 289 290complex_not_2a(A, B, C, D) 291 when A < B andalso not (B < C) andalso not is_list(D) -> 292 ok; 293complex_not_2a(_, _, _, _) -> 294 error. 295 296complex_not_2b(A, B, C, D) 297 when A < B, not (B < C), not is_list(D) -> 298 ok; 299complex_not_2b(_, _, _, _) -> 300 error. 301 302nested_nots(Config) when is_list(Config) -> 303 true = nested_not_1(0, 0), 304 true = nested_not_1(0, 1), 305 true = nested_not_1(a, b), 306 true = nested_not_1(10, 0), 307 false = nested_not_1(z, a), 308 false = nested_not_1(3.4, {anything,goes}), 309 false = nested_not_1(3.4, atom), 310 true = nested_not_1(3.0, [list]), 311 312 true = nested_not_2(false, false, 42), 313 true = nested_not_2(false, true, 42), 314 true = nested_not_2(true, false, 42), 315 true = nested_not_2(true, true, 42), 316 true = nested_not_2(false, false, atom), 317 false = nested_not_2(false, true, atom), 318 false = nested_not_2(true, false, atom), 319 false = nested_not_2(true, true, atom), 320 ok. 321 322nested_not_1(X, Y) -> 323 Res = nested_not_1a(X, Y), 324 Res = nested_not_1b(X, Y). 325 326nested_not_1a(X, Y) when not (((X>Y) or not(is_atom(X))) and 327 (is_atom(Y) or (X==3.4))) -> 328 true; 329nested_not_1a(_, _) -> 330 false. 331 332nested_not_1b(X, Y) when not (((X>Y) orelse not(is_atom(X))) andalso 333 (is_atom(Y) orelse (X==3.4))) -> 334 true; 335nested_not_1b(_, _) -> 336 false. 337 338nested_not_2(X, Y, Z) -> 339 Res = nested_not_2a(X, Y, Z, true), 340 Res = nested_not_2b(X, Y, Z, true). 341 342nested_not_2a(X, Y, Z, True) 343 when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) -> 344 true; 345nested_not_2a(_, _, _, _) -> 346 false. 347 348nested_not_2b(X, Y, Z, True) 349 when not(True andalso not((not(X) andalso not(Y)) orelse not(is_atom(Z)))) -> 350 true; 351nested_not_2b(_, _, _, _) -> 352 false. 353 354semicolon(Config) when is_list(Config) -> 355 356 %% True/false combined using ';' (literal atoms). 357 358 check(fun() -> if true; false -> ok end end, ok), 359 check(fun() -> if false; true -> ok end end, ok), 360 check(fun() -> if true; true -> ok end end, ok), 361 check(fun() -> if false; false -> ok; true -> error end end, error), 362 check(fun() -> 363 {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), 364 exit 365 end, exit), 366 367 %% True/false combined used ';'. 368 369 True = id(true), 370 False = id(false), 371 372 check(fun() -> if True; False -> ok end end, ok), 373 check(fun() -> if False; True -> ok end end, ok), 374 check(fun() -> if True; True -> ok end end, ok), 375 check(fun() -> if False; False -> ok; true -> error end end, error), 376 check(fun() -> 377 {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), 378 exit 379 end, exit), 380 381 %% Combine true/false with a non-boolean value. 382 Glurf = id(glurf), 383 384 385 check(fun() -> if True; Glurf -> ok end end, ok), 386 check(fun() -> if Glurf; True -> ok end end, ok), 387 check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), 388 check(fun() -> if False; Glurf -> ok; true -> error end end, error), 389 check(fun() -> if Glurf; False -> ok; true -> error end end, error), 390 check(fun() -> 391 {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), 392 exit 393 end, exit), 394 395 %% Combine true/false with errors. 396 397 ATuple = id({false,true,gurka}), 398 399 check(fun() -> if True; element(42, ATuple) -> ok end end, ok), 400 check(fun() -> if element(42, ATuple); True -> ok end end, ok), 401 check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; 402 true -> error end end, error), 403 check(fun() -> if False; element(42, ATuple) -> ok; 404 true -> error end end, error), 405 check(fun() -> if element(42, ATuple); 406 False -> ok; true -> error end end, error), 407 check(fun() -> 408 {'EXIT',{if_clause,_}} = 409 (catch if element(42, ATuple); 410 element(42, ATuple) -> ok end), 411 exit 412 end, exit), 413 414 ok. 415 416complex_semicolon(Config) when is_list(Config) -> 417 ok = csemi1(int, {blurf}), 418 ok = csemi1(string, {blurf}), 419 ok = csemi1(float, [a]), 420 error = csemi1(35, 42), 421 422 %% 2 423 ok = csemi2({}, {a,b,c}), 424 ok = csemi2({1,3.5}, {a,b,c}), 425 ok = csemi2(dum, {a,b,c}), 426 427 ok = csemi2({45,-19.3}, {}), 428 ok = csemi2({45,-19.3}, {dum}), 429 ok = csemi2({45,-19.3}, {dum,dum}), 430 431 error = csemi2({45}, {dum}), 432 error = csemi2([], {dum}), 433 error = csemi2({dum}, []), 434 error = csemi2([], []), 435 436 %% 3 437 csemi3(fun csemi3a/4), 438 csemi3(fun csemi3b/4), 439 csemi3(fun csemi3c/4), 440 441 %% 4 442 csemi4(fun csemi4a/4), 443 csemi4(fun csemi4b/4), 444 csemi4(fun csemi4c/4), 445 csemi4(fun csemi4d/4), 446 447 %% 4, 'orelse' instead of 'or' 448 csemi4_orelse(fun csemi4_orelse_a/4), 449 csemi4_orelse(fun csemi4_orelse_b/4), 450 csemi4_orelse(fun csemi4_orelse_c/4), 451 csemi4_orelse(fun csemi4_orelse_d/4), 452 453 %% 5 454 error = csemi5(0, 0), 455 ok = csemi5(5, 0), 456 ok = csemi5(4, -4), 457 ok = csemi5(10, -4), 458 459 %% 6 460 error = csemi6({a}, 0), 461 ok = csemi6({a,b}, 0), 462 ok = csemi6({}, 3), 463 ok = csemi6({a,b,c}, 3), 464 465 %% 7 466 error = csemi7(#{a=>1}, 1, 0), 467 error = csemi7(<<>>, 1, 0), 468 ok = csemi7(#{a=>1}, 3, 0), 469 ok = csemi7(#{a=>1}, 0, 3), 470 ok = csemi7(#{a=>1}, 3, 3), 471 ok = csemi7(#{a=>1, b=>3}, 0, 0), 472 473 %% 8: Make sure that funs cannot be copied into guards. 474 ok = csemi8(true), 475 error = csemi8(false), 476 error = csemi8(42), 477 478 ok. 479 480csemi1(Type, Val) when is_list(Val), Type == float; 481 Type == int; Type == string -> ok; 482csemi1(_, _) -> error. 483 484csemi2(A, B) when tuple_size(A) > 1; tuple_size(B) > 2 -> ok; 485csemi2(_, _) -> error. 486 487csemi3(Csemi3) -> 488 ok = Csemi3({}, {a,b,c}, [0], [0]), 489 ok = Csemi3({1,3.5}, {a,b,c}, -1, -1), 490 ok = Csemi3(dum, {a,b,c}, 0.0, 0.0), 491 ok = Csemi3(dum, {c}, b, a), 492 ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0), 493 ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1), 494 495 ok = Csemi3({45,-19.3}, {}, [], []), 496 ok = Csemi3({45,-19.3}, {dum}, 42, 42), 497 ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33), 498 499 ok = Csemi3({45}, {dum}, 1.0, 0), 500 ok = Csemi3([a], {dum}, 1.0, 0), 501 ok = Csemi3({dum}, [], 1.0, 0), 502 ok = Csemi3([], [], 1.0, 0), 503 ok = Csemi3(blurf, {dum}, 1.0, 0), 504 ok = Csemi3({a}, blurf, 1.0, 0), 505 ok = Csemi3([a], [dum], 1.0, 0), 506 ok = Csemi3({dum}, [], 1.0, 0), 507 ok = Csemi3([], [], 1.0, 0), 508 509 error = Csemi3({45}, {dum}, 0, 0), 510 error = Csemi3([a], {dum}, 0, 0), 511 error = Csemi3({dum}, [], 0, 0), 512 error = Csemi3([], [], 0, 0), 513 514 ok. 515 516csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok; 517csemi3a(_, _, _, _) -> error. 518 519csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok; 520csemi3b(_, _, _, _) -> error. 521 522csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok; 523csemi3c(_, _, _, _) -> error. 524 525 526csemi4(Test) -> 527 ok = Test({a,b}, 2, {c,d}, 2), 528 ok = Test({1,2,3}, 0, [], 0), 529 ok = Test({}, 2, blurf, 0), 530 ok = Test({}, 2, {1}, 2), 531 532 error = Test([], 4, {}, 0), 533 error = Test({}, 0, [a,b], 4), 534 error = Test({}, 0, [a,b], 0), 535 error = Test([], 0, {}, 0), 536 error = Test({}, 0, {}, 0), 537 538 ok. 539 540csemi4a(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1); 541 (tuple_size(B) > 1) or (Y > 1) -> ok; 542csemi4a(_, _, _, _) -> error. 543 544csemi4b(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); 545 (tuple_size(B) > 1) or (Y > 1) -> ok; 546csemi4b(_, _, _, _) -> error. 547 548csemi4c(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1); 549 (Y > 1) or (tuple_size(B) > 1) -> ok; 550csemi4c(_, _, _, _) -> error. 551 552csemi4d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); 553 (Y > 1) or (tuple_size(B) > 1) -> ok; 554csemi4d(_, _, _, _) -> error. 555 556 557csemi4_orelse(Test) -> 558 ok = Test({a,b}, 2, {c,d}, 2), 559 ok = Test({1,2,3}, 0, [], 0), 560 ok = Test({}, 2, blurf, 0), 561 ok = Test({}, 2, {1}, 2), 562 563 error = Test([], 1, {}, 0), 564 565 ok. 566 567csemi4_orelse_a(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1); 568 (tuple_size(B) > 1) orelse (Y > 1) -> ok; 569csemi4_orelse_a(_, _, _, _) -> error. 570 571csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (tuple_size(A) > 1); 572 (tuple_size(B) > 1) orelse (Y > 1) -> ok; 573csemi4_orelse_b(_, _, _, _) -> error. 574 575csemi4_orelse_c(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1); 576 (Y > 1) orelse (tuple_size(B) > 1) -> ok; 577csemi4_orelse_c(_, _, _, _) -> error. 578 579csemi4_orelse_d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1); 580 (Y > 1) or (tuple_size(B) > 1) -> ok; 581csemi4_orelse_d(_, _, _, _) -> error. 582 583csemi5(A, B) when hd([A+B]) > 1; abs(B) > 2 -> ok; 584csemi5(_, _) -> error. 585 586csemi6(A, B) when hd([tuple_size(A)]) > 1; abs(B) > 2 -> ok; 587csemi6(_, _) -> error. 588 589csemi7(A, B, C) when A#{a:=B} > #{a=>1}; abs(C) > 2 -> ok; 590csemi7(_, _, _) -> error. 591 592csemi8(Together) -> 593 case fun csemi8/1 of 594 Typically when Together; Typically, Together -> ok; 595 _ -> error 596 end. 597 598 599comma(Config) when is_list(Config) -> 600 601 %% ',' combinations of literal true/false. 602 603 check(fun() -> if true, false -> ok; true -> error end end, error), 604 check(fun() -> if false, true -> ok; true -> error end end, error), 605 check(fun() -> if true, true -> ok end end, ok), 606 check(fun() -> if false, false -> ok; true -> error end end, error), 607 check(fun() -> 608 {'EXIT',{if_clause,_}} = 609 (catch if true, false -> ok; 610 false, true -> ok; 611 false, false -> ok 612 end), 613 exit 614 end, exit), 615 616 %% ',' combinations of true/false in variables. 617 618 True = id(true), 619 False = id(false), 620 621 check(fun() -> if True, False -> ok; true -> error end end, error), 622 check(fun() -> if False, True -> ok; true -> error end end, error), 623 check(fun() -> if True, True -> ok end end, ok), 624 check(fun() -> if False, False -> ok; true -> error end end, error), 625 check(fun() -> 626 {'EXIT',{if_clause,_}} = 627 (catch if True, False -> ok; 628 False, True -> ok; 629 False, False -> ok 630 end), 631 exit 632 end, exit), 633 634 %% ',' combinations of true/false, and non-boolean in variables. 635 636 Glurf = id(glurf), 637 638 check(fun() -> if True, Glurf -> ok; true -> error end end, error), 639 check(fun() -> if Glurf, True -> ok; true -> error end end, error), 640 check(fun() -> if True, True -> ok end end, ok), 641 check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), 642 check(fun() -> 643 {'EXIT',{if_clause,_}} = 644 (catch if True, Glurf -> ok; 645 Glurf, True -> ok; 646 Glurf, Glurf -> ok 647 end), 648 exit 649 end, exit), 650 651 %% ',' combinations of true/false with errors. 652 ATuple = id({a,b,c}), 653 654 check(fun() -> if True, element(42, ATuple) -> ok; 655 true -> error end end, error), 656 check(fun() -> if element(42, ATuple), True -> ok; 657 true -> error end end, error), 658 check(fun() -> if True, True -> ok end end, ok), 659 check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; 660 true -> error end end, error), 661 check(fun() -> 662 {'EXIT',{if_clause,_}} = 663 (catch if True, element(42, ATuple) -> ok; 664 element(42, ATuple), True -> ok; 665 element(42, ATuple), element(42, ATuple) -> ok 666 end), 667 exit 668 end, exit), 669 670 ok. 671 672or_guard(Config) when is_list(Config) -> 673 True = id(true), 674 False = id(false), 675 Glurf = id(glurf), 676 677 %% 'or' combinations of literal true/false. 678 check(fun() -> if true or false -> ok end end, ok), 679 check(fun() -> if false or true -> ok end end, ok), 680 check(fun() -> if true or true -> ok end end, ok), 681 check(fun() -> if false or false -> ok; true -> error end end, error), 682 683 check(fun() -> if glurf or true -> ok; true -> error end end, error), 684 check(fun() -> if true or glurf -> ok; true -> error end end, error), 685 check(fun() -> if glurf or glurf -> ok; true -> error end end, error), 686 687 check(fun() -> 688 {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), 689 exit 690 end, exit), 691 692 693 %% 'or' combinations using variables containing true/false. 694 check(fun() -> if True or False -> ok end end, ok), 695 check(fun() -> if False or True -> ok end end, ok), 696 check(fun() -> if True or True -> ok end end, ok), 697 check(fun() -> if False or False -> ok; true -> error end end, error), 698 699 check(fun() -> if True or Glurf -> ok; true -> error end end, error), 700 check(fun() -> if Glurf or True -> ok; true -> error end end, error), 701 check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), 702 703 check(fun() -> 704 {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), 705 exit 706 end, exit), 707 708 ok. 709 710more_or_guards(Config) when is_list(Config) -> 711 True = id(true), 712 False = id(false), 713 ATuple = id({false,true,gurka}), 714 715 check(fun() -> 716 if element(42, ATuple) or False -> ok; 717 true -> error end 718 end, error), 719 720 check(fun() -> 721 if False or element(42, ATuple) -> ok; 722 true -> error end 723 end, error), 724 725 check(fun() -> 726 if element(18, ATuple) or element(42, ATuple) -> ok; 727 true -> error end 728 end, error), 729 730 check(fun() -> 731 if True or element(42, ATuple) -> ok; 732 true -> error end 733 end, error), 734 735 check(fun() -> 736 if element(42, ATuple) or True -> ok; 737 true -> error end 738 end, error), 739 740 check(fun() -> 741 if element(1, ATuple) or element(42, ATuple) or True -> ok; 742 true -> error end 743 end, error), 744 745 check(fun() -> 746 if element(1, ATuple) or True or element(42, ATuple) -> ok; 747 true -> error end 748 end, error), 749 750 check(fun() -> 751 if 752 (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; 753 true -> error end 754 end, error), 755 756 check(fun() -> 757 if 758 element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; 759 true -> error end 760 end, error), 761 762 check(fun() -> 763 if element(2, ATuple) or element(42, ATuple) -> ok; 764 true -> error end 765 end, error), 766 767 check(fun() -> 768 if 769 element(1, ATuple) or 770 element(2, ATuple) or 771 element(19, ATuple) -> ok; 772 true -> error end 773 end, error), 774 ok. 775 776complex_or_guards(Config) when is_list(Config) -> 777 %% complex_or_1/2 778 ok = complex_or_1({a,b,c,d}, {1,2,3}), 779 ok = complex_or_1({a,b,c,d}, {1}), 780 ok = complex_or_1({a}, {1,2,3}), 781 error = complex_or_1({a}, {1}), 782 783 error = complex_or_1(1, 2), 784 error = complex_or_1([], {a,b,c,d}), 785 error = complex_or_1({a,b,c,d}, []), 786 787 788 %% complex_or_2/1 789 ok = complex_or_2({true,{}}), 790 ok = complex_or_2({false,{a}}), 791 ok = complex_or_2({false,{a,b,c}}), 792 ok = complex_or_2({true,{a,b,c,d}}), 793 794 error = complex_or_2({blurf,{a,b,c}}), 795 796 error = complex_or_2({true}), 797 error = complex_or_2({true,no_tuple}), 798 error = complex_or_2({true,[]}), 799 800 %% complex_or_3/2 801 ok = complex_or_3({true}, {}), 802 ok = complex_or_3({false}, {a}), 803 ok = complex_or_3({false}, {a,b,c}), 804 ok = complex_or_3({true}, {a,b,c,d}), 805 ok = complex_or_3({false}, <<1,2,3>>), 806 ok = complex_or_3({true}, <<1,2,3,4>>), 807 808 error = complex_or_3(blurf, {a,b,c}), 809 810 error = complex_or_3({false}, <<1,2,3,4>>), 811 error = complex_or_3([], <<1,2>>), 812 error = complex_or_3({true}, 45), 813 error = complex_or_3(<<>>, <<>>), 814 815 %% complex_or_4/2 816 ok = complex_or_4(<<1,2,3>>, {true}), 817 ok = complex_or_4(<<1,2,3>>, {false}), 818 ok = complex_or_4(<<1,2,3>>, {true}), 819 ok = complex_or_4({1,2,3}, {true}), 820 error = complex_or_4({1,2,3,4}, {false}), 821 822 error = complex_or_4(<<1,2,3,4>>, []), 823 error = complex_or_4([], {true}), 824 825 %% complex_or_5/2 826 ok = complex_or_5(<<1>>, {false}), 827 ok = complex_or_5(<<1,2,3>>, {true}), 828 ok = complex_or_5(<<1,2,3,4>>, {false}), 829 ok = complex_or_5({1,2,3}, {false}), 830 ok = complex_or_5({1,2,3,4}, {false}), 831 832 error = complex_or_5(blurf, {false}), 833 error = complex_or_5(<<1>>, klarf), 834 error = complex_or_5(blurf, klarf), 835 836 %% complex_or_6/2 837 ok = complex_or_6({true,true}, {1,2,3,4}), 838 ok = complex_or_6({true,true}, <<1,2,3,4>>), 839 ok = complex_or_6({false,false}, <<1,2,3,4>>), 840 ok = complex_or_6({false,true}, <<1>>), 841 ok = complex_or_6({true,false}, {1}), 842 ok = complex_or_6({true,true}, {1}), 843 844 error = complex_or_6({false,false}, {1}), 845 846 error = complex_or_6({true}, {1,2,3,4}), 847 error = complex_or_6({}, {1,2,3,4}), 848 error = complex_or_6([], {1,2,3,4}), 849 error = complex_or_6([], {1,2,3,4}), 850 error = complex_or_6({true,false}, klurf), 851 852 ok. 853 854complex_or_1(A, B) -> 855 if 856 ((3 < tuple_size(A)) and (tuple_size(A) < 9)) or 857 ((2 < tuple_size(B)) and (tuple_size(B) < 7)) -> ok; 858 true -> error 859 end. 860 861complex_or_2(Tuple) -> 862 if 863 element(1, Tuple) or not (tuple_size(element(2, Tuple)) > 3) -> ok; 864 true -> error 865 end. 866 867complex_or_3(A, B) -> 868 if 869 not (size(B) > 3) or element(1, A) -> ok; 870 true -> error 871 end. 872 873complex_or_4(A, B) -> 874 if 875 not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok; 876 true -> error 877 end. 878 879complex_or_5(A, B) -> 880 if 881 not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok; 882 true -> error 883 end. 884 885complex_or_6(A, B) -> 886 if 887 not (not element(1, A) and not element(2, A)) or 888 not (not (size(B) > 3)) -> ok; 889 true -> error 890 end. 891 892and_guard(Config) when is_list(Config) -> 893 894 %% 'and' combinations of literal true/false. 895 896 check(fun() -> if true and false -> ok; true -> error end end, error), 897 check(fun() -> if false and true -> ok; true -> error end end, error), 898 check(fun() -> if true and true -> ok end end, ok), 899 check(fun() -> if false and false -> ok; true -> error end end, error), 900 901 check(fun() -> if glurf and true -> ok; true -> error end end, error), 902 check(fun() -> if true and glurf -> ok; true -> error end end, error), 903 check(fun() -> if glurf and glurf -> ok; true -> error end end, error), 904 905 check(fun() -> 906 {'EXIT',{if_clause,_}} = 907 (catch if true and false -> ok; 908 false and true -> ok; 909 false and false -> ok 910 end), 911 exit 912 end, exit), 913 914 %% 'and' combinations of true/false in variables. 915 916 True = id(true), 917 False = id(false), 918 919 check(fun() -> if True and False -> ok; true -> error end end, error), 920 check(fun() -> if False and True -> ok; true -> error end end, error), 921 check(fun() -> if True and True -> ok end end, ok), 922 check(fun() -> if False and False -> ok; true -> error end end, error), 923 check(fun() -> 924 {'EXIT',{if_clause,_}} = 925 (catch if True and False -> ok; 926 False and True -> ok; 927 False and False -> ok 928 end), 929 exit 930 end, exit), 931 932 %% 'and' combinations of true/false and a non-boolean in variables. 933 934 Glurf = id(glurf), 935 936 check(fun() -> if True and Glurf -> ok; true -> error end end, error), 937 check(fun() -> if Glurf and True -> ok; true -> error end end, error), 938 check(fun() -> if True and True -> ok end end, ok), 939 check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), 940 check(fun() -> 941 {'EXIT',{if_clause,_}} = 942 (catch if True and Glurf -> ok; 943 Glurf and True -> ok; 944 Glurf and Glurf -> ok 945 end), 946 exit 947 end, exit), 948 949 %% 'and' combinations of true/false with errors. 950 ATuple = id({a,b,c}), 951 952 check(fun() -> if True and element(42, ATuple) -> ok; 953 true -> error end end, error), 954 check(fun() -> if element(42, ATuple) and True -> ok; 955 true -> error end end, error), 956 check(fun() -> if True and True -> ok end end, ok), 957 check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; 958 true -> error end end, error), 959 check(fun() -> 960 {'EXIT',{if_clause,_}} = 961 (catch if True and element(42, ATuple) -> ok; 962 element(42, ATuple) and True -> ok; 963 element(42, ATuple) and element(42, ATuple) -> ok 964 end), 965 exit 966 end, exit), 967 968 ok = relprod({'Set',a,b}, {'Set',a,b}), 969 970 ok = and_same_var(42), 971 {'EXIT',{if_clause,_}} = (catch and_same_var(x)), 972 ok. 973 974and_same_var(V) -> 975 B = is_integer(V), 976 if 977 B or B -> ok 978 end. 979 980relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') -> 981 ok. 982 983 984xor_guard(Config) when is_list(Config) -> 985 986 %% 'xor' combinations of literal true/false. 987 check(fun() -> if true xor false -> ok end end, ok), 988 check(fun() -> if false xor true -> ok end end, ok), 989 check(fun() -> if true xor true -> ok; true -> error end end, error), 990 check(fun() -> if false xor false -> ok; true -> error end end, error), 991 check(fun() -> 992 {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), 993 exit 994 end, exit), 995 check(fun() -> 996 {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), 997 exit 998 end, exit), 999 1000 1001 %% 'xor' combinations using variables containing true/false. 1002 1003 True = id(true), 1004 False = id(false), 1005 1006 check(fun() -> if True xor False -> ok end end, ok), 1007 check(fun() -> if False xor True -> ok end end, ok), 1008 check(fun() -> if True xor True -> ok; true -> error end end, error), 1009 check(fun() -> if False xor False -> ok; true -> error end end, error), 1010 check(fun() -> 1011 {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), 1012 exit 1013 end, exit), 1014 check(fun() -> 1015 {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), 1016 exit 1017 end, exit), 1018 1019 ok. 1020 1021more_xor_guards(Config) when is_list(Config) -> 1022 True = id(true), 1023 False = id(false), 1024 ATuple = id({false,true,gurka}), 1025 1026 check(fun() -> 1027 if element(42, ATuple) xor False -> ok; 1028 true -> error end 1029 end, error), 1030 1031 check(fun() -> 1032 if False xor element(42, ATuple) xor False -> ok; 1033 true -> error end 1034 end, error), 1035 1036 check(fun() -> 1037 if element(18, ATuple) xor element(42, ATuple) -> ok; 1038 true -> error end 1039 end, error), 1040 1041 check(fun() -> 1042 if True xor element(42, ATuple) -> ok; 1043 true -> error end 1044 end, error), 1045 1046 check(fun() -> 1047 if element(42, ATuple) xor True -> ok; 1048 true -> error end 1049 end, error), 1050 ok. 1051 1052build_in_guard(Config) when is_list(Config) -> 1053 SubBin = <<5.0/float>>, 1054 B = <<1,SubBin/binary,3.5/float>>, 1055 if 1056 B =:= <<1,SubBin/binary,3.5/float>> -> ok 1057 end. 1058 1059old_guard_tests(Config) when list(Config) -> 1060 %% Check that all the old guard tests are still recognized. 1061 list = og(Config), 1062 atom = og(an_atom), 1063 binary = og(<<1,2>>), 1064 float = og(3.14), 1065 integer = og(43), 1066 a_function = og(fun() -> ok end), 1067 pid = og(self()), 1068 reference = og(make_ref()), 1069 tuple = og({}), 1070 1071 number = on(45.333), 1072 number = on(-19), 1073 ok. 1074 1075og(V) when atom(V) -> atom; 1076og(V) when binary(V) -> binary; 1077og(V) when float(V) -> float; 1078og(V) when integer(V) -> integer; 1079og(V) when function(V) -> a_function; 1080og(V) when list(V) -> list; 1081og(V) when pid(V) -> pid; 1082og(V) when port(V) -> port; 1083og(V) when reference(V) -> reference; 1084og(V) when tuple(V) -> tuple; 1085og(_) -> what. 1086 1087on(V) when number(V) -> number; 1088on(_) -> not_number. 1089 1090complex_guard(_Config) -> 1091 _ = [true = do_complex_guard_1(X, Y, Z) || 1092 X <- [4,5], Y <- [4,5], Z <- [4,5]], 1093 _ = [true = do_complex_guard_1(X, Y, Z) || 1094 X <- [1,2,3], Y <- [1,2,3], Z <- [1,2,3]], 1095 _ = [catch do_complex_guard_1(X, Y, Z) || 1096 X <- [1,2,3,4,5], Y <- [0,6], Z <- [1,2,3,4,5]], 1097 1098 b = do_complex_guard_2(false, false, true), 1099 c = do_complex_guard_2(false, false, false), 1100 c = do_complex_guard_2(false, true, true), 1101 a = do_complex_guard_2(false, true, false), 1102 1103 c = do_complex_guard_2(true, false, true), 1104 a = do_complex_guard_2(true, false, false), 1105 c = do_complex_guard_2(true, true, true), 1106 a = do_complex_guard_2(true, true, false), 1107 1108 c = do_complex_guard_2(other, false, true), 1109 c = do_complex_guard_2(other, false, false), 1110 c = do_complex_guard_2(other, true, true), 1111 c = do_complex_guard_2(other, true, false), 1112 1113 c = do_complex_guard_2(false, other, true), 1114 c = do_complex_guard_2(false, other, false), 1115 c = do_complex_guard_2(true, other, true), 1116 a = do_complex_guard_2(true, other, false), 1117 1118 c = do_complex_guard_2(false, false, other), 1119 c = do_complex_guard_2(false, true, other), 1120 c = do_complex_guard_2(true, false, other), 1121 c = do_complex_guard_2(true, true, other), 1122 1123 c = do_complex_guard_2(false, other, other), 1124 c = do_complex_guard_2(true, other, other), 1125 c = do_complex_guard_2(other, other, true), 1126 c = do_complex_guard_2(other, other, false), 1127 c = do_complex_guard_2(other, false, other), 1128 c = do_complex_guard_2(other, true, other), 1129 1130 c = do_complex_guard_2(other, other, other), 1131 1132 ok. 1133 1134do_complex_guard_1(X1, Y1, Z1) -> 1135 if 1136 ((X1 =:= 4) or (X1 =:= 5)) and 1137 ((Y1 =:= 4) or (Y1 =:= 5)) and 1138 ((Z1 =:= 4) or (Z1 =:= 5)) or 1139 ((X1 =:= 1) or (X1 =:= 2) or (X1 =:= 3)) and 1140 ((Y1 =:= 1) or (Y1 =:= 2) or (Y1 =:= 3)) and 1141 ((Z1 =:= 1) or (Z1 =:= 2) or (Z1 =:= 3)) -> 1142 true 1143 end. 1144 1145do_complex_guard_2(X, Y, Z) -> 1146 if 1147 (X orelse Y) andalso (not Z) -> a; 1148 Z andalso (not (X orelse Y)) -> b; 1149 true -> c 1150 end. 1151 1152gbif(Config) when is_list(Config) -> 1153 error = gbif_1(1, {false,true}), 1154 ok = gbif_1(2, {false,true}), 1155 ok. 1156 1157gbif_1(P, T) when element(P, T) -> ok; 1158gbif_1(_, _) -> error. 1159 1160 1161t_is_boolean(Config) when is_list(Config) -> 1162 true = is_boolean(true), 1163 true = is_boolean(false), 1164 true = is_boolean(id(true)), 1165 true = is_boolean(id(false)), 1166 1167 false = is_boolean(glurf), 1168 false = is_boolean(id(glurf)), 1169 1170 false = is_boolean([]), 1171 false = is_boolean(id([])), 1172 false = is_boolean(42), 1173 false = is_boolean(id(-42)), 1174 1175 false = is_boolean(math:pi()), 1176 false = is_boolean(384793478934378924978439789873478934897), 1177 1178 false = is_boolean(id(self())), 1179 false = is_boolean(id({x,y,z})), 1180 false = is_boolean(id([a,b,c])), 1181 false = is_boolean(id(make_ref())), 1182 false = is_boolean(id(<<1,2,3>>)), 1183 false = is_boolean({id(x),y,z}), 1184 false = is_boolean([id(a),b,c]), 1185 1186 ok = bool(true), 1187 ok = bool(false), 1188 ok = bool(id(true)), 1189 ok = bool(id(false)), 1190 1191 error = bool(glurf), 1192 error = bool(id(glurf)), 1193 1194 error = bool([]), 1195 error = bool(id([])), 1196 error = bool(42), 1197 error = bool(id(-42)), 1198 1199 error = bool(math:pi()), 1200 error = bool(384793478934378924978439789873478934897), 1201 1202 error = bool(id(self())), 1203 error = bool(id({x,y,z})), 1204 error = bool(id([a,b,c])), 1205 error = bool(id(make_ref())), 1206 error = bool(id(<<1,2,3>>)), 1207 1208 true = my_is_bool(true), 1209 true = my_is_bool(false), 1210 false = my_is_bool([]), 1211 false = my_is_bool([1,2,3,4]), 1212 false = my_is_bool({a,b,c}), 1213 1214 %% Cover code in beam_ssa_dead. 1215 ok = bool_semi(true), 1216 ok = bool_semi(false), 1217 error = bool_semi(a), 1218 1219 ok. 1220 1221bool(X) when is_boolean(X) -> ok; 1222bool(_) -> error. 1223 1224my_is_bool(V) -> 1225 Res = my_is_bool_a(V), 1226 Res = my_is_bool_b(V). 1227 1228my_is_bool_a(V) -> 1229 case V of 1230 true -> true; 1231 false -> true; 1232 _ -> false 1233 end. 1234 1235my_is_bool_b(V) -> 1236 case V of 1237 false -> true; 1238 true -> true; 1239 _ -> false 1240 end. 1241 1242bool_semi(V) when is_boolean(V); is_atom(not V) -> ok; 1243bool_semi(_) -> error. 1244 1245is_function_2(Config) when is_list(Config) -> 1246 true = is_function(id(fun ?MODULE:all/1), 1), 1247 true = is_function(id(fun() -> ok end), 0), 1248 false = is_function(id(fun ?MODULE:all/1), 0), 1249 false = is_function(id(fun() -> ok end), 1), 1250 {'EXIT',{badarg,_}} = 1251 (catch is_function(id(fun() -> ok end), -1) orelse error), 1252 {'EXIT',{badarg,_}} = 1253 (catch is_function(id(fun() -> ok end), '') orelse error), 1254 1255 F = fun(_) -> ok end, 1256 if 1257 is_function(F, 1) -> ok 1258 end. 1259 1260tricky(Config) when is_list(Config) -> 1261 not_ok = tricky_1(1, 2), 1262 not_ok = tricky_1(1, blurf), 1263 not_ok = tricky_1(foo, 2), 1264 not_ok = tricky_1(a, b), 1265 1266 error = tricky_2(0.5), 1267 error = tricky_2(a), 1268 error = tricky_2({a,b,c}), 1269 1270 false = rb(100000, [1], 42), 1271 true = rb(100000, [], 42), 1272 true = rb(555, [a,b,c], 19), 1273 1274 error = tricky_3(42), 1275 error = tricky_3(42.0), 1276 error = tricky_3(<<>>), 1277 error = tricky_3(#{}), 1278 error = tricky_3({a,b}), 1279 1280 {'EXIT',_} = (catch tricky_4(x)), 1281 {'EXIT',_} = (catch tricky_4(42)), 1282 {'EXIT',_} = (catch tricky_4(true)), 1283 1284 ok. 1285 1286tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok; 1287tricky_1(_, _) -> not_ok. 1288 1289tricky_2(X) when float(X) or float(X) -> ok; 1290tricky_2(_) -> error. 1291 1292tricky_3(X) 1293 when abs(X) or bit_size(X) or byte_size(X) or ceil(X) or 1294 float(X) or floor(X) or length(X) or 1295 map_size(X) or node() or node(X) or round(X) or 1296 self() or size(X) or tl(X) or trunc(X) or tuple_size(X) -> 1297 ok; 1298tricky_3(_) -> 1299 error. 1300 1301tricky_4(X) -> 1302 B = (abs(X) or abs(X)) =:= true, 1303 case B of 1304 true -> ok; 1305 false -> error 1306 end. 1307 1308%% From dets_v9:read_buckets/11, simplified. 1309 1310rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true; 1311rb(_, _, _) -> false. 1312 1313 1314-define(T(Op,A,B), 1315 ok = if A Op B -> ok; true -> error end, 1316 ok = if not (A Op B) -> error; true -> ok end, 1317 (fun(X, Y, True, False) -> 1318 ok = if X Op Y -> ok; true -> error end, 1319 ok = if False; X Op Y; False -> ok; true -> error end, 1320 ok = if X Op Y, True -> ok; true -> error end, 1321 ok = if not (X Op Y) -> error; true -> ok end, 1322 ok = if False; not (X Op Y); False -> error; true -> ok end 1323 end)(id(A), id(B), id(true), id(false))). 1324 1325-define(F(Op,A,B), 1326 ok = if A Op B -> error; true -> ok end, 1327 ok = if not (A Op B) -> ok; true -> error end, 1328 (fun(X, Y, True, False) -> 1329 ok = if X Op Y -> error; true -> ok end, 1330 ok = if False; X Op Y; False -> error; true -> ok end, 1331 ok = if not (X Op Y); False -> ok; true -> error end, 1332 ok = if not (X Op Y), True -> ok; true -> error end 1333 end)(id(A), id(B), id(true), id(false))). 1334 1335 1336rel_ops(Config) when is_list(Config) -> 1337 ?T(=/=, 1, 1.0), 1338 ?F(=/=, 2, 2), 1339 ?F(=/=, {a}, {a}), 1340 1341 ?F(/=, a, a), 1342 ?F(/=, 0, 0.0), 1343 ?T(/=, 0, 1), 1344 ?F(/=, {a}, {a}), 1345 1346 ?T(==, 1, 1.0), 1347 ?F(==, a, {}), 1348 1349 ?F(=:=, 1, 1.0), 1350 ?T(=:=, 42.0, 42.0), 1351 1352 ?F(>, a, b), 1353 ?T(>, 42, 1.0), 1354 ?F(>, 42, 42.0), 1355 1356 ?T(<, a, b), 1357 ?F(<, 42, 1.0), 1358 ?F(<, 42, 42.0), 1359 1360 ?T(=<, 1.5, 5), 1361 ?F(=<, -9, -100.344), 1362 ?T(=<, 42, 42.0), 1363 1364 ?T(>=, 42, 42.0), 1365 ?F(>=, a, b), 1366 ?T(>=, 1.0, 0), 1367 1368 %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1. 1369 true = any_atom /= id(42), 1370 true = [] /= id(42), 1371 1372 %% Coverage of beam_utils:bif_to_test/3 1373 Empty = id([]), 1374 ?T(==, [], Empty), 1375 1376 %% Cover beam_ssa_dead:turn_op('/='). 1377 ok = (fun(A, B) when is_atom(A) -> 1378 X = id(A /= B), 1379 if 1380 X -> ok; 1381 true -> error 1382 end 1383 end)(a, b), 1384 ok = (fun(A, B) when is_atom(A) -> 1385 X = id(B /= A), 1386 if 1387 X -> ok; 1388 true -> error 1389 end 1390 end)(a, b), 1391 1392 %% Cover beam_ssa_dead. 1393 Arrow = fun([T1,T2]) when T1 == $>, T2 == $>; 1394 T1 == $<, T2 == $| -> true; 1395 (_) -> false 1396 end, 1397 true = Arrow(">>"), 1398 true = Arrow("<|"), 1399 false = Arrow("><"), 1400 false = Arrow(""), 1401 1402 ok. 1403 1404-undef(TestOp). 1405 1406rel_op_combinations(Config) when is_list(Config) -> 1407 Digits0 = lists:seq(16#0030, 16#0039) ++ 1408 lists:seq(16#0660, 16#0669) ++ 1409 lists:seq(16#06F0, 16#06F9), 1410 Digits = gb_sets:from_list(Digits0), 1411 rel_op_combinations_1(16#0700, Digits), 1412 1413 BrokenRange0 = lists:seq(3, 5) ++ 1414 lists:seq(10, 12) ++ lists:seq(14, 20), 1415 BrokenRange = gb_sets:from_list(BrokenRange0), 1416 rel_op_combinations_2(30, BrokenRange), 1417 1418 Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++ 1419 [{I,5*I} || I <- lists:seq(51, 80)], 1420 Red = gb_trees:from_orddict(Red0), 1421 rel_op_combinations_3(100, Red), 1422 1423 rel_op_combinations_4(). 1424 1425rel_op_combinations_1(0, _) -> 1426 ok; 1427rel_op_combinations_1(N, Digits) -> 1428 Bool = gb_sets:is_member(N, Digits), 1429 Bool = is_digit_1(N), 1430 Bool = is_digit_2(N), 1431 Bool = is_digit_3(N), 1432 Bool = is_digit_4(N), 1433 Bool = is_digit_5(N), 1434 Bool = is_digit_6(N), 1435 Bool = is_digit_7(N), 1436 Bool = is_digit_8(N), 1437 Bool = is_digit_9(42, N), 1438 Bool = is_digit_10(N, 0), 1439 Bool = is_digit_11(N, 0), 1440 rel_op_combinations_1(N-1, Digits). 1441 1442is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true; 1443is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true; 1444is_digit_1(X) when 16#06F0 =< X, X =< 16#06F9 -> true; 1445is_digit_1(_) -> false. 1446 1447is_digit_2(X) when (16#0030-1) < X, X =< 16#0039 -> true; 1448is_digit_2(X) when (16#0660-1) < X, X =< 16#0669 -> true; 1449is_digit_2(X) when (16#06F0-1) < X, X =< 16#06F9 -> true; 1450is_digit_2(_) -> false. 1451 1452is_digit_3(X) when 16#0660 =< X, X < (16#0669+1) -> true; 1453is_digit_3(X) when 16#0030 =< X, X < (16#0039+1) -> true; 1454is_digit_3(X) when 16#06F0 =< X, X < (16#06F9+1) -> true; 1455is_digit_3(_) -> false. 1456 1457is_digit_4(X) when (16#0660-1) < X, X < (16#0669+1) -> true; 1458is_digit_4(X) when (16#0030-1) < X, X < (16#0039+1) -> true; 1459is_digit_4(X) when (16#06F0-1) < X, X < (16#06F9+1) -> true; 1460is_digit_4(_) -> false. 1461 1462is_digit_5(X) when X >= 16#0660, X =< 16#0669 -> true; 1463is_digit_5(X) when X >= 16#0030, X =< 16#0039 -> true; 1464is_digit_5(X) when X >= 16#06F0, X =< 16#06F9 -> true; 1465is_digit_5(_) -> false. 1466 1467is_digit_6(X) when X > (16#0660-1), X =< 16#0669 -> true; 1468is_digit_6(X) when X > (16#0030-1), X =< 16#0039 -> true; 1469is_digit_6(X) when X > (16#06F0-1), X =< 16#06F9 -> true; 1470is_digit_6(_) -> false. 1471 1472is_digit_7(X) when 16#0660 =< X, X =< 16#0669 -> true; 1473is_digit_7(X) when 16#0030 =< X, X =< 16#003A, X =/= 16#003A -> true; 1474is_digit_7(X) when 16#06F0 =< X, X =< 16#06F9 -> true; 1475is_digit_7(_) -> false. 1476 1477is_digit_8(X) when X =< 16#0039, X > (16#0030-1) -> true; 1478is_digit_8(X) when X =< 16#06F9, X > (16#06F0-1) -> true; 1479is_digit_8(X) when X =< 16#0669, X > (16#0660-1) -> true; 1480is_digit_8(16#0670) -> false; 1481is_digit_8(_) -> false. 1482 1483is_digit_9(A, 0) when A =:= 42 -> false; 1484is_digit_9(_, X) when X > 16#065F, X < 16#066A -> true; 1485is_digit_9(_, X) when 16#0030 =< X, X =< 16#0039 -> true; 1486is_digit_9(_, X) when 16#06F0 =< X, X =< 16#06F9 -> true; 1487is_digit_9(_, _) -> false. 1488 1489is_digit_10(0, 0) -> false; 1490is_digit_10(X, _) when X < 16#066A, 16#0660 =< X -> true; 1491is_digit_10(X, _) when 16#0030 =< X, X =< 16#0039 -> true; 1492is_digit_10(X, _) when 16#06F0 =< X, X =< 16#06F9 -> true; 1493is_digit_10(_, _) -> false. 1494 1495is_digit_11(0, 0) -> false; 1496is_digit_11(X, _) when X =< 16#0669, 16#0660 =< X -> true; 1497is_digit_11(X, _) when 16#0030 =< X, X =< 16#0039 -> true; 1498is_digit_11(X, _) when 16#06F0 =< X, X =< 16#06F9 -> true; 1499is_digit_11(_, _) -> false. 1500 1501rel_op_combinations_2(0, _) -> 1502 ok; 1503rel_op_combinations_2(N, Range) -> 1504 Bool = gb_sets:is_member(N, Range), 1505 Bool = broken_range_1(N), 1506 Bool = broken_range_2(N), 1507 Bool = broken_range_3(N), 1508 Bool = broken_range_4(N), 1509 Bool = broken_range_5(N), 1510 Bool = broken_range_6(N), 1511 Bool = broken_range_7(N), 1512 Bool = broken_range_8(N), 1513 Bool = broken_range_9(N), 1514 Bool = broken_range_10(N), 1515 Bool = broken_range_11(N), 1516 Bool = broken_range_12(N), 1517 Bool = broken_range_13(N), 1518 rel_op_combinations_2(N-1, Range). 1519 1520broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true; 1521broken_range_1(X) when X >= 3, X =< 5 -> true; 1522broken_range_1(_) -> false. 1523 1524broken_range_2(X) when X >= 10, X =< 12 -> true; 1525broken_range_2(X) when X >= 14, X =< 20 -> true; 1526broken_range_2(X) when X >= 3, X =< 5 -> true; 1527broken_range_2(_) -> false. 1528 1529broken_range_3(X) when X >= 10, X =< 12 -> true; 1530broken_range_3(X) when X >= 14, X < 21 -> true; 1531broken_range_3(3) -> true; 1532broken_range_3(4) -> true; 1533broken_range_3(5) -> true; 1534broken_range_3(_) -> false. 1535 1536broken_range_4(X) when X =< 5, X >= 3 -> true; 1537broken_range_4(X) when X >= 10, X =< 20, X =/= 13 -> true; 1538broken_range_4(X) when X =< 100 -> false; 1539broken_range_4(_) -> false. 1540 1541broken_range_5(X) when X >= 10, X =< 20, X =/= 13 -> true; 1542broken_range_5(X) when X > 2, X =< 5 -> true; 1543broken_range_5(_) -> false. 1544 1545broken_range_6(X) when X >= 10, X =< 20, X =/= 13 -> true; 1546broken_range_6(X) when X > 2, X < 6 -> true; 1547broken_range_6(_) -> false. 1548 1549broken_range_7(X) when X > 2, X < 6 -> true; 1550broken_range_7(X) when X >= 10, X =< 20, X =/= 13 -> true; 1551broken_range_7(X) when X > 30 -> false; 1552broken_range_7(_) -> false. 1553 1554broken_range_8(X) when X >= 10, X =< 20, X =/= 13 -> true; 1555broken_range_8(X) when X =:= 3 -> true; 1556broken_range_8(X) when X >= 3, X =< 5 -> true; 1557broken_range_8(_) -> false. 1558 1559broken_range_9(X) when X >= 10, X =< 20, X =/= 13 -> true; 1560broken_range_9(X) when X =:= 13 -> false; 1561broken_range_9(X) when X >= 3, X =< 5 -> true; 1562broken_range_9(_) -> false. 1563 1564broken_range_10(X) when X >= 3, X =< 5 -> true; 1565broken_range_10(X) when X >= 10, X =< 20, X =/= 13 -> true; 1566broken_range_10(X) when X =/= 13 -> false; 1567broken_range_10(_) -> false. 1568 1569broken_range_11(X) when X >= 10, X =< 20, X =/= 13 -> true; 1570broken_range_11(X) when is_tuple(X), X =:= 10 -> true; 1571broken_range_11(X) when X >= 3, X =< 5 -> true; 1572broken_range_11(_) -> false. 1573 1574broken_range_12(X) when X >= 3, X =< 5 -> true; 1575broken_range_12(X) when X >= 10, X =< 20, X =/= 13 -> true; 1576broken_range_12(X) when X < 30, X > 20 -> false; 1577broken_range_12(_) -> false. 1578 1579broken_range_13(X) when X >= 10, X =< 20, 13 =/= X -> true; 1580broken_range_13(X) when X >= 3, X =< 5 -> true; 1581broken_range_13(_) -> false. 1582 1583rel_op_combinations_3(0, _) -> 1584 ok; 1585rel_op_combinations_3(N, Red) -> 1586 Val = case gb_trees:lookup(N, Red) of 1587 none -> none; 1588 {value,V} -> V 1589 end, 1590 Val = redundant_1(N), 1591 Val = redundant_2(N), 1592 Val = redundant_3(N), 1593 Val = redundant_4(N), 1594 Val = redundant_5(N), 1595 Val = redundant_6(N), 1596 Val = redundant_7(N), 1597 Val = redundant_8(N), 1598 Val = redundant_9(N), 1599 Val = redundant_10(N), 1600 Val = redundant_11(N), 1601 Val = redundant_12(N), 1602 rel_op_combinations_3(N-1, Red). 1603 1604redundant_1(X) when X >= 51, X =< 80 -> 5*X; 1605redundant_1(X) when X < 51 -> 2*X; 1606redundant_1(_) -> none. 1607 1608redundant_2(X) when X < 51 -> 2*X; 1609redundant_2(X) when X >= 51, X =< 80 -> 5*X; 1610redundant_2(_) -> none. 1611 1612redundant_3(X) when X < 51 -> 2*X; 1613redundant_3(X) when X =< 80, X >= 51 -> 5*X; 1614redundant_3(X) when X =/= 100 -> none; 1615redundant_3(_) -> none. 1616 1617redundant_4(X) when X < 51 -> 2*X; 1618redundant_4(X) when X =< 80, X > 50 -> 5*X; 1619redundant_4(X) when X =/= 100 -> none; 1620redundant_4(_) -> none. 1621 1622redundant_5(X) when X < 51 -> 2*X; 1623redundant_5(X) when X > 50, X < 81 -> 5*X; 1624redundant_5(X) when X =< 10 -> none; 1625redundant_5(_) -> none. 1626 1627redundant_6(X) when X > 50, X =< 80 -> 5*X; 1628redundant_6(X) when X < 51 -> 2*X; 1629redundant_6(_) -> none. 1630 1631redundant_7(X) when is_integer(X), X >= 51, X =< 80 -> 5*X; 1632redundant_7(X) when is_integer(X), X < 51 -> 2*X; 1633redundant_7(_) -> none. 1634 1635redundant_8(X) when X >= 51, X =< 80 -> 5*X; 1636redundant_8(X) when X < 51 -> 2*X; 1637redundant_8(_) -> none. 1638 1639redundant_9(X) when X >= 51, X =< 80 -> 5*X; 1640redundant_9(X) when X < 51 -> 2*X; 1641redundant_9(90) -> none; 1642redundant_9(X) when X =/= 90 -> none; 1643redundant_9(_) -> none. 1644 1645redundant_10(X) when X >= 51, X =< 80 -> 5*X; 1646redundant_10(X) when X < 51 -> 2*X; 1647redundant_10(90) -> none; 1648redundant_10(X) when X =:= 90 -> none; 1649redundant_10(_) -> none. 1650 1651redundant_11(X) when X < 51 -> 2*X; 1652redundant_11(X) when X =:= 10 -> 2*X; 1653redundant_11(X) when X >= 51, X =< 80 -> 5*X; 1654redundant_11(_) -> none. 1655 1656redundant_12(50) -> 100; 1657redundant_12(X) when X >= 50, X =< 80 -> 5*X; 1658redundant_12(X) when X < 51 -> 2*X; 1659redundant_12(_) -> none. 1660 1661rel_op_combinations_4() -> 1662 ne = rel_op_vars_1(id(a), id(b)), 1663 le = rel_op_vars_1(id(x), id(x)), 1664 1665 ne = rel_op_vars_2(id(a), id(b)), 1666 ge = rel_op_vars_2(id(x), id(x)), 1667 1668 ok. 1669 1670rel_op_vars_1(X, N) when X =/= N -> ne; 1671rel_op_vars_1(X, N) when X =< N -> le. 1672 1673rel_op_vars_2(X, N) when X =/= N -> ne; 1674rel_op_vars_2(X, N) when X >= N -> ge. 1675 1676%% Exhaustively test all combinations of relational operators 1677%% to ensure the correctness of the optimizations in beam_ssa_dead. 1678 1679generated_combinations(_Config) -> 1680 Mod = ?FUNCTION_NAME, 1681 RelOps = ['=:=','=/=','==','/=','<','=<','>=','>'], 1682 Combinations0 = [{Op1,Op2} || Op1 <- RelOps, Op2 <- RelOps], 1683 Combinations1 = gen_lit_combs(Combinations0), 1684 Combinations2 = [{neq,Comb} || 1685 {_Op1,_Lit1,Op2,_Lit2}=Comb <- Combinations1, 1686 Op2 =:= '=/=' orelse Op2 =:= '/='] ++ Combinations1, 1687 Combinations = gen_func_names(Combinations2, 0), 1688 Fs = gen_rel_op_functions(Combinations), 1689 Tree = ?Q(["-module('@Mod@').", 1690 "-compile([export_all,nowarn_export_all])."]) ++ Fs, 1691 %%merl:print(Tree), 1692 Opts = test_lib:opt_opts(?MODULE), 1693 {ok,_Bin} = merl:compile_and_load(Tree, Opts), 1694 test_combinations(Combinations, Mod). 1695 1696gen_lit_combs([{Op1,Op2}|T]) -> 1697 [{Op1,7,Op2,6}, 1698 {Op1,7.0,Op2,6}, 1699 {Op1,7,Op2,6.0}, 1700 {Op1,7.0,Op2,6.0}, 1701 1702 {Op1,7,Op2,7}, 1703 {Op1,7.0,Op2,7}, 1704 {Op1,7,Op2,7.0}, 1705 {Op1,7.0,Op2,7.0}, 1706 1707 {Op1,6,Op2,7}, 1708 {Op1,6.0,Op2,7}, 1709 {Op1,6,Op2,7.0}, 1710 {Op1,6.0,Op2,7.0}|gen_lit_combs(T)]; 1711gen_lit_combs([]) -> []. 1712 1713gen_func_names([E|Es], I) -> 1714 Name = list_to_atom("f" ++ integer_to_list(I)), 1715 [{Name,E}|gen_func_names(Es, I+1)]; 1716gen_func_names([], _) -> []. 1717 1718gen_rel_op_functions([{Name,{neq,{Op1,Lit1,Op2,Lit2}}}|T]) -> 1719 %% Note that in the translation to SSA, '=/=' will be 1720 %% translated to '=:=' in a guard (with switched success 1721 %% and failure labels). Therefore, to test the optimization, 1722 %% we must use '=/=' (or '/=') in a body context. 1723 %% 1724 %% Here is an example of a generated function: 1725 %% 1726 %% f160(A) when erlang:'>='(A, 7) -> 1727 %% one; 1728 %% f160(A) -> 1729 %% true = erlang:'/='(A, 7), 1730 %% two. 1731 [?Q("'@Name@'(A) when erlang:'@Op1@'(A, _@Lit1@) -> one; 1732 '@Name@'(A) -> true = erlang:'@Op2@'(A, _@Lit2@), two. ")| 1733 gen_rel_op_functions(T)]; 1734gen_rel_op_functions([{Name,{Op1,Lit1,Op2,Lit2}}|T]) -> 1735 %% Example of a generated function: 1736 %% 1737 %% f721(A) when erlang:'=<'(A, 7.0) -> one; 1738 %% f721(A) when erlang:'<'(A, 6) -> two; 1739 %% f721(_) -> three. 1740 [?Q("'@Name@'(A) when erlang:'@Op1@'(A, _@Lit1@) -> one; 1741 '@Name@'(A) when erlang:'@Op2@'(A, _@Lit2@) -> two; 1742 '@Name@'(_) -> three.")|gen_rel_op_functions(T)]; 1743gen_rel_op_functions([]) -> []. 1744 1745test_combinations([{Name,E}|T], Mod) -> 1746 try 1747 test_combinations_1([5,6,7,8,9], E, fun Mod:Name/1), 1748 test_combination(6.5, E, fun Mod:Name/1) 1749 catch 1750 error:Reason:Stk -> 1751 io:format("~p: ~p\n", [Name,E]), 1752 erlang:raise(error, Reason, Stk) 1753 end, 1754 test_combinations(T, Mod); 1755test_combinations([], _Mod) -> ok. 1756 1757test_combinations_1([V|Vs], E, Fun) -> 1758 test_combination(V, E, Fun), 1759 test_combination(float(V), E, Fun), 1760 test_combinations_1(Vs, E, Fun); 1761test_combinations_1([], _, _) -> ok. 1762 1763test_combination(Val, {neq,Expr}, Fun) -> 1764 Result = eval_combination_expr(Expr, Val), 1765 Result = try 1766 Fun(Val) %Returns 'one' or 'two'. 1767 catch 1768 error:{badmatch,_} -> 1769 three 1770 end; 1771test_combination(Val, Expr, Fun) -> 1772 Result = eval_combination_expr(Expr, Val), 1773 Result = Fun(Val). 1774 1775eval_combination_expr({Op1,Lit1,Op2,Lit2}, Val) -> 1776 case erlang:Op1(Val, Lit1) of 1777 true -> 1778 one; 1779 false -> 1780 case erlang:Op2(Val, Lit2) of 1781 true -> two; 1782 false -> three 1783 end 1784 end. 1785 1786%% Test type tests on literal values. (From emulator test suites.) 1787literal_type_tests(Config) when is_list(Config) -> 1788 %% Generate an Erlang module with all different type of type tests. 1789 Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++ 1790 [{is_function,L1,L2} || 1791 L1 <- literals(), L2 <- literals()]), 1792 Mod = literal_test, 1793 Anno = erl_anno:new(0), 1794 Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]}, 1795 Form = [{attribute,Anno,module,Mod}, 1796 {attribute,Anno,compile,export_all}, 1797 Func, {eof,999}], 1798 1799 %% Print generated code for inspection. 1800 lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form), 1801 1802 %% Test compile:form/1. This implies full optimization (default). 1803 {ok,Mod,Code1} = compile:forms(Form), 1804 smoke_disasm(Config, Mod, Code1), 1805 {module,Mod} = code:load_binary(Mod, Mod, Code1), 1806 Mod:test(), 1807 true = code:delete(Mod), 1808 code:purge(Mod), 1809 1810 %% Test compile:form/2. Turn off all optimizations. 1811 {ok,Mod,Code2} = compile:forms(Form, [binary,report,time, 1812 no_copt,no_postopt]), 1813 smoke_disasm(Config, Mod, Code2), 1814 {module,Mod} = code:load_binary(Mod, Mod, Code2), 1815 Mod:test(), 1816 true = code:delete(Mod), 1817 code:purge(Mod), 1818 ok. 1819 1820make_test([{T,L1,L2}|Ts]) -> 1821 [test(T, L1, L2)|make_test(Ts)]; 1822make_test([{T,L}|Ts]) -> 1823 [test(T, L)|make_test(Ts)]; 1824make_test([]) -> []. 1825 1826test(T, L) -> 1827 S0 = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T,L,T,L]), 1828 S = lists:flatten(S0), 1829 {ok,Toks,_Line} = erl_scan:string(S), 1830 {ok,E} = erl_parse:parse_exprs(Toks), 1831 {value,Val,_Bs} = erl_eval:exprs(E, []), 1832 Anno = erl_anno:new(0), 1833 {match,Anno,{atom,Anno,Val},hd(E)}. 1834 1835test(T, L1, L2) -> 1836 S0 = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", [T,L1,L2,T,L1,L2]), 1837 S = lists:flatten(S0), 1838 {ok,Toks,_Line} = erl_scan:string(S), 1839 {ok,E} = erl_parse:parse_exprs(Toks), 1840 {value,Val,_Bs} = erl_eval:exprs(E, []), 1841 Anno = erl_anno:new(0), 1842 {match,Anno,{atom,Anno,Val},hd(E)}. 1843 1844smoke_disasm(Config, Mod, Bin) -> 1845 Priv = proplists:get_value(priv_dir, Config), 1846 File = filename:join(Priv, atom_to_list(Mod)++".beam"), 1847 ok = file:write_file(File, Bin), 1848 test_lib:smoke_disasm(File). 1849 1850literals() -> 1851 [42, 1852 3.14, 1853 -3, 1854 32982724987789283473473838474, 1855 [], 1856 xxxx, 1857 {a,b,c}, 1858 [a,list], 1859 <<1,2,3>>, 1860 <<42:17>>]. 1861 1862type_tests() -> 1863 [is_boolean, 1864 is_integer, 1865 is_float, 1866 is_number, 1867 is_atom, 1868 is_list, 1869 is_tuple, 1870 is_pid, 1871 is_reference, 1872 is_port, 1873 is_binary, 1874 is_bitstring, 1875 is_function, 1876 is_map]. 1877 1878basic_andalso_orelse(Config) when is_list(Config) -> 1879 T = id({type,integers,23,42}), 1880 65 = if 1881 ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso 1882 element(2, T)) == integers -> 1883 element(3, T) + element(4, T); 1884 true -> error 1885 end, 1886 65 = case [] of 1887 [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso 1888 element(2, T)) == integers -> 1889 element(3, T) + element(4, T) 1890 end, 1891 1892 42 = basic_rt({type,integers,40,2}), 1893 5.0 = basic_rt({vector,{3.0,4.0}}), 1894 20 = basic_rt(['+',3,7]), 1895 {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), 1896 12 = basic_rt({klurf,4}), 1897 1898 error = basic_rt({type,integers,40,2,3}), 1899 error = basic_rt({kalle,integers,40,2}), 1900 error = basic_rt({kalle,integers,40,2}), 1901 error = basic_rt({1,2}), 1902 error = basic_rt([]), 1903 1904 RelProdBody = 1905 fun(R1, R2) -> 1906 if 1907 (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'), 1908 (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') -> 1909 ok 1910 end 1911 end, 1912 1913 ok = RelProdBody({'Set',a,b}, {'Set',a,b}), 1914 1915 %% 'andalso'/'orelse' with calls known to fail already at compile time. 1916 %% Used to crash the code generator. 1917 error = (fun() -> 1918 R = {vars,true}, 1919 if 1920 is_record(R, vars, 2) andalso element(99, R) -> ok; 1921 true -> error 1922 end 1923 end)(), 1924 error = (fun(X) -> 1925 L = {a,b,c}, 1926 if 1927 is_list(X) andalso length(L) > 4 -> ok; 1928 true -> error 1929 end 1930 end)([]), 1931 ok. 1932 1933basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 4 andalso element(1, T) =:= type andalso 1934 element(2, T) == integers -> 1935 element(3, T) + element(4, T); 1936basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= vector -> 1937 {X,Y} = element(2, T), 1938 if 1939 is_float(X), is_float(Y) -> 1940 math:sqrt(X*X+Y*Y) 1941 end; 1942basic_rt(['+',A,B]) -> 1943 2*id(A+B); 1944basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set', 1945 erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' -> 1946 R1 = id(R1), 1947 R2 = id(R2), 1948 R1; 1949basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= klurf -> 1950 3*id(element(2, T)); 1951basic_rt(_) -> 1952 error. 1953 1954traverse_dcd(Config) when is_list(Config) -> 1955 L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c}, 1956 {log_header,dcd_log,"0.0",a,b,c},blurf], 1957 {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} = 1958 traverse_dcd({cont,L0}, log, funny), 1959 L1 = [{log_header,dcd_log,"1.0"}], 1960 {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny), 1961 L2 = [{a,tuple}], 1962 {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny), 1963 ok. 1964 1965%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}. 1966%% The outer match of a two tuple will places the first element in {x,3} and 1967%% second in {x,4}. The guard for the first clause must make ensure that all of those 1968%% registers are restored before entering the second clause. 1969%% 1970%% (From mnesia_checkpoint.erl, modified.) 1971 1972traverse_dcd({Cont,[LogH|Rest]},Log,Fun) 1973 when is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header 1974andalso erlang:element(2,LogH) == dcd_log, 1975is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header 1976andalso erlang:element(3,LogH) >= "1.0" -> 1977 traverse_dcd({Cont,Rest},Log,Fun); 1978traverse_dcd({Cont,Recs},Log,Fun) -> 1979 {Cont,Recs,Log,Fun}. 1980 1981 1982check_qlc_hrl(Config) when is_list(Config) -> 1983 St = {r1,false,dum}, 1984 foo = cqlc(qlc, q, [{lc,1,2,3}], St), 1985 foo = cqlc(qlc, q, [{lc,1,2,3},b], St), 1986 St = cqlc(qlc, q, [], St), 1987 St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), 1988 St = cqlc(q, q, [{lc,1,2,3},b], St), 1989 St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), 1990 St = cqlc(qlc, q, [a,b], St), 1991 {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), 1992 ok. 1993 1994%% From erl_lint.erl; original name was check_qlc_hrl/4. 1995cqlc(M, F, As, St) -> 1996 Arity = length(As), 1997 case As of 1998 [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q, 1999 Arity < 3, 2000 not (((element(1, St) =:= r1) orelse fail) and (tuple_size(St) =:= 3) and element(2, St)) -> 2001 foo; 2002 _ -> 2003 St 2004 end. 2005 2006%% OTP-7679: Thanks to Hunter Morris. 2007andalso_semi(Config) when is_list(Config) -> 2008 ok = andalso_semi_foo(0), 2009 ok = andalso_semi_foo(1), 2010 fc(catch andalso_semi_foo(2)), 2011 2012 ok = andalso_semi_bar([a,b,c]), 2013 ok = andalso_semi_bar(1), 2014 fc(catch andalso_semi_bar([a,b])), 2015 2016 ok = andalso_semi_dispatch(name, fun andalso_semi/1), 2017 ok = andalso_semi_dispatch(name, fun ?MODULE:andalso_semi/1), 2018 ok = andalso_semi_dispatch(name, {?MODULE,andalso_semi,1}), 2019 fc(catch andalso_semi_dispatch(42, fun andalso_semi/1)), 2020 fc(catch andalso_semi_dispatch(name, not_fun)), 2021 fc(catch andalso_semi_dispatch(name, fun andalso_semi_dispatch/2)), 2022 fc(catch andalso_semi_dispatch(42, {a,b})), 2023 2024 ok. 2025 2026andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 -> 2027 ok. 2028 2029andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 -> 2030 ok. 2031 2032andalso_semi_dispatch(Registry, MFAOrFun) when 2033 is_atom(Registry) andalso is_function(MFAOrFun, 1); 2034 is_atom(Registry) andalso tuple_size(MFAOrFun) == 3 -> 2035 ok. 2036 2037t_tuple_size(Config) when is_list(Config) -> 2038 10 = do_tuple_size({1,2,3,4}), 2039 fc(catch do_tuple_size({1,2,3})), 2040 fc(catch do_tuple_size(42)), 2041 2042 error = ludicrous_tuple_size({a,b,c}), 2043 error = ludicrous_tuple_size([a,b,c]), 2044 2045 good_ip({1,2,3,4}), 2046 good_ip({1,2,3,4,5,6,7,8}), 2047 error = validate_ip({42,11}), 2048 error = validate_ip(atom), 2049 2050 ok. 2051 2052do_tuple_size(T) when tuple_size(T) =:= 4 -> 2053 {A,B,C,D} = T, 2054 A+B+C+D. 2055 2056ludicrous_tuple_size(T) 2057 when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok; 2058ludicrous_tuple_size(T) 2059 when tuple_size(T) =:= 16#10000000000000000 -> ok; 2060ludicrous_tuple_size(T) 2061 when tuple_size(T) =:= (1 bsl 64) - 1 -> ok; 2062ludicrous_tuple_size(T) 2063 when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok; 2064ludicrous_tuple_size(_) -> error. 2065 2066good_ip(IP) -> 2067 IP = validate_ip(IP). 2068 2069validate_ip(Value) when is_tuple(Value) andalso 2070 ((size(Value) =:= 4) orelse (size(Value) =:= 8)) -> 2071 %% size/1 (converted to tuple_size) used more than once. 2072 Value; 2073validate_ip(_) -> 2074 error. 2075 2076%% 2077%% The binary_part/2,3 guard BIFs 2078%% 2079-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))). 2080mask_error({'EXIT',{Err,_}}) -> 2081 Err; 2082mask_error(Else) -> 2083 Else. 2084 2085%% Test the binary_part/2,3 guard (GC) BIFs. 2086binary_part(Config) when is_list(Config) -> 2087 %% This is more or less a copy of what the guard_SUITE in emulator 2088 %% does to cover the guard bif's 2089 1 = bptest(<<1,2,3>>), 2090 2 = bptest(<<2,1,3>>), 2091 error = bptest(<<1>>), 2092 error = bptest(<<>>), 2093 error = bptest(apa), 2094 3 = bptest(<<2,3,3>>), 2095 % With one variable (pos) 2096 1 = bptest(<<1,2,3>>,1), 2097 2 = bptest(<<2,1,3>>,1), 2098 error = bptest(<<1>>,1), 2099 error = bptest(<<>>,1), 2100 error = bptest(apa,1), 2101 3 = bptest(<<2,3,3>>,1), 2102 % With one variable (length) 2103 1 = bptesty(<<1,2,3>>,1), 2104 2 = bptesty(<<2,1,3>>,1), 2105 error = bptesty(<<1>>,1), 2106 error = bptesty(<<>>,1), 2107 error = bptesty(apa,1), 2108 3 = bptesty(<<2,3,3>>,2), 2109 % With one variable (whole tuple) 2110 1 = bptestx(<<1,2,3>>,{1,1}), 2111 2 = bptestx(<<2,1,3>>,{1,1}), 2112 error = bptestx(<<1>>,{1,1}), 2113 error = bptestx(<<>>,{1,1}), 2114 error = bptestx(apa,{1,1}), 2115 3 = bptestx(<<2,3,3>>,{1,2}), 2116 % With two variables 2117 1 = bptest(<<1,2,3>>,1,1), 2118 2 = bptest(<<2,1,3>>,1,1), 2119 error = bptest(<<1>>,1,1), 2120 error = bptest(<<>>,1,1), 2121 error = bptest(apa,1,1), 2122 3 = bptest(<<2,3,3>>,1,2), 2123 % Direct (autoimported) call, these will be evaluated by the compiler... 2124 <<2>> = binary_part(<<1,2,3>>,1,1), 2125 <<1>> = binary_part(<<2,1,3>>,1,1), 2126 % Compiler warnings due to constant evaluation expected (3) 2127 badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)), 2128 badarg = ?MASK_ERROR(binary_part(<<>>,1,1)), 2129 badarg = ?MASK_ERROR(binary_part(apa,1,1)), 2130 <<3,3>> = binary_part(<<2,3,3>>,1,2), 2131 % Direct call through apply 2132 <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]), 2133 <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]), 2134 % Compiler warnings due to constant evaluation expected (3) 2135 badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])), 2136 badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])), 2137 badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])), 2138 <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]), 2139 % Constant propagation 2140 Bin = <<1,2,3>>, 2141 ok = if 2142 binary_part(Bin,1,1) =:= <<2>> -> 2143 ok; 2144 %% Compiler warning, clause cannot match (expected) 2145 true -> 2146 error 2147 end, 2148 ok = if 2149 binary_part(Bin,{1,1}) =:= <<2>> -> 2150 ok; 2151 %% Compiler warning, clause cannot match (expected) 2152 true -> 2153 error 2154 end, 2155 ok. 2156 2157 2158bptest(B) when length(B) =:= 1337 -> 2159 1; 2160bptest(B) when binary_part(B,{1,1}) =:= <<2>> -> 2161 1; 2162bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> -> 2163 2; 2164bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> -> 2165 3; 2166bptest(_) -> 2167 error. 2168 2169bptest(B,A) when length(B) =:= A -> 2170 1; 2171bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> -> 2172 1; 2173bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> -> 2174 2; 2175bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> -> 2176 3; 2177bptest(_,_) -> 2178 error. 2179 2180bptestx(B,A) when length(B) =:= A -> 2181 1; 2182bptestx(B,A) when binary_part(B,A) =:= <<2>> -> 2183 1; 2184bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> -> 2185 2; 2186bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> -> 2187 3; 2188bptestx(_,_) -> 2189 error. 2190 2191bptesty(B,A) when length(B) =:= A -> 2192 1; 2193bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> -> 2194 1; 2195bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> -> 2196 2; 2197bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> -> 2198 3; 2199bptesty(_,_) -> 2200 error. 2201 2202bptest(B,A,_C) when length(B) =:= A -> 2203 1; 2204bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> -> 2205 1; 2206bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> -> 2207 2; 2208bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> -> 2209 3; 2210bptest(_,_,_) -> 2211 error. 2212 2213-define(FAILING(C), 2214 if 2215 C -> ct:fail(should_fail); 2216 true -> ok 2217 end, 2218 if 2219 true, C -> ct:fail(should_fail); 2220 true -> ok 2221 end). 2222 2223bad_constants(Config) when is_list(Config) -> 2224 ?FAILING(false), 2225 ?FAILING([]), 2226 ?FAILING([a]), 2227 ?FAILING([Config]), 2228 ?FAILING({a,b}), 2229 ?FAILING({a,Config}), 2230 ?FAILING(<<1>>), 2231 ?FAILING(42), 2232 ?FAILING(3.14), 2233 ok. 2234 2235bad_guards(Config) when is_list(Config) -> 2236 if erlang:float(self()); true -> ok end, 2237 2238 fc(catch bad_guards_1(1, [])), 2239 fc(catch bad_guards_1(1, [2])), 2240 fc(catch bad_guards_1(atom, [2])), 2241 2242 fc(catch bad_guards_2(#{a=>0,b=>0}, [])), 2243 fc(catch bad_guards_2(#{a=>0,b=>0}, [x])), 2244 fc(catch bad_guards_2(not_a_map, [x])), 2245 fc(catch bad_guards_2(42, [x])), 2246 2247 fc(catch bad_guards_3(#{a=>0,b=>0}, [])), 2248 fc(catch bad_guards_3(#{a=>0,b=>0}, [x])), 2249 fc(catch bad_guards_3(not_a_map, [x])), 2250 fc(catch bad_guards_3(42, [x])), 2251 2252 fc(catch bad_guards_4()), 2253 2254 {0,undefined} = bad_guards_5(id(<<>>), id(undefined)), 2255 2256 ok. 2257 2258%% beam_bool used to produce GC BIF instructions whose 2259%% Live operands included uninitialized registers. 2260 2261bad_guards_1(X, [_]) when {{X}}, -X -> 2262 ok. 2263 2264bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) -> 2265 ok. 2266 2267%% beam_type used to produce an GC BIF instruction whose Live operand 2268%% included uninitialized registers. 2269 2270bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) -> 2271 ok. 2272 2273%% v3_codegen would generate a jump to the failure label, but 2274%% without initializing x(0). The code at the failure label expected 2275%% x(0) to be initialized. 2276 2277bad_guards_4() when not (error#{}); {not 0.0} -> freedom. 2278 2279%% The JIT used to segfault when a guard rem instruction failed 2280%% with badarith AND a bif had been called just before it. 2281bad_guards_5(A, B) -> 2282 {byte_size(A), undefined = bad_guards_5_1(B)}. 2283bad_guards_5_1(A) when is_integer(A rem 255) -> 2284 A rem 255; 2285bad_guards_5_1(_) -> 2286 undefined. 2287 2288%% Building maps in a guard in a 'catch' would crash v3_codegen. 2289 2290guard_in_catch(_Config) -> 2291 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{}), 2292 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{a=>b}), 2293 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(atom), 2294 2295 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{}), 2296 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{a=>b}), 2297 {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(atom), 2298 2299 {'EXIT',{if_clause,_}} = (catch do_guard_in_catch_map_3()), 2300 2301 {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(42), 2302 {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(<<1,2,3>>), 2303 {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(atom), 2304 {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(#{}), 2305 2306 ok. 2307 2308do_guard_in_catch_map_1(From) -> 2309 catch 2310 if 2311 From#{[] => sufficient} -> 2312 saint 2313 end. 2314 2315do_guard_in_catch_map_2(From) -> 2316 catch 2317 if 2318 From#{From => sufficient} -> 2319 saint 2320 end. 2321 2322do_guard_in_catch_map_3() -> 2323 try 2324 if [] -> solo end 2325 catch 2326 Friendly when Friendly#{0 => []} -> minutes 2327 after 2328 membership 2329 end. 2330 2331do_guard_in_catch_bin(From) -> 2332 %% Would not crash v3_codegen, but there would be an unnecessary 2333 %% 'move' to a Y register. 2334 catch 2335 if 2336 <<From:32>> -> 2337 saint 2338 end. 2339 2340%%% 2341%%% The beam_bool pass has been eliminated. Here are the tests from 2342%%% beam_bool_SUITE, as well as new tests to test the new beam_ssa_bool 2343%%% module. 2344%%% 2345 2346beam_bool_SUITE(_Config) -> 2347 before_and_inside_if(), 2348 scotland(), 2349 y_registers(), 2350 protected(), 2351 maps(), 2352 cover_shortcut_branches(), 2353 wrong_order(), 2354 megaco(), 2355 looks_like_a_guard(), 2356 fail_in_guard(), 2357 in_catch(), 2358 recv_semi(), 2359 andalso_repeated_var(), 2360 erl1246(), 2361 erl1253(), 2362 erl1384(), 2363 gh4788(), 2364 beam_ssa_bool_coverage(), 2365 ok. 2366 2367before_and_inside_if() -> 2368 no = before_and_inside_if([a], [b], delete), 2369 no = before_and_inside_if([a], [b], x), 2370 no = before_and_inside_if([a], [], delete), 2371 no = before_and_inside_if([a], [], x), 2372 no = before_and_inside_if([], [], delete), 2373 yes = before_and_inside_if([], [], x), 2374 yes = before_and_inside_if([], [b], delete), 2375 yes = before_and_inside_if([], [b], x), 2376 2377 {ch1,ch2} = before_and_inside_if_2([a], [b], blah), 2378 {ch1,ch2} = before_and_inside_if_2([a], [b], xx), 2379 {ch1,ch2} = before_and_inside_if_2([a], [], blah), 2380 {ch1,ch2} = before_and_inside_if_2([a], [], xx), 2381 {no,no} = before_and_inside_if_2([], [b], blah), 2382 {no,no} = before_and_inside_if_2([], [b], xx), 2383 {ch1,no} = before_and_inside_if_2([], [], blah), 2384 {no,ch2} = before_and_inside_if_2([], [], xx), 2385 ok. 2386 2387%% Thanks to Simon Cornish and Kostis Sagonas. 2388%% Used to crash beam_bool. 2389before_and_inside_if(XDo1, XDo2, Do3) -> 2390 Do1 = (XDo1 =/= []), 2391 Do2 = (XDo2 =/= []), 2392 if 2393 %% This expression occurs in a try/catch (protected) 2394 %% block, which cannot refer to variables outside of 2395 %% the block that are boolean expressions. 2396 Do1 =:= true; 2397 Do1 =:= false, Do2 =:= false, Do3 =:= delete -> 2398 no; 2399 true -> 2400 yes 2401 end. 2402 2403%% Thanks to Simon Cornish. 2404%% Used to generate code that would not set {y,0} on 2405%% all paths before its use (and therefore fail 2406%% validation by the beam_validator). 2407before_and_inside_if_2(XDo1, XDo2, Do3) -> 2408 Do1 = (XDo1 =/= []), 2409 Do2 = (XDo2 =/= []), 2410 CH1 = if Do1 == true; 2411 Do1 == false,Do2==false,Do3 == blah -> 2412 ch1; 2413 true -> 2414 no 2415 end, 2416 CH2 = if Do1 == true; 2417 Do1 == false,Do2==false,Do3 == xx -> 2418 ch2; 2419 true -> 2420 no 2421 end, 2422 {CH1,CH2}. 2423 2424 2425%% beam_bool would remove the initialization of {y,0}. 2426%% (Thanks to Thomas Arts and QuickCheck.) 2427 2428scotland() -> 2429 million = do_scotland(placed), 2430 {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)), 2431 {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)), 2432 {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)), 2433 ok. 2434 2435do_scotland(Echo) -> 2436 found(case Echo of 2437 Echo when true; Echo, Echo, Echo -> 2438 Echo; 2439 echo -> 2440 [] 2441 end, 2442 Echo = placed). 2443 2444found(_, _) -> million. 2445 2446 2447%% ERL-143: beam_bool could not handle Y registers as a destination. 2448y_registers() -> 2449 {'EXIT',{badarith,[_|_]}} = (catch baker(valentine)), 2450 {'EXIT',{badarith,[_|_]}} = (catch baker(clementine)), 2451 2452 {not_ok,true} = potter([]), 2453 {ok,false} = potter([{encoding,any}]), 2454 2455 ok. 2456 2457%% Thanks to Quickcheck. 2458baker(Baker) -> 2459 (valentine == Baker) + 2460 case Baker of 2461 Baker when Baker; Baker -> 2462 Baker; 2463 Baker -> 2464 [] 2465 end. 2466 2467%% Thanks to Jose Valim. 2468potter(Modes) -> 2469 Raw = lists:keyfind(encoding, 1, Modes) == false, 2470 Final = case Raw of 2471 X when X == false; X == nil -> ok; 2472 _ -> not_ok 2473 end, 2474 {Final,Raw}. 2475 2476protected() -> 2477 {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)), 2478 2479 {{true}} = welcome({perfect, true}), 2480 {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})), 2481 ok. 2482 2483photographs({_Violation, surprise, Deep}, opinions) -> 2484 {if 2485 0; "here", Deep -> 2486 Deep = Deep 2487 end}. 2488 2489welcome({perfect, Profit}) -> 2490 if 2491 Profit, Profit, Profit; 0 -> 2492 {id({Profit})} 2493 end. 2494 2495maps() -> 2496 ok = evidence(#{0 => 42}). 2497 2498%% Cover handling of put_map in in split_block_label_used/2. 2499evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} -> 2500 ok. 2501 2502cover_shortcut_branches() -> 2503 ok = cover_shortcut_branches({r1}, 0, 42, false), 2504 ok = cover_shortcut_branches({r1}, 42, 42, true), 2505 error = cover_shortcut_branches({r1}, same, same, false), 2506 error = cover_shortcut_branches({r1}, x, y, true), 2507 error = cover_shortcut_branches({r2}, 0, 42, false), 2508 error = cover_shortcut_branches({}, 0, 42, false), 2509 error = cover_shortcut_branches(not_tuple, 0, 42, false), 2510 ok. 2511 2512cover_shortcut_branches(St, X, Y, Z) -> 2513 if 2514 %% The ((Y =:= X) =:= Z) part will test handling of a comparison 2515 %% operator followed by a one-way `br`. 2516 ((element(1, St) =:= r1) orelse fail) and ((Y =:= X) =:= Z) -> 2517 ok; 2518 true -> 2519 error 2520 end. 2521 2522wrong_order() -> 2523 ok = wrong_order(repeat_until_fail, true), 2524 ok = wrong_order(repeat_until_fail, whatever), 2525 error = wrong_order(repeat_until_fail, false), 2526 error = wrong_order(nope, true), 2527 ok. 2528 2529wrong_order(RepeatType, Mode) -> 2530 Parallel = Mode =/= false, 2531 RepeatStop = RepeatType =:= repeat_until_fail, 2532 if 2533 Parallel andalso RepeatStop -> 2534 ok; 2535 true -> 2536 error 2537 end. 2538 2539megaco() -> 2540 ok = megaco('NULL', 0), 2541 ok = megaco('NULL', 7), 2542 ok = megaco('NULL', 15), 2543 ok = megaco('NULL', asn1_NOVALUE), 2544 ok = megaco(asn1_NOVALUE, 0), 2545 ok = megaco(asn1_NOVALUE, 7), 2546 ok = megaco(asn1_NOVALUE, 15), 2547 ok = megaco(asn1_NOVALUE, asn1_NOVALUE), 2548 2549 error = megaco(bad, 0), 2550 error = megaco(bad, 7), 2551 error = megaco(bad, 15), 2552 error = megaco(bad, asn1_NOVALUE), 2553 2554 error = megaco('NULL', not_integer), 2555 error = megaco('NULL', -1), 2556 error = megaco('NULL', 16), 2557 error = megaco(asn1_NOVALUE, not_integer), 2558 error = megaco(asn1_NOVALUE, -1), 2559 error = megaco(asn1_NOVALUE, 16), 2560 2561 error = megaco(bad, bad), 2562 error = megaco(bad, -1), 2563 error = megaco(bad, 42), 2564 2565 ok. 2566 2567megaco(Top, SelPrio) 2568 when (Top =:= 'NULL' orelse Top =:= asn1_NOVALUE) andalso 2569 ((is_integer(SelPrio) andalso ((0 =< SelPrio) and (SelPrio =< 15))) orelse 2570 SelPrio =:= asn1_NOVALUE) -> 2571 ok; 2572megaco(_, _) -> 2573 error. 2574 2575%% ERL-1054. 2576looks_like_a_guard() -> 2577 ok = looks_like_a_guard(0), 2578 ok = looks_like_a_guard(1), 2579 ok. 2580 2581looks_like_a_guard(N) -> 2582 GuessPosition = id(42), 2583 %% The matching of `true` would look like a guard to 2584 %% beam_ssa_bool. The optimized code would not be safe. 2585 case {1 >= N, GuessPosition == 0} of 2586 {true, _} -> ok; 2587 {_, true} -> ok; 2588 _ -> looks_like_a_guard(N) 2589 end. 2590 2591-record(fail_in_guard, {f}). 2592fail_in_guard() -> 2593 false = struct_or_map(a, "foo"), 2594 false = struct_or_map(a, foo), 2595 false = struct_or_map(#{}, "foo"), 2596 true = struct_or_map(#{}, foo), 2597 2598 false = (fun() when whatever =/= (program andalso []) -> true; 2599 () -> false 2600 end)(), 2601 false = if whatever =/= (program orelse []) -> true; 2602 true -> false 2603 end, 2604 2605 %% Would crash the compiler if optimizing passes 2606 %% were disabled. 2607 error = if 2608 0.1 orelse "VZ", 42 -> ok; 2609 true -> error 2610 end, 2611 error = (fun() when 3.14; <<[]:(ceil($D))>> -> ok; 2612 () -> error 2613 end)(), 2614 error = fun() when eye; ""#fail_in_guard.f andalso #{[] => true and false} -> 2615 ok; 2616 () -> 2617 error 2618 end(), 2619 error = fun() when (0 #fail_in_guard.f)#fail_in_guard.f -> ok; 2620 () -> error 2621 end(), 2622 error = fun() when 42; <<0.5,0:(element(true, false))>> -> 2623 a = b; 2624 () -> error 2625 end(), 2626 2627 ok. 2628 2629%% ERL-1183. If Name is not an atom, the `fail` atom must cause the 2630%% entire guard to fail. 2631struct_or_map(Arg, Name) when 2632 (is_map(Arg) andalso (is_atom(Name) orelse fail) andalso 2633 is_map_key(struct, Arg)) orelse is_map(Arg) -> true; 2634struct_or_map(_Arg, _Name) -> 2635 false. 2636 2637in_catch() -> 2638 ok = in_catch(true), 2639 {'EXIT',{{case_clause,false},[_|_]}} = in_catch(false), 2640 {'EXIT',{badarg,[_|_]}} = in_catch(any), 2641 ok. 2642 2643in_catch(V) -> 2644 catch 2645 case false or V of 2646 true -> ok 2647 end. 2648 2649recv_semi() -> 2650 timeout = id(receive 2651 ok when home; <<(m#{}):false>> -> 2652 ok 2653 after 0 -> 2654 timeout 2655 end). 2656 2657andalso_repeated_var() -> 2658 ok = andalso_repeated_var(true), 2659 error = andalso_repeated_var(false), 2660 error = andalso_repeated_var([not_boolean]), 2661 ok. 2662 2663andalso_repeated_var(B) when B andalso B -> ok; 2664andalso_repeated_var(_) -> error. 2665 2666-record(erl1246, {tran_stat = 0}). 2667 2668erl1246() -> 2669 false = erl1246(#erl1246{tran_stat = 0}, #{cid => 1131}), 2670 false = erl1246(#erl1246{tran_stat = 12}, #{cid => 1131}), 2671 false = erl1246(#erl1246{tran_stat = 12}, #{cid => 9502}), 2672 true = erl1246(#erl1246{tran_stat = 0}, #{cid => 9502}), 2673 ok. 2674 2675erl1246(Rec, #{cid := CollID}) -> 2676 {GiftCollID, _} = erl1246_conf(gift_coll), 2677 IsTranStat = Rec#erl1246.tran_stat =:= erl1246_conf(transform_id), 2678 if 2679 %% Optimization of 'not' in a guard was broken. 2680 CollID =:= GiftCollID andalso not IsTranStat -> 2681 true; 2682 true -> 2683 false 2684 end. 2685 2686erl1246_conf(gift_coll) -> {9502, {112, 45}}; 2687erl1246_conf(transform_id) -> 12; 2688erl1246_conf(_) -> undefined. 2689 2690erl1253() -> 2691 ok = erl1253_orelse_false(a, a, any), 2692 ok = erl1253_orelse_false(a, a, true), 2693 ok = erl1253_orelse_false(a, a, false), 2694 error = erl1253_orelse_false(a, b, any), 2695 error = erl1253_orelse_false(a, b, true), 2696 ok = erl1253_orelse_false(a, b, false), 2697 2698 ok = erl1253_orelse_true(a, a, any), 2699 ok = erl1253_orelse_true(a, a, true), 2700 ok = erl1253_orelse_true(a, a, false), 2701 error = erl1253_orelse_true(a, b, any), 2702 ok = erl1253_orelse_true(a, b, true), 2703 error = erl1253_orelse_true(a, b, false), 2704 2705 error = erl1253_andalso_false(a, a, any), 2706 error = erl1253_andalso_false(a, a, true), 2707 ok = erl1253_andalso_false(a, a, false), 2708 error = erl1253_andalso_false(a, b, any), 2709 error = erl1253_andalso_false(a, b, true), 2710 error = erl1253_andalso_false(a, b, false), 2711 2712 error = erl1253_andalso_true(a, a, any), 2713 ok = erl1253_andalso_true(a, a, true), 2714 error = erl1253_andalso_true(a, a, false), 2715 error = erl1253_andalso_true(a, b, any), 2716 error = erl1253_andalso_true(a, b, true), 2717 error = erl1253_andalso_true(a, b, false), 2718 2719 ok. 2720 2721erl1253_orelse_false(X, Y, Z) -> 2722 Res = erl1253_orelse_false_1(X, Y, Z), 2723 Res = erl1253_orelse_false_2(X, Y, Z), 2724 Res = erl1253_orelse_false_3(X, Y, Z). 2725 2726erl1253_orelse_false_1(X, Y, Z) -> 2727 Bool = Z =:= false, 2728 if 2729 X =:= Y orelse Bool -> ok; 2730 true -> error 2731 end. 2732 2733erl1253_orelse_false_2(X, Y, Z) -> 2734 Bool = Z =:= false, 2735 if 2736 Bool orelse X =:= Y -> ok; 2737 true -> error 2738 end. 2739 2740erl1253_orelse_false_3(X, Y, Z) -> 2741 Bool1 = X =:= Y, 2742 Bool2 = Z =:= false, 2743 if 2744 Bool1 orelse Bool2 -> ok; 2745 true -> error 2746 end. 2747 2748erl1253_orelse_true(X, Y, Z) -> 2749 Res = erl1253_orelse_true_1(X, Y, Z), 2750 Res = erl1253_orelse_true_2(X, Y, Z), 2751 Res = erl1253_orelse_true_3(X, Y, Z). 2752 2753erl1253_orelse_true_1(X, Y, Z) -> 2754 Bool = Z =:= true, 2755 if 2756 X =:= Y orelse Bool -> ok; 2757 true -> error 2758 end. 2759 2760erl1253_orelse_true_2(X, Y, Z) -> 2761 Bool = Z =:= true, 2762 if 2763 Bool orelse X =:= Y -> ok; 2764 true -> error 2765 end. 2766 2767erl1253_orelse_true_3(X, Y, Z) -> 2768 Bool1 = X =:= Y, 2769 Bool2 = Z =:= true, 2770 if 2771 Bool1 orelse Bool2 -> ok; 2772 true -> error 2773 end. 2774 2775erl1253_andalso_false(X, Y, Z) -> 2776 Res = erl1253_andalso_false_1(X, Y, Z), 2777 Res = erl1253_andalso_false_2(X, Y, Z), 2778 Res = erl1253_andalso_false_3(X, Y, Z). 2779 2780erl1253_andalso_false_1(X, Y, Z) -> 2781 Bool = Z =:= false, 2782 if 2783 X =:= Y andalso Bool -> ok; 2784 true -> error 2785 end. 2786 2787erl1253_andalso_false_2(X, Y, Z) -> 2788 Bool1 = X =:= Y, 2789 Bool2 = Z =:= false, 2790 if 2791 Bool1 andalso Bool2 -> ok; 2792 true -> error 2793 end. 2794 2795erl1253_andalso_false_3(X, Y, Z) -> 2796 Bool1 = X =:= Y, 2797 Bool2 = Z =:= false, 2798 if 2799 Bool1 andalso Bool2 -> ok; 2800 true -> error 2801 end. 2802 2803erl1253_andalso_true(X, Y, Z) -> 2804 Res = erl1253_andalso_true_1(X, Y, Z), 2805 Res = erl1253_andalso_true_2(X, Y, Z), 2806 Res = erl1253_andalso_true_3(X, Y, Z). 2807 2808erl1253_andalso_true_1(X, Y, Z) -> 2809 Bool = Z =:= true, 2810 if 2811 X =:= Y andalso Bool -> ok; 2812 true -> error 2813 end. 2814 2815erl1253_andalso_true_2(X, Y, Z) -> 2816 Bool = Z =:= true, 2817 if 2818 Bool andalso X =:= Y-> ok; 2819 true -> error 2820 end. 2821 2822erl1253_andalso_true_3(X, Y, Z) -> 2823 Bool1 = X =:= Y, 2824 Bool2 = Z =:= true, 2825 if 2826 Bool1 andalso Bool2 -> ok; 2827 true -> error 2828 end. 2829 2830erl1384() -> 2831 gurka = erl1384_1(id(a)), 2832 gaffel = erl1384_1(id(b)), 2833 ok. 2834 2835erl1384_1(V) -> 2836 case {id(false), V =/= a} of 2837 {true, true} -> not_reachable; 2838 {_, false} -> gurka; 2839 _ -> gaffel 2840 end. 2841 2842gh4788() -> 2843 ok = do_gh4788(id(0)), 2844 ok = do_gh4788(id(1)), 2845 ok = do_gh4788(id(undefined)), 2846 lt_0_or_undefined = catch do_gh4788(id(-1)), 2847 ok. 2848 2849do_gh4788(N) -> 2850 %% beam_ssa_bool would do an unsafe optimization when run after 2851 %% the beam_ssa_share pass. 2852 case {N >= 0, N == undefined} of 2853 {true, _} -> ok; 2854 {_, true} -> ok; 2855 _ -> throw(lt_0_or_undefined) 2856 end, 2857 ok. 2858 2859beam_ssa_bool_coverage() -> 2860 {"*","abc"} = collect_modifiers("abc*", []), 2861 error = beam_ssa_bool_coverage_1(true), 2862 ok. 2863 2864collect_modifiers([H | T], Buffer) 2865 when (H >= $a andalso H =< $z) or 2866 (H >= $A andalso H =< $Z) -> 2867 collect_modifiers(T, [H | Buffer]); 2868collect_modifiers(Rest, Buffer) -> 2869 {Rest, lists:reverse(Buffer)}. 2870 2871beam_ssa_bool_coverage_1(V) when V andalso 0, tuple_size(0) -> 2872 ok; 2873beam_ssa_bool_coverage_1(_) -> 2874 error. 2875 2876%%% 2877%%% End of beam_bool_SUITE tests. 2878%%% 2879 2880repeated_type_tests(_Config) -> 2881 binary = repeated_type_test(<<42>>), 2882 bitstring = repeated_type_test(<<1:1>>), 2883 other = repeated_type_test(atom), 2884 ok. 2885 2886repeated_type_test(T) -> 2887 %% Test for a bug in beam_ssa_dead. 2888 if is_bitstring(T) -> 2889 if is_binary(T) -> %This test would be optimized away. 2890 binary; 2891 true -> 2892 bitstring 2893 end; 2894 true -> 2895 other 2896 end. 2897 2898%% ERL-1179: The result of '=/=' would be flipped if it was used after being 2899%% branched on. 2900use_after_branch(_Config) -> 2901 {false, gaffel} = use_after_branch_1(foo), 2902 {true, gurka} = use_after_branch_1(bar), 2903 ok. 2904 2905use_after_branch_1(A) -> 2906 Boolean = A =/= foo, 2907 case Boolean of 2908 true -> id(something); 2909 false -> id(other) 2910 end, 2911 case Boolean of 2912 true -> {id(Boolean), gurka}; 2913 false -> {id(Boolean), gaffel} 2914 end. 2915 2916%% Call this function to turn off constant propagation. 2917id(I) -> I. 2918 2919check(F, Result) -> 2920 case F() of 2921 Result -> ok; 2922 Other -> 2923 io:format("Expected: ~p\n", [Result]), 2924 io:format(" Got: ~p\n", [Other]), 2925 ct:fail(check_failed) 2926 end. 2927 2928fc({'EXIT',{function_clause,_}}) -> ok; 2929fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= guard_inline_SUITE -> ok. 2930