Merge pull request #4665 from juj/emscripten_strict

emscripten_strict
diff --git a/AUTHORS b/AUTHORS
index 171a697..0441963 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -267,3 +267,5 @@
 * Christopher Serr <christopher.serr@gmail.com>
 * Aaron Ruß <aaron.russ@dfki.de> (copyright owned by DFKI GmbH)
 * Vilibald WanĨa <vilibald@wvi.cz>
+* Alex Hixon <alex@alexhixon.com>
+* Vladimir Davidovich <thy.ringo@gmail.com>
diff --git a/emcc.py b/emcc.py
index ac09303..3b113d0 100755
--- a/emcc.py
+++ b/emcc.py
@@ -115,6 +115,8 @@
   if len(sys.argv) <= 1 or ('--help' not in sys.argv and len(sys.argv) >= 2 and sys.argv[1] != '--version'):
     shared.check_sanity(force=DEBUG)
 
+  misc_temp_files = shared.configuration.get_temp_files()
+
   # Handle some global flags
 
   if len(sys.argv) == 1:
@@ -181,6 +183,22 @@
     print shared.get_llvm_target()
     exit(0)
 
+  elif '--cflags' in sys.argv:
+    # fake running the command, to see the full args we pass to clang
+    debug_env = os.environ.copy()
+    debug_env['EMCC_DEBUG'] = '1'
+    args = filter(lambda x: x != '--cflags', sys.argv)
+    with misc_temp_files.get_file(suffix='.o') as temp_target:
+      input_file = 'hello_world.c'
+      out, err = subprocess.Popen([shared.PYTHON] + args + [shared.path_from_root('tests', input_file), '-c', '-o', temp_target], stderr=subprocess.PIPE, env=debug_env).communicate()
+      lines = filter(lambda x: shared.CLANG_CC in x and input_file in x, err.split(os.linesep))
+      line = lines[0]
+      assert 'running:' in line
+      parts = line.split(' ')[2:]
+      parts = filter(lambda x: x != '-c' and x != '-o' and input_file not in x and temp_target not in x and '-emit-llvm' not in x, parts)
+      print ' '.join(parts)
+    exit(0)
+
   def is_minus_s_for_emcc(newargs, i):
     assert newargs[i] == '-s'
     if i+1 < len(newargs) and '=' in newargs[i+1] and not newargs[i+1].startswith('-'): # -s OPT=VALUE is for us, -s by itself is a linker option
@@ -401,8 +419,6 @@
 
   use_cxx = True
 
-  misc_temp_files = shared.configuration.get_temp_files()
-
   try:
     with ToolchainProfiler.profile_block('parse arguments and setup'):
       ## Parse args
@@ -1192,13 +1208,16 @@
 
       if shared.Settings.USE_PTHREADS:
         if shared.Settings.LINKABLE:
-          logging.error('-s LINKABLE=1 is not supported with -s USE_PTHREADS=1!')
+          logging.error('-s LINKABLE=1 is not supported with -s USE_PTHREADS>0!')
           exit(1)
         if shared.Settings.SIDE_MODULE:
-          logging.error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS=1!')
+          logging.error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS>0!')
           exit(1)
         if shared.Settings.MAIN_MODULE:
-          logging.error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS=1!')
+          logging.error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS>0!')
+          exit(1)
+        if shared.Settings.EMTERPRETIFY:
+          logging.error('-s EMTERPRETIFY=1 is not supported with -s USE_PTHREADS>0!')
           exit(1)
 
       if shared.Settings.OUTLINING_LIMIT:
@@ -2030,6 +2049,14 @@
           print jsrun.run_js(shared.path_from_root('tools', 'js-optimizer.js'), shared.NODE_JS, args=[asm_target, 'eliminateDeadGlobals', 'last', 'asm'], stdout=open(temp, 'w'))
           shutil.move(temp, asm_target)
 
+      if shared.Settings.BINARYEN_METHOD:
+        methods = shared.Settings.BINARYEN_METHOD.split(',')
+        valid_methods = ['asmjs', 'native-wasm', 'interpret-s-expr', 'interpret-binary', 'interpret-asm2wasm']
+        for m in methods:
+          if not m.strip() in valid_methods:
+            logging.error('Unrecognized BINARYEN_METHOD "' + m.strip() + '" specified! Please pass a comma-delimited list containing one or more of: ' + ','.join(valid_methods))
+            sys.exit(1)
+
       if shared.Settings.BINARYEN:
         logging.debug('using binaryen, with method: ' + shared.Settings.BINARYEN_METHOD)
         binaryen_bin = os.path.join(shared.Settings.BINARYEN_ROOT, 'bin')
