summaryrefslogtreecommitdiff
path: root/lib/compiler/test/guard_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/test/guard_SUITE.erl')
-rw-r--r--lib/compiler/test/guard_SUITE.erl246
1 files changed, 234 insertions, 12 deletions
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 5f45eb3f68..1a96fa4b6c 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,6 +19,10 @@
%%
-module(guard_SUITE).
+%% Warnings for obsolete guards are generated by erl_lint, so we will not
+%% any less testing of the compiler by suppressing them.
+-compile([nowarn_obsolete_guard]).
+
-include_lib("syntax_tools/include/merl.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -1254,8 +1258,30 @@ is_function_2(Config) when is_list(Config) ->
F = fun(_) -> ok end,
if
- is_function(F, 1) -> ok
- end.
+ is_function(F, 1) -> ok
+ end,
+
+ variable_is_function_2(),
+
+ ok.
+
+variable_is_function_2() ->
+ F = fun() -> ok end,
+ [F] = vif_1([id(F)], id(0), []),
+ [F] = vif_2([id(F)], id(0) band 15, []),
+ ok.
+
+%% Completely unknown arity
+vif_1([F | Fs], Arity, Acc) when is_function(F, Arity) ->
+ vif_1(Fs, Arity, [F | Acc]);
+vif_1([], _Arity, Acc) ->
+ Acc.
+
+%% Arity known to be between 0 and 15
+vif_2([F | Fs], Arity, Acc) when is_function(F, Arity) ->
+ vif_2(Fs, Arity, [F | Acc]);
+vif_2([], _Arity, Acc) ->
+ Acc.
tricky(Config) when is_list(Config) ->
not_ok = tricky_1(1, 2),
@@ -1409,23 +1435,37 @@ rel_op_combinations(Config) when is_list(Config) ->
lists:seq(16#06F0, 16#06F9),
Digits = gb_sets:from_list(Digits0),
rel_op_combinations_1(16#0700, Digits),
+ false = is_digit(-1 bsl 59),
+ false = is_digit(-1 bsl 64),
+ false = is_digit((1 bsl 59) - 1),
+ false = is_digit(1 bsl 64),
BrokenRange0 = lists:seq(3, 5) ++
lists:seq(10, 12) ++ lists:seq(14, 20),
BrokenRange = gb_sets:from_list(BrokenRange0),
rel_op_combinations_2(30, BrokenRange),
+ false = broken_range(-1 bsl 64),
+ false = broken_range(1 bsl 64),
Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++
[{I,5*I} || I <- lists:seq(51, 80)],
Red = gb_trees:from_orddict(Red0),
rel_op_combinations_3(100, Red),
+ 2 * (-1 bsl 64) = redundant(-1 bsl 64),
+ none = redundant(1 bsl 64),
+
+ rel_op_combinations_4(),
- rel_op_combinations_4().
+ rel_op_combinations_5().
rel_op_combinations_1(0, _) ->
ok;
rel_op_combinations_1(N, Digits) ->
Bool = gb_sets:is_member(N, Digits),
+ Bool = is_digit(N),
+ rel_op_combinations_1(N-1, Digits).
+
+is_digit(N) ->
Bool = is_digit_1(N),
Bool = is_digit_2(N),
Bool = is_digit_3(N),
@@ -1436,8 +1476,7 @@ rel_op_combinations_1(N, Digits) ->
Bool = is_digit_8(N),
Bool = is_digit_9(42, N),
Bool = is_digit_10(N, 0),
- Bool = is_digit_11(N, 0),
- rel_op_combinations_1(N-1, Digits).
+ Bool = is_digit_11(N, 0).
is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
@@ -1502,6 +1541,10 @@ rel_op_combinations_2(0, _) ->
ok;
rel_op_combinations_2(N, Range) ->
Bool = gb_sets:is_member(N, Range),
+ Bool = broken_range(N),
+ rel_op_combinations_2(N-1, Range).
+
+broken_range(N) ->
Bool = broken_range_1(N),
Bool = broken_range_2(N),
Bool = broken_range_3(N),
@@ -1514,8 +1557,7 @@ rel_op_combinations_2(N, Range) ->
Bool = broken_range_10(N),
Bool = broken_range_11(N),
Bool = broken_range_12(N),
- Bool = broken_range_13(N),
- rel_op_combinations_2(N-1, Range).
+ Bool = broken_range_13(N).
broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
broken_range_1(X) when X >= 3, X =< 5 -> true;
@@ -1587,6 +1629,10 @@ rel_op_combinations_3(N, Red) ->
none -> none;
{value,V} -> V
end,
+ Val = redundant(N),
+ rel_op_combinations_3(N-1, Red).
+
+redundant(N) ->
Val = redundant_1(N),
Val = redundant_2(N),
Val = redundant_3(N),
@@ -1598,8 +1644,7 @@ rel_op_combinations_3(N, Red) ->
Val = redundant_9(N),
Val = redundant_10(N),
Val = redundant_11(N),
- Val = redundant_12(N),
- rel_op_combinations_3(N-1, Red).
+ Val = redundant_12(N).
redundant_1(X) when X >= 51, X =< 80 -> 5*X;
redundant_1(X) when X < 51 -> 2*X;
@@ -1673,6 +1718,145 @@ rel_op_vars_1(X, N) when X =< N -> le.
rel_op_vars_2(X, N) when X =/= N -> ne;
rel_op_vars_2(X, N) when X >= N -> ge.
+rel_op_combinations_5() ->
+ lt = lt_gt_eq(a, b),
+ lt = lt_gt_eq(1.0, 42),
+ lt = lt_gt_eq(1, 42.0),
+
+ eq = lt_gt_eq(a, a),
+ eq = lt_gt_eq(42, 42),
+ eq = lt_gt_eq(42.0, 42),
+ eq = lt_gt_eq(42, 42.0),
+ eq = lt_gt_eq(42.0, 42.0),
+
+ gt = lt_gt_eq(b, a),
+ gt = lt_gt_eq(42.0, 1),
+ gt = lt_gt_eq(42, 1.0),
+
+ lt = eq_exact_lt_gt(a, b),
+ lt = eq_exact_lt_gt(1.0, 42),
+ lt = eq_exact_lt_gt(1, 42.0),
+
+ eq = eq_exact_lt_gt(a, a),
+ eq = eq_exact_lt_gt(42, 42),
+ none = eq_exact_lt_gt(42, 42.0),
+
+ gt = eq_exact_lt_gt(b, a),
+ gt = eq_exact_lt_gt(42.0, 1),
+ gt = eq_exact_lt_gt(42, 1.0),
+
+ ok.
+
+lt_gt_eq(A, B) ->
+ Res = lt_gt_eq_1(A, B),
+ Res = lt_gt_eq_2(A, B),
+ Res = lt_gt_eq_3(A, B),
+ Res = lt_gt_eq_4(A, B),
+ Res = lt_gt_eq_5(A, B),
+ lt_gt_eq_6(A, B).
+
+%% The last test in each 'if' is unnecessary.
+lt_gt_eq_1(A, B) ->
+ if
+ A < B -> lt;
+ A == B -> eq;
+ A > B -> gt
+ end.
+
+lt_gt_eq_2(A, B) ->
+ if
+ A > B -> gt;
+ A == B -> eq;
+ A < B -> lt
+ end.
+
+lt_gt_eq_3(A, B) ->
+ if
+ A == B -> eq;
+ A < B -> lt;
+ A > B -> gt
+ end.
+
+lt_gt_eq_4(A, B) ->
+ if
+ A == B -> eq;
+ A > B -> gt;
+ A < B -> lt
+ end.
+
+lt_gt_eq_5(A, B) ->
+ if
+ A < B -> lt;
+ A > B -> gt;
+ A == B -> eq
+ end.
+
+lt_gt_eq_6(A, B) ->
+ if
+ A > B -> gt;
+ A < B -> lt;
+ A == B -> eq
+ end.
+
+eq_exact_lt_gt(A, B) ->
+ Res = eq_exact_lt_gt_1(A, B),
+ Res = eq_exact_lt_gt_2(A, B),
+ Res = eq_exact_lt_gt_3(A, B),
+ Res = eq_exact_lt_gt_4(A, B),
+ Res = eq_exact_lt_gt_5(A, B),
+ Res = eq_exact_lt_gt_6(A, B).
+
+%% Not possible to optimize (unless we have type information so we
+%% know that A == B and A =:= B produces the same result).
+
+eq_exact_lt_gt_1(A, B) ->
+ if
+ A < B -> lt;
+ A =:= B -> eq;
+ A > B -> gt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_2(A, B) ->
+ if
+ A > B -> gt;
+ A =:= B -> eq;
+ A < B -> lt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_3(A, B) ->
+ if
+ A =:= B -> eq;
+ A < B -> lt;
+ A > B -> gt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_4(A, B) ->
+ if
+ A =:= B -> eq;
+ A > B -> gt;
+ A < B -> lt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_5(A, B) ->
+ if
+ A < B -> lt;
+ A > B -> gt;
+ A =:= B -> eq;
+ true -> none
+ end.
+
+eq_exact_lt_gt_6(A, B) ->
+ if
+ A > B -> gt;
+ A < B -> lt;
+ A =:= B -> eq;
+ true -> none
+ end.
+
%% Exhaustively test all combinations of relational operators
%% to ensure the correctness of the optimizations in beam_ssa_dead.
@@ -2362,6 +2546,9 @@ beam_bool_SUITE(_Config) ->
erl1384(),
gh4788(),
beam_ssa_bool_coverage(),
+ bad_map_in_guard(),
+ gh_6164(),
+ gh_6184(),
ok.
before_and_inside_if() ->
@@ -2873,6 +3060,42 @@ beam_ssa_bool_coverage_1(V) when V andalso 0, tuple_size(0) ->
beam_ssa_bool_coverage_1(_) ->
error.
+gh_6164() ->
+ true = do_gh_6164(id([])),
+ {'EXIT',{{case_clause,42},_}} = catch do_gh_6164(id(0)),
+
+ ok.
+
+do_gh_6164(V1) ->
+ case 42 of
+ V2 ->
+ case is_list(V1) of
+ V3 ->
+ case V3 orelse V2 of
+ _ when V3 -> 100
+ end =< V3
+ end
+ end.
+
+gh_6184() ->
+ {'EXIT',{function_clause,_}} = catch do_gh_6184(id(true), id({a,b,c})),
+ {'EXIT',{function_clause,_}} = catch do_gh_6184(true, true),
+ {'EXIT',{function_clause,_}} = catch do_gh_6184({a,b,c}, {x,y,z}),
+
+ ok.
+
+do_gh_6184(V1, V2) when (false and is_tuple(V2)) andalso (V1 orelse V2) ->
+ V2 orelse V2.
+
+-record(bad_map_in_guard, {name}).
+bad_map_in_guard() ->
+ error = bad_map_in_guard_1().
+
+bad_map_in_guard_1() when (a#{key => value})#bad_map_in_guard.name ->
+ ok;
+bad_map_in_guard_1() ->
+ error.
+
%%%
%%% End of beam_bool_SUITE tests.
%%%
@@ -2925,5 +3148,4 @@ check(F, Result) ->
ct:fail(check_failed)
end.
-fc({'EXIT',{function_clause,_}}) -> ok;
-fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= guard_inline_SUITE -> ok.
+fc({'EXIT',{function_clause,_}}) -> ok.