aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/test')
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl32
-rw-r--r--lib/compiler/test/guard_SUITE.erl79
-rw-r--r--lib/compiler/test/map_SUITE.erl3
3 files changed, 110 insertions, 4 deletions
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index b4601b0798..7fb0a16540 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -36,7 +36,8 @@
match_string/1,zero_width/1,bad_size/1,haystack/1,
cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1,
no_partition/1,calling_a_binary/1,binary_in_map/1,
- match_string_opt/1,map_and_binary/1]).
+ match_string_opt/1,map_and_binary/1,
+ unsafe_branch_caching/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -62,7 +63,8 @@ groups() ->
otp_7498,match_string,zero_width,bad_size,haystack,
cover_beam_bool,matched_out_size,follow_fail_branch,
no_partition,calling_a_binary,binary_in_map,
- match_string_opt,map_and_binary]}].
+ match_string_opt,map_and_binary,
+ unsafe_branch_caching]}].
init_per_suite(Config) ->
@@ -1243,6 +1245,32 @@ do_map_and_binary(#{time := _} = T) ->
do_map_and_binary(#{hour := Hour, min := Min} = T) ->
{Hour, Min, T}.
+%% Unsafe caching of branch outcomes in beam_bsm would cause the
+%% delayed creation of sub-binaries optimization to be applied even
+%% when it was unsafe.
+
+unsafe_branch_caching(_Config) ->
+ <<>> = do_unsafe_branch_caching(<<42,1>>),
+ <<>> = do_unsafe_branch_caching(<<42,2>>),
+ <<>> = do_unsafe_branch_caching(<<42,3>>),
+ <<17,18>> = do_unsafe_branch_caching(<<42,3,17,18>>),
+ <<>> = do_unsafe_branch_caching(<<1,3,42,2>>),
+
+ ok.
+
+do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) ->
+ <<C1/integer, B1/binary>> = Bin,
+ case C1 of
+ X when X =:= 1 orelse X =:= 2 ->
+ Bin2 = <<>>;
+ _ ->
+ Bin2 = B1
+ end,
+ case Code of
+ 1 -> do_unsafe_branch_caching(Bin2);
+ _ -> Bin2
+ end.
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index b3b67155b3..47eb1ba78b 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -34,7 +34,8 @@
tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1,
basic_andalso_orelse/1,traverse_dcd/1,
check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
- bad_constants/1,bad_guards/1]).
+ bad_constants/1,bad_guards/1,scotland/1,
+ guard_in_catch/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -52,7 +53,7 @@ groups() ->
rel_ops,rel_op_combinations,
literal_type_tests,basic_andalso_orelse,traverse_dcd,
check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
- bad_constants,bad_guards]}].
+ bad_constants,bad_guards,scotland,guard_in_catch]}].
init_per_suite(Config) ->
Config.
@@ -1831,6 +1832,80 @@ bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) ->
bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) ->
ok.
+%% beam_bool would remove the initialization of {y,0}.
+%% (Thanks to Thomas Arts and QuickCheck.)
+
+scotland(_Config) ->
+ million = do_scotland(placed),
+ {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)),
+ {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)),
+ {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)),
+ ok.
+
+do_scotland(Echo) ->
+ found(case Echo of
+ Echo when true; Echo, Echo, Echo ->
+ Echo;
+ echo ->
+ []
+ end,
+ Echo = placed).
+
+found(_, _) -> million.
+
+%% Building maps in a guard in a 'catch' would crash v3_codegen.
+
+guard_in_catch(_Config) ->
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{}),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{a=>b}),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(atom),
+
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{}),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{a=>b}),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(atom),
+
+ {'EXIT',{if_clause,_}} = (catch do_guard_in_catch_map_3()),
+
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(42),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(<<1,2,3>>),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(atom),
+ {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(#{}),
+
+ ok.
+
+do_guard_in_catch_map_1(From) ->
+ catch
+ if
+ From#{[] => sufficient} ->
+ saint
+ end.
+
+do_guard_in_catch_map_2(From) ->
+ catch
+ if
+ From#{From => sufficient} ->
+ saint
+ end.
+
+do_guard_in_catch_map_3() ->
+ try
+ if [] -> solo end
+ catch
+ Friendly when Friendly#{0 => []} -> minutes
+ after
+ membership
+ end.
+
+do_guard_in_catch_bin(From) ->
+ %% Would not crash v3_codegen, but there would be an unnecessary
+ %% 'move' to a Y register.
+ catch
+ if
+ <<From:32>> ->
+ saint
+ end.
+
+
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 411b15eebe..cff3b5deb4 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -883,6 +883,9 @@ t_update_map_expressions(Config) when is_list(Config) ->
%% Error cases.
{'EXIT',{{badmap,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }),
{'EXIT',{{badmap,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }),
+ {'EXIT',{{badmap,_},_}} =
+ (catch (fun t_update_map_expressions/1)#{u => 42}),
+
ok.