diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/doc/src/compile.xml | 14 | ||||
-rw-r--r-- | lib/compiler/src/Makefile | 69 | ||||
-rw-r--r-- | lib/compiler/src/beam_asm.erl | 2 | ||||
-rw-r--r-- | lib/compiler/src/beam_bool.erl | 27 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 16 | ||||
-rw-r--r-- | lib/compiler/src/compile.erl | 113 | ||||
-rw-r--r-- | lib/compiler/src/sys_pre_expand.erl | 60 | ||||
-rw-r--r-- | lib/compiler/src/v3_core.erl | 14 | ||||
-rw-r--r-- | lib/compiler/test/andor_SUITE.erl | 66 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 46 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE_data/on_load.erl | 2 | ||||
-rw-r--r-- | lib/compiler/test/error_SUITE.erl | 30 | ||||
-rw-r--r-- | lib/compiler/vsn.mk | 2 |
13 files changed, 303 insertions, 158 deletions
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index c39c9b25eb..bbd3f1043d 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>compile</title> @@ -212,6 +212,12 @@ success.</p> </item> + <tag><c>warnings_as_errors</c></tag> + <item> + <p>Causes warnings to be treated as errors. This option is supported + since R13B04.</p> + </item> + <tag><c>return</c></tag> <item> <p>This is a short form for both <c>return_errors</c> and @@ -726,7 +732,7 @@ pi() -> 3.1416. <p>A string describing the error is obtained with the following call:</p> <code> -apply(Module, format_error, ErrorDescriptor) +Module:format_error(ErrorDescriptor) </code> </section> diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index fde2b1a655..70ddd54145 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 1996-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1996-2010. All Rights Reserved. +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # @@ -45,46 +45,46 @@ RELSYSDIR = $(RELEASE_PATH)/lib/compiler-$(VSN) # Target Specs # ---------------------------------------------------- MODULES = \ - compile \ - sys_pre_attributes \ - sys_pre_expand \ - sys_expand_pmod \ - v3_core \ - sys_core_fold \ - sys_core_inline \ - sys_core_dsetel \ - core_lib \ - core_scan \ - core_parse \ - core_lint \ - core_pp \ - v3_kernel \ - v3_kernel_pp \ - v3_life \ - v3_codegen \ + beam_asm \ beam_block \ beam_bool \ - beam_dead \ - beam_jump \ - beam_type \ - beam_clean \ - beam_peep \ beam_bsm \ - beam_trim \ + beam_clean \ + beam_dead \ + beam_dict \ + beam_disasm \ beam_flatten \ + beam_jump \ beam_listing \ - beam_asm \ - beam_dict \ beam_opcodes \ - beam_disasm \ + beam_peep \ + beam_trim \ + beam_type \ beam_utils \ beam_validator \ - erl_bifs \ cerl \ cerl_clauses \ cerl_inline \ cerl_trees \ - rec_env + compile \ + core_lib \ + core_lint \ + core_parse \ + core_pp \ + core_scan \ + erl_bifs \ + rec_env \ + sys_core_dsetel \ + sys_core_fold \ + sys_core_inline \ + sys_expand_pmod \ + sys_pre_attributes \ + sys_pre_expand \ + v3_codegen \ + v3_core \ + v3_kernel \ + v3_kernel_pp \ + v3_life BEAM_H = $(wildcard ../priv/beam_h/*.h) @@ -114,6 +114,9 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) # FLAGS # ---------------------------------------------------- +ifeq ($(NATIVE_LIBS_ENABLED),yes) +ERL_COMPILE_FLAGS += +native +endif ERL_COMPILE_FLAGS += +inline +warn_unused_import -I../../stdlib/include -I$(EGEN) -W # ---------------------------------------------------- diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl index 90d25d87b2..497c4fa07b 100644 --- a/lib/compiler/src/beam_asm.erl +++ b/lib/compiler/src/beam_asm.erl @@ -150,7 +150,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) -> %% Create IFF chunk. Chunks = case member(slim, Opts) of - true -> [Essentials,AttrChunk,CompileChunk,AbstChunk]; + true -> [Essentials,AttrChunk,AbstChunk]; false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk] end, build_form(<<"BEAM">>, Chunks). diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl index d8c201a194..dcc6ad4c7c 100644 --- a/lib/compiler/src/beam_bool.erl +++ b/lib/compiler/src/beam_bool.erl @@ -123,6 +123,12 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> throw:mixed -> failed; + %% There was a reference to a boolean expression + %% from inside a protected block (try/catch), to + %% a boolean expression outside. + throw:protected_barrier -> + failed; + %% The 'xor' operator was used. We currently don't %% find it worthwile to translate 'xor' operators %% (the code would be clumsy). @@ -167,7 +173,7 @@ bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) -> %% whether the optimized code is guaranteed to work in the same %% way as the original code. %% -%% Throws an exception if the optmization is not safe. +%% Throw an exception if the optimization is not safe. %% ensure_opt_safe(Bl, NewCode, OldIs, Fail, PreceedingCode, St) -> %% Here are the conditions that must be true for the @@ -184,10 +190,10 @@ ensure_opt_safe(Bl, NewCode, OldIs, Fail, PreceedingCode, St) -> %% by the code that follows. %% %% 3. Any register that is assigned a value in the optimized - %% code must be UNUSED or KILLED in the following code. - %% (Possible future improvement: Registers that are known - %% to be assigned the SAME value in the original and optimized - %% code don't need to be unused in the following code.) + %% code must be UNUSED or KILLED in the following code + %% (because the register might be assigned the wrong value, + %% and even if the value is right it might no longer be + %% assigned on *all* paths leading to its use). InitInPreceeding = initialized_regs(PreceedingCode), @@ -304,6 +310,8 @@ dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); dst_regs([{set,[D],_,{alloc,_,{gc_bif,_,{f,_}}}}|Is], Acc) -> dst_regs(Is, [D|Acc]); +dst_regs([{set,[D],_,move}|Is], Acc) -> + dst_regs(Is, [D|Acc]); dst_regs([_|Is], Acc) -> dst_regs(Is, Acc); dst_regs([], Acc) -> ordsets:from_list(Acc). @@ -414,11 +422,10 @@ bopt_good_args([A|As], Regs) -> bopt_good_args([], _) -> ok. bopt_good_arg({Tag,_}=X, Regs) when Tag =:= x; Tag =:= tmp -> - case gb_trees:get(X, Regs) of - any -> ok; - _Other -> - %%io:format("not any: ~p: ~p\n", [X,_Other]), - throw(mixed) + case gb_trees:lookup(X, Regs) of + {value,any} -> ok; + {value,_} -> throw(mixed); + none -> throw(protected_barrier) end; bopt_good_arg(_, _) -> ok. diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 08ba9c3ee4..1fd61831e0 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% -module(beam_validator). @@ -604,9 +604,9 @@ valfun_4({gc_bif,Op,{f,Fail},Live,Src,Dst}, #vst{current=St0}=Vst0) -> St = kill_heap_allocation(St0), Vst1 = Vst0#vst{current=St}, verify_live(Live, Vst1), - Vst2 = prune_x_regs(Live, Vst1), - validate_src(Src, Vst2), - Vst = branch_state(Fail, Vst2), + Vst2 = branch_state(Fail, Vst1), + Vst = prune_x_regs(Live, Vst2), + validate_src(Src, Vst), Type = bif_type(Op, Src, Vst), set_type_reg(Type, Dst, Vst); valfun_4(return, #vst{current=#st{numy=none}}=Vst) -> diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e725083a9f..b853800d73 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% Purpose: Run the Erlang compiler. @@ -187,9 +187,9 @@ format_error(no_crypto_key) -> format_error({native, E}) -> io_lib:fwrite("native-code compilation failed with reason: ~P.", [E, 25]); -format_error({native_crash, E}) -> - io_lib:fwrite("native-code compilation crashed with reason: ~P.", - [E, 25]); +format_error({native_crash,E,Stk}) -> + io_lib:fwrite("native-code compilation crashed with reason: ~P.\n~P\n", + [E,25,Stk,25]); format_error({open,E}) -> io_lib:format("open error '~s'", [file:format_error(E)]); format_error({epp,E}) -> @@ -302,7 +302,7 @@ os_process_size() -> list_to_integer(lib:nonl(Size)); _ -> 0 - end. + end. run_tc({Name,Fun}, St) -> Before0 = statistics(runtime), @@ -318,17 +318,30 @@ run_tc({Name,Fun}, St) -> Val. comp_ret_ok(#compile{code=Code,warnings=Warn0,module=Mod,options=Opts}=St) -> - Warn = messages_per_file(Warn0), - report_warnings(St#compile{warnings = Warn}), - Ret1 = case member(binary, Opts) andalso not member(no_code_generation, Opts) of - true -> [Code]; - false -> [] - end, - Ret2 = case member(return_warnings, Opts) of - true -> Ret1 ++ [Warn]; - false -> Ret1 - end, - list_to_tuple([ok,Mod|Ret2]). + case member(warnings_as_errors, Opts) andalso length(Warn0) > 0 of + true -> + case member(report_warnings, Opts) of + true -> + io:format("~p: warnings being treated as errors\n", + [?MODULE]); + false -> + ok + end, + comp_ret_err(St); + false -> + Warn = messages_per_file(Warn0), + report_warnings(St#compile{warnings = Warn}), + Ret1 = case member(binary, Opts) andalso + not member(no_code_generation, Opts) of + true -> [Code]; + false -> [] + end, + Ret2 = case member(return_warnings, Opts) of + true -> Ret1 ++ [Warn]; + false -> Ret1 + end, + list_to_tuple([ok,Mod|Ret2]) + end. comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) -> Warn = messages_per_file(Warn0), @@ -344,18 +357,18 @@ comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) -> messages_per_file(Ms) -> T = lists:sort([{File,M} || {File,Messages} <- Ms, M <- Messages]), PrioMs = [erl_scan, epp, erl_parse], - {Prio0, Rest} = + {Prio0, Rest} = lists:mapfoldl(fun(M, A) -> lists:partition(fun({_,{_,Mod,_}}) -> Mod =:= M; (_) -> false end, A) end, T, PrioMs), - Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end, + Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end, lists:append(Prio0)), flatmap(fun mpf/1, [Prio, Rest]). mpf(Ms) -> - [{File,[M || {F,M} <- Ms, F =:= File]} || + [{File,[M || {F,M} <- Ms, F =:= File]} || File <- lists:usort([F || {F,_} <- Ms])]. %% passes(form|file, [Option]) -> [{Name,PassFun}] @@ -495,14 +508,14 @@ select_passes([List|Ps], Opts) when is_list(List) -> select_cond(Flag, ShouldBe, Pass, Ps, Opts) -> ShouldNotBe = not ShouldBe, - case member(Flag, Opts) of + case member(Flag, Opts) of ShouldBe -> select_passes([Pass|Ps], Opts); ShouldNotBe -> select_passes(Ps, Opts) end. %% select_list_passes([Pass], Opts) -> {done,[Pass]} | {not_done,[Pass]} %% Evaluate all conditions having to do with listings in the list of -%% passes. +%% passes. select_list_passes(Ps, Opts) -> select_list_passes_1(Ps, Opts, []). @@ -704,7 +717,7 @@ read_beam_file(St) -> case file:read_file(St#compile.ifile) of {ok,Beam} -> Infile = St#compile.ifile, - case is_too_old(Infile) of + case no_native_compilation(Infile, St) of true -> {ok,St#compile{module=none,code=none}}; false -> @@ -717,12 +730,15 @@ read_beam_file(St) -> {error,St#compile{errors=St#compile.errors ++ Es}} end. -is_too_old(BeamFile) -> +no_native_compilation(BeamFile, #compile{options=Opts0}) -> case beam_lib:chunks(BeamFile, ["CInf"]) of {ok,{_,[{"CInf",Term0}]}} -> Term = binary_to_term(Term0), - Opts = proplists:get_value(options, Term, []), - lists:member(no_new_funs, Opts); + + %% Compiler options in the beam file will override + %% options passed to the compiler. + Opts = proplists:get_value(options, Term, []) ++ Opts0, + member(no_new_funs, Opts) orelse not is_native_enabled(Opts); _ -> false end. @@ -782,7 +798,7 @@ clean_parse_transforms_1([F|Fs], Acc) -> clean_parse_transforms_1(Fs, [F|Acc]); clean_parse_transforms_1([], Acc) -> reverse(Acc). -transforms(Os) -> [ M || {parse_transform,M} <- Os ]. +transforms(Os) -> [ M || {parse_transform,M} <- Os ]. transform_module(#compile{options=Opt,code=Code0}=St0) -> %% Extract compile options from code into options field. @@ -815,7 +831,7 @@ foldl_transform(St, [T|Ts]) -> end; foldl_transform(St, []) -> {ok,St}. -get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts]. +get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts]. core_transforms(St) -> %% The options field holds the complete list of options at this @@ -1033,7 +1049,14 @@ beam_asm(#compile{ifile=File,code=Code0,abstract_code=Abst,options=Opts0}=St) -> test_native(#compile{options=Opts}) -> %% This test is done late, in case some other option has turned off native. - member(native, Opts). + %% 'native' given on the command line can be overridden by + %% 'no_native' in the module itself. + is_native_enabled(Opts). + +is_native_enabled([native|_]) -> true; +is_native_enabled([no_native|_]) -> false; +is_native_enabled([_|Opts]) -> is_native_enabled(Opts); +is_native_enabled([]) -> false. native_compile(#compile{code=none}=St) -> {ok,St}; native_compile(St) -> @@ -1057,25 +1080,27 @@ native_compile_1(St) -> St#compile.core_code, St#compile.code, Opts) of - {ok, {_Type,Bin} = T} when is_binary(Bin) -> - {ok, embed_native_code(St, T)}; - {error, R} -> + {ok,{_Type,Bin}=T} when is_binary(Bin) -> + {ok,embed_native_code(St, T)}; + {error,R} -> case IgnoreErrors of true -> - Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}], - {ok, St#compile{warnings=St#compile.warnings ++ Ws}}; + Ws = [{St#compile.ifile,[{?MODULE,{native,R}}]}], + {ok,St#compile{warnings=St#compile.warnings ++ Ws}}; false -> - Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}], - {error, St#compile{errors=St#compile.errors ++ Es}} + Es = [{St#compile.ifile,[{?MODULE,{native,R}}]}], + {error,St#compile{errors=St#compile.errors ++ Es}} end catch - error:R -> + Class:R -> + Stk = erlang:get_stacktrace(), case IgnoreErrors of true -> - Ws = [{St#compile.ifile,[{none,?MODULE,{native_crash,R}}]}], - {ok, St#compile{warnings=St#compile.warnings ++ Ws}}; + Ws = [{St#compile.ifile, + [{?MODULE,{native_crash,R,Stk}}]}], + {ok,St#compile{warnings=St#compile.warnings ++ Ws}}; false -> - exit(R) + erlang:raise(Class, R, Stk) end end. @@ -1264,7 +1289,7 @@ listing(Ext, St) -> listing(LFun, Ext, St) -> Lfile = outfile(St#compile.base, Ext, St#compile.options), case file:open(Lfile, [write,delayed_write]) of - {ok,Lf} -> + {ok,Lf} -> Code = restore_expanded_types(Ext, St#compile.code), LFun(Lf, Code), ok = file:close(Lf), diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 78dd73e0a2..f80d03dfac 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% Purpose : Expand some source Erlang constructions. This is part of the @@ -114,7 +114,7 @@ expand_pmod(Fs0, St0) -> St1 = St0#expand{exports=Xs, defined=Ds}, {Fs2,St2} = add_instance(Ps, Fs1, St1), {Fs3,St3} = ensure_new(Base, Ps0, Fs2, St2), - {Fs3,St3#expand{attributes = [{abstract, [true]} + {Fs3,St3#expand{attributes = [{abstract, 0, [true]} | St3#expand.attributes]}} end. @@ -173,7 +173,7 @@ define_functions(Forms, #expand{defined=Predef}=St) -> St#expand{defined=ordsets:from_list(Fs)}. module_attrs(St) -> - {[{attribute,0,Name,Val} || {Name,Val} <- St#expand.attributes],St}. + {[{attribute,Line,Name,Val} || {Name,Line,Val} <- St#expand.attributes],St}. module_predef_funcs(St) -> PreDef = [{module_info,0},{module_info,1}], @@ -197,8 +197,8 @@ module_predef_funcs(St) -> forms([{attribute,_,file,_File}=F|Fs0], St0) -> {Fs,St1} = forms(Fs0, St0), {[F|Fs],St1}; -forms([{attribute,_,Name,Val}|Fs0], St0) -> - St1 = attribute(Name, Val, St0), +forms([{attribute,Line,Name,Val}|Fs0], St0) -> + St1 = attribute(Name, Val, Line, St0), forms(Fs0, St1); forms([{function,L,N,A,Cs}|Fs0], St0) -> {Ff,St1} = function(L, N, A, Cs, St0), @@ -207,30 +207,30 @@ forms([{function,L,N,A,Cs}|Fs0], St0) -> forms([_|Fs], St) -> forms(Fs, St); forms([], St) -> {[],St}. -%% attribute(Attribute, Value, State) -> State'. +%% attribute(Attribute, Value, Line, State) -> State'. %% Process an attribute, this just affects the state. -attribute(module, {Module, As}, St) -> +attribute(module, {Module, As}, _L, St) -> M = package_to_string(Module), St#expand{module=list_to_atom(M), - package = packages:strip_last(M), + package=packages:strip_last(M), parameters=As}; -attribute(module, Module, St) -> +attribute(module, Module, _L, St) -> M = package_to_string(Module), St#expand{module=list_to_atom(M), - package = packages:strip_last(M)}; -attribute(export, Es, St) -> + package=packages:strip_last(M)}; +attribute(export, Es, _L, St) -> St#expand{exports=union(from_list(Es), St#expand.exports)}; -attribute(import, Is, St) -> +attribute(import, Is, _L, St) -> import(Is, St); -attribute(compile, C, St) when is_list(C) -> +attribute(compile, C, _L, St) when is_list(C) -> St#expand{compile=St#expand.compile ++ C}; -attribute(compile, C, St) -> +attribute(compile, C, _L, St) -> St#expand{compile=St#expand.compile ++ [C]}; -attribute(Name, Val, St) when is_list(Val) -> - St#expand{attributes=St#expand.attributes ++ [{Name,Val}]}; -attribute(Name, Val, St) -> - St#expand{attributes=St#expand.attributes ++ [{Name,[Val]}]}. +attribute(Name, Val, Line, St) when is_list(Val) -> + St#expand{attributes=St#expand.attributes ++ [{Name,Line,Val}]}; +attribute(Name, Val, Line, St) -> + St#expand{attributes=St#expand.attributes ++ [{Name,Line,[Val]}]}. function(L, N, A, Cs0, St0) -> {Cs,St} = clauses(Cs0, St0#expand{func=N,arity=A,fcount=0}), @@ -299,10 +299,10 @@ pattern({match,Line,Pat1, Pat2}, St0) -> {TT,St2} = pattern(Pat1, St1), {{match,Line,TT,TH},St2}; %% Compile-time pattern expressions, including unary operators. -pattern({op,Line,Op,A}, St) -> - {erl_eval:partial_eval({op,Line,Op,A}),St}; -pattern({op,Line,Op,L,R}, St) -> - {erl_eval:partial_eval({op,Line,Op,L,R}),St}. +pattern({op,_Line,_Op,_A}=Op, St) -> + {erl_eval:partial_eval(Op),St}; +pattern({op,_Line,_Op,_L,_R}=Op, St) -> + {erl_eval:partial_eval(Op),St}. pattern_list([P0|Ps0], St0) -> {P,St1} = pattern(P0, St0), @@ -400,18 +400,18 @@ expr({'receive',Line,Cs0,To0,ToEs0}, St0) -> {{'receive',Line,Cs,To,ToEs},St3}; expr({'fun',Line,Body}, St) -> fun_tq(Line, Body, St); -expr({call,Line,{atom,La,N},As0}, St0) -> +expr({call,Line,{atom,La,N}=Atom,As0}, St0) -> {As,St1} = expr_list(As0, St0), Ar = length(As), case erl_internal:bif(N, Ar) of true -> - {{call,Line,{remote,La,{atom,La,erlang},{atom,La,N}},As},St1}; + {{call,Line,{remote,La,{atom,La,erlang},Atom},As},St1}; false -> case imported(N, Ar, St1) of {yes,Mod} -> - {{call,Line,{remote,La,{atom,La,Mod},{atom,La,N}},As},St1}; + {{call,Line,{remote,La,{atom,La,Mod},Atom},As},St1}; no -> - {{call,Line,{atom,La,N},As},St1} + {{call,Line,Atom,As},St1} end end; expr({call,Line,{record_field,_,_,_}=M,As0}, St0) -> diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index a39a3c538f..dfe15de4ff 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% Purpose : Transform normal Erlang to Core Erlang @@ -164,8 +164,8 @@ form({attribute,_,file,{File,_Line}}, {Fs,As,Es,Ws,_}, _Opts) -> form({attribute,_,_,_}=F, {Fs,As,Es,Ws,File}, _Opts) -> {Fs,[attribute(F)|As],Es,Ws,File}. -attribute({attribute,_,Name,Val}) -> - {#c_literal{val=Name},#c_literal{val=Val}}. +attribute({attribute,Line,Name,Val}) -> + {#c_literal{val=Name, anno=[Line]}, #c_literal{val=Val, anno=[Line]}}. function({function,_,Name,Arity,Cs0}, Es0, Ws0, File, Opts) -> %%ok = io:fwrite("~p - ", [{Name,Arity}]), diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl index 34609a49f2..a460d54239 100644 --- a/lib/compiler/test/andor_SUITE.erl +++ b/lib/compiler/test/andor_SUITE.erl @@ -20,13 +20,14 @@ -export([all/1, t_case/1,t_and_or/1,t_andalso/1,t_orelse/1,inside/1,overlap/1, - combined/1,in_case/1]). + combined/1,in_case/1,before_and_inside_if/1]). -include("test_server.hrl"). all(suite) -> test_lib:recompile(?MODULE), - [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case]. + [t_case,t_and_or,t_andalso,t_orelse,inside,overlap,combined,in_case, + before_and_inside_if]. t_case(Config) when is_list(Config) -> %% We test boolean cases almost but not quite like cases @@ -380,6 +381,65 @@ in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) -> false -> loop end. +before_and_inside_if(Config) when is_list(Config) -> + ?line no = before_and_inside_if([a], [b], delete), + ?line no = before_and_inside_if([a], [b], x), + ?line no = before_and_inside_if([a], [], delete), + ?line no = before_and_inside_if([a], [], x), + ?line no = before_and_inside_if([], [], delete), + ?line yes = before_and_inside_if([], [], x), + ?line yes = before_and_inside_if([], [b], delete), + ?line yes = before_and_inside_if([], [b], x), + + ?line {ch1,ch2} = before_and_inside_if_2([a], [b], blah), + ?line {ch1,ch2} = before_and_inside_if_2([a], [b], xx), + ?line {ch1,ch2} = before_and_inside_if_2([a], [], blah), + ?line {ch1,ch2} = before_and_inside_if_2([a], [], xx), + ?line {no,no} = before_and_inside_if_2([], [b], blah), + ?line {no,no} = before_and_inside_if_2([], [b], xx), + ?line {ch1,no} = before_and_inside_if_2([], [], blah), + ?line {no,ch2} = before_and_inside_if_2([], [], xx), + ok. + +%% Thanks to Simon Cornish and Kostis Sagonas. +%% Used to crash beam_bool. +before_and_inside_if(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + if + %% This expression occurs in a try/catch (protected) + %% block, which cannot refer to variables outside of + %% the block that are boolean expressions. + Do1 =:= true; + Do1 =:= false, Do2 =:= false, Do3 =:= delete -> + no; + true -> + yes + end. + +%% Thanks to Simon Cornish. +%% Used to generate code that would not set {y,0} on +%% all paths before its use (and therefore fail +%% validation by the beam_validator). +before_and_inside_if_2(XDo1, XDo2, Do3) -> + Do1 = (XDo1 =/= []), + Do2 = (XDo2 =/= []), + CH1 = if Do1 == true; + Do1 == false,Do2==false,Do3 == blah -> + ch1; + true -> + no + end, + CH2 = if Do1 == true; + Do1 == false,Do2==false,Do3 == xx -> + ch2; + true -> + no + end, + {CH1,CH2}. + +%% Utilities. + check(V1, V0) -> if V1 /= V0 -> io:fwrite("error: ~w.\n", [V1]), @@ -393,5 +453,3 @@ echo(X) -> X. id(I) -> I. - - diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index ef8feb8a27..74b5d7c7eb 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(beam_validator_SUITE). @@ -28,7 +28,7 @@ freg_range/1,freg_uninit/1,freg_state/1, bin_match/1,bin_aligned/1,bad_dsetel/1, state_after_fault_in_catch/1,no_exception_in_catch/1, - undef_label/1,illegal_instruction/1]). + undef_label/1,illegal_instruction/1,failing_gc_guard_bif/1]). -include("test_server.hrl"). @@ -52,13 +52,13 @@ all(suite) -> freg_range,freg_uninit,freg_state, bin_match,bin_aligned, bad_dsetel,state_after_fault_in_catch,no_exception_in_catch, - undef_label,illegal_instruction]. + undef_label,illegal_instruction,failing_gc_guard_bif]. beam_files(Config) when is_list(Config) -> ?line {ok,Cwd} = file:get_cwd(), ?line Parent = filename:dirname(Cwd), ?line Wc = filename:join([Parent,"*","*.beam"]), - %% Must have at least two files here, or there will could be + %% Must have at least two files here, or there will be %% a grammatical error in the output of the io:format/2 call below. ;-) ?line [_,_|_] = Fs = filelib:wildcard(Wc), ?line io:format("~p files\n", [length(Fs)]), @@ -356,6 +356,36 @@ illegal_instruction(Config) when is_list(Config) -> {{'_',y,0},{[],0,illegal_instruction}}] = Errors, ok. +%% The beam_validator used to assume that a GC guard BIF could +%% do a garbage collection even if it failed. That assumption +%% is not correct, and will cause the beam_validator to reject +%% valid programs such as this test case. +%% +%% (Thanks to Kiran Khaladkar.) +%% +failing_gc_guard_bif(Config) when is_list(Config) -> + ?line ok = process_request(lists:seq(1, 36)), + ?line error = process_request([]), + ?line error = process_request(not_a_list), + ok. + +process_request(ConfId) -> + case process_request_foo(ConfId) of + false -> + if + length(ConfId) == 36 -> + Response = ok; + true -> + Response = error + end + end, + process_request_bar(self(), [Response]). + +process_request_foo(_) -> + false. + +process_request_bar(Pid, [Response]) when is_pid(Pid) -> + Response. %%%------------------------------------------------------------------------- diff --git a/lib/compiler/test/compilation_SUITE_data/on_load.erl b/lib/compiler/test/compilation_SUITE_data/on_load.erl index 92bcf74624..e9b5ec7f34 100644 --- a/lib/compiler/test/compilation_SUITE_data/on_load.erl +++ b/lib/compiler/test/compilation_SUITE_data/on_load.erl @@ -12,7 +12,7 @@ do_on_load() -> local_function(), - true. + ok. local_function() -> ok. diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl index 477730c3ac..cdd2434b25 100644 --- a/lib/compiler/test/error_SUITE.erl +++ b/lib/compiler/test/error_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(error_SUITE). @@ -21,11 +21,11 @@ -include("test_server.hrl"). -export([all/1, - head_mismatch_line/1,r11b_binaries/1]). + head_mismatch_line/1,r11b_binaries/1,warnings_as_errors/1]). all(suite) -> test_lib:recompile(?MODULE), - [head_mismatch_line,r11b_binaries]. + [head_mismatch_line,r11b_binaries,warnings_as_errors]. %% Tests that a head mismatch is reported on the correct line (OTP-2125). head_mismatch_line(Config) when is_list(Config) -> @@ -73,6 +73,20 @@ r11b_binaries(Config) when is_list(Config) -> ?line [] = run(Config, Ts), ok. +warnings_as_errors(Config) when is_list(Config) -> + Ts = [{warnings_as_errors, + <<" + t() -> + A = unused, + ok. + ">>, + [warnings_as_errors], + {error, + [], + [{3,erl_lint,{unused_var,'A'}}]} }], + ?line [] = run(Config, Ts), + ok. + run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> @@ -104,6 +118,8 @@ run_test(Conf, Test0, Warnings) -> %% Test result of compilation. ?line Res = case compile:file(File, Opts) of {error,[{_File,Es}],Ws} -> + {error,Es,Ws}; + {error,Es,[{_File,Ws}]} -> {error,Es,Ws} end, file:delete(File), diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 72abcdde10..a5e6de7b5f 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 4.6.4 +COMPILER_VSN = 4.6.5 |