From 00ff3b3776a62402e7977fd9172a926ad62ea449 Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Thu, 23 Apr 2015 11:15:47 +0200 Subject: Fix a bug related to constraints generated for erlang:'*'/2 For Rst = A1 * A2, typesig for erlang:'*'/2 was constraining the arguments A1 and A2 in the 'reverse' direction by requiring that A2 is a subtype of Rst div A1, unless A1 is a hard zero. This is not correct: if for example both Rst and A1 are non_negative, such a constraint will first force A1 to be non-zero for the division to go through and then require A2 to be non_negative as non_negative div positive = non_negative, always (see commited test). In the fixed version, we are not constraining an argument if the other operand *may* be zero. --- lib/dialyzer/src/dialyzer_typesig.erl | 8 ++++---- lib/dialyzer/test/small_SUITE_data/src/inv_mult.erl | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/src/inv_mult.erl (limited to 'lib/dialyzer') diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 1737bfd3a9..6c14860d7d 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -1579,11 +1579,11 @@ get_bif_constr({M, F, A} = _BIF, Dst, Args, _State) -> eval_inv_arith('+', _Pos, Dst, Arg) -> bif_return(erlang, '-', 2, [Dst, Arg]); eval_inv_arith('*', _Pos, Dst, Arg) -> - case t_number_vals(Arg) of - [0] -> t_integer(); - _ -> + Zero = t_from_term(0), + case t_is_none(t_inf(Arg, Zero)) of + false -> t_integer(); + true -> TmpRet = bif_return(erlang, 'div', 2, [Dst, Arg]), - Zero = t_from_term(0), %% If 0 is not part of the result, it cannot be part of the argument. case t_is_subtype(Zero, Dst) of false -> t_subtract(TmpRet, Zero); diff --git a/lib/dialyzer/test/small_SUITE_data/src/inv_mult.erl b/lib/dialyzer/test/small_SUITE_data/src/inv_mult.erl new file mode 100644 index 0000000000..3413556813 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/inv_mult.erl @@ -0,0 +1,15 @@ +%% Dialyzer was too constraining when checking the relation between the +%% arguments and result of a multiplication. We should not constrain an argument +%% if the other operand *may* be zero. +%% +%% Bug found by Kostis Sagonas, fixed by Stavros Aronis + +-module(inv_mult). +-compile(export_all). + +main(L) -> + N = -1 * length(L), + fact(N). + +fact(0) -> 1; +fact(N) -> N * fact(N-1). -- cgit v1.2.3 From e09dd66dc4d89c62ddfd8c19791f9678d5d787c6 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 12 May 2015 18:18:55 +0200 Subject: Prepare release --- lib/dialyzer/doc/src/notes.xml | 86 ++++++++++++++++++++++++++++++++++++++++++ lib/dialyzer/vsn.mk | 2 +- 2 files changed, 87 insertions(+), 1 deletion(-) (limited to 'lib/dialyzer') diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 8976679c1d..d30882b5b9 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -31,6 +31,92 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 2.8 + +
Fixed Bugs and Malfunctions + + +

The translation of Erlang forms to the type + representation used by Dialyzer has been improved in + several ways. The most important change is that deeply + nested records can be handled.

+

+ Own Id: OTP-12350

+
+ +

Update the PLT properly when a module is changed. + (Thanks to James Fish for the bug report, and to Stavros + Aronis for fixing the bug.)

+

+ Own Id: OTP-12637

+
+ +

+ An argument of '*'/2 is not constraind if the other + operand can be zero.

+

+ Own Id: OTP-12725

+
+
+
+ + +
Improvements and New Features + + +

The -dialyzer() attribute can be used for + suppressing warnings in a module by specifying functions + or warning options. It can also be used for requesting + warnings in a module.

+

+ Own Id: OTP-10280

+
+ +

The pre-defined types array(), dict(), + digraph(), gb_set(), gb_tree(), + queue(), set(), and tid() have been + removed.

