aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL-WIN32.md78
-rw-r--r--bootstrap/bin/start.script2
-rw-r--r--bootstrap/bin/start_clean.script2
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin12776 -> 12848 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin18036 -> 18176 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.beambin3556 -> 3596 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin48304 -> 48440 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v8.beambin25116 -> 25132 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin45764 -> 45776 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin21908 -> 22132 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin76924 -> 77048 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin18124 -> 18312 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ordsets.beambin1808 -> 1844 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/string.beambin4324 -> 4328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin14528 -> 14544 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin10808 -> 10848 bytes
-rw-r--r--erts/include/internal/ethr_mutex.h19
-rw-r--r--erts/lib_src/common/ethr_mutex.c25
-rw-r--r--lib/asn1/src/asn1rt_driver_handler.erl5
-rw-r--r--lib/common_test/test/ct_test_support.erl30
-rw-r--r--lib/compiler/src/beam_utils.erl36
-rw-r--r--lib/compiler/test/compilation_SUITE.erl44
-rw-r--r--lib/dialyzer/doc/manual.txt12
-rw-r--r--lib/dialyzer/src/dialyzer.erl20
-rw-r--r--lib/dialyzer/src/dialyzer.hrl2
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl120
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl44
-rw-r--r--lib/dialyzer/src/dialyzer_gui.erl14
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl14
-rw-r--r--lib/dialyzer/src/dialyzer_options.erl19
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl65
-rw-r--r--lib/kernel/test/file_SUITE.erl17
-rw-r--r--lib/mnesia/src/mnesia.appup.src6
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/odbc/src/odbc.appup.src9
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/public_key/src/public_key.appup.src12
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/ssl/src/ssl.appup.src2
-rw-r--r--lib/ssl/vsn.mk2
40 files changed, 475 insertions, 130 deletions
diff --git a/INSTALL-WIN32.md b/INSTALL-WIN32.md
index 6481ca1b06..59b9086c39 100644
--- a/INSTALL-WIN32.md
+++ b/INSTALL-WIN32.md
@@ -92,7 +92,9 @@ Frequently Asked Questions
A: The SMP version of Erlang needs features in the Visual Studio 2005.
Can't live without them. Besides the new compiler gives the Erlang
- emulator a ~40% performance boost(!)
+ emulator a ~40% performance boost(!). Alternatively you can build Erlang
+ successfully using the free (proprietary) Visual Studio 2008 Express
+ edition C++ compiler.
* Q: Can/will I build a Cygwin binary with the procedure you describe?
@@ -208,20 +210,15 @@ Frequently Asked Questions
* (Buy and) Install Microsoft Visual studio 2005 and SP1 (or higher)
- * Get and install Sun's JDK 1.4.2
+ * Alternatively install the free MS Visual Studio 2008 Express [msvc++]
+ and the Windows SDK [32bit-SDK] or [64bit-SDK] depending on the Windows
+ platform you are running.
- * Get and install NSIS 2.01 or higher (up to 2.30 tried and working)
+ * Get and install Sun's JDK 1.4.2
- * Get and install OpenSSL 0.9.7c or higher
+ * Get and install NSIS 2.01 or higher (up to 2.46 tried and working)
- * Get and unpack wxWidgets-2.8.9 or higher to `/opt/local/pgm` inside
- cygwin.
- * Open `/cygwin/opt/local/pgm/wxWidgets-2.8.9/build/msw/wx.dsw`
- * Enable `wxUSE_GLCANVAS`, `wxUSE_POSTSCRIPT` and
- `wxUSE_GRAPHICS_CONTEXT` in `include/wx/msw/setup.h`
- * Build all unicode release (and unicode debug) packages
- * Open `/cygwin/opt/local/pgm/wxWidgets-2.8.9/contrib/build/stc/stc.dsw`
- * Build the unicode release (and unicode debug) packages
+ * Get and install OpenSSL 0.9.7c or higher (up to 1.0.0a tried & working)
* Get the Erlang source distribution (from
<http://www.erlang.org/download.html>) and unpack with Cygwin's `tar`.
@@ -363,6 +360,15 @@ Well' here's the list:
your `PATH` to allow the environment to find mc.exe. The next Visual Studio
(2010) is expected to include this tool.
+ Alternatively install the free MS Visual Studio 2008 Express [msvc++] and
+ the Windows SDK [32bit-SDK] or [64bit-SDK] depending on the Windows
+ platform you are running, which includes the missing mc.exe message
+ compiler.
+
+[msvc++]: http://download.microsoft.com/download/E/8/E/E8EEB394-7F42-4963-A2D8-29559B738298/VS2008ExpressWithSP1ENUX1504728.iso
+[32bit-SDK]: http://download.microsoft.com/download/2/E/9/2E911956-F90F-4BFB-8231-E292A7B6F287/GRMSDK_EN_DVD.iso
+[64bit-SDK]: http://download.microsoft.com/download/2/E/9/2E911956-F90F-4BFB-8231-E292A7B6F287/GRMSDKX_EN_DVD.iso
+
* Sun's Java JDK 1.5.0 or higher. Our Java code (jinterface, ic) is
written for JDK 1.5.0. Get it for Windows and install it, the JRE is
not enough. If you don't care about Java, you can skip this step, the
@@ -401,9 +407,10 @@ Well' here's the list:
on the `Related` link and then on the `Binaries` link (upper right
corner of the page last time I looked), you can then reach the
"Shining Lights Productions" Web site for Windows binaries
- distributions. Get the latest or 0.9.7c if you get trouble with the
- latest. It's a nifty installer. The rest should be handled by
- `configure`, you needn't put anything in the path or anything.
+ distributions. Get the latest 32-bit installer, or use 0.9.7c if you get
+ trouble with the latest, and install to C:\OpenSSL which is where the
+ Makefiles are expecting to find it. It's a nifty installer. The rest should
+ be handled by `configure`, you needn't put anything in the path or anything.
If you want to build openssl for windows yourself (which might be
possible, as you wouldn't be reading this if you weren't a
@@ -422,18 +429,51 @@ Well' here's the list:
release (2.9.\* is a developer release which currently does not work
with wxErlang).
- Install or unpack it to `DRIVE:/PATH/cygwin/opt/local/pgm`
+ Install or unpack it to `DRIVE:/PATH/cygwin/opt/local/pgm`.
Open from explorer (i.e. by double clicking the file)
- `C:\cygwin\opt\local\pgm\wxMSW-2.8.10\build\msw\wx.dsw`
+ `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\build\msw\wx.dsw`
In Microsoft Visual Studio, click File/Open/File, locate and
- open: `C:\cygwin\opt\local\pgm\wxMSW-2.8.10\include\wx\msw\setup.h`
+ open: `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\include\wx\msw\setup.h`
enable `wxUSE_GLCANVAS`, `wxUSE_POSTSCRIPT` and `wxUSE_GRAPHICS_CONTEXT`
Build it by clicking Build/Batch Build and select all unicode release
(and unicode debug) packages.
- Open `C:\cygwin\opt\local\pgm\wxMSW-2.8.10\contrib/build/stc/stc.dsw`
+ Open `C:\cygwin\opt\local\pgm\wxMSW-2.8.11\contrib/build/stc/stc.dsw`
and batch build all unicode packages.
+ If you are using Visual C++ 9.0 or higher (Visual Studio 2008 onwards) you
+ will also need to convert and re-create the project dependencies in the new
+ .sln "Solution" format.
+
+ * Open VSC++ & the project `wxMSW-2.8.11\build\msw\wx.dsw`, accepting the
+ automatic conversion to the newer VC++ format and save as
+ `\wxMSW-2.8.11\build\msw\wx.sln`
+
+ * right-click on the project, and set up the project dependencies for
+ `wx.dsw` to achieve the below build order
+
+ jpeg, png, tiff, zlib, regex, expat, base, net, odbc, core,
+ gl, html, media, qa, adv, dbgrid, xrc, aui, richtext, xml
+
+ Build all unicode release (and unicode debug) packages either from the
+ GUI or alternatively launch a new prompt from somewhere like Start ->
+ Programs -> Microsoft Visual C++ -> Visual Studio Tools -> VS2008 Cmd Prompt
+ and cd to where you unpacked wxMSW
+
+ pushd c:\wxMSW*\build\msw
+ vcbuild /useenv /platform:Win32 /M4 wx.sln "Unicode Release|Win32"
+ vcbuild /useenv /platform:Win32 /M4 wx.sln "Unicode Debug|Win32"
+
+ Open VSC++ & convert `C:\wxMSW-2.8.11\contrib\build\stc\stc.dsw` to
+ `C:\wxMSW-2.8.11\contrib\build\stc\stc.sln`
+
+ * build the unicode release (and unicode debug) packages from the GUI or
+ alternatively open a VS2008 Cmd Prompt and cd to where you unpacked wxMSW
+
+ pushd c:\wxMSW*\contrib\build\stc
+ vcbuild /useenv /platform:Win32 /M4 stc.sln "Unicode Release|Win32"
+ vcbuild /useenv /platform:Win32 /M4 stc.sln "Unicode Debug|Win32"
+
* The Erlang source distribution (from <http://www.erlang.org/download.html>).
The same as for Unix platforms. Preferably use tar from within Cygwin to
unpack the source tar.gz (`tar zxf otp_src_%OTP-REL%.tar.gz`).
diff --git a/bootstrap/bin/start.script b/bootstrap/bin/start.script
index 3f472b5e8c..6ca908f22e 100644
--- a/bootstrap/bin/start.script
+++ b/bootstrap/bin/start.script
@@ -1,4 +1,4 @@
-%% script generated at {2010,10,18} {14,19,26}
+%% script generated at {2010,12,2} {17,24,15}
{script,
{"OTP APN 181 01","R14B01"},
[{preLoaded,
diff --git a/bootstrap/bin/start_clean.script b/bootstrap/bin/start_clean.script
index 3f472b5e8c..6d3a393d56 100644
--- a/bootstrap/bin/start_clean.script
+++ b/bootstrap/bin/start_clean.script
@@ -1,4 +1,4 @@
-%% script generated at {2010,10,18} {14,19,26}
+%% script generated at {2010,12,2} {17,24,16}
{script,
{"OTP APN 181 01","R14B01"},
[{preLoaded,
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index 7b9c08439e..c335748e8a 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index 63088b2e1b..622110bcdb 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel.beam b/bootstrap/lib/kernel/ebin/kernel.beam
index 471ab154e8..e1db5986dc 100644
--- a/bootstrap/lib/kernel/ebin/kernel.beam
+++ b/bootstrap/lib/kernel/ebin/kernel.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index 3e133f4ff2..4b6e3756e9 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v8.beam b/bootstrap/lib/stdlib/ebin/dets_v8.beam
index 2ad134d371..968b9bcb28 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v8.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v8.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 2eabd08ed4..355c5819cf 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 8115d9c474..0483b561d4 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 5ebd228586..9b54fff03b 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index 6b25af9b1b..9ade9e2edd 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ordsets.beam b/bootstrap/lib/stdlib/ebin/ordsets.beam
index c3f2c3b7b1..48effb764e 100644
--- a/bootstrap/lib/stdlib/ebin/ordsets.beam
+++ b/bootstrap/lib/stdlib/ebin/ordsets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index 3c3eaf6ed2..0de0b44cb8 100644
--- a/bootstrap/lib/stdlib/ebin/string.beam
+++ b/bootstrap/lib/stdlib/ebin/string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index a9e30b4d5d..13cb6032a9 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 4ca769b9a2..cc3a3c1859 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index 636fdc1e2f..01855864e3 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -95,6 +95,19 @@
#define ETHR_CND_WAIT_FLG__ ETHR_RWMTX_R_WAIT_FLG__
+#ifdef ETHR_DEBUG
+#define ETHR_DBG_CHK_UNUSED_FLG_BITS(V) \
+ ETHR_ASSERT(!((V) & ~(ETHR_RWMTX_W_FLG__ \
+ | ETHR_RWMTX_W_WAIT_FLG__ \
+ | ETHR_RWMTX_R_WAIT_FLG__ \
+ | ETHR_RWMTX_RS_MASK__)))
+#else
+#define ETHR_DBG_CHK_UNUSED_FLG_BITS(V)
+#endif
+
+#define ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(MTX) \
+ ETHR_DBG_CHK_UNUSED_FLG_BITS(ethr_atomic_read(&(MTX)->mtxb.flgs))
+
struct ethr_mutex_base_ {
#ifdef ETHR_MTX_HARD_DEBUG_FENCE
long pre_fence;
@@ -497,6 +510,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
long act;
int res;
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
act = ethr_atomic_cmpxchg_acqb(&mtx->mtxb.flgs, ETHR_RWMTX_W_FLG__, 0);
res = (act == 0) ? 0 : EBUSY;
@@ -508,6 +522,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_trylock)(ethr_mutex *mtx)
ETHR_MTX_HARD_DEBUG_LFS_TRYRWLOCK(&mtx->mtxb, res);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
ETHR_COMPILER_BARRIER;
return res;
@@ -518,6 +533,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
{
long act;
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
act = ethr_atomic_cmpxchg_acqb(&mtx->mtxb.flgs, ETHR_RWMTX_W_FLG__, 0);
if (act != 0)
@@ -527,6 +543,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_lock)(ethr_mutex *mtx)
ETHR_MTX_HARD_DEBUG_LFS_RWLOCK(&mtx->mtxb);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
ETHR_COMPILER_BARRIER;
}
@@ -538,6 +555,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
ETHR_COMPILER_BARRIER;
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
ETHR_MTX_HARD_DEBUG_LFS_RWUNLOCK(&mtx->mtxb);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
ETHR_MTX_CHK_EXCL_UNSET_EXCL(&mtx->mtxb);
@@ -546,6 +564,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
ethr_mutex_unlock_wake__(mtx, act);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(mtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(mtx);
}
#endif /* ETHR_TRY_INLINE_FUNCS */
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index c5738c3d77..95fedc0ba2 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -270,6 +270,8 @@ rwmutex_freqread_rdrs_inc(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
}
}
+#if 0 /* Not used */
+
static ETHR_INLINE void
rwmutex_freqread_rdrs_dec(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
{
@@ -289,6 +291,8 @@ rwmutex_freqread_rdrs_dec(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
}
}
+#endif
+
static ETHR_INLINE long
rwmutex_freqread_rdrs_dec_read(ethr_rwmutex *rwmtx, ethr_ts_event *tse)
{
@@ -1908,7 +1912,7 @@ rwmutex_freqread_rwlock_wait(ethr_rwmutex *rwmtx, long initial)
}
static ETHR_INLINE void
-rwlock_wake_set_flags(ethr_rwmutex *rwmtx, long new_initial, int act_initial)
+rwlock_wake_set_flags(ethr_rwmutex *rwmtx, long new_initial, long act_initial)
{
long act, act_mask;
int chk_abrt_flg;
@@ -2315,6 +2319,7 @@ ethr_rwmutex_destroy(ethr_rwmutex *rwmtx)
return EINVAL;
}
#endif
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
if (rwmtx->type != ETHR_RWMUTEX_TYPE_NORMAL) {
long act = ethr_atomic_read(&rwmtx->mtxb.flgs);
if (act == ETHR_RWMTX_R_FLG__)
@@ -2345,6 +2350,8 @@ ethr_rwmutex_tryrlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL: {
#ifdef ETHR_RLOCK_WITH_INC_DEC
@@ -2399,6 +2406,7 @@ ethr_rwmutex_tryrlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_LFS_TRYRLOCK(&rwmtx->mtxb, res);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
return res;
}
@@ -2413,6 +2421,8 @@ ethr_rwmutex_rlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL: {
#ifdef ETHR_RLOCK_WITH_INC_DEC
@@ -2446,6 +2456,7 @@ ethr_rwmutex_rlock(ethr_rwmutex *rwmtx)
}
}
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
ETHR_MTX_CHK_EXCL_SET_NON_EXCL(&rwmtx->mtxb);
ETHR_MTX_CHK_EXCL_IS_NOT_EXCL(&rwmtx->mtxb);
ETHR_MTX_HARD_DEBUG_LFS_RLOCK(&rwmtx->mtxb);
@@ -2466,6 +2477,8 @@ ethr_rwmutex_runlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
ETHR_MTX_HARD_DEBUG_LFS_RUNLOCK(&rwmtx->mtxb);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL:
act = ethr_atomic_dec_read_relb(&rwmtx->mtxb.flgs);
@@ -2497,6 +2510,7 @@ ethr_rwmutex_runlock(ethr_rwmutex *rwmtx)
}
}
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
}
@@ -2512,6 +2526,8 @@ ethr_rwmutex_tryrwlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL:
act = ethr_atomic_cmpxchg_acqb(&rwmtx->mtxb.flgs,
@@ -2553,6 +2569,7 @@ ethr_rwmutex_tryrwlock(ethr_rwmutex *rwmtx)
}
#endif
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
ETHR_MTX_HARD_DEBUG_LFS_TRYRWLOCK(&rwmtx->mtxb, res);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
@@ -2569,6 +2586,8 @@ ethr_rwmutex_rwlock(ethr_rwmutex *rwmtx)
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL:
act = ethr_atomic_cmpxchg_acqb(&rwmtx->mtxb.flgs,
@@ -2601,6 +2620,7 @@ ethr_rwmutex_rwlock(ethr_rwmutex *rwmtx)
ETHR_MTX_CHK_EXCL_IS_NOT_NON_EXCL(&rwmtx->mtxb);
ETHR_MTX_HARD_DEBUG_LFS_RWLOCK(&rwmtx->mtxb);
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
}
@@ -2618,6 +2638,8 @@ ethr_rwmutex_rwunlock(ethr_rwmutex *rwmtx)
ETHR_MTX_CHK_EXCL_IS_NOT_NON_EXCL(&rwmtx->mtxb);
ETHR_MTX_CHK_EXCL_UNSET_EXCL(&rwmtx->mtxb);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
+
switch (rwmtx->type) {
case ETHR_RWMUTEX_TYPE_NORMAL:
act = ethr_atomic_cmpxchg_relb(&rwmtx->mtxb.flgs,
@@ -2636,6 +2658,7 @@ ethr_rwmutex_rwunlock(ethr_rwmutex *rwmtx)
}
ETHR_MTX_HARD_DEBUG_FENCE_CHK(rwmtx);
+ ETHR_MTX_DBG_CHK_UNUSED_FLG_BITS(rwmtx);
}
#else
diff --git a/lib/asn1/src/asn1rt_driver_handler.erl b/lib/asn1/src/asn1rt_driver_handler.erl
index c95b243ae0..cc2b501e16 100644
--- a/lib/asn1/src/asn1rt_driver_handler.erl
+++ b/lib/asn1/src/asn1rt_driver_handler.erl
@@ -71,7 +71,10 @@ load_driver(Reason) ->
end.
init(FromPid,FromRef) ->
- register(asn1_driver_owner,self()),
+ case catch register(asn1_driver_owner,self()) of
+ true -> true;
+ _Other -> exit(normal)
+ end,
Dir = filename:join([code:priv_dir(asn1),"lib"]),
case catch erl_ddll:load_driver(Dir,asn1_erl_drv) of
ok ->
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 5b9d3d79c3..5e9792f02c 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -361,13 +361,33 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
case Evs of
[{TEH,#event{name=tc_start,
node=Node,
- data={M,{init_per_group,GroupName,Props}}}},
- {TEH,#event{name=tc_done,
- node=Node,
- data={M,{init_per_group,GroupName,Props},R}}} | Es] ->
+ data={M,{init_per_group,
+ GroupName,Props}}}}|Es] ->
+ %% Use dropwhile here as a tc_done from a
+ %% previous testcase might sneak in here
+ EvsG = lists:dropwhile(
+ fun({EH,#event{name=tc_done,
+ node=EvNode,
+ data={EvM,{init_per_group,
+ EvGroupName,
+ EvProps},EvR}}})
+ when TEH == EH, EvNode == Node, EvM == M,
+ EvGroupName == GroupName,
+ EvProps == Props,
+ EvR == R ->
+ false;
+ ({EH,#event{name=stop_logging,
+ node=EvNode,data=_}})
+ when EH == TEH, EvNode == Node ->
+ exit({group_init_done_not_found,
+ GroupName,Props});
+ (_) ->
+ true
+ end, Es),
+
test_server:format("Found ~p!", [InitStart]),
test_server:format("Found ~p!", [InitDone]),
- {TEs,Es};
+ {TEs,EvsG};
_ ->
nomatch
end;
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 761d4ffec0..45cdf8a659 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -407,16 +407,23 @@ check_liveness(R, [{bif,Op,{f,Fail},Ss,D}|Is], St0) ->
Other ->
Other
end;
-check_liveness(R, [{gc_bif,Op,{f,Fail},_,Ss,D}|Is], St0) ->
- case check_liveness_fail(R, Op, Ss, Fail, St0) of
- {killed,St} = Killed ->
- case member(R, Ss) of
- true -> {used,St};
- false when R =:= D -> Killed;
- false -> check_liveness(R, Is, St)
- end;
- Other ->
- Other
+check_liveness(R, [{gc_bif,Op,{f,Fail},Live,Ss,D}|Is], St0) ->
+ case R of
+ {x,X} when X >= Live ->
+ {killed,St0};
+ {x,_} ->
+ {used,St0};
+ _ ->
+ case check_liveness_fail(R, Op, Ss, Fail, St0) of
+ {killed,St}=Killed ->
+ case member(R, Ss) of
+ true -> {used,St};
+ false when R =:= D -> Killed;
+ false -> check_liveness(R, Is, St)
+ end;
+ Other ->
+ Other
+ end
end;
check_liveness(R, [{bs_add,{f,0},Ss,D}|Is], St) ->
case member(R, Ss) of
@@ -482,10 +489,13 @@ check_liveness(R, [{bs_context_to_binary,S}|Is], St) ->
S -> {used,St};
_ -> check_liveness(R, Is, St)
end;
-check_liveness(R, [{loop_rec,{f,_},{x,0}}|Is], St) ->
+check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) ->
case R of
- {x,_} -> {killed,St};
- _ -> check_liveness(R, Is, St)
+ {x,_} ->
+ {killed,St};
+ _ ->
+ %% y register. Rarely happens. Be very conversative.
+ {unknown,St}
end;
check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) ->
check_liveness_at(R, Fail, St);
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index 9c06740816..935e384d2d 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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
@@ -46,7 +46,7 @@ all(suite) ->
trycatch_4, opt_crash,
otp_5404,otp_5436,otp_5481,otp_5553,otp_5632,
otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b,
- otp_7202,otp_7345,on_load,string_table
+ otp_7202,otp_7345,on_load,string_table,otp_8949_a,otp_8949_a
].
-define(comp(N),
@@ -606,5 +606,45 @@ string_table(Config) when is_list(Config) ->
?line {"StrT", <<"stringabletringtable">>} = StringTableChunk,
ok.
+otp_8949_a(Config) when is_list(Config) ->
+ value = otp_8949_a(),
+ ok.
+
+-record(cs, {exs,keys = [],flags = 1}).
+-record(exs, {children = []}).
+
+otp_8949_a() ->
+ case id([#cs{}]) of
+ [#cs{}=Cs] ->
+ SomeVar = id(value),
+ if
+ Cs#cs.flags band 1 =/= 0 ->
+ id(SomeVar);
+ (((Cs#cs.exs)#exs.children /= [])
+ and
+ (Cs#cs.flags band (1 bsl 0 bor (1 bsl 22)) == 0));
+ Cs#cs.flags band (1 bsl 22) =/= 0 ->
+ ok
+ end
+ end.
+
+otp_8949_b(Config) when is_list(Config) ->
+ self() ! something,
+ ?line value = otp_8949_b([], false),
+ ?line {'EXIT',_} = (catch otp_8949_b([], true)),
+ ok.
+
+%% Would cause an endless loop in beam_utils.
+otp_8949_b(A, B) ->
+ Var = id(value),
+ if
+ A == [], B == false ->
+ ok
+ end,
+ receive
+ something ->
+ id(Var)
+ end.
+
id(I) -> I.
diff --git a/lib/dialyzer/doc/manual.txt b/lib/dialyzer/doc/manual.txt
index 470ddd6c73..d9cb52f722 100644
--- a/lib/dialyzer/doc/manual.txt
+++ b/lib/dialyzer/doc/manual.txt
@@ -123,9 +123,10 @@ The exit status of the command line version is:
Usage: dialyzer [--help] [--version] [--shell] [--quiet] [--verbose]
- [-pa dir]* [--plt plt] [-Ddefine]* [-I include_dir]*
- [--output_plt file] [-Wwarn]* [--src] [--gui | --wx]
- [files_or_dirs] [-r dirs] [--apps applications] [-o outfile]
+ [-pa dir]* [--plt plt] [--plts plts] [-Ddefine]*
+ [-I include_dir]* [--output_plt file] [-Wwarn]*
+ [--src] [--gui | --wx] [files_or_dirs] [-r dirs]
+ [--apps applications] [-o outfile]
[--build_plt] [--add_to_plt] [--remove_from_plt]
[--check_plt] [--no_check_plt] [--plt_info] [--get_warnings]
[--no_native]
@@ -167,6 +168,10 @@ Options:
--plt plt
Use the specified plt as the initial plt (if the plt was built
during setup the files will be checked for consistency)
+ --plts plts
+ Merges the specified plts to create the initial plt -- requires
+ that the plts are disjoint (i.e., do not have any module
+ appearing in more than one plt)
-Wwarn
A family of options which selectively turn on/off warnings
(for help on the names of warnings use dialyzer -Whelp)
@@ -294,6 +299,7 @@ Option :: {files, [Filename :: string()]}
| {defines, [{Macro :: atom(), Value :: term()}]}
| {from, src_code | byte_code} %% Defaults to byte_code
| {init_plt, FileName :: string()} %% If changed from default
+ | {plts, [FileName :: string()]} %% If changed from default
| {include_dirs, [DirName :: string()]}
| {output_file, FileName :: string()}
| {output_plt, FileName :: string()}
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index b4161ea194..471f9fccd2 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -106,27 +106,35 @@ cl_print_plt_info(Opts) ->
end,
doit(F).
-print_plt_info(#options{init_plt = PLT, output_file = OutputFile}) ->
+print_plt_info(#options{init_plts = PLTs, output_file = OutputFile}) ->
+ PLTInfo = get_plt_info(PLTs),
+ do_print_plt_info(PLTInfo, OutputFile).
+
+get_plt_info([PLT|PLTs]) ->
String =
case dialyzer_plt:included_files(PLT) of
{ok, Files} ->
- io_lib:format("The PLT ~s includes the following files:\n~p\n",
+ io_lib:format("The PLT ~s includes the following files:\n~p\n\n",
[PLT, Files]);
{error, read_error} ->
- Msg = io_lib:format("Could not read the PLT file ~p\n", [PLT]),
+ Msg = io_lib:format("Could not read the PLT file ~p\n\n", [PLT]),
throw({dialyzer_error, Msg});
{error, no_such_file} ->
- Msg = io_lib:format("The PLT file ~p does not exist\n", [PLT]),
+ Msg = io_lib:format("The PLT file ~p does not exist\n\n", [PLT]),
throw({dialyzer_error, Msg})
end,
+ String ++ get_plt_info(PLTs);
+get_plt_info([]) -> "".
+
+do_print_plt_info(PLTInfo, OutputFile) ->
case OutputFile =:= none of
true ->
- io:format("~s", [String]),
+ io:format("~s", [PLTInfo]),
?RET_NOTHING_SUSPICIOUS;
false ->
case file:open(OutputFile, [write]) of
{ok, FileDesc} ->
- io:format(FileDesc, "~s", [String]),
+ io:format(FileDesc, "~s", [PLTInfo]),
ok = file:close(FileDesc),
?RET_NOTHING_SUSPICIOUS;
{error, Reason} ->
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index 2da8ed2e5d..1d98574585 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -129,7 +129,7 @@
defines = [] :: [dial_define()],
from = byte_code :: start_from(),
get_warnings = maybe :: boolean() | 'maybe',
- init_plt = none :: 'none' | file:filename(),
+ init_plts = [] :: [file:filename()],
include_dirs = [] :: [file:filename()],
output_plt = none :: 'none' | file:filename(),
legal_warnings = ordsets:new() :: ordset(dial_warn_tag()),
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 0250c47ad0..1987c1732c 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -81,11 +81,15 @@ build_plt(Opts) ->
init_opts_for_build(Opts) ->
case Opts#options.output_plt =:= none of
true ->
- case Opts#options.init_plt of
- none -> Opts#options{init_plt = none, output_plt = get_default_plt()};
- Plt -> Opts#options{init_plt = none, output_plt = Plt}
+ case Opts#options.init_plts of
+ [] -> Opts#options{output_plt = get_default_output_plt()};
+ [Plt] -> Opts#options{init_plts = [], output_plt = Plt};
+ Plts ->
+ Msg = io_lib:format("Could not build multiple PLT files: ~s\n",
+ [format_plts(Plts)]),
+ error(Msg)
end;
- false -> Opts#options{init_plt = none}
+ false -> Opts#options{init_plts = []}
end.
%%--------------------------------------------------------------------
@@ -98,39 +102,58 @@ add_to_plt(Opts) ->
init_opts_for_add(Opts) ->
case Opts#options.output_plt =:= none of
true ->
- case Opts#options.init_plt of
- none -> Opts#options{output_plt = get_default_plt(),
- init_plt = get_default_plt()};
- Plt -> Opts#options{output_plt = Plt}
+ case Opts#options.init_plts of
+ [] -> Opts#options{output_plt = get_default_output_plt(),
+ init_plts = get_default_init_plt()};
+ [Plt] -> Opts#options{output_plt = Plt};
+ Plts ->
+ Msg = io_lib:format("Could not add to multiple PLT files: ~s\n",
+ [format_plts(Plts)]),
+ error(Msg)
end;
false ->
- case Opts#options.init_plt =:= none of
- true -> Opts#options{init_plt = get_default_plt()};
+ case Opts#options.init_plts =:= [] of
+ true -> Opts#options{init_plts = get_default_init_plt()};
false -> Opts
end
end.
%%--------------------------------------------------------------------
-check_plt(Opts) ->
+check_plt(#options{init_plts = []} = Opts) ->
Opts1 = init_opts_for_check(Opts),
- report_check(Opts),
- plt_common(Opts1, [], []).
+ report_check(Opts1),
+ plt_common(Opts1, [], []);
+check_plt(#options{init_plts = Plts} = Opts) ->
+ check_plt_aux(Plts, Opts).
+
+check_plt_aux([_] = Plt, Opts) ->
+ Opts1 = Opts#options{init_plts = Plt},
+ Opts2 = init_opts_for_check(Opts1),
+ report_check(Opts2),
+ plt_common(Opts2, [], []);
+check_plt_aux([Plt|Plts], Opts) ->
+ Opts1 = Opts#options{init_plts = [Plt]},
+ Opts2 = init_opts_for_check(Opts1),
+ report_check(Opts2),
+ plt_common(Opts2, [], []),
+ check_plt_aux(Plts, Opts).
init_opts_for_check(Opts) ->
- Plt =
- case Opts#options.init_plt of
- none -> get_default_plt();
- Plt0 -> Plt0
+ InitPlt =
+ case Opts#options.init_plts of
+ []-> get_default_init_plt();
+ Plt -> Plt
end,
+ [OutputPlt] = InitPlt,
Opts#options{files = [],
files_rec = [],
analysis_type = plt_check,
defines = [],
from = byte_code,
- init_plt = Plt,
+ init_plts = InitPlt,
include_dirs = [],
- output_plt = Plt,
+ output_plt = OutputPlt,
use_contracts = true
}.
@@ -144,21 +167,25 @@ remove_from_plt(Opts) ->
init_opts_for_remove(Opts) ->
case Opts#options.output_plt =:= none of
true ->
- case Opts#options.init_plt of
- none -> Opts#options{output_plt = get_default_plt(),
- init_plt = get_default_plt()};
- Plt -> Opts#options{output_plt = Plt}
+ case Opts#options.init_plts of
+ [] -> Opts#options{output_plt = get_default_output_plt(),
+ init_plts = get_default_init_plt()};
+ [Plt] -> Opts#options{output_plt = Plt};
+ Plts ->
+ Msg = io_lib:format("Could not remove from multiple PLT files: ~s\n",
+ [format_plts(Plts)]),
+ error(Msg)
end;
false ->
- case Opts#options.init_plt =:= none of
- true -> Opts#options{init_plt = get_default_plt()};
+ case Opts#options.init_plts =:= [] of
+ true -> Opts#options{init_plts = get_default_init_plt()};
false -> Opts
end
end.
%%--------------------------------------------------------------------
-plt_common(Opts, RemoveFiles, AddFiles) ->
+plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
case check_plt(Opts, RemoveFiles, AddFiles) of
ok ->
case Opts#options.report_mode of
@@ -174,7 +201,7 @@ plt_common(Opts, RemoveFiles, AddFiles) ->
report_failed_plt_check(Opts, DiffMd5),
{AnalFiles, RemovedMods, ModDeps1} =
expand_dependent_modules(Md5, DiffMd5, ModDeps),
- Plt = clean_plt(Opts#options.init_plt, RemovedMods),
+ Plt = clean_plt(InitPlt, RemovedMods),
case AnalFiles =:= [] of
true ->
%% Only removed stuff. Just write the PLT.
@@ -186,19 +213,19 @@ plt_common(Opts, RemoveFiles, AddFiles) ->
end;
{error, no_such_file} ->
Msg = io_lib:format("Could not find the PLT: ~s\n~s",
- [Opts#options.init_plt, default_plt_error_msg()]),
+ [InitPlt, default_plt_error_msg()]),
error(Msg);
{error, not_valid} ->
Msg = io_lib:format("The file: ~s is not a valid PLT file\n~s",
- [Opts#options.init_plt, default_plt_error_msg()]),
+ [InitPlt, default_plt_error_msg()]),
error(Msg);
{error, read_error} ->
Msg = io_lib:format("Could not read the PLT: ~s\n~s",
- [Opts#options.init_plt, default_plt_error_msg()]),
+ [InitPlt, default_plt_error_msg()]),
error(Msg);
{error, {no_file_to_remove, F}} ->
Msg = io_lib:format("Could not remove the file ~s from the PLT: ~s\n",
- [F, Opts#options.init_plt]),
+ [F, InitPlt]),
error(Msg)
end.
@@ -218,8 +245,7 @@ default_plt_error_msg() ->
%%--------------------------------------------------------------------
-check_plt(Opts, RemoveFiles, AddFiles) ->
- Plt = Opts#options.init_plt,
+check_plt(#options{init_plts = [Plt]} = Opts, RemoveFiles, AddFiles) ->
case dialyzer_plt:check_plt(Plt, RemoveFiles, AddFiles) of
{old_version, _MD5} = OldVersion ->
report_old_version(Opts),
@@ -234,14 +260,14 @@ check_plt(Opts, RemoveFiles, AddFiles) ->
%%--------------------------------------------------------------------
-report_check(#options{report_mode = ReportMode, init_plt = InitPlt}) ->
+report_check(#options{report_mode = ReportMode, init_plts = [InitPlt]}) ->
case ReportMode of
quiet -> ok;
_ ->
io:format(" Checking whether the PLT ~s is up-to-date...", [InitPlt])
end.
-report_old_version(#options{report_mode = ReportMode, init_plt = InitPlt}) ->
+report_old_version(#options{report_mode = ReportMode, init_plts = [InitPlt]}) ->
case ReportMode of
quiet -> ok;
_ ->
@@ -264,7 +290,7 @@ report_failed_plt_check(#options{analysis_type = AnalType,
report_analysis_start(#options{analysis_type = Type,
report_mode = ReportMode,
- init_plt = InitPlt,
+ init_plts = InitPlts,
output_plt = OutputPlt}) ->
case ReportMode of
quiet -> ok;
@@ -272,6 +298,7 @@ report_analysis_start(#options{analysis_type = Type,
io:format(" "),
case Type of
plt_add ->
+ [InitPlt] = InitPlts,
case InitPlt =:= OutputPlt of
true -> io:format("Adding information to ~s...", [OutputPlt]);
false -> io:format("Adding information from ~s to ~s...",
@@ -282,6 +309,7 @@ report_analysis_start(#options{analysis_type = Type,
plt_check ->
io:format("Rebuilding the information in ~s...", [OutputPlt]);
plt_remove ->
+ [InitPlt] = InitPlts,
case InitPlt =:= OutputPlt of
true -> io:format("Removing information from ~s...", [OutputPlt]);
false -> io:format("Removing information from ~s to ~s...",
@@ -320,16 +348,28 @@ report_md5_diff(List) ->
%%--------------------------------------------------------------------
-get_default_plt() ->
+get_default_init_plt() ->
+ [dialyzer_plt:get_default_plt()].
+
+get_default_output_plt() ->
dialyzer_plt:get_default_plt().
%%--------------------------------------------------------------------
+format_plts([Plt]) -> Plt;
+format_plts([Plt|Plts]) ->
+ Plt ++ ", " ++ format_plts(Plts).
+
+%%--------------------------------------------------------------------
+
do_analysis(Options) ->
Files = get_files_from_opts(Options),
- case Options#options.init_plt of
- none -> do_analysis(Files, Options, dialyzer_plt:new(), none);
- File -> do_analysis(Files, Options, dialyzer_plt:from_file(File), none)
+ case Options#options.init_plts of
+ [] -> do_analysis(Files, Options, dialyzer_plt:new(), none);
+ PltFiles ->
+ Plts = [dialyzer_plt:from_file(F) || F <- PltFiles],
+ Plt = dialyzer_plt:merge_plts_or_report_conflicts(PltFiles, Plts),
+ do_analysis(Files, Options, Plt, none)
end.
do_analysis(Files, Options, Plt, PltInfo) ->
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index 0160b84abc..2f9e577544 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -138,11 +138,17 @@ cl(["-pa", Path|T]) ->
true -> cl(T);
{error, _} -> error("Bad directory for -pa: "++Path)
end;
-cl(["--plt", PLT|T]) ->
- put(dialyzer_init_plt, PLT),
- cl(T);
cl(["--plt"]) ->
error("No plt specified for --plt");
+cl(["--plt", PLT|T]) ->
+ put(dialyzer_init_plts, [PLT]),
+ cl(T);
+cl(["--plts"]) ->
+ error("No plts specified for --plts");
+cl(["--plts"|T]) ->
+ {PLTs, NewT} = get_plts(T, []),
+ put(dialyzer_init_plts, PLTs),
+ cl(NewT);
cl(["-q"|T]) ->
put(dialyzer_options_report_mode, quiet),
cl(T);
@@ -284,7 +290,7 @@ common_options() ->
[{defines, get(dialyzer_options_defines)},
{from, get(dialyzer_options_from)},
{include_dirs, get(dialyzer_include)},
- {init_plt, get(dialyzer_init_plt)},
+ {plts, get(dialyzer_init_plts)},
{output_plt, get(dialyzer_output_plt)},
{report_mode, get(dialyzer_options_report_mode)},
{use_spec, get(dialyzer_options_use_contracts)},
@@ -309,6 +315,13 @@ get_lib_dir([], Acc) ->
%%-----------------------------------------------------------------------
+get_plts(["--"|T], Acc) -> {lists:reverse(Acc), T};
+get_plts(["-"++_Opt = H|T], Acc) -> {lists:reverse(Acc), [H|T]};
+get_plts([H|T], Acc) -> get_plts(T, [H|Acc]);
+get_plts([], Acc) -> {lists:reverse(Acc), []}.
+
+%%-----------------------------------------------------------------------
+
help_warnings() ->
S = warning_options_msg(),
io:put_chars(S),
@@ -316,9 +329,10 @@ help_warnings() ->
help_message() ->
S = "Usage: dialyzer [--help] [--version] [--shell] [--quiet] [--verbose]
- [-pa dir]* [--plt plt] [-Ddefine]* [-I include_dir]*
- [--output_plt file] [-Wwarn]* [--src] [--gui | --wx]
- [files_or_dirs] [-r dirs] [--apps applications] [-o outfile]
+ [-pa dir]* [--plt plt] [--plts plts] [-Ddefine]*
+ [-I include_dir]* [--output_plt file] [-Wwarn]*
+ [--src] [--gui | --wx] [files_or_dirs] [-r dirs]
+ [--apps applications] [-o outfile]
[--build_plt] [--add_to_plt] [--remove_from_plt]
[--check_plt] [--no_check_plt] [--plt_info] [--get_warnings]
[--no_native]
@@ -362,6 +376,10 @@ Options:
--plt plt
Use the specified plt as the initial plt (if the plt was built
during setup the files will be checked for consistency)
+ --plts plts
+ Merges the specified plts to create the initial plt -- requires
+ that the plts are disjoint (i.e., do not have any module
+ appearing in more than one plt)
-Wwarn
A family of options which selectively turn on/off warnings
(for help on the names of warnings use dialyzer -Whelp)
@@ -378,12 +396,12 @@ Options:
--build_plt
The analysis starts from an empty plt and creates a new one from the
files specified with -c and -r. Only works for beam files.
- Use --plt or --output_plt to override the default plt location.
+ Use --plt(s) or --output_plt to override the default plt location.
--add_to_plt
The plt is extended to also include the files specified with -c and -r.
- Use --plt to specify wich plt to start from, and --output_plt to
- specify where to put the plt. Note that the analysis might include
- files from the plt if they depend on the new files.
+ Use --plt(s) to specify wich plt to start from, and --output_plt to
+ specify where to put the plt. Note that the analysis might include
+ files from the plt if they depend on the new files.
This option only works with beam files.
--remove_from_plt
The information from the files specified with -c and -r is removed
@@ -396,8 +414,8 @@ Options:
Skip the plt check when running Dialyzer. Useful when working with
installed plts that never change.
--plt_info
- Makes Dialyzer print information about the plt and then quit. The plt
- can be specified with --plt.
+ Makes Dialyzer print information about the plt and then quit. The plt
+ can be specified with --plt(s).
--get_warnings
Makes Dialyzer emit warnings even when manipulating the plt. Only
emits warnings for files that are actually analyzed.
diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl
index f353638cdf..4436330f7f 100644
--- a/lib/dialyzer/src/dialyzer_gui.erl
+++ b/lib/dialyzer/src/dialyzer_gui.erl
@@ -88,8 +88,8 @@
-spec start(#options{}) -> ?RET_NOTHING_SUSPICIOUS.
-start(DialyzerOptions = #options{from = From, init_plt = InitPltFile,
- legal_warnings = LegalWarnings}) ->
+start(#options{from = From, init_plts = InitPltFiles,
+ legal_warnings = LegalWarnings} = DialyzerOptions) ->
process_flag(trap_exit, true),
GS = gs:start(),
@@ -336,9 +336,13 @@ start(DialyzerOptions = #options{from = From, init_plt = InitPltFile,
gs:config(Packer, WH),
{ok, CWD} = file:get_cwd(),
- InitPlt = try dialyzer_plt:from_file(InitPltFile)
- catch throw:{dialyzer_error, _} -> dialyzer_plt:new()
- end,
+ InitPlt =
+ case InitPltFiles of
+ [] -> dialyzer_plt:new();
+ _ ->
+ Plts = [dialyzer_plt:from_file(F) || F <- InitPltFiles],
+ dialyzer_plt:merge_plts_or_report_conflicts(InitPltFiles, Plts)
+ end,
State = #gui_state{add_all = AddAll,
add_file = AddFile,
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index 2e309d7ec1..e711c15ea7 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -88,7 +88,7 @@ start(DialyzerOptions) ->
State = wx:batch(fun() -> create_window(Wx, DialyzerOptions) end),
gui_loop(State).
-create_window(Wx, DialyzerOptions) ->
+create_window(Wx, #options{init_plts = InitPltFiles} = DialyzerOptions) ->
{ok, Host} = inet:gethostname(),
%%---------- initializing frame ---------
@@ -258,11 +258,15 @@ create_window(Wx, DialyzerOptions) ->
plt = PltMenu,
options =OptionsMenu,
help = HelpMenu},
-
- InitPlt = try dialyzer_plt:from_file(DialyzerOptions#options.init_plt)
- catch throw:{dialyzer_error, _} -> dialyzer_plt:new()
- end,
+ InitPlt =
+ case InitPltFiles of
+ [] -> dialyzer_plt:new();
+ _ ->
+ Plts = [dialyzer_plt:from_file(F) || F <- InitPltFiles],
+ dialyzer_plt:merge_plts_or_report_conflicts(InitPltFiles, Plts)
+ end,
+
#gui_state{add = AddButton,
add_dir = AddDirButton,
add_rec = AddRecButton,
diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl
index 010625b7bd..2c0afa6e2b 100644
--- a/lib/dialyzer/src/dialyzer_options.erl
+++ b/lib/dialyzer/src/dialyzer_options.erl
@@ -53,14 +53,21 @@ build(Opts) ->
InitPlt = dialyzer_plt:get_default_plt(),
DefaultOpts = #options{},
DefaultOpts1 = DefaultOpts#options{legal_warnings = DefaultWarns1,
- init_plt = InitPlt},
- try
- NewOpts = build_options(Opts, DefaultOpts1),
+ init_plts = [InitPlt]},
+ try
+ Opts1 = preprocess_opts(Opts),
+ NewOpts = build_options(Opts1, DefaultOpts1),
postprocess_opts(NewOpts)
catch
throw:{dialyzer_options_error, Msg} -> {error, Msg}
end.
+preprocess_opts([]) -> [];
+preprocess_opts([{init_plt, File}|Opts]) ->
+ [{plts, [File]}|preprocess_opts(Opts)];
+preprocess_opts([Opt|Opts]) ->
+ [Opt|preprocess_opts(Opts)].
+
postprocess_opts(Opts = #options{}) ->
Opts1 = check_output_plt(Opts),
adapt_get_warnings(Opts1).
@@ -144,9 +151,9 @@ build_options([{OptionName, Value} = Term|Rest], Options) ->
build_options(Rest, Options#options{from = Value});
get_warnings ->
build_options(Rest, Options#options{get_warnings = Value});
- init_plt ->
- assert_filenames([Term], [Value]),
- build_options(Rest, Options#options{init_plt = Value});
+ plts ->
+ assert_filenames(Term, Value),
+ build_options(Rest, Options#options{init_plts = Value});
include_dirs ->
assert_filenames(Term, Value),
OldVal = Options#options.include_dirs,
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 08d0b318b5..a7ba270c41 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -51,6 +51,7 @@
lookup_contract/2,
lookup_module/2,
merge_plts/1,
+ merge_plts_or_report_conflicts/2,
new/0,
plt_and_info_from_file/1,
get_specs/1,
@@ -292,6 +293,38 @@ merge_plts(List) ->
exported_types = sets_merge(ExpTypesList),
contracts = table_merge(ContractsList)}.
+-spec merge_disj_plts([plt()]) -> plt().
+
+merge_disj_plts(List) ->
+ InfoList = [Info || #plt{info = Info} <- List],
+ TypesList = [Types || #plt{types = Types} <- List],
+ ExpTypesList = [ExpTypes || #plt{exported_types = ExpTypes} <- List],
+ ContractsList = [Contracts || #plt{contracts = Contracts} <- List],
+ #plt{info = table_disj_merge(InfoList),
+ types = table_disj_merge(TypesList),
+ exported_types = sets_disj_merge(ExpTypesList),
+ contracts = table_disj_merge(ContractsList)}.
+
+-spec merge_plts_or_report_conflicts([file:filename()], [plt()]) -> plt().
+
+merge_plts_or_report_conflicts(PltFiles, Plts) ->
+ try
+ merge_disj_plts(Plts)
+ catch throw:{dialyzer_error, not_disjoint_plts} ->
+ IncFiles = lists:append([begin {ok, Fs} = included_files(F), Fs end
+ || F <- PltFiles]),
+ ConfFiles = find_duplicates(IncFiles),
+ Msg = io_lib:format("Could not merge PLTs since they are not disjoint\n"
+ "The following files are included in more than one "
+ "PLTs:\n~p\n", [ConfFiles]),
+ error(Msg)
+ end.
+
+find_duplicates(List) ->
+ ModList = [filename:basename(E) || E <- List],
+ SortedList = lists:usort(ModList),
+ lists:usort(ModList -- SortedList).
+
-spec to_file(file:filename(), plt(), mod_deps(), {[file_md5()], mod_deps()}) -> 'ok'.
to_file(FileName,
@@ -556,6 +589,25 @@ table_merge([Plt|Plts], Acc) ->
NewAcc = dict:merge(fun(_Key, Val, Val) -> Val end, Plt, Acc),
table_merge(Plts, NewAcc).
+table_disj_merge([H|T]) ->
+ table_disj_merge(T, H).
+
+table_disj_merge([], Acc) ->
+ Acc;
+table_disj_merge([Plt|Plts], Acc) ->
+ case table_is_disjoint(Plt, Acc) of
+ true ->
+ NewAcc = dict:merge(fun(_Key, _Val1, _Val2) -> gazonk end,
+ Plt, Acc),
+ table_disj_merge(Plts, NewAcc);
+ false -> throw({dialyzer_error, not_disjoint_plts})
+ end.
+
+table_is_disjoint(T1, T2) ->
+ K1 = dict:fetch_keys(T1),
+ K2 = dict:fetch_keys(T2),
+ lists:all(fun(E) -> not lists:member(E, K2) end, K1).
+
sets_merge([H|T]) ->
sets_merge(T, H).
@@ -565,6 +617,19 @@ sets_merge([Plt|Plts], Acc) ->
NewAcc = sets:union(Plt, Acc),
sets_merge(Plts, NewAcc).
+sets_disj_merge([H|T]) ->
+ sets_disj_merge(T, H).
+
+sets_disj_merge([], Acc) ->
+ Acc;
+sets_disj_merge([Plt|Plts], Acc) ->
+ case sets:is_disjoint(Plt, Acc) of
+ true ->
+ NewAcc = sets:union(Plt, Acc),
+ sets_disj_merge(Plts, NewAcc);
+ false -> throw({dialyzer_error, not_disjoint_plts})
+ end.
+
%%---------------------------------------------------------------------------
%% Debug utilities.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 17c47f871d..47592ddb14 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -3268,7 +3268,7 @@ large_file(Config) when is_list(Config) ->
{{unix,sunos},{A,B,C}}
when A == 5, B == 5, C >= 1; A == 5, B >= 6; A >= 6 ->
do_large_file(Config);
- {{unix,Unix},_} when Unix =:= linux; Unix =:= darwin ->
+ {{unix,Unix},_} when Unix =/= sunos ->
N = unix_free(Config),
io:format("Free: ~w KByte~n", [N]),
if N < 5 * (1 bsl 20) ->
@@ -3278,7 +3278,7 @@ large_file(Config) when is_list(Config) ->
do_large_file(Config)
end;
_ ->
- {skipped,"Only supported on Win32, Linux, or SunOS >= 5.5.1"}
+ {skipped,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
end.
unix_free(Config) ->
@@ -3290,7 +3290,7 @@ unix_free(Config) ->
N.
do_large_file(Config) ->
- ?line Watchdog = ?t:timetrap(?t:minutes(4)),
+ ?line Watchdog = ?t:timetrap(?t:minutes(5)),
%%
?line Name = filename:join(?config(priv_dir, Config),
?MODULE_STRING ++ "_large_file"),
@@ -3329,6 +3329,17 @@ do_large_file(Config) ->
?line {ok,P} = ?FILE_MODULE:position(F, {eof,-L}),
?line {ok,Rs} = ?FILE_MODULE:read(F, L+1),
?line ok = ?FILE_MODULE:close(F),
+ %% Reopen the file with 'append'; used to fail on Windows causing
+ %% writes to go to the beginning of the file for files > 4GB.
+ ?line PL = P + L,
+ ?line PLL = PL + L,
+ ?line {ok,F1} = ?FILE_MODULE:open(Name, [raw,read,write,append]),
+ ?line ok = ?FILE_MODULE:write(F1, R),
+ ?line {ok,PLL} = ?FILE_MODULE:position(F1, {cur,0}),
+ ?line {ok,Rs} = ?FILE_MODULE:pread(F1, P, L),
+ ?line {ok,PL} = ?FILE_MODULE:position(F1, {eof,-L}),
+ ?line {ok,R} = ?FILE_MODULE:read(F1, L+1),
+ ?line ok = ?FILE_MODULE:close(F1),
%%
?line Mref = erlang:monitor(process, Deleter),
?line Deleter ! {Tester,done},
diff --git a/lib/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src
index 47c9bf9979..22ef5178a7 100644
--- a/lib/mnesia/src/mnesia.appup.src
+++ b/lib/mnesia/src/mnesia.appup.src
@@ -1,7 +1,13 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.4.15",[
+ {update, mnesia_dumper, soft, soft_purge, soft_purge, []}
+ ]}
],
[
+ {"4.4.15",[
+ {update, mnesia_dumper, soft, soft_purge, soft_purge, []}
+ ]}
]
}.
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index bce0f7b739..5b52bc6075 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.4.15
+MNESIA_VSN = 4.4.16
diff --git a/lib/odbc/src/odbc.appup.src b/lib/odbc/src/odbc.appup.src
index e95e542ff5..f1a370d925 100644
--- a/lib/odbc/src/odbc.appup.src
+++ b/lib/odbc/src/odbc.appup.src
@@ -1 +1,8 @@
-{"%VSN%", [],[]}
+%% -*- erlang -*-
+{"%VSN%",
+ [
+ {"2.10.8", [{restart_application, ssl}]}
+ ],
+ [
+ {"2.10.8", [{restart_application, ssl}]}
+ ]}.
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index fac3f06d4b..aacf3924db 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.8
+ODBC_VSN = 2.10.9
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index 0f9f62d2f6..6b6b76d0a5 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,6 +1,12 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"0.9",
+ [
+ {update, public_key, soft, soft_purge, soft_purge, []},
+ {update, pubkey_cert, soft, soft_purge, soft_purge, []}
+ ]
+ },
{"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
@@ -12,6 +18,12 @@
}
],
[
+ {"0.9",
+ [
+ {update, public_key, soft, soft_purge, soft_purge, []},
+ {update, pubkey_cert, soft, soft_purge, soft_purge, []}
+ ]
+ },
{"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 2810942171..334b9d792e 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.9
+PUBLIC_KEY_VSN = 0.10
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index f4e6b59b6d..51c5289bd2 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,9 +1,11 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.1", [{restart_application, ssl}]},
{"4.0.1", [{restart_application, ssl}]}
],
[
+ {"4.1", [{restart_application, ssl}]},
{"4.0.1", [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 30a0a3b3f7..ee692adb3b 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1,2 +1,2 @@
-SSL_VSN = 4.1
+SSL_VSN = 4.1.1