PageRenderTime 80ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/compiler/test/guard_SUITE.erl

https://github.com/cobusc/otp
Erlang | 2248 lines | 1738 code | 387 blank | 123 comment | 208 complexity | 9e55987c7b08e35dd26da3065e2f0caf MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2001-2017. 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. -include_lib("common_test/include/ct.hrl").
  22. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
  23. init_per_group/2,end_per_group/2,
  24. misc/1,const_cond/1,basic_not/1,complex_not/1,nested_nots/1,
  25. semicolon/1,complex_semicolon/1,comma/1,
  26. or_guard/1,more_or_guards/1,
  27. complex_or_guards/1,and_guard/1,
  28. xor_guard/1,more_xor_guards/1,
  29. old_guard_tests/1,complex_guard/1,
  30. build_in_guard/1,gbif/1,
  31. t_is_boolean/1,is_function_2/1,
  32. tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1,
  33. basic_andalso_orelse/1,traverse_dcd/1,
  34. check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
  35. bad_constants/1,bad_guards/1,
  36. guard_in_catch/1,beam_bool_SUITE/1,
  37. cover_beam_dead/1]).
  38. suite() -> [{ct_hooks,[ts_install_cth]}].
  39. all() ->
  40. [{group,p}].
  41. groups() ->
  42. [{p,[parallel],
  43. [misc,const_cond,basic_not,complex_not,nested_nots,
  44. semicolon,complex_semicolon,comma,or_guard,
  45. more_or_guards,complex_or_guards,and_guard,xor_guard,
  46. more_xor_guards,build_in_guard,
  47. old_guard_tests,complex_guard,gbif,
  48. t_is_boolean,is_function_2,tricky,
  49. rel_ops,rel_op_combinations,
  50. literal_type_tests,basic_andalso_orelse,traverse_dcd,
  51. check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
  52. bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE,
  53. cover_beam_dead]}].
  54. init_per_suite(Config) ->
  55. test_lib:recompile(?MODULE),
  56. Config.
  57. end_per_suite(_Config) ->
  58. ok.
  59. init_per_group(_GroupName, Config) ->
  60. Config.
  61. end_per_group(_GroupName, Config) ->
  62. Config.
  63. misc(Config) when is_list(Config) ->
  64. 42 = case id(42) of
  65. X when -X -> ok;
  66. X -> X
  67. end,
  68. {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]),
  69. none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]),
  70. none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]),
  71. none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]),
  72. {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf),
  73. {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf),
  74. {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf),
  75. error = get_data({o,false,raw}, 42, buf),
  76. {ok,buf,<<>>} = get_data({o,true,0}, 0, buf),
  77. {ok,buf,<<>>} = get_data({o,true,0}, 42, buf),
  78. {ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
  79. error = get_data({o,false,0}, 42, buf),
  80. relief = misc_2(0),
  81. error = misc_2(1),
  82. error = misc_2(true),
  83. if
  84. is_integer(Config) =/= true ->
  85. ok
  86. end,
  87. true = misc_3(1, 0),
  88. true = misc_3(0, 0),
  89. false = misc_3(0, 2),
  90. %% Abuse of boolean values.
  91. Zero = id(0),
  92. One = id(1),
  93. ok = if (Zero == 0) > false -> ok end,
  94. ok = if (Zero == 0) =:= (One == 1) -> ok end,
  95. ok = if (Zero == 0) =:= (One == 1) -> ok end,
  96. ok = if is_atom(Zero > One) -> ok end,
  97. error = if abs(Zero > One) -> ok; true -> error end,
  98. ok = if is_integer(Zero) >= is_integer(One) -> ok end,
  99. ok.
  100. misc_1([{W},{X},{Y},{Z}]) ->
  101. if
  102. X > Y andalso abs(Z) =:= 2 ->
  103. id(W);
  104. true ->
  105. none
  106. end.
  107. misc_2(0) -> relief;
  108. misc_2(Adapter = 1) when Adapter -> franklin;
  109. misc_2(_) -> error.
  110. misc_3(LenUp, LenDw) ->
  111. if
  112. %% Cover handling of #k_alt{}.
  113. LenUp >= 1 orelse ((LenDw >= 2) xor true) -> true;
  114. true -> false
  115. end.
  116. get_data({o,Active,Raw}, BytesToRead, Buffer)
  117. when Raw =:= raw; Raw =:= 0 ->
  118. if
  119. Active =/= false orelse BytesToRead =:= 0 ->
  120. {ok,Buffer,<<>>};
  121. true ->
  122. error
  123. end.
  124. const_cond(Config) when is_list(Config) ->
  125. ok = const_cond({}, 0),
  126. ok = const_cond({a}, 1),
  127. error = const_cond({a,b}, 3),
  128. error = const_cond({a}, 0),
  129. error = const_cond({a,b}, 1),
  130. ok.
  131. const_cond(T, Sz) ->
  132. case T of
  133. _X when false -> never;
  134. _X when is_tuple(T), eq == eq, tuple_size(T) == Sz -> ok;
  135. _X when is_tuple(T), eq == leq, tuple_size(T) =< Sz -> ok;
  136. _X -> error
  137. end.
  138. basic_not(Config) when is_list(Config) ->
  139. True = id(true),
  140. False = id(false),
  141. Glurf = id(glurf),
  142. A = id(5),
  143. B = id(37.5),
  144. C = id(-1),
  145. D = id(5),
  146. ATuple = {False,True,Glurf},
  147. check(fun() -> if not false -> ok; true -> error end end, ok),
  148. check(fun() -> if not true -> ok; true -> error end end, error),
  149. check(fun() -> if not False -> ok; true -> error end end, ok),
  150. check(fun() -> if not True -> ok; true -> error end end, error),
  151. check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
  152. check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
  153. check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
  154. check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
  155. not (7 == 453) -> ne; true -> eq end end, le),
  156. check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
  157. not (7 == -8) -> ne; true -> eq end end, ge),
  158. check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
  159. not (7 == 7) -> ne; true -> eq end end, le),
  160. check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
  161. not (A == B) -> ne; true -> eq end end, le),
  162. check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
  163. not (A == C) -> ne; true -> eq end end, ge),
  164. check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
  165. not (A == D) -> ne; true -> eq end end, le),
  166. check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
  167. check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
  168. check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
  169. check(fun() -> if not glurf -> ok; true -> error end end, error),
  170. check(fun() -> if not Glurf -> ok; true -> error end end, error),
  171. check(fun() -> if not (not true) -> broken end end, broken),
  172. check(fun() -> if not (True xor True) -> ok end end, ok),
  173. check(fun() -> if not (True xor False) -> ok;
  174. true -> error end end, error),
  175. ok.
  176. complex_not(Config) when is_list(Config) ->
  177. ATuple = id({false,true,gurka}),
  178. check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
  179. check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
  180. check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
  181. true -> error end end, error),
  182. check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
  183. true -> error end end, ok),
  184. check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
  185. true -> error end end, ok),
  186. check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
  187. true -> error end end, error),
  188. check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
  189. true -> error end end, error),
  190. %% orelse
  191. check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
  192. true -> error end end, error),
  193. %% complex_not_1/4
  194. ok = complex_not_1(1, 1, 1, a),
  195. error = complex_not_1(1, 1, 1, []),
  196. error = complex_not_1(1, 1, 3, a),
  197. error = complex_not_1(1, 1, 3, []),
  198. error = complex_not_1(1, 2, 1, a),
  199. error = complex_not_1(1, 2, 1, []),
  200. error = complex_not_1(1, 2, 3, a),
  201. error = complex_not_1(1, 2, 3, []),
  202. %% complex_not_2/4
  203. ok = complex_not_2(1, 2, 0, x),
  204. error = complex_not_2(1, 2, 0, []),
  205. error = complex_not_2(1, 2, 3, x),
  206. error = complex_not_2(1, 2, 3, []),
  207. error = complex_not_2(1, 1, 0, x),
  208. error = complex_not_2(1, 1, 0, []),
  209. error = complex_not_2(1, 1, 3, x),
  210. error = complex_not_2(1, 1, 3, []),
  211. ok.
  212. complex_not_1(A, B, C, D) ->
  213. Res = complex_not_1a(A, B, C, D),
  214. Res = complex_not_1b(A, B, C, D).
  215. complex_not_1a(A, B, C, D)
  216. when (not (A < B)) andalso (not (B < C)) andalso (not is_list(D)) ->
  217. ok;
  218. complex_not_1a(_, _, _, _) ->
  219. error.
  220. complex_not_1b(A, B, C, D)
  221. when (not (A < B)) and (not (B < C)) and (not is_list(D)) ->
  222. ok;
  223. complex_not_1b(_, _, _, _) ->
  224. error.
  225. complex_not_2(A, B, C, D) ->
  226. Res = complex_not_2a(A, B, C, D),
  227. Res = complex_not_2b(A, B, C, D).
  228. complex_not_2a(A, B, C, D)
  229. when A < B andalso not (B < C) andalso not is_list(D) ->
  230. ok;
  231. complex_not_2a(_, _, _, _) ->
  232. error.
  233. complex_not_2b(A, B, C, D)
  234. when A < B, not (B < C), not is_list(D) ->
  235. ok;
  236. complex_not_2b(_, _, _, _) ->
  237. error.
  238. nested_nots(Config) when is_list(Config) ->
  239. true = nested_not_1(0, 0),
  240. true = nested_not_1(0, 1),
  241. true = nested_not_1(a, b),
  242. true = nested_not_1(10, 0),
  243. false = nested_not_1(z, a),
  244. false = nested_not_1(3.4, {anything,goes}),
  245. false = nested_not_1(3.4, atom),
  246. true = nested_not_1(3.0, [list]),
  247. true = nested_not_2(false, false, 42),
  248. true = nested_not_2(false, true, 42),
  249. true = nested_not_2(true, false, 42),
  250. true = nested_not_2(true, true, 42),
  251. true = nested_not_2(false, false, atom),
  252. false = nested_not_2(false, true, atom),
  253. false = nested_not_2(true, false, atom),
  254. false = nested_not_2(true, true, atom),
  255. ok.
  256. nested_not_1(X, Y) ->
  257. Res = nested_not_1a(X, Y),
  258. Res = nested_not_1b(X, Y).
  259. nested_not_1a(X, Y) when not (((X>Y) or not(is_atom(X))) and
  260. (is_atom(Y) or (X==3.4))) ->
  261. true;
  262. nested_not_1a(_, _) ->
  263. false.
  264. nested_not_1b(X, Y) when not (((X>Y) orelse not(is_atom(X))) andalso
  265. (is_atom(Y) orelse (X==3.4))) ->
  266. true;
  267. nested_not_1b(_, _) ->
  268. false.
  269. nested_not_2(X, Y, Z) ->
  270. Res = nested_not_2a(X, Y, Z, true),
  271. Res = nested_not_2b(X, Y, Z, true).
  272. nested_not_2a(X, Y, Z, True)
  273. when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) ->
  274. true;
  275. nested_not_2a(_, _, _, _) ->
  276. false.
  277. nested_not_2b(X, Y, Z, True)
  278. when not(True andalso not((not(X) andalso not(Y)) orelse not(is_atom(Z)))) ->
  279. true;
  280. nested_not_2b(_, _, _, _) ->
  281. false.
  282. semicolon(Config) when is_list(Config) ->
  283. %% True/false combined using ';' (literal atoms).
  284. check(fun() -> if true; false -> ok end end, ok),
  285. check(fun() -> if false; true -> ok end end, ok),
  286. check(fun() -> if true; true -> ok end end, ok),
  287. check(fun() -> if false; false -> ok; true -> error end end, error),
  288. check(fun() ->
  289. {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
  290. exit
  291. end, exit),
  292. %% True/false combined used ';'.
  293. True = id(true),
  294. False = id(false),
  295. check(fun() -> if True; False -> ok end end, ok),
  296. check(fun() -> if False; True -> ok end end, ok),
  297. check(fun() -> if True; True -> ok end end, ok),
  298. check(fun() -> if False; False -> ok; true -> error end end, error),
  299. check(fun() ->
  300. {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
  301. exit
  302. end, exit),
  303. %% Combine true/false with a non-boolean value.
  304. Glurf = id(glurf),
  305. check(fun() -> if True; Glurf -> ok end end, ok),
  306. check(fun() -> if Glurf; True -> ok end end, ok),
  307. check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
  308. check(fun() -> if False; Glurf -> ok; true -> error end end, error),
  309. check(fun() -> if Glurf; False -> ok; true -> error end end, error),
  310. check(fun() ->
  311. {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
  312. exit
  313. end, exit),
  314. %% Combine true/false with errors.
  315. ATuple = id({false,true,gurka}),
  316. check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
  317. check(fun() -> if element(42, ATuple); True -> ok end end, ok),
  318. check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
  319. true -> error end end, error),
  320. check(fun() -> if False; element(42, ATuple) -> ok;
  321. true -> error end end, error),
  322. check(fun() -> if element(42, ATuple);
  323. False -> ok; true -> error end end, error),
  324. check(fun() ->
  325. {'EXIT',{if_clause,_}} =
  326. (catch if element(42, ATuple);
  327. element(42, ATuple) -> ok end),
  328. exit
  329. end, exit),
  330. ok.
  331. complex_semicolon(Config) when is_list(Config) ->
  332. ok = csemi1(int, {blurf}),
  333. ok = csemi1(string, {blurf}),
  334. ok = csemi1(float, [a]),
  335. error = csemi1(35, 42),
  336. %% 2
  337. ok = csemi2({}, {a,b,c}),
  338. ok = csemi2({1,3.5}, {a,b,c}),
  339. ok = csemi2(dum, {a,b,c}),
  340. ok = csemi2({45,-19.3}, {}),
  341. ok = csemi2({45,-19.3}, {dum}),
  342. ok = csemi2({45,-19.3}, {dum,dum}),
  343. error = csemi2({45}, {dum}),
  344. error = csemi2([], {dum}),
  345. error = csemi2({dum}, []),
  346. error = csemi2([], []),
  347. %% 3
  348. csemi3(fun csemi3a/4),
  349. csemi3(fun csemi3b/4),
  350. csemi3(fun csemi3c/4),
  351. %% 4
  352. csemi4(fun csemi4a/4),
  353. csemi4(fun csemi4b/4),
  354. csemi4(fun csemi4c/4),
  355. csemi4(fun csemi4d/4),
  356. %% 4, 'orelse' instead of 'or'
  357. csemi4_orelse(fun csemi4_orelse_a/4),
  358. csemi4_orelse(fun csemi4_orelse_b/4),
  359. csemi4_orelse(fun csemi4_orelse_c/4),
  360. csemi4_orelse(fun csemi4_orelse_d/4),
  361. %% 5
  362. error = csemi5(0, 0),
  363. ok = csemi5(5, 0),
  364. ok = csemi5(4, -4),
  365. ok = csemi5(10, -4),
  366. %% 6
  367. error = csemi6({a}, 0),
  368. ok = csemi6({a,b}, 0),
  369. ok = csemi6({}, 3),
  370. ok = csemi6({a,b,c}, 3),
  371. %% 7
  372. error = csemi7(#{a=>1}, 1, 0),
  373. error = csemi7(<<>>, 1, 0),
  374. ok = csemi7(#{a=>1}, 3, 0),
  375. ok = csemi7(#{a=>1}, 0, 3),
  376. ok = csemi7(#{a=>1}, 3, 3),
  377. ok = csemi7(#{a=>1, b=>3}, 0, 0),
  378. %% 8: Make sure that funs cannot be copied into guards.
  379. ok = csemi8(true),
  380. error = csemi8(false),
  381. error = csemi8(42),
  382. ok.
  383. csemi1(Type, Val) when is_list(Val), Type == float;
  384. Type == int; Type == string -> ok;
  385. csemi1(_, _) -> error.
  386. csemi2(A, B) when tuple_size(A) > 1; tuple_size(B) > 2 -> ok;
  387. csemi2(_, _) -> error.
  388. csemi3(Csemi3) ->
  389. ok = Csemi3({}, {a,b,c}, [0], [0]),
  390. ok = Csemi3({1,3.5}, {a,b,c}, -1, -1),
  391. ok = Csemi3(dum, {a,b,c}, 0.0, 0.0),
  392. ok = Csemi3(dum, {c}, b, a),
  393. ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0),
  394. ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1),
  395. ok = Csemi3({45,-19.3}, {}, [], []),
  396. ok = Csemi3({45,-19.3}, {dum}, 42, 42),
  397. ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33),
  398. ok = Csemi3({45}, {dum}, 1.0, 0),
  399. ok = Csemi3([a], {dum}, 1.0, 0),
  400. ok = Csemi3({dum}, [], 1.0, 0),
  401. ok = Csemi3([], [], 1.0, 0),
  402. ok = Csemi3(blurf, {dum}, 1.0, 0),
  403. ok = Csemi3({a}, blurf, 1.0, 0),
  404. ok = Csemi3([a], [dum], 1.0, 0),
  405. ok = Csemi3({dum}, [], 1.0, 0),
  406. ok = Csemi3([], [], 1.0, 0),
  407. error = Csemi3({45}, {dum}, 0, 0),
  408. error = Csemi3([a], {dum}, 0, 0),
  409. error = Csemi3({dum}, [], 0, 0),
  410. error = Csemi3([], [], 0, 0),
  411. ok.
  412. csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok;
  413. csemi3a(_, _, _, _) -> error.
  414. csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok;
  415. csemi3b(_, _, _, _) -> error.
  416. csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok;
  417. csemi3c(_, _, _, _) -> error.
  418. csemi4(Test) ->
  419. ok = Test({a,b}, 2, {c,d}, 2),
  420. ok = Test({1,2,3}, 0, [], 0),
  421. ok = Test({}, 2, blurf, 0),
  422. ok = Test({}, 2, {1}, 2),
  423. error = Test([], 4, {}, 0),
  424. error = Test({}, 0, [a,b], 4),
  425. error = Test({}, 0, [a,b], 0),
  426. error = Test([], 0, {}, 0),
  427. error = Test({}, 0, {}, 0),
  428. ok.
  429. csemi4a(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
  430. (tuple_size(B) > 1) or (Y > 1) -> ok;
  431. csemi4a(_, _, _, _) -> error.
  432. csemi4b(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  433. (tuple_size(B) > 1) or (Y > 1) -> ok;
  434. csemi4b(_, _, _, _) -> error.
  435. csemi4c(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
  436. (Y > 1) or (tuple_size(B) > 1) -> ok;
  437. csemi4c(_, _, _, _) -> error.
  438. csemi4d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  439. (Y > 1) or (tuple_size(B) > 1) -> ok;
  440. csemi4d(_, _, _, _) -> error.
  441. csemi4_orelse(Test) ->
  442. ok = Test({a,b}, 2, {c,d}, 2),
  443. ok = Test({1,2,3}, 0, [], 0),
  444. ok = Test({}, 2, blurf, 0),
  445. ok = Test({}, 2, {1}, 2),
  446. error = Test([], 1, {}, 0),
  447. ok.
  448. csemi4_orelse_a(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
  449. (tuple_size(B) > 1) orelse (Y > 1) -> ok;
  450. csemi4_orelse_a(_, _, _, _) -> error.
  451. csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (tuple_size(A) > 1);
  452. (tuple_size(B) > 1) orelse (Y > 1) -> ok;
  453. csemi4_orelse_b(_, _, _, _) -> error.
  454. csemi4_orelse_c(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
  455. (Y > 1) orelse (tuple_size(B) > 1) -> ok;
  456. csemi4_orelse_c(_, _, _, _) -> error.
  457. csemi4_orelse_d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  458. (Y > 1) or (tuple_size(B) > 1) -> ok;
  459. csemi4_orelse_d(_, _, _, _) -> error.
  460. csemi5(A, B) when hd([A+B]) > 1; abs(B) > 2 -> ok;
  461. csemi5(_, _) -> error.
  462. csemi6(A, B) when hd([tuple_size(A)]) > 1; abs(B) > 2 -> ok;
  463. csemi6(_, _) -> error.
  464. csemi7(A, B, C) when A#{a:=B} > #{a=>1}; abs(C) > 2 -> ok;
  465. csemi7(_, _, _) -> error.
  466. csemi8(Together) ->
  467. case fun csemi8/1 of
  468. Typically when Together; Typically, Together -> ok;
  469. _ -> error
  470. end.
  471. comma(Config) when is_list(Config) ->
  472. %% ',' combinations of literal true/false.
  473. check(fun() -> if true, false -> ok; true -> error end end, error),
  474. check(fun() -> if false, true -> ok; true -> error end end, error),
  475. check(fun() -> if true, true -> ok end end, ok),
  476. check(fun() -> if false, false -> ok; true -> error end end, error),
  477. check(fun() ->
  478. {'EXIT',{if_clause,_}} =
  479. (catch if true, false -> ok;
  480. false, true -> ok;
  481. false, false -> ok
  482. end),
  483. exit
  484. end, exit),
  485. %% ',' combinations of true/false in variables.
  486. True = id(true),
  487. False = id(false),
  488. check(fun() -> if True, False -> ok; true -> error end end, error),
  489. check(fun() -> if False, True -> ok; true -> error end end, error),
  490. check(fun() -> if True, True -> ok end end, ok),
  491. check(fun() -> if False, False -> ok; true -> error end end, error),
  492. check(fun() ->
  493. {'EXIT',{if_clause,_}} =
  494. (catch if True, False -> ok;
  495. False, True -> ok;
  496. False, False -> ok
  497. end),
  498. exit
  499. end, exit),
  500. %% ',' combinations of true/false, and non-boolean in variables.
  501. Glurf = id(glurf),
  502. check(fun() -> if True, Glurf -> ok; true -> error end end, error),
  503. check(fun() -> if Glurf, True -> ok; true -> error end end, error),
  504. check(fun() -> if True, True -> ok end end, ok),
  505. check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
  506. check(fun() ->
  507. {'EXIT',{if_clause,_}} =
  508. (catch if True, Glurf -> ok;
  509. Glurf, True -> ok;
  510. Glurf, Glurf -> ok
  511. end),
  512. exit
  513. end, exit),
  514. %% ',' combinations of true/false with errors.
  515. ATuple = id({a,b,c}),
  516. check(fun() -> if True, element(42, ATuple) -> ok;
  517. true -> error end end, error),
  518. check(fun() -> if element(42, ATuple), True -> ok;
  519. true -> error end end, error),
  520. check(fun() -> if True, True -> ok end end, ok),
  521. check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
  522. true -> error end end, error),
  523. check(fun() ->
  524. {'EXIT',{if_clause,_}} =
  525. (catch if True, element(42, ATuple) -> ok;
  526. element(42, ATuple), True -> ok;
  527. element(42, ATuple), element(42, ATuple) -> ok
  528. end),
  529. exit
  530. end, exit),
  531. ok.
  532. or_guard(Config) when is_list(Config) ->
  533. True = id(true),
  534. False = id(false),
  535. Glurf = id(glurf),
  536. %% 'or' combinations of literal true/false.
  537. check(fun() -> if true or false -> ok end end, ok),
  538. check(fun() -> if false or true -> ok end end, ok),
  539. check(fun() -> if true or true -> ok end end, ok),
  540. check(fun() -> if false or false -> ok; true -> error end end, error),
  541. check(fun() -> if glurf or true -> ok; true -> error end end, error),
  542. check(fun() -> if true or glurf -> ok; true -> error end end, error),
  543. check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
  544. check(fun() ->
  545. {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
  546. exit
  547. end, exit),
  548. %% 'or' combinations using variables containing true/false.
  549. check(fun() -> if True or False -> ok end end, ok),
  550. check(fun() -> if False or True -> ok end end, ok),
  551. check(fun() -> if True or True -> ok end end, ok),
  552. check(fun() -> if False or False -> ok; true -> error end end, error),
  553. check(fun() -> if True or Glurf -> ok; true -> error end end, error),
  554. check(fun() -> if Glurf or True -> ok; true -> error end end, error),
  555. check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
  556. check(fun() ->
  557. {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
  558. exit
  559. end, exit),
  560. ok.
  561. more_or_guards(Config) when is_list(Config) ->
  562. True = id(true),
  563. False = id(false),
  564. ATuple = id({false,true,gurka}),
  565. check(fun() ->
  566. if element(42, ATuple) or False -> ok;
  567. true -> error end
  568. end, error),
  569. check(fun() ->
  570. if False or element(42, ATuple) -> ok;
  571. true -> error end
  572. end, error),
  573. check(fun() ->
  574. if element(18, ATuple) or element(42, ATuple) -> ok;
  575. true -> error end
  576. end, error),
  577. check(fun() ->
  578. if True or element(42, ATuple) -> ok;
  579. true -> error end
  580. end, error),
  581. check(fun() ->
  582. if element(42, ATuple) or True -> ok;
  583. true -> error end
  584. end, error),
  585. check(fun() ->
  586. if element(1, ATuple) or element(42, ATuple) or True -> ok;
  587. true -> error end
  588. end, error),
  589. check(fun() ->
  590. if element(1, ATuple) or True or element(42, ATuple) -> ok;
  591. true -> error end
  592. end, error),
  593. check(fun() ->
  594. if
  595. (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
  596. true -> error end
  597. end, error),
  598. check(fun() ->
  599. if
  600. element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
  601. true -> error end
  602. end, error),
  603. check(fun() ->
  604. if element(2, ATuple) or element(42, ATuple) -> ok;
  605. true -> error end
  606. end, error),
  607. check(fun() ->
  608. if
  609. element(1, ATuple) or
  610. element(2, ATuple) or
  611. element(19, ATuple) -> ok;
  612. true -> error end
  613. end, error),
  614. ok.
  615. complex_or_guards(Config) when is_list(Config) ->
  616. %% complex_or_1/2
  617. ok = complex_or_1({a,b,c,d}, {1,2,3}),
  618. ok = complex_or_1({a,b,c,d}, {1}),
  619. ok = complex_or_1({a}, {1,2,3}),
  620. error = complex_or_1({a}, {1}),
  621. error = complex_or_1(1, 2),
  622. error = complex_or_1([], {a,b,c,d}),
  623. error = complex_or_1({a,b,c,d}, []),
  624. %% complex_or_2/1
  625. ok = complex_or_2({true,{}}),
  626. ok = complex_or_2({false,{a}}),
  627. ok = complex_or_2({false,{a,b,c}}),
  628. ok = complex_or_2({true,{a,b,c,d}}),
  629. error = complex_or_2({blurf,{a,b,c}}),
  630. error = complex_or_2({true}),
  631. error = complex_or_2({true,no_tuple}),
  632. error = complex_or_2({true,[]}),
  633. %% complex_or_3/2
  634. ok = complex_or_3({true}, {}),
  635. ok = complex_or_3({false}, {a}),
  636. ok = complex_or_3({false}, {a,b,c}),
  637. ok = complex_or_3({true}, {a,b,c,d}),
  638. ok = complex_or_3({false}, <<1,2,3>>),
  639. ok = complex_or_3({true}, <<1,2,3,4>>),
  640. error = complex_or_3(blurf, {a,b,c}),
  641. error = complex_or_3({false}, <<1,2,3,4>>),
  642. error = complex_or_3([], <<1,2>>),
  643. error = complex_or_3({true}, 45),
  644. error = complex_or_3(<<>>, <<>>),
  645. %% complex_or_4/2
  646. ok = complex_or_4(<<1,2,3>>, {true}),
  647. ok = complex_or_4(<<1,2,3>>, {false}),
  648. ok = complex_or_4(<<1,2,3>>, {true}),
  649. ok = complex_or_4({1,2,3}, {true}),
  650. error = complex_or_4({1,2,3,4}, {false}),
  651. error = complex_or_4(<<1,2,3,4>>, []),
  652. error = complex_or_4([], {true}),
  653. %% complex_or_5/2
  654. ok = complex_or_5(<<1>>, {false}),
  655. ok = complex_or_5(<<1,2,3>>, {true}),
  656. ok = complex_or_5(<<1,2,3,4>>, {false}),
  657. ok = complex_or_5({1,2,3}, {false}),
  658. ok = complex_or_5({1,2,3,4}, {false}),
  659. error = complex_or_5(blurf, {false}),
  660. error = complex_or_5(<<1>>, klarf),
  661. error = complex_or_5(blurf, klarf),
  662. %% complex_or_6/2
  663. ok = complex_or_6({true,true}, {1,2,3,4}),
  664. ok = complex_or_6({true,true}, <<1,2,3,4>>),
  665. ok = complex_or_6({false,false}, <<1,2,3,4>>),
  666. ok = complex_or_6({false,true}, <<1>>),
  667. ok = complex_or_6({true,false}, {1}),
  668. ok = complex_or_6({true,true}, {1}),
  669. error = complex_or_6({false,false}, {1}),
  670. error = complex_or_6({true}, {1,2,3,4}),
  671. error = complex_or_6({}, {1,2,3,4}),
  672. error = complex_or_6([], {1,2,3,4}),
  673. error = complex_or_6([], {1,2,3,4}),
  674. error = complex_or_6({true,false}, klurf),
  675. ok.
  676. complex_or_1(A, B) ->
  677. if
  678. ((3 < tuple_size(A)) and (tuple_size(A) < 9)) or
  679. ((2 < tuple_size(B)) and (tuple_size(B) < 7)) -> ok;
  680. true -> error
  681. end.
  682. complex_or_2(Tuple) ->
  683. if
  684. element(1, Tuple) or not (tuple_size(element(2, Tuple)) > 3) -> ok;
  685. true -> error
  686. end.
  687. complex_or_3(A, B) ->
  688. if
  689. not (size(B) > 3) or element(1, A) -> ok;
  690. true -> error
  691. end.
  692. complex_or_4(A, B) ->
  693. if
  694. not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok;
  695. true -> error
  696. end.
  697. complex_or_5(A, B) ->
  698. if
  699. not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok;
  700. true -> error
  701. end.
  702. complex_or_6(A, B) ->
  703. if
  704. not (not element(1, A) and not element(2, A)) or
  705. not (not (size(B) > 3)) -> ok;
  706. true -> error
  707. end.
  708. and_guard(Config) when is_list(Config) ->
  709. %% 'and' combinations of literal true/false.
  710. check(fun() -> if true and false -> ok; true -> error end end, error),
  711. check(fun() -> if false and true -> ok; true -> error end end, error),
  712. check(fun() -> if true and true -> ok end end, ok),
  713. check(fun() -> if false and false -> ok; true -> error end end, error),
  714. check(fun() -> if glurf and true -> ok; true -> error end end, error),
  715. check(fun() -> if true and glurf -> ok; true -> error end end, error),
  716. check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
  717. check(fun() ->
  718. {'EXIT',{if_clause,_}} =
  719. (catch if true and false -> ok;
  720. false and true -> ok;
  721. false and false -> ok
  722. end),
  723. exit
  724. end, exit),
  725. %% 'and' combinations of true/false in variables.
  726. True = id(true),
  727. False = id(false),
  728. check(fun() -> if True and False -> ok; true -> error end end, error),
  729. check(fun() -> if False and True -> ok; true -> error end end, error),
  730. check(fun() -> if True and True -> ok end end, ok),
  731. check(fun() -> if False and False -> ok; true -> error end end, error),
  732. check(fun() ->
  733. {'EXIT',{if_clause,_}} =
  734. (catch if True and False -> ok;
  735. False and True -> ok;
  736. False and False -> ok
  737. end),
  738. exit
  739. end, exit),
  740. %% 'and' combinations of true/false and a non-boolean in variables.
  741. Glurf = id(glurf),
  742. check(fun() -> if True and Glurf -> ok; true -> error end end, error),
  743. check(fun() -> if Glurf and True -> ok; true -> error end end, error),
  744. check(fun() -> if True and True -> ok end end, ok),
  745. check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
  746. check(fun() ->
  747. {'EXIT',{if_clause,_}} =
  748. (catch if True and Glurf -> ok;
  749. Glurf and True -> ok;
  750. Glurf and Glurf -> ok
  751. end),
  752. exit
  753. end, exit),
  754. %% 'and' combinations of true/false with errors.
  755. ATuple = id({a,b,c}),
  756. check(fun() -> if True and element(42, ATuple) -> ok;
  757. true -> error end end, error),
  758. check(fun() -> if element(42, ATuple) and True -> ok;
  759. true -> error end end, error),
  760. check(fun() -> if True and True -> ok end end, ok),
  761. check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
  762. true -> error end end, error),
  763. check(fun() ->
  764. {'EXIT',{if_clause,_}} =
  765. (catch if True and element(42, ATuple) -> ok;
  766. element(42, ATuple) and True -> ok;
  767. element(42, ATuple) and element(42, ATuple) -> ok
  768. end),
  769. exit
  770. end, exit),
  771. ok = relprod({'Set',a,b}, {'Set',a,b}),
  772. ok = and_same_var(42),
  773. {'EXIT',{if_clause,_}} = (catch and_same_var(x)),
  774. ok.
  775. and_same_var(V) ->
  776. B = is_integer(V),
  777. if
  778. B or B -> ok
  779. end.
  780. relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') ->
  781. ok.
  782. xor_guard(Config) when is_list(Config) ->
  783. %% 'xor' combinations of literal true/false.
  784. check(fun() -> if true xor false -> ok end end, ok),
  785. check(fun() -> if false xor true -> ok end end, ok),
  786. check(fun() -> if true xor true -> ok; true -> error end end, error),
  787. check(fun() -> if false xor false -> ok; true -> error end end, error),
  788. check(fun() ->
  789. {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
  790. exit
  791. end, exit),
  792. check(fun() ->
  793. {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
  794. exit
  795. end, exit),
  796. %% 'xor' combinations using variables containing true/false.
  797. True = id(true),
  798. False = id(false),
  799. check(fun() -> if True xor False -> ok end end, ok),
  800. check(fun() -> if False xor True -> ok end end, ok),
  801. check(fun() -> if True xor True -> ok; true -> error end end, error),
  802. check(fun() -> if False xor False -> ok; true -> error end end, error),
  803. check(fun() ->
  804. {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
  805. exit
  806. end, exit),
  807. check(fun() ->
  808. {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
  809. exit
  810. end, exit),
  811. ok.
  812. more_xor_guards(Config) when is_list(Config) ->
  813. True = id(true),
  814. False = id(false),
  815. ATuple = id({false,true,gurka}),
  816. check(fun() ->
  817. if element(42, ATuple) xor False -> ok;
  818. true -> error end
  819. end, error),
  820. check(fun() ->
  821. if False xor element(42, ATuple) xor False -> ok;
  822. true -> error end
  823. end, error),
  824. check(fun() ->
  825. if element(18, ATuple) xor element(42, ATuple) -> ok;
  826. true -> error end
  827. end, error),
  828. check(fun() ->
  829. if True xor element(42, ATuple) -> ok;
  830. true -> error end
  831. end, error),
  832. check(fun() ->
  833. if element(42, ATuple) xor True -> ok;
  834. true -> error end
  835. end, error),
  836. ok.
  837. build_in_guard(Config) when is_list(Config) ->
  838. SubBin = <<5.0/float>>,
  839. B = <<1,SubBin/binary,3.5/float>>,
  840. if
  841. B =:= <<1,SubBin/binary,3.5/float>> -> ok
  842. end.
  843. old_guard_tests(Config) when list(Config) ->
  844. %% Check that all the old guard tests are still recognized.
  845. list = og(Config),
  846. atom = og(an_atom),
  847. binary = og(<<1,2>>),
  848. float = og(3.14),
  849. integer = og(43),
  850. a_function = og(fun() -> ok end),
  851. pid = og(self()),
  852. reference = og(make_ref()),
  853. tuple = og({}),
  854. number = on(45.333),
  855. number = on(-19),
  856. ok.
  857. og(V) when atom(V) -> atom;
  858. og(V) when binary(V) -> binary;
  859. og(V) when float(V) -> float;
  860. og(V) when integer(V) -> integer;
  861. og(V) when function(V) -> a_function;
  862. og(V) when list(V) -> list;
  863. og(V) when pid(V) -> pid;
  864. og(V) when port(V) -> port;
  865. og(V) when reference(V) -> reference;
  866. og(V) when tuple(V) -> tuple;
  867. og(_) -> what.
  868. on(V) when number(V) -> number;
  869. on(_) -> not_number.
  870. complex_guard(_Config) ->
  871. _ = [true = do_complex_guard(X, Y, Z) ||
  872. X <- [4,5], Y <- [4,5], Z <- [4,5]],
  873. _ = [true = do_complex_guard(X, Y, Z) ||
  874. X <- [1,2,3], Y <- [1,2,3], Z <- [1,2,3]],
  875. _ = [catch do_complex_guard(X, Y, Z) ||
  876. X <- [1,2,3,4,5], Y <- [0,6], Z <- [1,2,3,4,5]],
  877. ok.
  878. do_complex_guard(X1, Y1, Z1) ->
  879. if
  880. ((X1 =:= 4) or (X1 =:= 5)) and
  881. ((Y1 =:= 4) or (Y1 =:= 5)) and
  882. ((Z1 =:= 4) or (Z1 =:= 5)) or
  883. ((X1 =:= 1) or (X1 =:= 2) or (X1 =:= 3)) and
  884. ((Y1 =:= 1) or (Y1 =:= 2) or (Y1 =:= 3)) and
  885. ((Z1 =:= 1) or (Z1 =:= 2) or (Z1 =:= 3)) ->
  886. true
  887. end.
  888. gbif(Config) when is_list(Config) ->
  889. error = gbif_1(1, {false,true}),
  890. ok = gbif_1(2, {false,true}),
  891. ok.
  892. gbif_1(P, T) when element(P, T) -> ok;
  893. gbif_1(_, _) -> error.
  894. t_is_boolean(Config) when is_list(Config) ->
  895. true = is_boolean(true),
  896. true = is_boolean(false),
  897. true = is_boolean(id(true)),
  898. true = is_boolean(id(false)),
  899. false = is_boolean(glurf),
  900. false = is_boolean(id(glurf)),
  901. false = is_boolean([]),
  902. false = is_boolean(id([])),
  903. false = is_boolean(42),
  904. false = is_boolean(id(-42)),
  905. false = is_boolean(math:pi()),
  906. false = is_boolean(384793478934378924978439789873478934897),
  907. false = is_boolean(id(self())),
  908. false = is_boolean(id({x,y,z})),
  909. false = is_boolean(id([a,b,c])),
  910. false = is_boolean(id(make_ref())),
  911. false = is_boolean(id(<<1,2,3>>)),
  912. false = is_boolean({id(x),y,z}),
  913. false = is_boolean([id(a),b,c]),
  914. ok = bool(true),
  915. ok = bool(false),
  916. ok = bool(id(true)),
  917. ok = bool(id(false)),
  918. error = bool(glurf),
  919. error = bool(id(glurf)),
  920. error = bool([]),
  921. error = bool(id([])),
  922. error = bool(42),
  923. error = bool(id(-42)),
  924. error = bool(math:pi()),
  925. error = bool(384793478934378924978439789873478934897),
  926. error = bool(id(self())),
  927. error = bool(id({x,y,z})),
  928. error = bool(id([a,b,c])),
  929. error = bool(id(make_ref())),
  930. error = bool(id(<<1,2,3>>)),
  931. true = my_is_bool(true),
  932. true = my_is_bool(false),
  933. false = my_is_bool([]),
  934. false = my_is_bool([1,2,3,4]),
  935. false = my_is_bool({a,b,c}),
  936. ok.
  937. bool(X) when is_boolean(X) -> ok;
  938. bool(_) -> error.
  939. my_is_bool(V) ->
  940. Res = my_is_bool_a(V),
  941. Res = my_is_bool_b(V).
  942. my_is_bool_a(V) ->
  943. case V of
  944. true -> true;
  945. false -> true;
  946. _ -> false
  947. end.
  948. my_is_bool_b(V) ->
  949. case V of
  950. false -> true;
  951. true -> true;
  952. _ -> false
  953. end.
  954. is_function_2(Config) when is_list(Config) ->
  955. true = is_function(id(fun ?MODULE:all/1), 1),
  956. true = is_function(id(fun() -> ok end), 0),
  957. false = is_function(id(fun ?MODULE:all/1), 0),
  958. false = is_function(id(fun() -> ok end), 1),
  959. {'EXIT',{badarg,_}} =
  960. (catch is_function(id(fun() -> ok end), -1) orelse error),
  961. {'EXIT',{badarg,_}} =
  962. (catch is_function(id(fun() -> ok end), '') orelse error),
  963. F = fun(_) -> ok end,
  964. if
  965. is_function(F, 1) -> ok
  966. end.
  967. tricky(Config) when is_list(Config) ->
  968. not_ok = tricky_1(1, 2),
  969. not_ok = tricky_1(1, blurf),
  970. not_ok = tricky_1(foo, 2),
  971. not_ok = tricky_1(a, b),
  972. error = tricky_2(0.5),
  973. error = tricky_2(a),
  974. error = tricky_2({a,b,c}),
  975. false = rb(100000, [1], 42),
  976. true = rb(100000, [], 42),
  977. true = rb(555, [a,b,c], 19),
  978. error = tricky_3(42),
  979. error = tricky_3(42.0),
  980. error = tricky_3(<<>>),
  981. error = tricky_3(#{}),
  982. error = tricky_3({a,b}),
  983. ok.
  984. tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
  985. tricky_1(_, _) -> not_ok.
  986. tricky_2(X) when float(X) or float(X) -> ok;
  987. tricky_2(_) -> error.
  988. tricky_3(X)
  989. when abs(X) or bit_size(X) or byte_size(X) or ceil(X) or
  990. float(X) or floor(X) or length(X) or
  991. map_size(X) or node() or node(X) or round(X) or
  992. self() or size(X) or tl(X) or trunc(X) or tuple_size(X) ->
  993. ok;
  994. tricky_3(_) ->
  995. error.
  996. %% From dets_v9:read_buckets/11, simplified.
  997. rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true;
  998. rb(_, _, _) -> false.
  999. -define(T(Op,A,B),
  1000. ok = if A Op B -> ok; true -> error end,
  1001. ok = if not (A Op B) -> error; true -> ok end,
  1002. (fun(X, Y, True, False) ->
  1003. ok = if X Op Y -> ok; true -> error end,
  1004. ok = if False; X Op Y; False -> ok; true -> error end,
  1005. ok = if X Op Y, True -> ok; true -> error end,
  1006. ok = if not (X Op Y) -> error; true -> ok end,
  1007. ok = if False; not (X Op Y); False -> error; true -> ok end
  1008. end)(id(A), id(B), id(true), id(false))).
  1009. -define(F(Op,A,B),
  1010. ok = if A Op B -> error; true -> ok end,
  1011. ok = if not (A Op B) -> ok; true -> error end,
  1012. (fun(X, Y, True, False) ->
  1013. ok = if X Op Y -> error; true -> ok end,
  1014. ok = if False; X Op Y; False -> error; true -> ok end,
  1015. ok = if not (X Op Y); False -> ok; true -> error end,
  1016. ok = if not (X Op Y), True -> ok; true -> error end
  1017. end)(id(A), id(B), id(true), id(false))).
  1018. rel_ops(Config) when is_list(Config) ->
  1019. ?T(=/=, 1, 1.0),
  1020. ?F(=/=, 2, 2),
  1021. ?F(=/=, {a}, {a}),
  1022. ?F(/=, a, a),
  1023. ?F(/=, 0, 0.0),
  1024. ?T(/=, 0, 1),
  1025. ?F(/=, {a}, {a}),
  1026. ?T(==, 1, 1.0),
  1027. ?F(==, a, {}),
  1028. ?F(=:=, 1, 1.0),
  1029. ?T(=:=, 42.0, 42.0),
  1030. ?F(>, a, b),
  1031. ?T(>, 42, 1.0),
  1032. ?F(>, 42, 42.0),
  1033. ?T(<, a, b),
  1034. ?F(<, 42, 1.0),
  1035. ?F(<, 42, 42.0),
  1036. ?T(=<, 1.5, 5),
  1037. ?F(=<, -9, -100.344),
  1038. ?T(=<, 42, 42.0),
  1039. ?T(>=, 42, 42.0),
  1040. ?F(>=, a, b),
  1041. ?T(>=, 1.0, 0),
  1042. %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1.
  1043. true = any_atom /= id(42),
  1044. true = [] /= id(42),
  1045. %% Coverage of beam_utils:bif_to_test/3
  1046. Empty = id([]),
  1047. ?T(==, [], Empty),
  1048. ok.
  1049. -undef(TestOp).
  1050. rel_op_combinations(Config) when is_list(Config) ->
  1051. Digits0 = lists:seq(16#0030, 16#0039) ++
  1052. lists:seq(16#0660, 16#0669) ++
  1053. lists:seq(16#06F0, 16#06F9),
  1054. Digits = gb_sets:from_list(Digits0),
  1055. rel_op_combinations_1(16#0700, Digits),
  1056. BrokenRange0 = lists:seq(3, 5) ++
  1057. lists:seq(10, 12) ++ lists:seq(14, 20),
  1058. BrokenRange = gb_sets:from_list(BrokenRange0),
  1059. rel_op_combinations_2(30, BrokenRange),
  1060. Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++
  1061. [{I,5*I} || I <- lists:seq(51, 80)],
  1062. Red = gb_trees:from_orddict(Red0),
  1063. rel_op_combinations_3(100, Red).
  1064. rel_op_combinations_1(0, _) ->
  1065. ok;
  1066. rel_op_combinations_1(N, Digits) ->
  1067. Bool = gb_sets:is_member(N, Digits),
  1068. Bool = is_digit_1(N),
  1069. Bool = is_digit_2(N),
  1070. Bool = is_digit_3(N),
  1071. Bool = is_digit_4(N),
  1072. Bool = is_digit_5(N),
  1073. Bool = is_digit_6(N),
  1074. Bool = is_digit_7(N),
  1075. Bool = is_digit_8(N),
  1076. rel_op_combinations_1(N-1, Digits).
  1077. is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
  1078. is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
  1079. is_digit_1(X) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1080. is_digit_1(_) -> false.
  1081. is_digit_2(X) when (16#0030-1) < X, X =< 16#0039 -> true;
  1082. is_digit_2(X) when (16#0660-1) < X, X =< 16#0669 -> true;
  1083. is_digit_2(X) when (16#06F0-1) < X, X =< 16#06F9 -> true;
  1084. is_digit_2(_) -> false.
  1085. is_digit_3(X) when 16#0660 =< X, X < (16#0669+1) -> true;
  1086. is_digit_3(X) when 16#0030 =< X, X < (16#0039+1) -> true;
  1087. is_digit_3(X) when 16#06F0 =< X, X < (16#06F9+1) -> true;
  1088. is_digit_3(_) -> false.
  1089. is_digit_4(X) when (16#0660-1) < X, X < (16#0669+1) -> true;
  1090. is_digit_4(X) when (16#0030-1) < X, X < (16#0039+1) -> true;
  1091. is_digit_4(X) when (16#06F0-1) < X, X < (16#06F9+1) -> true;
  1092. is_digit_4(_) -> false.
  1093. is_digit_5(X) when X >= 16#0660, X =< 16#0669 -> true;
  1094. is_digit_5(X) when X >= 16#0030, X =< 16#0039 -> true;
  1095. is_digit_5(X) when X >= 16#06F0, X =< 16#06F9 -> true;
  1096. is_digit_5(_) -> false.
  1097. is_digit_6(X) when X > (16#0660-1), X =< 16#0669 -> true;
  1098. is_digit_6(X) when X > (16#0030-1), X =< 16#0039 -> true;
  1099. is_digit_6(X) when X > (16#06F0-1), X =< 16#06F9 -> true;
  1100. is_digit_6(_) -> false.
  1101. is_digit_7(X) when 16#0660 =< X, X =< 16#0669 -> true;
  1102. is_digit_7(X) when 16#0030 =< X, X =< 16#003A, X =/= 16#003A -> true;
  1103. is_digit_7(X) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1104. is_digit_7(_) -> false.
  1105. is_digit_8(X) when X =< 16#0039, X > (16#0030-1) -> true;
  1106. is_digit_8(X) when X =< 16#06F9, X > (16#06F0-1) -> true;
  1107. is_digit_8(X) when X =< 16#0669, X > (16#0660-1) -> true;
  1108. is_digit_8(16#0670) -> false;
  1109. is_digit_8(_) -> false.
  1110. rel_op_combinations_2(0, _) ->
  1111. ok;
  1112. rel_op_combinations_2(N, Range) ->
  1113. Bool = gb_sets:is_member(N, Range),
  1114. Bool = broken_range_1(N),
  1115. Bool = broken_range_2(N),
  1116. Bool = broken_range_3(N),
  1117. Bool = broken_range_4(N),
  1118. Bool = broken_range_5(N),
  1119. Bool = broken_range_6(N),
  1120. Bool = broken_range_7(N),
  1121. Bool = broken_range_8(N),
  1122. Bool = broken_range_9(N),
  1123. Bool = broken_range_10(N),
  1124. Bool = broken_range_11(N),
  1125. Bool = broken_range_12(N),
  1126. Bool = broken_range_13(N),
  1127. rel_op_combinations_2(N-1, Range).
  1128. broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1129. broken_range_1(X) when X >= 3, X =< 5 -> true;
  1130. broken_range_1(_) -> false.
  1131. broken_range_2(X) when X >= 10, X =< 12 -> true;
  1132. broken_range_2(X) when X >= 14, X =< 20 -> true;
  1133. broken_range_2(X) when X >= 3, X =< 5 -> true;
  1134. broken_range_2(_) -> false.
  1135. broken_range_3(X) when X >= 10, X =< 12 -> true;
  1136. broken_range_3(X) when X >= 14, X < 21 -> true;
  1137. broken_range_3(3) -> true;
  1138. broken_range_3(4) -> true;
  1139. broken_range_3(5) -> true;
  1140. broken_range_3(_) -> false.
  1141. broken_range_4(X) when X =< 5, X >= 3 -> true;
  1142. broken_range_4(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1143. broken_range_4(X) when X =< 100 -> false;
  1144. broken_range_4(_) -> false.
  1145. broken_range_5(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1146. broken_range_5(X) when X > 2, X =< 5 -> true;
  1147. broken_range_5(_) -> false.
  1148. broken_range_6(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1149. broken_range_6(X) when X > 2, X < 6 -> true;
  1150. broken_range_6(_) -> false.
  1151. broken_range_7(X) when X > 2, X < 6 -> true;
  1152. broken_range_7(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1153. broken_range_7(X) when X > 30 -> false;
  1154. broken_range_7(_) -> false.
  1155. broken_range_8(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1156. broken_range_8(X) when X =:= 3 -> true;
  1157. broken_range_8(X) when X >= 3, X =< 5 -> true;
  1158. broken_range_8(_) -> false.
  1159. broken_range_9(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1160. broken_range_9(X) when X =:= 13 -> false;
  1161. broken_range_9(X) when X >= 3, X =< 5 -> true;
  1162. broken_range_9(_) -> false.
  1163. broken_range_10(X) when X >= 3, X =< 5 -> true;
  1164. broken_range_10(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1165. broken_range_10(X) when X =/= 13 -> false;
  1166. broken_range_10(_) -> false.
  1167. broken_range_11(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1168. broken_range_11(X) when is_tuple(X), X =:= 10 -> true;
  1169. broken_range_11(X) when X >= 3, X =< 5 -> true;
  1170. broken_range_11(_) -> false.
  1171. broken_range_12(X) when X >= 3, X =< 5 -> true;
  1172. broken_range_12(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1173. broken_range_12(X) when X < 30, X > 20 -> false;
  1174. broken_range_12(_) -> false.
  1175. broken_range_13(X) when X >= 10, X =< 20, 13 =/= X -> true;
  1176. broken_range_13(X) when X >= 3, X =< 5 -> true;
  1177. broken_range_13(_) -> false.
  1178. rel_op_combinations_3(0, _) ->
  1179. ok;
  1180. rel_op_combinations_3(N, Red) ->
  1181. Val = case gb_trees:lookup(N, Red) of
  1182. none -> none;
  1183. {value,V} -> V
  1184. end,
  1185. Val = redundant_1(N),
  1186. Val = redundant_2(N),
  1187. Val = redundant_3(N),
  1188. Val = redundant_4(N),
  1189. Val = redundant_5(N),
  1190. Val = redundant_6(N),
  1191. Val = redundant_7(N),
  1192. Val = redundant_8(N),
  1193. Val = redundant_9(N),
  1194. Val = redundant_10(N),
  1195. Val = redundant_11(N),
  1196. rel_op_combinations_3(N-1, Red).
  1197. redundant_1(X) when X >= 51, X =< 80 -> 5*X;
  1198. redundant_1(X) when X < 51 -> 2*X;
  1199. redundant_1(_) -> none.
  1200. redundant_2(X) when X < 51 -> 2*X;
  1201. redundant_2(X) when X >= 51, X =< 80 -> 5*X;
  1202. redundant_2(_) -> none.
  1203. redundant_3(X) when X < 51 -> 2*X;
  1204. redundant_3(X) when X =< 80, X >= 51 -> 5*X;
  1205. redundant_3(X) when X =/= 100 -> none;
  1206. redundant_3(_) -> none.
  1207. redundant_4(X) when X < 51 -> 2*X;
  1208. redundant_4(X) when X =< 80, X > 50 -> 5*X;
  1209. redundant_4(X) when X =/= 100 -> none;
  1210. redundant_4(_) -> none.
  1211. redundant_5(X) when X < 51 -> 2*X;
  1212. redundant_5(X) when X > 50, X < 81 -> 5*X;
  1213. redundant_5(X) when X =< 10 -> none;
  1214. redundant_5(_) -> none.
  1215. redundant_6(X) when X > 50, X =< 80 -> 5*X;
  1216. redundant_6(X) when X < 51 -> 2*X;
  1217. redundant_6(_) -> none.
  1218. redundant_7(X) when is_integer(X), X >= 51, X =< 80 -> 5*X;
  1219. redundant_7(X) when is_integer(X), X < 51 -> 2*X;
  1220. redundant_7(_) -> none.
  1221. redundant_8(X) when X >= 51, X =< 80 -> 5*X;
  1222. redundant_8(X) when X < 51 -> 2*X;
  1223. redundant_8(_) -> none.
  1224. redundant_9(X) when X >= 51, X =< 80 -> 5*X;
  1225. redundant_9(X) when X < 51 -> 2*X;
  1226. redundant_9(90) -> none;
  1227. redundant_9(X) when X =/= 90 -> none;
  1228. redundant_9(_) -> none.
  1229. redundant_10(X) when X >= 51, X =< 80 -> 5*X;
  1230. redundant_10(X) when X < 51 -> 2*X;
  1231. redundant_10(90) -> none;
  1232. redundant_10(X) when X =:= 90 -> none;
  1233. redundant_10(_) -> none.
  1234. redundant_11(X) when X < 51 -> 2*X;
  1235. redundant_11(X) when X =:= 10 -> 2*X;
  1236. redundant_11(X) when X >= 51, X =< 80 -> 5*X;
  1237. redundant_11(_) -> none.
  1238. %% Test type tests on literal values. (From emulator test suites.)
  1239. literal_type_tests(Config) when is_list(Config) ->
  1240. case ?MODULE of
  1241. guard_SUITE -> literal_type_tests_1(Config);
  1242. _ -> {skip,"Enough to run this case once."}
  1243. end.
  1244. literal_type_tests_1(Config) ->
  1245. %% Generate an Erlang module with all different type of type tests.
  1246. Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++
  1247. [{is_function,L1,L2} ||
  1248. L1 <- literals(), L2 <- literals()]),
  1249. Mod = literal_test,
  1250. Anno = erl_anno:new(0),
  1251. Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]},
  1252. Form = [{attribute,Anno,module,Mod},
  1253. {attribute,Anno,compile,export_all},
  1254. Func, {eof,999}],
  1255. %% Print generated code for inspection.
  1256. lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
  1257. %% Test compile:form/1. This implies full optimization (default).
  1258. {ok,Mod,Code1} = compile:forms(Form),
  1259. smoke_disasm(Config, Mod, Code1),
  1260. {module,Mod} = code:load_binary(Mod, Mod, Code1),
  1261. Mod:test(),
  1262. true = code:delete(Mod),
  1263. code:purge(Mod),
  1264. %% Test compile:form/2. Turn off all optimizations.
  1265. {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
  1266. no_copt,no_postopt]),
  1267. smoke_disasm(Config, Mod, Code2),
  1268. {module,Mod} = code:load_binary(Mod, Mod, Code2),
  1269. Mod:test(),
  1270. true = code:delete(Mod),
  1271. code:purge(Mod),
  1272. ok.
  1273. make_test([{T,L1,L2}|Ts]) ->
  1274. [test(T, L1, L2)|make_test(Ts)];
  1275. make_test([{T,L}|Ts]) ->
  1276. [test(T, L)|make_test(Ts)];
  1277. make_test([]) -> [].
  1278. test(T, L) ->
  1279. S0 = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T,L,T,L]),
  1280. S = lists:flatten(S0),
  1281. {ok,Toks,_Line} = erl_scan:string(S),
  1282. {ok,E} = erl_parse:parse_exprs(Toks),
  1283. {value,Val,_Bs} = erl_eval:exprs(E, []),
  1284. Anno = erl_anno:new(0),
  1285. {match,Anno,{atom,Anno,Val},hd(E)}.
  1286. test(T, L1, L2) ->
  1287. 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]),
  1288. S = lists:flatten(S0),
  1289. {ok,Toks,_Line} = erl_scan:string(S),
  1290. {ok,E} = erl_parse:parse_exprs(Toks),
  1291. {value,Val,_Bs} = erl_eval:exprs(E, []),
  1292. Anno = erl_anno:new(0),
  1293. {match,Anno,{atom,Anno,Val},hd(E)}.
  1294. smoke_disasm(Config, Mod, Bin) ->
  1295. Priv = proplists:get_value(priv_dir, Config),
  1296. File = filename:join(Priv, atom_to_list(Mod)++".beam"),
  1297. ok = file:write_file(File, Bin),
  1298. test_lib:smoke_disasm(File).
  1299. literals() ->
  1300. [42,
  1301. 3.14,
  1302. -3,
  1303. 32982724987789283473473838474,
  1304. [],
  1305. xxxx,
  1306. {a,b,c},
  1307. [a,list],
  1308. <<1,2,3>>,
  1309. <<42:17>>].
  1310. type_tests() ->
  1311. [is_boolean,
  1312. is_integer,
  1313. is_float,
  1314. is_number,
  1315. is_atom,
  1316. is_list,
  1317. is_tuple,
  1318. is_pid,
  1319. is_reference,
  1320. is_port,
  1321. is_binary,
  1322. is_bitstring,
  1323. is_function,
  1324. is_map].
  1325. basic_andalso_orelse(Config) when is_list(Config) ->
  1326. T = id({type,integers,23,42}),
  1327. 65 = if
  1328. ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
  1329. element(2, T)) == integers ->
  1330. element(3, T) + element(4, T);
  1331. true -> error
  1332. end,
  1333. 65 = case [] of
  1334. [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
  1335. element(2, T)) == integers ->
  1336. element(3, T) + element(4, T)
  1337. end,
  1338. 42 = basic_rt({type,integers,40,2}),
  1339. 5.0 = basic_rt({vector,{3.0,4.0}}),
  1340. 20 = basic_rt(['+',3,7]),
  1341. {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
  1342. 12 = basic_rt({klurf,4}),
  1343. error = basic_rt({type,integers,40,2,3}),
  1344. error = basic_rt({kalle,integers,40,2}),
  1345. error = basic_rt({kalle,integers,40,2}),
  1346. error = basic_rt({1,2}),
  1347. error = basic_rt([]),
  1348. RelProdBody =
  1349. fun(R1, R2) ->
  1350. if
  1351. (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'),
  1352. (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') ->
  1353. ok
  1354. end
  1355. end,
  1356. ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
  1357. %% 'andalso'/'orelse' with calls known to fail already at compile time.
  1358. %% Used to crash the code generator.
  1359. error = (fun() ->
  1360. R = {vars,true},
  1361. if
  1362. is_record(R, vars, 2) andalso element(99, R) -> ok;
  1363. true -> error
  1364. end
  1365. end)(),
  1366. error = (fun(X) ->
  1367. L = {a,b,c},
  1368. if
  1369. is_list(X) andalso length(L) > 4 -> ok;
  1370. true -> error
  1371. end
  1372. end)([]),
  1373. ok.
  1374. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 4 andalso element(1, T) =:= type andalso
  1375. element(2, T) == integers ->
  1376. element(3, T) + element(4, T);
  1377. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= vector ->
  1378. {X,Y} = element(2, T),
  1379. if
  1380. is_float(X), is_float(Y) ->
  1381. math:sqrt(X*X+Y*Y)
  1382. end;
  1383. basic_rt(['+',A,B]) ->
  1384. 2*id(A+B);
  1385. basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set',
  1386. erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' ->
  1387. R1 = id(R1),
  1388. R2 = id(R2),
  1389. R1;
  1390. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= klurf ->
  1391. 3*id(element(2, T));
  1392. basic_rt(_) ->
  1393. error.
  1394. traverse_dcd(Config) when is_list(Config) ->
  1395. L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c},
  1396. {log_header,dcd_log,"0.0",a,b,c},blurf],
  1397. {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} =
  1398. traverse_dcd({cont,L0}, log, funny),
  1399. L1 = [{log_header,dcd_log,"1.0"}],
  1400. {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny),
  1401. L2 = [{a,tuple}],
  1402. {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny),
  1403. ok.
  1404. %% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}.
  1405. %% The outer match of a two tuple will places the first element in {x,3} and
  1406. %% second in {x,4}. The guard for the first clause must make ensure that all of those
  1407. %% registers are restored before entering the second clause.
  1408. %%
  1409. %% (From mnesia_checkpoint.erl, modified.)
  1410. traverse_dcd({Cont,[LogH|Rest]},Log,Fun)
  1411. when is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
  1412. andalso erlang:element(2,LogH) == dcd_log,
  1413. is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
  1414. andalso erlang:element(3,LogH) >= "1.0" ->
  1415. traverse_dcd({Cont,Rest},Log,Fun);
  1416. traverse_dcd({Cont,Recs},Log,Fun) ->
  1417. {Cont,Recs,Log,Fun}.
  1418. check_qlc_hrl(Config) when is_list(Config) ->
  1419. St = {r1,false,dum},
  1420. foo = cqlc(qlc, q, [{lc,1,2,3}], St),
  1421. foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
  1422. St = cqlc(qlc, q, [], St),
  1423. St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
  1424. St = cqlc(q, q, [{lc,1,2,3},b], St),
  1425. St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
  1426. St = cqlc(qlc, q, [a,b], St),
  1427. {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
  1428. ok.
  1429. %% From erl_lint.erl; original name was check_qlc_hrl/4.
  1430. cqlc(M, F, As, St) ->
  1431. Arity = length(As),
  1432. case As of
  1433. [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q,
  1434. Arity < 3,
  1435. not (((element(1, St) =:= r1) orelse fail) and (tuple_size(St) =:= 3) and element(2, St)) ->
  1436. foo;
  1437. _ ->
  1438. St
  1439. end.
  1440. %% OTP-7679: Thanks to Hunter Morris.
  1441. andalso_semi(Config) when is_list(Config) ->
  1442. ok = andalso_semi_foo(0),
  1443. ok = andalso_semi_foo(1),
  1444. fc(catch andalso_semi_foo(2)),
  1445. ok = andalso_semi_bar([a,b,c]),
  1446. ok = andalso_semi_bar(1),
  1447. fc(catch andalso_semi_bar([a,b])),
  1448. ok.
  1449. andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
  1450. ok.
  1451. andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
  1452. ok.
  1453. t_tuple_size(Config) when is_list(Config) ->
  1454. 10 = do_tuple_size({1,2,3,4}),
  1455. fc(catch do_tuple_size({1,2,3})),
  1456. fc(catch do_tuple_size(42)),
  1457. error = ludicrous_tuple_size({a,b,c}),
  1458. error = ludicrous_tuple_size([a,b,c]),
  1459. %% Test the "unsafe case" - the register assigned the tuple size is
  1460. %% not killed.
  1461. DataDir = test_lib:get_data_dir(Config),
  1462. File = filename:join(DataDir, "guard_SUITE_tuple_size"),
  1463. {ok,Mod,Code} = compile:file(File, [from_asm,binary]),
  1464. code:load_binary(Mod, File, Code),
  1465. 14 = Mod:t({1,2,3,4}),
  1466. _ = code:delete(Mod),
  1467. _ = code:purge(Mod),
  1468. ok.
  1469. do_tuple_size(T) when tuple_size(T) =:= 4 ->
  1470. {A,B,C,D} = T,
  1471. A+B+C+D.
  1472. ludicrous_tuple_size(T)
  1473. when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok;
  1474. ludicrous_tuple_size(T)
  1475. when tuple_size(T) =:= 16#10000000000000000 -> ok;
  1476. ludicrous_tuple_size(T)
  1477. when tuple_size(T) =:= (1 bsl 64) - 1 -> ok;
  1478. ludicrous_tuple_size(T)
  1479. when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
  1480. ludicrous_tuple_size(_) -> error.
  1481. %%
  1482. %% The binary_part/2,3 guard BIFs
  1483. %%
  1484. -define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
  1485. mask_error({'EXIT',{Err,_}}) ->
  1486. Err;
  1487. mask_error(Else) ->
  1488. Else.
  1489. %% Test the binary_part/2,3 guard (GC) BIFs.
  1490. binary_part(Config) when is_list(Config) ->
  1491. %% This is more or less a copy of what the guard_SUITE in emulator
  1492. %% does to cover the guard bif's
  1493. 1 = bptest(<<1,2,3>>),
  1494. 2 = bptest(<<2,1,3>>),
  1495. error = bptest(<<1>>),
  1496. error = bptest(<<>>),
  1497. error = bptest(apa),
  1498. 3 = bptest(<<2,3,3>>),
  1499. % With one variable (pos)
  1500. 1 = bptest(<<1,2,3>>,1),
  1501. 2 = bptest(<<2,1,3>>,1),
  1502. error = bptest(<<1>>,1),
  1503. error = bptest(<<>>,1),
  1504. error = bptest(apa,1),
  1505. 3 = bptest(<<2,3,3>>,1),
  1506. % With one variable (length)
  1507. 1 = bptesty(<<1,2,3>>,1),
  1508. 2 = bptesty(<<2,1,3>>,1),
  1509. error = bptesty(<<1>>,1),
  1510. error = bptesty(<<>>,1),
  1511. error = bptesty(apa,1),
  1512. 3 = bptesty(<<2,3,3>>,2),
  1513. % With one variable (whole tuple)
  1514. 1 = bptestx(<<1,2,3>>,{1,1}),
  1515. 2 = bptestx(<<2,1,3>>,{1,1}),
  1516. error = bptestx(<<1>>,{1,1}),
  1517. error = bptestx(<<>>,{1,1}),
  1518. error = bptestx(apa,{1,1}),
  1519. 3 = bptestx(<<2,3,3>>,{1,2}),
  1520. % With two variables
  1521. 1 = bptest(<<1,2,3>>,1,1),
  1522. 2 = bptest(<<2,1,3>>,1,1),
  1523. error = bptest(<<1>>,1,1),
  1524. error = bptest(<<>>,1,1),
  1525. error = bptest(apa,1,1),
  1526. 3 = bptest(<<2,3,3>>,1,2),
  1527. % Direct (autoimported) call, these will be evaluated by the compiler...
  1528. <<2>> = binary_part(<<1,2,3>>,1,1),
  1529. <<1>> = binary_part(<<2,1,3>>,1,1),
  1530. % Compiler warnings due to constant evaluation expected (3)
  1531. badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
  1532. badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
  1533. badarg = ?MASK_ERROR(binary_part(apa,1,1)),
  1534. <<3,3>> = binary_part(<<2,3,3>>,1,2),
  1535. % Direct call through apply
  1536. <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
  1537. <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
  1538. % Compiler warnings due to constant evaluation expected (3)
  1539. badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
  1540. badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
  1541. badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
  1542. <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
  1543. % Constant propagation
  1544. Bin = <<1,2,3>>,
  1545. ok = if
  1546. binary_part(Bin,1,1) =:= <<2>> ->
  1547. ok;
  1548. %% Compiler warning, clause cannot match (expected)
  1549. true ->
  1550. error
  1551. end,
  1552. ok = if
  1553. binary_part(Bin,{1,1}) =:= <<2>> ->
  1554. ok;
  1555. %% Compiler warning, clause cannot match (expected)
  1556. true ->
  1557. error
  1558. end,
  1559. ok.
  1560. bptest(B) when length(B) =:= 1337 ->
  1561. 1;
  1562. bptest(B) when binary_part(B,{1,1}) =:= <<2>> ->
  1563. 1;
  1564. bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> ->
  1565. 2;
  1566. bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> ->
  1567. 3;
  1568. bptest(_) ->
  1569. error.
  1570. bptest(B,A) when length(B) =:= A ->
  1571. 1;
  1572. bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> ->
  1573. 1;
  1574. bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> ->
  1575. 2;
  1576. bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> ->
  1577. 3;
  1578. bptest(_,_) ->
  1579. error.
  1580. bptestx(B,A) when length(B) =:= A ->
  1581. 1;
  1582. bptestx(B,A) when binary_part(B,A) =:= <<2>> ->
  1583. 1;
  1584. bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> ->
  1585. 2;
  1586. bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> ->
  1587. 3;
  1588. bptestx(_,_) ->
  1589. error.
  1590. bptesty(B,A) when length(B) =:= A ->
  1591. 1;
  1592. bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> ->
  1593. 1;
  1594. bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> ->
  1595. 2;
  1596. bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> ->
  1597. 3;
  1598. bptesty(_,_) ->
  1599. error.
  1600. bptest(B,A,_C) when length(B) =:= A ->
  1601. 1;
  1602. bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> ->
  1603. 1;
  1604. bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> ->
  1605. 2;
  1606. bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
  1607. 3;
  1608. bptest(_,_,_) ->
  1609. error.
  1610. -define(FAILING(C),
  1611. if
  1612. C -> ct:fail(should_fail);
  1613. true -> ok
  1614. end,
  1615. if
  1616. true, C -> ct:fail(should_fail);
  1617. true -> ok
  1618. end).
  1619. bad_constants(Config) when is_list(Config) ->
  1620. ?FAILING(false),
  1621. ?FAILING([]),
  1622. ?FAILING([a]),
  1623. ?FAILING([Config]),
  1624. ?FAILING({a,b}),
  1625. ?FAILING({a,Config}),
  1626. ?FAILING(<<1>>),
  1627. ?FAILING(42),
  1628. ?FAILING(3.14),
  1629. ok.
  1630. bad_guards(Config) when is_list(Config) ->
  1631. if erlang:float(self()); true -> ok end,
  1632. fc(catch bad_guards_1(1, [])),
  1633. fc(catch bad_guards_1(1, [2])),
  1634. fc(catch bad_guards_1(atom, [2])),
  1635. fc(catch bad_guards_2(#{a=>0,b=>0}, [])),
  1636. fc(catch bad_guards_2(#{a=>0,b=>0}, [x])),
  1637. fc(catch bad_guards_2(not_a_map, [x])),
  1638. fc(catch bad_guards_2(42, [x])),
  1639. fc(catch bad_guards_3(#{a=>0,b=>0}, [])),
  1640. fc(catch bad_guards_3(#{a=>0,b=>0}, [x])),
  1641. fc(catch bad_guards_3(not_a_map, [x])),
  1642. fc(catch bad_guards_3(42, [x])),
  1643. fc(catch bad_guards_4()),
  1644. ok.
  1645. %% beam_bool used to produce GC BIF instructions whose
  1646. %% Live operands included uninitialized registers.
  1647. bad_guards_1(X, [_]) when {{X}}, -X ->
  1648. ok.
  1649. bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) ->
  1650. ok.
  1651. %% beam_type used to produce an GC BIF instruction whose Live operand
  1652. %% included uninitialized registers.
  1653. bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) ->
  1654. ok.
  1655. %% v3_codegen would generate a jump to the failure label, but
  1656. %% without initializing x(0). The code at the failure label expected
  1657. %% x(0) to be initialized.
  1658. bad_guards_4() when not (error#{}); {not 0.0} -> freedom.
  1659. %% Building maps in a guard in a 'catch' would crash v3_codegen.
  1660. guard_in_catch(_Config) ->
  1661. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{}),
  1662. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{a=>b}),
  1663. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(atom),
  1664. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{}),
  1665. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{a=>b}),
  1666. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(atom),
  1667. {'EXIT',{if_clause,_}} = (catch do_guard_in_catch_map_3()),
  1668. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(42),
  1669. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(<<1,2,3>>),
  1670. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(atom),
  1671. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(#{}),
  1672. ok.
  1673. do_guard_in_catch_map_1(From) ->
  1674. catch
  1675. if
  1676. From#{[] => sufficient} ->
  1677. saint
  1678. end.
  1679. do_guard_in_catch_map_2(From) ->
  1680. catch
  1681. if
  1682. From#{From => sufficient} ->
  1683. saint
  1684. end.
  1685. do_guard_in_catch_map_3() ->
  1686. try
  1687. if [] -> solo end
  1688. catch
  1689. Friendly when Friendly#{0 => []} -> minutes
  1690. after
  1691. membership
  1692. end.
  1693. do_guard_in_catch_bin(From) ->
  1694. %% Would not crash v3_codegen, but there would be an unnecessary
  1695. %% 'move' to a Y register.
  1696. catch
  1697. if
  1698. <<From:32>> ->
  1699. saint
  1700. end.
  1701. %%%
  1702. %%% The beam_bool pass has been eliminated. Here are the tests from
  1703. %%% beam_bool_SUITE.
  1704. %%%
  1705. beam_bool_SUITE(_Config) ->
  1706. before_and_inside_if(),
  1707. scotland(),
  1708. y_registers(),
  1709. protected(),
  1710. maps(),
  1711. ok.
  1712. before_and_inside_if() ->
  1713. no = before_and_inside_if([a], [b], delete),
  1714. no = before_and_inside_if([a], [b], x),
  1715. no = before_and_inside_if([a], [], delete),
  1716. no = before_and_inside_if([a], [], x),
  1717. no = before_and_inside_if([], [], delete),
  1718. yes = before_and_inside_if([], [], x),
  1719. yes = before_and_inside_if([], [b], delete),
  1720. yes = before_and_inside_if([], [b], x),
  1721. {ch1,ch2} = before_and_inside_if_2([a], [b], blah),
  1722. {ch1,ch2} = before_and_inside_if_2([a], [b], xx),
  1723. {ch1,ch2} = before_and_inside_if_2([a], [], blah),
  1724. {ch1,ch2} = before_and_inside_if_2([a], [], xx),
  1725. {no,no} = before_and_inside_if_2([], [b], blah),
  1726. {no,no} = before_and_inside_if_2([], [b], xx),
  1727. {ch1,no} = before_and_inside_if_2([], [], blah),
  1728. {no,ch2} = before_and_inside_if_2([], [], xx),
  1729. ok.
  1730. %% Thanks to Simon Cornish and Kostis Sagonas.
  1731. %% Used to crash beam_bool.
  1732. before_and_inside_if(XDo1, XDo2, Do3) ->
  1733. Do1 = (XDo1 =/= []),
  1734. Do2 = (XDo2 =/= []),
  1735. if
  1736. %% This expression occurs in a try/catch (protected)
  1737. %% block, which cannot refer to variables outside of
  1738. %% the block that are boolean expressions.
  1739. Do1 =:= true;
  1740. Do1 =:= false, Do2 =:= false, Do3 =:= delete ->
  1741. no;
  1742. true ->
  1743. yes
  1744. end.
  1745. %% Thanks to Simon Cornish.
  1746. %% Used to generate code that would not set {y,0} on
  1747. %% all paths before its use (and therefore fail
  1748. %% validation by the beam_validator).
  1749. before_and_inside_if_2(XDo1, XDo2, Do3) ->
  1750. Do1 = (XDo1 =/= []),
  1751. Do2 = (XDo2 =/= []),
  1752. CH1 = if Do1 == true;
  1753. Do1 == false,Do2==false,Do3 == blah ->
  1754. ch1;
  1755. true ->
  1756. no
  1757. end,
  1758. CH2 = if Do1 == true;
  1759. Do1 == false,Do2==false,Do3 == xx ->
  1760. ch2;
  1761. true ->
  1762. no
  1763. end,
  1764. {CH1,CH2}.
  1765. %% beam_bool would remove the initialization of {y,0}.
  1766. %% (Thanks to Thomas Arts and QuickCheck.)
  1767. scotland() ->
  1768. million = do_scotland(placed),
  1769. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)),
  1770. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)),
  1771. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)),
  1772. ok.
  1773. do_scotland(Echo) ->
  1774. found(case Echo of
  1775. Echo when true; Echo, Echo, Echo ->
  1776. Echo;
  1777. echo ->
  1778. []
  1779. end,
  1780. Echo = placed).
  1781. found(_, _) -> million.
  1782. %% ERL-143: beam_bool could not handle Y registers as a destination.
  1783. y_registers() ->
  1784. {'EXIT',{badarith,[_|_]}} = (catch baker(valentine)),
  1785. {'EXIT',{badarith,[_|_]}} = (catch baker(clementine)),
  1786. {not_ok,true} = potter([]),
  1787. {ok,false} = potter([{encoding,any}]),
  1788. ok.
  1789. %% Thanks to Quickcheck.
  1790. baker(Baker) ->
  1791. (valentine == Baker) +
  1792. case Baker of
  1793. Baker when Baker; Baker ->
  1794. Baker;
  1795. Baker ->
  1796. []
  1797. end.
  1798. %% Thanks to Jose Valim.
  1799. potter(Modes) ->
  1800. Raw = lists:keyfind(encoding, 1, Modes) == false,
  1801. Final = case Raw of
  1802. X when X == false; X == nil -> ok;
  1803. _ -> not_ok
  1804. end,
  1805. {Final,Raw}.
  1806. protected() ->
  1807. {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)),
  1808. {{true}} = welcome({perfect, true}),
  1809. {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})),
  1810. ok.
  1811. photographs({_Violation, surprise, Deep}, opinions) ->
  1812. {if
  1813. 0; "here", Deep ->
  1814. Deep = Deep
  1815. end}.
  1816. welcome({perfect, Profit}) ->
  1817. if
  1818. Profit, Profit, Profit; 0 ->
  1819. {id({Profit})}
  1820. end.
  1821. maps() ->
  1822. ok = evidence(#{0 => 42}).
  1823. %% Cover handling of put_map in in split_block_label_used/2.
  1824. evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} ->
  1825. ok.
  1826. cover_beam_dead(_Config) ->
  1827. Mod = ?FUNCTION_NAME,
  1828. Attr = [],
  1829. Fs = [{function,test,1,2,
  1830. [{label,1},
  1831. {line,[]},
  1832. {func_info,{atom,Mod},{atom,test},1},
  1833. {label,2},
  1834. %% Cover beam_dead:turn_op/1 using swapped operand order.
  1835. {test,is_ne_exact,{f,3},[{integer,1},{x,0}]},
  1836. {test,is_eq_exact,{f,1},[{atom,a},{x,0}]},
  1837. {label,3},
  1838. {move,{atom,ok},{x,0}},
  1839. return]}],
  1840. Exp = [{test,1}],
  1841. Asm = {Mod,Exp,Attr,Fs,3},
  1842. {ok,Mod,Beam} = compile:forms(Asm, [from_asm,binary,report]),
  1843. {module,Mod} = code:load_binary(Mod, Mod, Beam),
  1844. ok = Mod:test(1),
  1845. ok = Mod:test(a),
  1846. {'EXIT',_} = (catch Mod:test(other)),
  1847. true = code:delete(Mod),
  1848. _ = code:purge(Mod),
  1849. ok.
  1850. %% Call this function to turn off constant propagation.
  1851. id(I) -> I.
  1852. check(F, Result) ->
  1853. case F() of
  1854. Result -> ok;
  1855. Other ->
  1856. io:format("Expected: ~p\n", [Result]),
  1857. io:format(" Got: ~p\n", [Other]),
  1858. ct:fail(check_failed)
  1859. end.
  1860. fc({'EXIT',{function_clause,_}}) -> ok;
  1861. fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= guard_inline_SUITE -> ok.