diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/Makefile | 4 | ||||
-rw-r--r-- | lib/compiler/test/beam_block_SUITE.erl | 21 | ||||
-rw-r--r-- | lib/compiler/test/beam_bool_SUITE.erl | 41 | ||||
-rw-r--r-- | lib/compiler/test/beam_except_SUITE.erl | 26 | ||||
-rw-r--r-- | lib/compiler/test/beam_jump_SUITE.erl | 59 | ||||
-rw-r--r-- | lib/compiler/test/beam_reorder_SUITE.erl | 16 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 36 | ||||
-rw-r--r-- | lib/compiler/test/beam_utils_SUITE.erl | 88 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 120 | ||||
-rw-r--r-- | lib/compiler/test/bif_SUITE.erl | 65 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 22 | ||||
-rw-r--r-- | lib/compiler/test/core_fold_SUITE.erl | 49 | ||||
-rw-r--r-- | lib/compiler/test/guard_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/map_SUITE.erl | 44 | ||||
-rw-r--r-- | lib/compiler/test/match_SUITE.erl | 80 | ||||
-rw-r--r-- | lib/compiler/test/misc_SUITE.erl | 7 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE.erl | 6 |
17 files changed, 656 insertions, 36 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 203a50db55..f0185acbc7 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -13,9 +13,11 @@ MODULES= \ beam_validator_SUITE \ beam_disasm_SUITE \ beam_except_SUITE \ + beam_jump_SUITE \ beam_reorder_SUITE \ beam_type_SUITE \ beam_utils_SUITE \ + bif_SUITE \ bs_bincomp_SUITE \ bs_bit_binaries_SUITE \ bs_construct_SUITE \ @@ -49,9 +51,11 @@ NO_OPT= \ beam_block \ beam_bool \ beam_except \ + beam_jump \ beam_reorder \ beam_type \ beam_utils \ + bif \ bs_construct \ bs_match \ bs_utf \ diff --git a/lib/compiler/test/beam_block_SUITE.erl b/lib/compiler/test/beam_block_SUITE.erl index d343e26737..4bcb252833 100644 --- a/lib/compiler/test/beam_block_SUITE.erl +++ b/lib/compiler/test/beam_block_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, - get_map_elements/1,otp_7345/1]). + get_map_elements/1,otp_7345/1,move_opt_across_gc_bif/1]). %% The only test for the following functions is that %% the code compiles and is accepted by beam_validator. @@ -36,7 +36,8 @@ all() -> groups() -> [{p,[parallel], [get_map_elements, - otp_7345 + otp_7345, + move_opt_across_gc_bif ]}]. init_per_suite(Config) -> @@ -118,6 +119,22 @@ otp_7345(ObjRef, _RdEnv, Args) -> 10}, id(LlUnitdataReq). + +%% Doing move optimizations across GC bifs are in general not safe. +move_opt_across_gc_bif(_Config) -> + [0,true,1] = positive(speaking), + ok. + +positive(speaking) -> + try + Positive = 0, + [+Positive, case Positive of _ -> true end, paris([], Positive)] + after + mailing + end. + +paris([], P) -> P + 1. + %%% %%% The only test of the following code is that it compiles. %%% diff --git a/lib/compiler/test/beam_bool_SUITE.erl b/lib/compiler/test/beam_bool_SUITE.erl index 84d634e5ca..e585eaedb5 100644 --- a/lib/compiler/test/beam_bool_SUITE.erl +++ b/lib/compiler/test/beam_bool_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, before_and_inside_if/1, - scotland/1,y_registers/1]). + scotland/1,y_registers/1,protected/1, + maps/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -35,7 +36,9 @@ groups() -> [{p,[parallel], [before_and_inside_if, scotland, - y_registers + y_registers, + protected, + maps ]}]. init_per_suite(Config) -> @@ -158,3 +161,37 @@ potter(Modes) -> _ -> not_ok end, {Final,Raw}. + +protected(_Config) -> + {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)), + + {{true}} = welcome({perfect, true}), + {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})), + ok. + +photographs({_Violation, surprise, Deep}, opinions) -> + {if + 0; "here", Deep -> + Deep = Deep + end}. + +welcome({perfect, Profit}) -> + if + Profit, Profit, Profit; 0 -> + {id({Profit})} + end. + +maps(_Config) -> + ok = evidence(#{0 => 42}). + +%% Cover handling of put_map in in split_block_label_used/2. +evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} -> + ok. + + +%%% +%%% Common utilities. +%%% + +id(I) -> + I. diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl index 8746e62fb9..47367d6eab 100644 --- a/lib/compiler/test/beam_except_SUITE.erl +++ b/lib/compiler/test/beam_except_SUITE.erl @@ -21,15 +21,18 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - coverage/1]). + multiple_allocs/1,coverage/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [coverage]. + test_lib:recompile(?MODULE), + [{group,p}]. groups() -> - []. + [{p,[parallel], + [multiple_allocs, + coverage]}]. init_per_suite(Config) -> Config. @@ -43,6 +46,23 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +multiple_allocs(_Config) -> + {'EXIT',{{badmatch,#{true:=[p]}},_}} = + (catch could(pda, 0.0, {false,true}, {p})), + {'EXIT',{function_clause,_}} = (catch place(lee)), + {'EXIT',{{badmatch,wanted},_}} = (catch conditions()), + + ok. + +could(Coupons = pda, Favorite = _pleasure = 0.0, {_, true}, {Presents}) -> + (0 = true) = #{true => [Presents]}. + +place(lee) -> + (pregnancy = presentations) = [hours | [purchase || _ <- 0]] + wine. + +conditions() -> + (talking = going) = storage + [large = wanted]. + coverage(_) -> File = {file,"fake.erl"}, ok = fc(a), diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl new file mode 100644 index 0000000000..0b13adaff2 --- /dev/null +++ b/lib/compiler/test/beam_jump_SUITE.erl @@ -0,0 +1,59 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. 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. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_jump_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + undefined_label/1]). + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [undefined_label + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +undefined_label(_Config) -> + {'EXIT',{function_clause,_}} = (catch flights(0, [], [])), + ok. + +%% Would lose a label when compiled with no_copt. + +flights(0, [], []) when [], 0; 0.0, [], false -> + clark; +flights(_, Reproduction, introduction) when false, Reproduction -> + responsible. diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl index 4b2262f65b..ff31f2d3bd 100644 --- a/lib/compiler/test/beam_reorder_SUITE.erl +++ b/lib/compiler/test/beam_reorder_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, - alloc/1]). + alloc/1,confused_beam_validator/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -31,7 +31,8 @@ all() -> groups() -> [{p,[parallel], - [alloc + [alloc, + confused_beam_validator ]}]. init_per_suite(Config) -> @@ -65,5 +66,16 @@ alloc_b(_U1, _U2, R) -> _ = id(0), Res. +confused_beam_validator(_Config) -> + {'EXIT',{{badmap,{any}},_}} = (catch efficient({any})), + ok. + +efficient({Var}=God) -> + id(God#{}), + catch + receive _ -> + Var + end. + id(I) -> I. diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 8d5c0190ed..69e2f1838d 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -21,7 +21,8 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, - integers/1,coverage/1,booleans/1]). + integers/1,coverage/1,booleans/1,setelement/1,cons/1, + tuple/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -33,7 +34,10 @@ groups() -> [{p,[parallel], [integers, coverage, - booleans + booleans, + setelement, + cons, + tuple ]}]. init_per_suite(Config) -> @@ -55,6 +59,8 @@ integers(_Config) -> a = do_integers_2(<<0:1>>), {'EXIT',{{case_clause,-1},_}} = (catch do_integers_2(<<1:1>>)), + college = do_integers_3(), + ok. do_integers_1(B0) -> @@ -71,6 +77,12 @@ do_integers_2(Bin) -> 1 -> b end. +do_integers_3() -> + case try 0 after [] end of + 0 -> college; + 1 -> 0 + end. + coverage(_Config) -> {'EXIT',{badarith,_}} = (catch id(1) bsl 0.5), {'EXIT',{badarith,_}} = (catch id(2.0) bsl 2), @@ -94,5 +106,25 @@ do_booleans(B) -> no -> no end. +setelement(_Config) -> + T0 = id({a,42}), + {a,_} = T0, + {b,_} = setelement(1, T0, b), + ok. + +cons(_Config) -> + [did] = cons(assigned, did), + ok. + +cons(assigned, Instrument) -> + [Instrument] = [did]. + +tuple(_Config) -> + {'EXIT',{{badmatch,{necessary}},_}} = (catch do_tuple()), + ok. + +do_tuple() -> + {0, _} = {necessary}. + id(I) -> I. diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl index 6353ed3242..f6d4a311bb 100644 --- a/lib/compiler/test/beam_utils_SUITE.erl +++ b/lib/compiler/test/beam_utils_SUITE.erl @@ -23,7 +23,8 @@ init_per_group/2,end_per_group/2, apply_fun/1,apply_mf/1,bs_init/1,bs_save/1, is_not_killed/1,is_not_used_at/1, - select/1,y_catch/1,otp_8949_b/1,liveopt/1]). + select/1,y_catch/1,otp_8949_b/1,liveopt/1,coverage/1, + y_registers/1]). -export([id/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -43,7 +44,9 @@ groups() -> select, y_catch, otp_8949_b, - liveopt + liveopt, + coverage, + y_registers ]}]. init_per_suite(Config) -> @@ -268,6 +271,87 @@ liveopt_fun(Peer, Cause, Origin) -> void end. +%% Thanks to QuickCheck. +coverage(_Config) -> + 42+7 = merchant([[],7,false]), + + {'EXIT',{{try_clause,0},_}} = (catch resulting([0], stone)), + 0.0 = resulting([true], stone), + + {'EXIT',{if_clause,_}} = (catch clinic(false)), + {'EXIT',{{try_clause,"trials"},_}} = (catch clinic(true)), + + {'EXIT',{function_clause,_}} = (catch town(overall, {{abc},alcohol})), + + ok. + +%% Cover check_liveness/3. +merchant([Merchant, Laws, Electric]) -> + id(42), + oklahoma([[] || 0 <- Merchant], + if true; Electric -> Laws end) + 42. +oklahoma([], Int) -> Int. + +town(overall, {{If}, Healing = alcohol}) + when Healing#{[] => Healing}; include -> + [If || Healing <- awareness]. + +%% Cover is_reg_used_at/3. +resulting([Conservation], stone) -> + try 0 of + Conservation when Conservation -> Conservation; + _ when Conservation; 0 -> 0.0 + after + Conservation + end. + +%% Cover is_reg_used_at_1/3. +clinic(Damage) -> + if + Damage -> + try "trials" of Damage when Damage -> Damage catch true -> [] end + end, + carefully. + +y_registers(_Config) -> + {'EXIT',{{badfun,0},_}} = (catch economic(0.0, jim)), + {'EXIT',{{badmatch,apartments},_}} = (catch louisiana()), + {a,b} = (boxes(true))({a,b}), + {'EXIT',{{case_clause,webmaster},_}} = (catch yellow(true)), + ok. + +economic(0.0 = Serves, Existence) -> + case Serves of + Serves -> 0 + end, + Existence = jim, + 0(), + Serves, + Existence. + +louisiana() -> + {catch necessarily, + try + [] == reg, + true = apartments + catch [] -> barbara + end}. + +boxes(Call) -> + case Call of + Call -> approval + end, + Call, + fun id/1. + +yellow(Hill) -> + case webmaster of + station -> eyes; Hill -> + "under" + end, + Hill, + id(42). + %% The identity function. id(I) -> I. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 7c4e88ca3e..263fd2ca7e 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -32,7 +32,7 @@ bad_bin_match/1,bad_dsetel/1, state_after_fault_in_catch/1,no_exception_in_catch/1, undef_label/1,illegal_instruction/1,failing_gc_guard_bif/1, - map_field_lists/1]). + map_field_lists/1,cover_bin_opt/1]). -include_lib("common_test/include/ct.hrl"). @@ -60,7 +60,7 @@ groups() -> freg_state,bad_bin_match,bad_dsetel, state_after_fault_in_catch,no_exception_in_catch, undef_label,illegal_instruction,failing_gc_guard_bif, - map_field_lists]}]. + map_field_lists,cover_bin_opt]}]. init_per_suite(Config) -> Config. @@ -406,8 +406,124 @@ map_field_lists(Config) -> empty_field_list}} ] = Errors. +%% Coverage and smoke test of beam_validator. +cover_bin_opt(_Config) -> + Ms = [beam_utils_SUITE, + bs_match_SUITE, + bs_bincomp_SUITE, + bs_bit_binaries_SUITE, + bs_utf_SUITE], + test_lib:p_run(fun try_bin_opt/1, Ms), + ok. + +try_bin_opt(Mod) -> + try + do_bin_opt(Mod) + catch + Class:Error -> + io:format("~p: ~p ~p\n~p\n", + [Mod,Class,Error,erlang:get_stacktrace()]), + error + end. + +do_bin_opt(Mod) -> + Beam = code:which(Mod), + {ok,{Mod,[{abstract_code, + {raw_abstract_v1,Abstr}}]}} = + beam_lib:chunks(Beam, [abstract_code]), + {ok,Mod,Asm} = compile:forms(Abstr, ['S']), + do_bin_opt(Mod, Asm). + +do_bin_opt(Mod, Asm) -> + do_bin_opt(fun enable_bin_opt/1, Mod, Asm), + do_bin_opt(fun remove_bs_start_match/1, Mod, Asm), + do_bin_opt(fun remove_bs_save/1, Mod, Asm), + do_bin_opt(fun destroy_ctxt/1, Mod, Asm), + do_bin_opt(fun destroy_save_point/1, Mod, Asm), + ok. + +do_bin_opt(Transform, Mod, Asm0) -> + Asm = Transform(Asm0), + case compile:forms(Asm, [from_asm,no_postopt,return]) of + {ok,[],Code,_Warnings} when is_binary(Code) -> + ok; + {error,Errors0,_} -> + %% beam_validator must return errors, not simply crash, + %% when illegal code is found. + ModString = atom_to_list(Mod), + [{ModString,Errors}] = Errors0, + _ = [verify_bin_opt_error(E) || E <- Errors], + ok + end. + +verify_bin_opt_error({beam_validator,_}) -> + ok. + +enable_bin_opt(Module) -> + transform_is(fun enable_bin_opt_body/1, Module). + +enable_bin_opt_body([_,{'%',{no_bin_opt,_Reason,_Anno}}|Is]) -> + enable_bin_opt_body(Is); +enable_bin_opt_body([I|Is]) -> + [I|enable_bin_opt_body(Is)]; +enable_bin_opt_body([]) -> + []. + +remove_bs_start_match(Module) -> + transform_remove(fun({test,bs_start_match2,_,_,_,_}) -> true; + (_) -> false + end, Module). + +remove_bs_save(Module) -> + transform_remove(fun({bs_save2,_,_}) -> true; + (_) -> false + end, Module). + +destroy_save_point(Module) -> + transform_i(fun do_destroy_save_point/1, Module). + +do_destroy_save_point({I,Ctx,_Point}) + when I =:= bs_save2; I =:= bs_restore2 -> + {I,Ctx,42}; +do_destroy_save_point(I) -> + I. + +destroy_ctxt(Module) -> + transform_i(fun do_destroy_ctxt/1, Module). + +do_destroy_ctxt({bs_save2=I,Ctx,Point}) -> + {I,destroy_reg(Ctx),Point}; +do_destroy_ctxt({bs_restore2=I,Ctx,Point}) -> + {I,destroy_reg(Ctx),Point}; +do_destroy_ctxt({bs_context_to_binary=I,Ctx}) -> + {I,destroy_reg(Ctx)}; +do_destroy_ctxt(I) -> + I. + +destroy_reg({Tag,N}) -> + case rand:uniform() of + R when R < 0.6 -> + {Tag,N+1}; + _ -> + {y,N+1} + end. + %%%------------------------------------------------------------------------- +transform_remove(Remove, Module) -> + transform_is(fun(Is) -> [I || I <- Is, not Remove(I)] end, Module). + +transform_i(Transform, Module) -> + transform_is(fun(Is) -> [Transform(I) || I <- Is] end, Module). + +transform_is(Transform, {Mod,Exp,Imp,Fs0,Lc}) -> + Fs = [transform_is_1(Transform, F) || F <- Fs0], + {Mod,Exp,Imp,Fs,Lc}. + +transform_is_1(Transform, {function,N,A,E,Is0}) -> + Is = Transform(Is0), + {function,N,A,E,Is}. + do_val(Mod, Config) -> Data = proplists:get_value(data_dir, Config), Base = atom_to_list(Mod), diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl new file mode 100644 index 0000000000..51bc71da81 --- /dev/null +++ b/lib/compiler/test/bif_SUITE.erl @@ -0,0 +1,65 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. 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. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(bif_SUITE). + +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + beam_validator/1]). + +suite() -> + [{ct_hooks,[ts_install_cth]}]. + +all() -> + test_lib:recompile(?MODULE), + [{group,p}]. + +groups() -> + [{p,[parallel], + [beam_validator + ]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +%% Cover code in beam_validator. + +beam_validator(Config) -> + [false,Config] = food(Config), + + true = is_number(42.0), + false = is_port(Config), + + ok. + +food(Curriculum) -> + [try + is_bitstring(functions) + catch _ -> + 0 + end, Curriculum]. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index a15efc2a00..b0148f7103 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -34,7 +34,7 @@ cover/1, env/1, core/1, core_roundtrip/1, asm/1, sys_pre_attributes/1, dialyzer/1, - warnings/1, pre_load_check/1 + warnings/1, pre_load_check/1, env_compiler_options/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -50,7 +50,8 @@ all() -> other_output, encrypted_abstr, strict_record, cover, env, core, core_roundtrip, asm, - sys_pre_attributes, dialyzer, warnings, pre_load_check]. + sys_pre_attributes, dialyzer, warnings, pre_load_check, + env_compiler_options]. groups() -> []. @@ -1092,6 +1093,23 @@ compiler_modules() -> FN = filename, [list_to_atom(FN:rootname(FN:basename(M), ".beam")) || M <- Ms]. +%% Test that ERL_COMPILER_OPTIONS are correctly retrieved +%% by env_compiler_options/0 + +env_compiler_options(_Config) -> + Cases = [ + {"bin_opt_info", [bin_opt_info]}, + {"'S'", ['S']}, + {"{source, \"test.erl\"}", [{source, "test.erl"}]}, + {"[{d,macro_one,1},{d,macro_two}]", [{d, macro_one, 1}, {d, macro_two}]}, + {"[warn_export_all, warn_export_vars]", [warn_export_all, warn_export_vars]} + ], + F = fun({Env, Expected}) -> + true = os:putenv("ERL_COMPILER_OPTIONS", Env), + Expected = compile:env_compiler_options() + end, + lists:foreach(F, Cases). + %%% %%% Utilities. %%% diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index 442b2d424c..376d2c8e9a 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -25,7 +25,8 @@ eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1, unused_multiple_values_error/1,unused_multiple_values/1, multiple_aliases/1,redundant_boolean_clauses/1, - mixed_matching_clauses/1,unnecessary_building/1]). + mixed_matching_clauses/1,unnecessary_building/1, + no_no_file/1]). -export([foo/0,foo/1,foo/2,foo/3]). @@ -43,7 +44,8 @@ groups() -> eq,nested_call_in_case,guard_try_catch,coverage, unused_multiple_values_error,unused_multiple_values, multiple_aliases,redundant_boolean_clauses, - mixed_matching_clauses,unnecessary_building]}]. + mixed_matching_clauses,unnecessary_building, + no_no_file]}]. init_per_suite(Config) -> @@ -454,4 +456,47 @@ do_unnecessary_building_2({a,_,_}=T) -> [_,_] = [T,none], x}. +%% This test tests that v3_core has provided annotations and that +%% sys_core_fold retains them, so that warnings produced by +%% sys_core_fold will have proper filenames and line numbers. Thus, no +%% "no_file" warnings. +no_no_file(_Config) -> + {'EXIT',{{case_clause,0},_}} = (catch source(true, any)), + surgery = (tim(#{reduction => any}))(), + + false = soul(#{[] => true}), + {'EXIT',{{case_clause,true},_}} = (catch soul(#{[] => false})), + + ok = experiment(), + ok. + +source(true, Activities) -> + case 0 of + Activities when [] -> + Activities + end. + +tim(#{reduction := Emergency}) -> + try + fun() -> surgery end + catch + _ when [] -> + planet + end. + +soul(#{[] := Properly}) -> + not case true of + Properly -> true; + Properly -> 0 + end. + +experiment() -> + case kingdom of + _ -> + +case "map" of + _ -> 0.0 + end + end, + ok. + id(I) -> I. diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index 83298e546e..6302f82f29 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -1835,6 +1835,8 @@ bad_guards(Config) when is_list(Config) -> fc(catch bad_guards_3(not_a_map, [x])), fc(catch bad_guards_3(42, [x])), + fc(catch bad_guards_4()), + ok. %% beam_bool used to produce GC BIF instructions whose @@ -1852,6 +1854,12 @@ 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. +%% v3_codegen would generate a jump to the failure label, but +%% without initializing x(0). The code at the failure label expected +%% x(0) to be initialized. + +bad_guards_4() when not (error#{}); {not 0.0} -> freedom. + %% Building maps in a guard in a 'catch' would crash v3_codegen. guard_in_catch(_Config) -> diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 14d175b92c..36e82c1459 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -66,7 +66,9 @@ t_export/1, %% errors in 18 - t_register_corruption/1 + t_register_corruption/1, + t_bad_update/1 + ]). suite() -> []. @@ -117,7 +119,8 @@ all() -> t_export, %% errors in 18 - t_register_corruption + t_register_corruption, + t_bad_update ]. groups() -> []. @@ -1284,6 +1287,7 @@ t_guard_update(Config) when is_list(Config) -> first = map_guard_update(#{}, #{x=>first}), second = map_guard_update(#{y=>old}, #{x=>second,y=>old}), third = map_guard_update(#{x=>old,y=>old}, #{x=>third,y=>old}), + bad_map_guard_update(), ok. t_guard_update_large(Config) when is_list(Config) -> @@ -1350,6 +1354,29 @@ map_guard_update(M1, M2) when M1#{x=>second} =:= M2 -> second; map_guard_update(M1, M2) when M1#{x:=third} =:= M2 -> third; map_guard_update(_, _) -> error. +bad_map_guard_update() -> + do_bad_map_guard_update(fun burns/1), + do_bad_map_guard_update(fun turns/1), + ok. + +do_bad_map_guard_update(Fun) -> + do_bad_map_guard_update_1(Fun, #{}), + do_bad_map_guard_update_1(Fun, #{true=>1}), + ok. + +do_bad_map_guard_update_1(Fun, Value) -> + %% Note: The business with the seemingly redundant fun + %% disables inlining, which would otherwise change the + %% EXIT reason. + {'EXIT',{function_clause,_}} = (catch Fun(Value)), + ok. + +burns(Richmond) when not (Richmond#{true := 0}); [Richmond] -> + specification. + +turns(Richmond) when not (Richmond#{true => 0}); [Richmond] -> + specification. + t_guard_receive(Config) when is_list(Config) -> M0 = #{ id => 0 }, Pid = spawn_link(fun() -> guard_receive_loop() end), @@ -1922,6 +1949,19 @@ validate_frequency([{T,C}|Fs],Tf) -> validate_frequency([], _) -> ok. +t_bad_update(_Config) -> + {#{0.0:=Id},#{}} = properly(#{}), + 42 = Id(42), + {'EXIT',{{badmap,_},_}} = (catch increase(0)), + ok. + +properly(Item) -> + {Item#{0.0 => fun id/1},Item}. + +increase(Allows) -> + catch fun() -> Allows end#{[] => +Allows, "warranty" => fun id/1}. + + %% aux rand_terms(0) -> []; diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 92a9802cad..31402ac717 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -21,8 +21,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - pmatch/1,mixed/1,aliases/1,match_in_call/1, - untuplify/1,shortcut_boolean/1,letify_guard/1, + pmatch/1,mixed/1,aliases/1,non_matching_aliases/1, + match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, selectify/1,underscore/1,match_map/1,map_vars_used/1, coverage/1,grab_bag/1]). @@ -36,7 +36,8 @@ all() -> groups() -> [{p,[parallel], - [pmatch,mixed,aliases,match_in_call,untuplify, + [pmatch,mixed,aliases,non_matching_aliases, + match_in_call,untuplify, shortcut_boolean,letify_guard,selectify, underscore,match_map,map_vars_used,coverage, grab_bag]}]. @@ -143,16 +144,6 @@ aliases(Config) when is_list(Config) -> {a,b} = list_alias2([a,b]), {a,b} = list_alias3([a,b]), - %% Non-matching aliases. - none = mixed_aliases(<<42>>), - none = mixed_aliases([b]), - none = mixed_aliases([d]), - none = mixed_aliases({a,42}), - none = mixed_aliases(42), - - %% Non-matching aliases. - {'EXIT',{{badmatch,42},_}} = (catch nomatch_alias(42)), - ok. str_alias(V) -> @@ -256,6 +247,33 @@ list_alias2([X,Y]=[a,b]) -> list_alias3([X,b]=[a,Y]) -> {X,Y}. +non_matching_aliases(_Config) -> + none = mixed_aliases(<<42>>), + none = mixed_aliases([b]), + none = mixed_aliases([d]), + none = mixed_aliases({a,42}), + none = mixed_aliases(42), + + {'EXIT',{{badmatch,42},_}} = (catch nomatch_alias(42)), + {'EXIT',{{badmatch,job},_}} = (catch entirely()), + {'EXIT',{{badmatch,associates},_}} = (catch printer()), + {'EXIT',{{badmatch,borogoves},_}} = (catch tench()), + + put(perch, 0), + {'EXIT',{{badmatch,{spine,42}},_}} = (catch perch(42)), + 1 = erase(perch), + + put(salmon, 0), + {'EXIT',{{badmatch,mimsy},_}} = (catch salmon()), + 1 = erase(salmon), + + put(shark, 0), + {'EXIT',{{badmatch,_},_}} = (catch shark()), + 1 = erase(shark), + + {'EXIT',{{badmatch,_},_}} = (catch radio(research)), + ok. + mixed_aliases(<<X:8>> = x) -> {a,X}; mixed_aliases([b] = <<X:8>>) -> {b,X}; mixed_aliases(<<X:8>> = {a,X}) -> {c,X}; @@ -266,6 +284,42 @@ nomatch_alias(I) -> {ok={A,B}} = id(I), {A,B}. +entirely() -> + 0(((Voice = true) = cool) = job), + [receive _ -> Voice end || banking <- printer]. + +printer() -> + {[Indoor] = [] = associates}, + [ireland || Indoor <- Indoor]. + +tench() -> + E = begin + [A] = [] = borogoves, + A + 1 + end, + E + 7 * A. + +perch(X) -> + begin + put(perch, get(perch)+1), + [A] = [] = {spine,X} + end. + +salmon() -> + {put(salmon, get(salmon)+1),#{key:=([A]=[])}=mimsy,exit(fail)}, + A + 10. + +shark() -> + (hello = there) = (catch shark(put(shark, get(shark)+1), a = b)). + +shark(_, _) -> + ok. + +radio(research) -> + (connection = proof) = + (catch erlang:trace_pattern(catch mechanisms + assist, + summary = mechanisms)). + %% OTP-7018. match_in_call(Config) when is_list(Config) -> diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index f05fe6c943..f543f0d4de 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -256,12 +256,15 @@ silly_coverage(Config) when is_list(Config) -> {jump,{f,42}}]}],99}, expect_error(fun() -> beam_clean:module(CleanInput, []) end), - %% beam_peep + %% beam_peep. This is tricky. Use a select instruction with + %% an odd number of elements in the list to crash + %% prune_redundant_values/2 but not beam_clean:clean_labels/1. PeepInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, [{label,1}, {func_info,{atom,?MODULE},{atom,foo},0}, - {label,2}|non_proper_list]}],99}, + {label,2},{select,op,r,{f,2},[{f,2}]}]}], + 2}, expect_error(fun() -> beam_peep:module(PeepInput, []) end), %% beam_bsm. This is tricky. Our function must be sane enough to not crash diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index 3c397561fc..8304672558 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -118,8 +118,14 @@ coverage(Config) when is_list(Config) -> 59 = tuple_to_values(infinity, x), 61 = tuple_to_values(999999, x), 0 = tuple_to_values(1, x), + + {'EXIT',{{badmap,[]},_}} = (catch monitor_plus_badmap(self())), + ok. +monitor_plus_badmap(Pid) -> + monitor(process, Pid) + []#{}. + receive_all() -> receive Any -> |