+

+ Own Id: OTP-11445 Aux Id: OTP-10342, OTP-9352

+
+ +

A few type names that have been used for representing + certain predefined types can now be used for user-defined + types. This affects the types product/_, + union/_, and range/2 as well as + tuple/N (N > 0), map/N (N > 0), + atom/1, integer/1, binary/2, + record/_, and 'fun'/_. A consequence is + that, for example, it is no longer possible to refer to a + record type with record(r); instead the usual + record notation, #r{}, is to be used.

+

+ *** POTENTIAL INCOMPATIBILITY ***

+

+ Own Id: OTP-11851

+
+ +

When implementing user-defined behaviours it is now + possible to specify optional callback functions. See OTP + Design Principles User's Guide, Sys and Proc_Lib, + User-Defined Behaviours, for details.

+

+ Own Id: OTP-11861

+
+ +

Add two options to the Dialyzer: + no_missing_calls suppresses warnings about calls + to missing or unexported functions; unknown lets + warnings about unknown functions or types affect the exit + status. See also dialyzer(3).

+

+ Own Id: OTP-12682

+
+
+
+ +
+
Dialyzer 2.7.4
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 527afaf4ef..48e0830109 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.7.4 +DIALYZER_VSN = 2.8 -- cgit v1.2.3 From 9a81b28598fadc44bf506354c9227e41aac786f6 Mon Sep 17 00:00:00 2001 From: Henrik Nord Date: Wed, 13 May 2015 09:40:16 +0200 Subject: Revert "Prepare release" This reverts commit e09dd66dc4d89c62ddfd8c19791f9678d5d787c6. --- lib/dialyzer/doc/src/notes.xml | 86 ------------------------------------------ lib/dialyzer/vsn.mk | 2 +- 2 files changed, 1 insertion(+), 87 deletions(-) (limited to 'lib/dialyzer') diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index d30882b5b9..8976679c1d 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -31,92 +31,6 @@

This document describes the changes made to the Dialyzer application.

-
Dialyzer 2.8 - -
Fixed Bugs and Malfunctions - - -

The translation of Erlang forms to the type - representation used by Dialyzer has been improved in - several ways. The most important change is that deeply - nested records can be handled.

-

- Own Id: OTP-12350

-
- -

Update the PLT properly when a module is changed. - (Thanks to James Fish for the bug report, and to Stavros - Aronis for fixing the bug.)

-

- Own Id: OTP-12637

-
- -

- An argument of '*'/2 is not constraind if the other - operand can be zero.

-

- Own Id: OTP-12725

-
-
-
- - -
Improvements and New Features - - -

The -dialyzer() attribute can be used for - suppressing warnings in a module by specifying functions - or warning options. It can also be used for requesting - warnings in a module.

-

- Own Id: OTP-10280

-
- -

The pre-defined types array(), dict(), - digraph(), gb_set(), gb_tree(), - queue(), set(), and tid() have been - removed.

-

- Own Id: OTP-11445 Aux Id: OTP-10342, OTP-9352

-
- -

A few type names that have been used for representing - certain predefined types can now be used for user-defined - types. This affects the types product/_, - union/_, and range/2 as well as - tuple/N (N > 0), map/N (N > 0), - atom/1, integer/1, binary/2, - record/_, and 'fun'/_. A consequence is - that, for example, it is no longer possible to refer to a - record type with record(r); instead the usual - record notation, #r{}, is to be used.

-

- *** POTENTIAL INCOMPATIBILITY ***

-

- Own Id: OTP-11851

-
- -

When implementing user-defined behaviours it is now - possible to specify optional callback functions. See OTP - Design Principles User's Guide, Sys and Proc_Lib, - User-Defined Behaviours, for details.

-

- Own Id: OTP-11861

-
- -

Add two options to the Dialyzer: - no_missing_calls suppresses warnings about calls - to missing or unexported functions; unknown lets - warnings about unknown functions or types affect the exit - status. See also dialyzer(3).