diff --git a/emscripten.py b/emscripten.py
index aec62eb..a297740 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -1329,7 +1329,7 @@
                     '-o', temp_s]
     backend_args += ['-thread-model=single'] # no threads support in backend, tell llc to not emit atomics
     # disable slow and relatively unimportant optimization passes
-    backend_args += ['-combiner-alias-analysis=false', '-combiner-global-alias-analysis=false']
+    backend_args += ['-combiner-global-alias-analysis=false']
 
     # asm.js-style exception handling
     if settings['DISABLE_EXCEPTION_CATCHING'] != 1:
diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst
index 595a994..1577333 100644
--- a/site/source/docs/tools_reference/emcc.rst
+++ b/site/source/docs/tools_reference/emcc.rst
@@ -450,6 +450,9 @@
 ``--output-eol windows|linux``
 	Specifies the line ending to generate for the text files that are outputted. If "--output-eol windows" is passed, the final output files will have Windows \r\n line endings in them. With "--output-eol linux", the final generated files will be written with Unix \n line endings.
 
+``--cflags``
+	Prints out the flags ``emcc`` would pass to ``clang`` to compile source code to object/bitcode form. You can use this to invoke clang yourself, and then run ``emcc`` on those outputs just for the final linking+conversion to JS.
+
 .. _emcc-environment-variables:
 
 Environment variables
diff --git a/src/deps_info.json b/src/deps_info.json
index 18e290a..ff5cb49 100644
--- a/src/deps_info.json
+++ b/src/deps_info.json
@@ -44,6 +44,8 @@
   "bind": ["htonl", "htons", "ntohs"],
   "connect": ["htonl", "htons", "ntohs"],
   "socket": ["htonl", "htons", "ntohs"],
-  "sleep": ["usleep"]
+  "sleep": ["usleep"],
+  "recv": ["htons"],
+  "send": ["htons"]
 }
 
diff --git a/src/embind/embind.js b/src/embind/embind.js
index e0e39a8..e39ac1a 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -144,6 +144,7 @@
     }
     else {
         Module[name] = value;
+        Module[name].argCount = numArguments;
     }
   },
 
@@ -1949,6 +1950,8 @@
             // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types
             // are resolved. If multiple overloads are registered for this function, the function goes into an overload table.
             if (undefined === proto[methodName].overloadTable) {
+                // Set argCount in case an overload is registered later
+                memberFunction.argCount = argCount - 2;
                 proto[methodName] = memberFunction;
             } else {
                 proto[methodName].overloadTable[argCount - 2] = memberFunction;
diff --git a/src/jsifier.js b/src/jsifier.js
index 2428828..3358061 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -299,7 +299,10 @@
           print('// STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); // comment as metadata only
         }
         if (BINARYEN) {
+          // export static base and bump, needed for linking in wasm binary's memory, dynamic linking, etc.
           print('var STATIC_BUMP = {{{ STATIC_BUMP }}};');
+          print('Module["STATIC_BASE"] = STATIC_BASE;');
+          print('Module["STATIC_BUMP"] = STATIC_BUMP;');
         }
       }
       var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable);
diff --git a/src/library_openal.js b/src/library_openal.js
index 17b7505..6d71f72 100644
--- a/src/library_openal.js
+++ b/src/library_openal.js
@@ -314,6 +314,25 @@
       }
       {{{ makeSetValue('data', '0', '0', 'i32') }}};
       break;
