diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 33 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 21 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE.erl | 5 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE_data/fun_letrec_effect.core | 25 | ||||
-rw-r--r-- | lib/compiler/test/core_fold_SUITE.erl | 24 | ||||
-rw-r--r-- | lib/compiler/test/map_SUITE.erl | 46 |
6 files changed, 145 insertions, 9 deletions
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index e737839575..7814738449 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -40,7 +40,7 @@ map_and_binary/1,unsafe_branch_caching/1, bad_literals/1,good_literals/1,constant_propagation/1, parse_xml/1,get_payload/1,escape/1,num_slots_different/1, - beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1]). + beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -72,7 +72,7 @@ groups() -> map_and_binary,unsafe_branch_caching, bad_literals,good_literals,constant_propagation,parse_xml, get_payload,escape,num_slots_different, - beam_bsm,guard,is_ascii,non_opt_eq]}]. + beam_bsm,guard,is_ascii,non_opt_eq,erl_689]}]. init_per_suite(Config) -> @@ -1688,6 +1688,35 @@ non_opt_eq([_|_], <<_,_/binary>>) -> non_opt_eq([], <<>>) -> true. +%% ERL-689 + +erl_689(Config) -> + {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE), + {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE), + {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>), + {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>), + ok. + +do_erl_689_1(<<Length, Data/binary>>, _) -> + case {Data, Length} of + {_, 0} -> + %% bs_context_to_binary would incorrectly set Data to the original + %% binary (before matching in the function head). + {{0, 0, 0}, Data}; + {<<Y:16/little, M, D, Rest/binary>>, 4} -> + {{Y, M, D}, Rest} + end. + +do_erl_689_2(_, <<Length, Data/binary>>) -> + case {Length, Data} of + {0, _} -> + %% bs_context_to_binary would incorrectly set Data to the original + %% binary (before matching in the function head). + {{0, 0, 0}, Data}; + {4, <<Y:16/little, M, D, Rest/binary>>} -> + {{Y, M, D}, Rest} + end. + check(F, R) -> R = F(). diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 2206927ed1..1ecae06128 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -36,7 +36,7 @@ core_roundtrip/1, asm/1, optimized_guards/1, sys_pre_attributes/1, dialyzer/1, warnings/1, pre_load_check/1, env_compiler_options/1, - bc_options/1 + bc_options/1, deterministic_include/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -53,7 +53,7 @@ all() -> cover, env, core_pp, core_roundtrip, asm, optimized_guards, sys_pre_attributes, dialyzer, warnings, pre_load_check, env_compiler_options, custom_debug_info, bc_options, - custom_compile_info]. + custom_compile_info, deterministic_include]. groups() -> []. @@ -1514,6 +1514,23 @@ highest_opcode(DataDir, Mod, Opt) -> <<16:32,0:32,HighestOpcode:32,_/binary>> = Code, HighestOpcode. +deterministic_include(Config) when is_list(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Simple = filename:join(DataDir, "simple"), + + %% Files without +deterministic should differ if their include paths do, + %% as their debug info will be different. + {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]), + {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]), + true = NonDetA =/= NonDetB, + + %% ... but files with +deterministic shouldn't. + {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]), + {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]), + true = DetC =:= DetD, + + ok. + %%% %%% Utilities. %%% diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index 23f420f5f2..e5611e99d1 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -29,7 +29,7 @@ bs_shadowed_size_var/1, cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1, cover_v3_kernel_4/1,cover_v3_kernel_5/1, - non_variable_apply/1,name_capture/1]). + non_variable_apply/1,name_capture/1,fun_letrec_effect/1]). -include_lib("common_test/include/ct.hrl"). @@ -57,7 +57,7 @@ groups() -> bs_shadowed_size_var, cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3, cover_v3_kernel_4,cover_v3_kernel_5, - non_variable_apply,name_capture + non_variable_apply,name_capture,fun_letrec_effect ]}]. @@ -94,6 +94,7 @@ end_per_group(_GroupName, Config) -> ?comp(cover_v3_kernel_5). ?comp(non_variable_apply). ?comp(name_capture). +?comp(fun_letrec_effect). try_it(Mod, Conf) -> Src = filename:join(proplists:get_value(data_dir, Conf), diff --git a/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core new file mode 100644 index 0000000000..ab6f5b7940 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core @@ -0,0 +1,25 @@ +module 'fun_letrec_effect' ['fun_letrec_effect'/0, 'ok'/0, 'wat'/0] +attributes [] + +'fun_letrec_effect'/0 = + fun () -> + do apply 'wat'/0() + receive + <'bar'> when 'true' -> 'ok' + <_0> when 'true' -> 'failed' + after 'infinity' -> + 'true' + +%% The return value (bar) of the fun was optimized away because the result of +%% the `letrec ... in` was unused, despite the fun's return value being +%% relevant for the side-effect of the expression. +'wat'/0 = + fun () -> + let <Self> = call 'erlang':'self'() in + do letrec 'f'/0 = fun () -> + do call 'maps':'put'('foo', 'bar', ~{}~) + 'bar' + in call 'erlang':'send'(Self, apply 'f'/0()) + 'undefined' + +end diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index 2a2369fff9..47606014c3 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -28,7 +28,7 @@ mixed_matching_clauses/1,unnecessary_building/1, no_no_file/1,configuration/1,supplies/1, redundant_stack_frame/1,export_from_case/1, - empty_values/1]). + empty_values/1,cover_letrec_effect/1]). -export([foo/0,foo/1,foo/2,foo/3]). @@ -48,7 +48,7 @@ groups() -> mixed_matching_clauses,unnecessary_building, no_no_file,configuration,supplies, redundant_stack_frame,export_from_case, - empty_values]}]. + empty_values,cover_letrec_effect]}]. init_per_suite(Config) -> @@ -598,5 +598,25 @@ empty_values(_Config) -> do_empty_values() when (#{})#{} -> c. +cover_letrec_effect(_Config) -> + self() ! {tag,42}, + _ = try + try + ignore + after + receive + {tag,Int}=Term -> + Res = #{k => {Term,<<Int:16>>}}, + self() ! Res + end + end + after + ok + end, + receive + Any -> + #{k := {{tag,42},<<42:16>>}} = Any + end, + ok. id(I) -> I. diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 9182c1b5ed..c004dca834 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -1212,10 +1212,25 @@ t_guard_bifs(Config) when is_list(Config) -> true = map_guard_empty_2(), true = map_guard_head(#{a=>1}), false = map_guard_head([]), + true = map_get_head(#{a=>1}), + false = map_get_head(#{}), + false = map_get_head([]), + + true = map_get_head_not(#{a=>false}), + false = map_get_head_not(#{a=>true}), + false = map_get_head(#{}), false = map_get_head([]), + true = map_is_key_head(#{a=>1}), false = map_is_key_head(#{}), + false = map_is_key_head(not_a_map), + + false = map_is_key_head_not(#{a=>1}), + true = map_is_key_head_not(#{b=>1}), + true = map_is_key_head_not(#{}), + false = map_is_key_head_not(not_a_map), + true = map_guard_body(#{a=>1}), false = map_guard_body({}), true = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }), @@ -1224,6 +1239,25 @@ t_guard_bifs(Config) when is_list(Config) -> true = map_guard_ill_map_size(), true = map_field_check_sequence(#{a=>1}), false = map_field_check_sequence(#{}), + + %% The guard BIFs used in a body. + + v = map_get(a, id(#{a=>v})), + {'EXIT',{{badkey,a},_}} = + (catch map_get(a, id(#{}))), + {'EXIT',{{badmap,not_a_map},_}} = + (catch map_get(a, id(not_a_map))), + + true = is_map_key(a, id(#{a=>1})), + false = is_map_key(b, id(#{a=>1})), + false = is_map_key(b, id(#{})), + {'EXIT',{{badmap,not_a_map},_}} = + (catch is_map_key(b, id(not_a_map))), + + {true,v} = erl_699(#{k=>v}), + {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})), + {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)), + ok. map_guard_empty() when is_map(#{}); false -> true. @@ -1236,8 +1270,14 @@ map_guard_head(_) -> false. map_get_head(M) when map_get(a, M) =:= 1 -> true; map_get_head(_) -> false. +map_get_head_not(M) when not map_get(a, M) -> true; +map_get_head_not(_) -> false. + map_is_key_head(M) when is_map_key(a, M) -> true; -map_is_key_head(M) -> false. +map_is_key_head(_) -> false. + +map_is_key_head_not(M) when not is_map_key(a, M) -> true; +map_is_key_head_not(_) -> false. map_guard_body(M) -> is_map(M). @@ -1254,6 +1294,10 @@ map_field_check_sequence(M) map_field_check_sequence(_) -> false. +erl_699(M) -> + %% Used to cause an internal consistency failure. + {is_map_key(k, M),maps:get(k, M)}. + t_guard_sequence(Config) when is_list(Config) -> {1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}), {2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}), |