-

- Own Id: OTP-12682

-
-
-
- -
-
Dialyzer 2.7.4
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 48e0830109..527afaf4ef 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.8 +DIALYZER_VSN = 2.7.4 -- cgit v1.2.3 From d1851f267d96e41a0dc8f2d123ec5e5fef514518 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 19 May 2015 12:58:23 +0200 Subject: dialyzer: Document dialyzer:gui() option 'check_plt' * Mention the option 'check_plt' among gui() options. * No longer check a PLT twice when the analysis type is 'plt_check'. * No longer raise a case_clause error when checking a PLT finds warnings. Thanks to James Fish. --- lib/dialyzer/doc/src/dialyzer.xml | 1 + lib/dialyzer/src/dialyzer.erl | 39 +++++++++--------- lib/dialyzer/test/plt_SUITE.erl | 85 +++++++++++++++++++++++++++++++++++---- 3 files changed, 97 insertions(+), 28 deletions(-) (limited to 'lib/dialyzer') diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml index 2a8bf6edcc..5f52906625 100644 --- a/lib/dialyzer/doc/src/dialyzer.xml +++ b/lib/dialyzer/doc/src/dialyzer.xml @@ -368,6 +368,7 @@ Option :: {files, [Filename :: string()]} | {include_dirs, [DirName :: string()]} | {output_file, FileName :: string()} | {output_plt, FileName :: string()} + | {check_plt, boolean()}, | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index c9e7da9ef0..c8537e3bd8 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2014. All Rights Reserved. +%% Copyright Ericsson AB 2006-2015. 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 @@ -162,14 +162,7 @@ run(Opts) -> {error, Msg} -> throw({dialyzer_error, Msg}); OptsRecord -> - case OptsRecord#options.check_plt of - true -> - case cl_check_init(OptsRecord) of - {ok, ?RET_NOTHING_SUSPICIOUS} -> ok; - {error, ErrorMsg1} -> throw({dialyzer_error, ErrorMsg1}) - end; - false -> ok - end, + ok = check_init(OptsRecord), case dialyzer_cl:start(OptsRecord) of {?RET_DISCREPANCIES, Warnings} -> Warnings; {?RET_NOTHING_SUSPICIOUS, _} -> [] @@ -179,6 +172,16 @@ run(Opts) -> erlang:error({dialyzer_error, lists:flatten(ErrorMsg)}) end. +check_init(#options{analysis_type = plt_check}) -> + ok; +check_init(#options{check_plt = true} = OptsRecord) -> + case cl_check_init(OptsRecord) of + {ok, _} -> ok; + {error, Msg} -> throw({dialyzer_error, Msg}) + end; +check_init(#options{check_plt = false}) -> + ok. + internal_gui(OptsRecord) -> F = fun() -> dialyzer_gui_wx:start(OptsRecord), @@ -199,17 +202,13 @@ gui(Opts) -> throw({dialyzer_error, Msg}); OptsRecord -> ok = check_gui_options(OptsRecord), - case cl_check_init(OptsRecord) of - {ok, ?RET_NOTHING_SUSPICIOUS} -> - F = fun() -> - dialyzer_gui_wx:start(OptsRecord) - end, - case doit(F) of - {ok, _} -> ok; - {error, Msg} -> throw({dialyzer_error, Msg}) - end; - {error, ErrorMsg1} -> - throw({dialyzer_error, ErrorMsg1}) + ok = check_init(OptsRecord), + F = fun() -> + dialyzer_gui_wx:start(OptsRecord) + end, + case doit(F) of + {ok, _} -> ok; + {error, Msg} -> throw({dialyzer_error, Msg}) end catch throw:{dialyzer_error, ErrorMsg} -> diff --git a/lib/dialyzer/test/plt_SUITE.erl b/lib/dialyzer/test/plt_SUITE.erl index ef4cdc57f0..ecbac14e5d 100644 --- a/lib/dialyzer/test/plt_SUITE.erl +++ b/lib/dialyzer/test/plt_SUITE.erl @@ -6,12 +6,13 @@ -include_lib("common_test/include/ct.hrl"). -include("dialyzer_test_constants.hrl"). --export([suite/0, all/0, build_plt/1, beam_tests/1, update_plt/1]). +-export([suite/0, all/0, build_plt/1, beam_tests/1, update_plt/1, + run_plt_check/1, run_succ_typings/1]). suite() -> [{timetrap, ?plt_timeout}]. -all() -> [build_plt, beam_tests, update_plt]. +all() -> [build_plt, beam_tests, update_plt, run_plt_check, run_succ_typings]. build_plt(Config) -> OutDir = ?config(priv_dir, Config), @@ -37,14 +38,76 @@ beam_tests(Config) when is_list(Config) -> ">>, Opts = [no_auto_import], {ok, BeamFile} = compile(Config, Prog, no_auto_import, Opts), - [] = run_dialyzer([BeamFile]), + [] = run_dialyzer(plt_build, [BeamFile], []), ok. -run_dialyzer(Files) -> - dialyzer:run([{analysis_type, plt_build}, - {files, Files}, - {from, byte_code}, - {check_plt, false}]). +run_plt_check(Config) when is_list(Config) -> + Mod1 = <<" + -module(run_plt_check1). + ">>, + + Mod2A = <<" + -module(run_plt_check2). + ">>, + + {ok, BeamFile1} = compile(Config, Mod1, run_plt_check1, []), + {ok, BeamFile2} = compile(Config, Mod2A, run_plt_check2, []), + [] = run_dialyzer(plt_build, [BeamFile1, BeamFile2], []), + + Mod2B = <<" + -module(run_plt_check2). + + -export([call/1]). + + call(X) -> run_plt_check1:call(X). + ">>, + + {ok, BeamFile2} = compile(Config, Mod2B, run_plt_check2, []), + + % callgraph warning as run_plt_check2:call/1 makes a call to unexported + % function run_plt_check1:call/1. + [_] = run_dialyzer(plt_check, [], []), + + ok. + +run_succ_typings(Config) when is_list(Config) -> + Mod1A = <<" + -module(run_succ_typings1). + + -export([call/0]). + + call() -> a. + ">>, + + {ok, BeamFile1} = compile(Config, Mod1A, run_succ_typings1, []), + [] = run_dialyzer(plt_build, [BeamFile1], []), + + Mod1B = <<" + -module(run_succ_typings1). + + -export([call/0]). + + call() -> b. + ">>, + + Mod2 = <<" + -module(run_succ_typings2). + + -export([call/0]). + + -spec call() -> b. + call() -> run_succ_typings1:call(). + ">>, + + {ok, BeamFile1} = compile(Config, Mod1B, run_succ_typings1, []), + {ok, BeamFile2} = compile(Config, Mod2, run_succ_typings2, []), + % contract types warning as run_succ_typings2:call/0 makes a call to + % run_succ_typings1:call/0, which returns a (not b) in the PLT. + [_] = run_dialyzer(succ_typings, [BeamFile2], [{check_plt, false}]), + % warning not returned as run_succ_typings1 is updated in the PLT. + [] = run_dialyzer(succ_typings, [BeamFile2], [{check_plt, true}]), + + ok. %%% [James Fish:] %%% If a function is removed from a module and the module has previously @@ -103,3 +166,9 @@ compile(Config, Prog, Module, CompileOpts) -> Opts = [{outdir, PrivDir}, debug_info | CompileOpts], {ok, Module} = compile:file(Filename, Opts), {ok, filename:join([PrivDir, lists:concat([Module, ".beam"])])}. + +run_dialyzer(Analysis, Files, Opts) -> + dialyzer:run([{analysis_type, Analysis}, + {files, Files}, + {from, byte_code} | + Opts]). -- cgit v1.2.3