+    case 0x1007 /* ALC_FREQUENCY */:
+      if (!device) {
+        AL.alcErr = 0xA001 /* ALC_INVALID_DEVICE */;
+        return 0;
+      }
+      if (!AL.currentContext) {
+        AL.alcErr = 0xA002 /* ALC_INVALID_CONTEXT */;
+        return 0;
+      }
+      {{{ makeSetValue('data', '0', 'AL.currentContext.ctx.sampleRate', 'i32') }}};
+      break;
+    case 0x1010 /* ALC_MONO_SOURCES */:
+    case 0x1011 /* ALC_STEREO_SOURCES */:
+      if (!device) {
+        AL.alcErr = 0xA001 /* ALC_INVALID_DEVICE */;
+        return 0;
+      }
+      {{{ makeSetValue('data', '0', '0x7FFFFFFF', 'i32') }}};
+      break;
     case 0x20003 /* ALC_MAX_AUXILIARY_SENDS */:
       if (!device) {
         AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */;
@@ -397,7 +416,9 @@
           this._velocity[0] = val[0];
           this._velocity[1] = val[1];
           this._velocity[2] = val[2];
-          if (this.panner) this.panner.setVelocity(val[0], val[1], val[2]);
+          // TODO: The velocity values are not currently used to implement a doppler effect.
+          // If support for doppler effect is reintroduced, compute the doppler
+          // speed pitch factor and apply it here.
         },
         get direction() {
           return this._direction;
@@ -504,7 +525,8 @@
           panner.maxDistance = src.maxDistance;
           panner.rolloffFactor = src.rolloffFactor;
           panner.setPosition(src.position[0], src.position[1], src.position[2]);
-          panner.setVelocity(src.velocity[0], src.velocity[1], src.velocity[2]);
+          // TODO: If support for doppler effect is reintroduced, compute the doppler
+          // speed pitch factor and apply it here.
           panner.connect(AL.currentContext.gain);
 
           // Disconnect from the default source.
@@ -606,7 +628,7 @@
     }
   },
 
-  alSource3i: ['alSource3f'],
+  alSource3i__deps: ['alSource3f'],
   alSource3i: function(source, param, v1, v2, v3) {
     _alSource3f(source, param, v1, v2, v3);
   },
@@ -1367,7 +1389,9 @@
       AL.currentContext.ctx.listener._velocity[0] = v1;
       AL.currentContext.ctx.listener._velocity[1] = v2;
       AL.currentContext.ctx.listener._velocity[2] = v3;
-      AL.currentContext.ctx.listener.setVelocity(v1, v2, v3);
+      // TODO: The velocity values are not currently used to implement a doppler effect.
+      // If support for doppler effect is reintroduced, compute the doppler
+      // speed pitch factor and apply it here.
       break;
     default:
 #if OPENAL_DEBUG
@@ -1402,7 +1426,9 @@
       AL.currentContext.ctx.listener._velocity[0] = x;
       AL.currentContext.ctx.listener._velocity[1] = y;
       AL.currentContext.ctx.listener._velocity[2] = z;
-      AL.currentContext.ctx.listener.setVelocity(x, y, z);
+      // TODO: The velocity values are not currently used to implement a doppler effect.
+      // If support for doppler effect is reintroduced, compute the doppler
+      // speed pitch factor and apply it here.
       break;
     case 0x100F /* AL_ORIENTATION */:
       var x = {{{ makeGetValue('values', '0', 'float') }}};
diff --git a/src/library_syscall.js b/src/library_syscall.js
index 0e89393..f5de059 100644
--- a/src/library_syscall.js
+++ b/src/library_syscall.js
@@ -969,7 +969,7 @@
       stream.getdents = FS.readdir(stream.path);
     }
     var pos = 0;
-    while (stream.getdents.length > 0 && pos + {{{ C_STRUCTS.dirent.__size__ }}} < count) {
+    while (stream.getdents.length > 0 && pos + {{{ C_STRUCTS.dirent.__size__ }}} <= count) {
       var id;
       var type;
       var name = stream.getdents.pop();
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index 0ca77a2..4bff008 100644
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -876,6 +876,34 @@
             p.delete();
         });
 */
+
+        test("no undefined entry in overload table when depending on already bound types", function() {
+            var dummy_overloads = cm.MultipleOverloadsDependingOnDummy.prototype.dummy;
+            // check if the overloadTable is correctly named
+            // it can be minimized if using closure compiler
+            if (dummy_overloads.hasOwnProperty('overloadTable')) {
+                assert.false(dummy_overloads.overloadTable.hasOwnProperty('undefined'));
+            }
+
+            // this part should fail anyway if there is no overloadTable
+            var dependOnDummy = new cm.MultipleOverloadsDependingOnDummy();
+            var dummy = dependOnDummy.dummy();
+            dependOnDummy.dummy(dummy);
+            dummy.delete();
+            dependOnDummy.delete();
+        });
+
+        test("no undefined entry in overload table for free functions", function() {
+            var dummy_free_func = cm.getDummy;
+            console.log(dummy_free_func);
+
+            if (dummy_free_func.hasOwnProperty('overloadTable')) {
+                assert.false(dummy_free_func.overloadTable.hasOwnProperty('undefined'));
+            }
+
+            var dummy = cm.getDummy();
+            cm.getDummy(dummy);
+        });
     });
 
     BaseFixture.extend("vector", function() {
diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp
index c2065dc..0c03ca5 100644
--- a/tests/embind/embind_test.cpp
+++ b/tests/embind/embind_test.cpp
@@ -2294,6 +2294,27 @@
     }
 };
 
+class DummyForOverloads {};
+
+class MultipleOverloadsDependingOnDummy {
+public:
+    DummyForOverloads dummy() {
+        return DummyForOverloads();
+    }
+
+    DummyForOverloads dummy(DummyForOverloads d) {
+        return d;
+    }
+};
+
+DummyForOverloads getDummy() {
+    return DummyForOverloads();
+}
+
+DummyForOverloads getDummy(DummyForOverloads d) {
+    return d;
+}
+
 EMSCRIPTEN_BINDINGS(overloads) {
     function("overloaded_function", select_overload<int(int)>(&overloaded_function));
     function("overloaded_function", select_overload<int(int, int)>(&overloaded_function));
@@ -2337,6 +2358,17 @@
     class_<ConstAndNonConst>("ConstAndNonConst")
         .function("method", select_const(&ConstAndNonConst::method))
         ;
+
+    class_<DummyForOverloads>("DummyForOverloads").constructor();
+
+    class_<MultipleOverloadsDependingOnDummy>("MultipleOverloadsDependingOnDummy")
+        .constructor()
+        .function("dummy", select_overload<DummyForOverloads()>(&MultipleOverloadsDependingOnDummy::dummy))
+        .function("dummy", select_overload<DummyForOverloads(DummyForOverloads)>(&MultipleOverloadsDependingOnDummy::dummy))
+        ;
+
+    function("getDummy", select_overload<DummyForOverloads(void)>(&getDummy));
+    function("getDummy", select_overload<DummyForOverloads(DummyForOverloads)>(&getDummy));
 }
 
 // tests for out-of-order registration
diff --git a/tests/fs/test_getdents64.cpp b/tests/fs/test_getdents64.cpp
new file mode 100644
index 0000000..ae09276
--- /dev/null
+++ b/tests/fs/test_getdents64.cpp
@@ -0,0 +1,53 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+#define BUF_SIZE (sizeof(dirent)*2)
+
+int main(int argc, char *argv[])
+{
+  int fd = open(".", O_RDONLY | O_DIRECTORY);
+  assert(fd > 0);
+
+  printf("sizeof(dirent): %d, sizeof(buffer): %d\n", sizeof(dirent), BUF_SIZE);
+
+  bool first = true;
+
+  for(;;)
+  {
+    char buf[BUF_SIZE];
+    int nread = getdents(fd, (dirent*)buf, BUF_SIZE);
+    assert(nread != -1);
+    if (nread == 0)
+      break;
+
+    // In this test, we provide enough space to read two dirent entries at a time.
+    // Test that on the first iteration of the loop we get exactly two entries. (there's at least "." and ".." in each directory)
+    assert(nread == BUF_SIZE || !first);
+    first = false;
+
+    printf("--------------- nread=%d ---------------\n", nread);
+    printf("i-node#  file type  d_reclen  d_off   d_name\n");
+    int bpos = 0;
+    while(bpos < nread)
+    {
+      dirent *d = (dirent *)(buf + bpos);
+      printf("%8ld  ", (long)d->d_ino);
+      char d_type = *(buf + bpos + d->d_reclen - 1);
+      printf("%-10s ", (d_type == DT_REG) ?  "regular" :
+                       (d_type == DT_DIR) ?  "directory" :
+                       (d_type == DT_FIFO) ? "FIFO" :
+                       (d_type == DT_SOCK) ? "socket" :
+                       (d_type == DT_LNK) ?  "symlink" :
+                       (d_type == DT_BLK) ?  "block dev" :
+                       (d_type == DT_CHR) ?  "char dev" : "???");
+      printf("%4d %10lld  %s\n", d->d_reclen, (long long) d->d_off, d->d_name);
+      bpos += d->d_reclen;
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py
index 6f4c440..5f9e9ba 100644
--- a/tests/test_benchmark.py
+++ b/tests/test_benchmark.py
@@ -68,8 +68,8 @@
     if lib_builder: native_args = native_args + lib_builder(self.name, native=True, env_init={ 'CC': self.cc, 'CXX': self.cxx })
     if not native_exec:
       compiler = self.cxx if filename.endswith('cpp') else self.cc
-      cmd = [compiler, '-fno-math-errno', filename, '-o', filename+'.native'] + self.args + shared_args + native_args
-      process = Popen(cmd, stdout=PIPE, stderr=parent.stderr_redirect)
+      cmd = [compiler, '-fno-math-errno', filename, '-o', filename+'.native'] + self.args + shared_args + native_args + get_clang_native_args()
+      process = Popen(cmd, stdout=PIPE, stderr=parent.stderr_redirect, env=get_clang_native_env())
       output = process.communicate()
       if process.returncode is not 0:
         print >> sys.stderr, "Building native executable with command failed", ' '.join(cmd)
@@ -132,12 +132,16 @@
 # Benchmarkers
 try:
   benchmarkers_error = ''
-  benchmarkers = [
-    NativeBenchmarker('clang', CLANG_CC, CLANG),
-    JSBenchmarker('sm-asmjs', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2']),
-    JSBenchmarker('sm-wasm',  SPIDERMONKEY_ENGINE, ['-s', 'BINARYEN=1', '-s', 'BINARYEN_METHOD="native-wasm"', '-s', 'BINARYEN_IMPRECISE=1']),
-    JSBenchmarker('v8-wasm',  V8_ENGINE,           ['-s', 'BINARYEN=1', '-s', 'BINARYEN_METHOD="native-wasm"', '-s', 'BINARYEN_IMPRECISE=1']),
-  ]
+  benchmarkers = [NativeBenchmarker('clang', CLANG_CC, CLANG)]
+  if SPIDERMONKEY_ENGINE and SPIDERMONKEY_ENGINE[0]:
+    benchmarkers += [
+      JSBenchmarker('sm-asmjs', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2']),
+      JSBenchmarker('sm-wasm',  SPIDERMONKEY_ENGINE, ['-s', 'BINARYEN=1', '-s', 'BINARYEN_METHOD="native-wasm"', '-s', 'BINARYEN_IMPRECISE=1'])
+    ]
+  if V8_ENGINE and V8_ENGINE[0]:
+    benchmarkers += [
+      JSBenchmarker('v8-wasm',  V8_ENGINE,           ['-s', 'BINARYEN=1', '-s', 'BINARYEN_METHOD="native-wasm"', '-s', 'BINARYEN_IMPRECISE=1'])
+    ]
 except Exception, e:
   benchmarkers_error = str(e)
   benchmarkers = []
diff --git a/tests/test_core.py b/tests/test_core.py
index 4fe99de..9c658f8 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -4117,6 +4117,10 @@
     src = open(path_from_root('tests', 'fs', 'test_mount.c'), 'r').read()
     self.do_run(src, 'success', force_c=True)
 
+  def test_getdents64(self):
+    src = open(path_from_root('tests', 'fs', 'test_getdents64.cpp'), 'r').read()
+    self.do_run(src, '..')
+
   def test_fwrite_0(self):
     test_path = path_from_root('tests', 'core', 'test_fwrite_0')
     src, output = (test_path + s for s in ('.c', '.out'))
@@ -6114,7 +6118,7 @@
     self.emcc_args += ['--emit-symbol-map']
     self.do_run(open(path_from_root('tests', 'core', 'test_demangle_stacks.c')).read(), 'abort')
     # make sure the shortened name is the right one
-    symbols = open('src.cpp.o.js.symbols').read().split(os.linesep)
+    symbols = open('src.cpp.o.js.symbols').read().split('\n')
     for line in symbols:
       if ':' not in line: continue
       short, full = line.split(':')
diff --git a/tests/test_other.py b/tests/test_other.py
index 269aaf1..ff80494 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -398,6 +398,17 @@
       os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
       shutil.rmtree(tempdirname)
 
+  def test_emcc_cflags(self):
+    # see we print them out
+    output = Popen([PYTHON, EMCC, '--cflags'], stdout=PIPE, stderr=PIPE).communicate()
+    flags = output[0].strip()
+    self.assertContained(' '.join(COMPILER_OPTS), flags)
+    # check they work
+    cmd = [CLANG, path_from_root('tests', 'hello_world.cpp')] + flags.split(' ') + ['-c', '-emit-llvm', '-o', 'a.bc']
+    subprocess.check_call(cmd)
+    subprocess.check_call([PYTHON, EMCC, 'a.bc'])
+    self.assertContained('hello, world!', run_js(self.in_dir('a.out.js')))
+
   def test_emar_em_config_flag(self):
     # We expand this in case the EM_CONFIG is ~/.emscripten (default)
     config = os.path.expanduser(EM_CONFIG)
@@ -855,6 +866,33 @@
 
     assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
 
+  def test_commons_link(self):
+    open('a.h', 'w').write(r'''
+#if !defined(A_H)
+#define A_H
+extern int foo[8];
+#endif
+''')
+    open('a.c', 'w').write(r'''
+#include "a.h"
+int foo[8];
+''')
+    open('main.c', 'w').write(r'''
+#include <stdio.h>
+#include "a.h"
+
+int main() {
+    printf("|%d|\n", foo[0]);
+    return 0;
+}
+''')
+
+    subprocess.check_call([PYTHON, EMCC, '-o', 'a.o', 'a.c'])
+    subprocess.check_call([PYTHON, EMAR, 'rv', 'library.a', 'a.o'])
+    subprocess.check_call([PYTHON, EMCC, '-o', 'main.o', 'main.c'])
+    subprocess.check_call([PYTHON, EMCC, '-o', 'a.js', 'main.o', 'library.a', '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'])
+    self.assertContained('|0|', run_js('a.js'))
+
   def test_outline(self):
     if WINDOWS and not Building.which('mingw32-make'):
       return self.skip('Skipping other.test_outline: This test requires "mingw32-make" tool in PATH on Windows to drive a Makefile build of zlib')
@@ -6974,6 +7012,11 @@
     subprocess.check_call([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-s', 'WASM=1', '-s', 'BINARYEN_METHOD="native-wasm"', '-s', 'TOTAL_MEMORY=' + str(16*1024*1024), '--pre-js', 'pre.js', '-s', 'ALLOW_MEMORY_GROWTH=1'])
     self.assertContained('hello, world!', run_js('a.out.js', engine=SPIDERMONKEY_ENGINE))
 
+  def test_binaryen_invalid_method(self):
+    proc = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-o', 'test.js', '-s', "BINARYEN_METHOD='invalid'"])
+    proc.communicate()
+    assert proc.returncode != 0
+
   def test_binaryen_default_method(self):
     if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey')
     subprocess.check_call([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-s', 'WASM=1'])
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index 80237c2..6629179 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -343,8 +343,13 @@
     self.do_run(r'''
 #include <netdb.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+
 int main () {
     void* thing = gethostbyname("bing.com");
+    ssize_t rval = recv (0, thing, 0, 0);
+    rval = send (0, thing, 0, 0);
     return 0;
 }''', '', force_c=True)
 
diff --git a/tools/shared.py b/tools/shared.py
index 5037efa..378f7e3 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1454,15 +1454,16 @@
     # returns True.
     def consider_object(f, force_add=False):
       new_symbols = Building.llvm_nm(f)
-      do_add = force_add or not unresolved_symbols.isdisjoint(new_symbols.defs)
+      provided = new_symbols.defs.union(new_symbols.commons)
+      do_add = force_add or not unresolved_symbols.isdisjoint(provided)
       if do_add:
         logging.debug('adding object %s to link' % (f))
         # Update resolved_symbols table with newly resolved symbols
-        resolved_symbols.update(new_symbols.defs)
+        resolved_symbols.update(provided)
         # Update unresolved_symbols table by adding newly unresolved symbols and
         # removing newly resolved symbols.
         unresolved_symbols.update(new_symbols.undefs.difference(resolved_symbols))
-        unresolved_symbols.difference_update(new_symbols.defs)
+        unresolved_symbols.difference_update(provided)
         actual_files.append(f)
       return do_add
 
@@ -1493,7 +1494,7 @@
             dirname = os.path.dirname(content)
             if dirname:
               safe_ensure_dirs(dirname)
-          Popen([LLVM_AR, 'xo', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
+          Popen([LLVM_AR, 'x', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
           contents = map(lambda content: os.path.join(temp_dir, content), contents)
           contents = filter(os.path.exists, map(os.path.abspath, contents))
           contents = filter(Building.is_bitcode, contents)