Skip to content

Commit 9d383a4

Browse files
authored
Upgrade to Clang 15 (#7886)
* Pull in sorbet/bazel-toolchain#8 Required to make Clang 15 available. * llvm toolchain: 12.0.0 → 15.0.7 * Silence this warning globally * Fix "unused but set variable" warnings * Stop linking against mimalloc on macOS release builds * Fix path to sanitizer archives Clang moved these at some point. Note that we only ever ran the sanitize build on x86_64--it never ran over arm64 builds. That might be nice to add some day, but I'm not blocking on it. * Add doc on how to build and publish LLVM * tools/scripts/format_cxx.sh * Silence some warning for abseil for now * Backport a patch from upstream to fix -Warray-parameter warning I couldn't get this silenced by adding `--copt=-Wno-array-parameter` because it looks like abseil builds this with a bunch of specific warning flags, and those take precedence over ours. The issue is fixed upstream, and when we upgrade we'll get this change for free, but as mentioned in the previous commit we can't upgrade abseil until after we upgrade clang. * Ignore unknown warnings on emscripten build * Defer throwing an exception until all threads have exited In clang 15, the sanitizer was catching a stack-use-after-return error from this multithreaded codepath. The test which caught this was //test/cli:test_folder-input-not-found (Because it is multithreaded, the bug only manifested about 30% of the time, depending on the order that threads were scheduled by the OS.) The bug was that we were attempting to (atomically) write to `pendingJobs` from children threads after the function that spawned those threads exited. A sequence of steps that could happen: - A worker thread would realize that the input was not a directory. It would return a result requesting that the parent thread throw an exception, and queue up a bunch of jobs that would have the effect of shutting down the other threads. - The parent thread would get scheduled first. It would see that a child asked to throw, and it would throw, in effect returning from the function before all children were done. - The children would wake up and attempt to decrement the `pendingJobs` variable in the worker threads' closure by reference. That stack slot is not there anymore because the enclosing function raised. The fix is simply wait for all the threads to finish, and only raise the requested exception after we're sure that all the children threads have finished processing and shut down. For posterity, this is what the test failure looked like +================================================================= +==1781049==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f435a57c140 at pc 0x55cac4f42fd8 bp 0x7f43420ef940 sp 0x7f43420ef938 +WRITE of size 8 at 0x7f435a57c140 thread T7 (options.findFil) + #0 0x55cac4f42fd7 in unsigned long std::__1::__cxx_atomic_fetch_add[abi:v15007]<unsigned long>(std::__1::__cxx_atomic_base_impl<unsigned long>*, unsigned long, std::__1::memory_order) realmain.cc + #1 0x55cac6e4d9b8 in std::__1::__atomic_base<unsigned long, true>::operator+=[abi:v15007](unsigned long) common.cc + #2 0x55cac6e3f5a6 in std::__1::__function::__func<appendFilesInDir(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, absl::flat_hash_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, absl::container_internal::StringHash, absl::container_internal::StringHashEq::Eq, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, sorbet::WorkerPool&, bool, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&)::$_0, std::__1::allocator<appendFilesInDir(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, absl::flat_hash_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, absl::container_internal::StringHash, absl::container_internal::StringHashEq::Eq, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, sorbet::WorkerPool&, bool, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&)::$_0>, void ()>::operator()() common.cc + #3 0x55cac629c0e1 in std::__1::__function::__value_func<void ()>::operator()[abi:v15007]() const driver.cc + #4 0x55cac6265778 in std::__1::function<void ()>::operator()() const (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x43e7778) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #5 0x55cac6ed26ac in std::__1::__function::__func<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::function<void ()>)::$_2, std::__1::allocator<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::function<void ()>)::$_2>, bool ()>::operator()() WorkerPoolImpl.cc + #6 0x55cac6ed12c5 in std::__1::__function::__func<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0, std::__1::allocator<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0>, void ()>::operator()() WorkerPoolImpl.cc + #7 0x55cac629c0e1 in std::__1::__function::__value_func<void ()>::operator()[abi:v15007]() const driver.cc + #8 0x55cac6265778 in std::__1::function<void ()>::operator()() const (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x43e7778) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #9 0x55cac6ee3e33 in Joinable::trampoline(void*) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x5065e33) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #10 0x7f435c953608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8608) (BuildId: c6d0d79d906d62bb768421fc6dada0d5e729f177) + #11 0x7f435c84c352 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x11f352) (BuildId: 87b331c034a6458c64ce09c03939e947212e18ce) + +Address 0x7f435a57c140 is located in stack of thread T0 at offset 320 in frame + #0 0x55cac6e3bb4c in appendFilesInDir(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, absl::flat_hash_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, absl::container_internal::StringHash, absl::container_internal::StringHashEq::Eq, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, sorbet::WorkerPool&, bool, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x4fbdb4c) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + + This frame has 20 object(s): + [32, 40) '__p.addr.i.i.i.i' + [64, 65) '__af.i.i.i' + [80, 104) '__hold.i.i.i' + [144, 160) 'ref.tmp.i.i.i' + [176, 177) 'ref.tmp.i' + [192, 208) 'basePath' + [224, 225) 'recursive.addr' + [240, 244) 'numWorkers' + [256, 272) 'jobq' + [288, 304) 'resultq' + [320, 328) 'pendingJobs' <== Memory access at offset 320 is inside this variable + [352, 384) 'ref.tmp24' + [416, 464) 'agg.tmp41' + [496, 584) 'agg.tmp42' + [624, 656) 'threadResult' + [688, 704) 'ref.tmp73' + [720, 728) 'ref.tmp89' + [752, 832) '__enforceTimer' + [864, 880) 'agg.tmp199' + [896, 904) 'ref.tmp225' +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) +SUMMARY: AddressSanitizer: stack-use-after-return realmain.cc in unsigned long std::__1::__cxx_atomic_fetch_add[abi:v15007]<unsigned long>(std::__1::__cxx_atomic_base_impl<unsigned long>*, unsigned long, std::__1::memory_order) +Shadow bytes around the buggy address: + 0x0fe8eb4a77d0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a77e0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a77f0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7800: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7810: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 +=>0x0fe8eb4a7820: f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7830: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7840: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7850: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7860: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 + 0x0fe8eb4a7870: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb +Thread T7 (options.findFil) created by T0 here: + #0 0x55cac4eadd9c in pthread_create (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x302fd9c) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #1 0x55cac6ee4267 in runInAThread(std::__1::basic_string_view<char, std::__1::char_traits<char>>, std::__1::function<void ()>, std::__1::optional<int>) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x5066267) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #2 0x55cac6ecf33f in sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x505133f) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #3 0x55cac6ece73c in sorbet::WorkerPool::create(int, spdlog::logger&) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x505073c) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #4 0x55cac6a300a6 in sorbet::realmain::options::readOptions(sorbet::realmain::options::Options&, std::__1::vector<std::__1::unique_ptr<sorbet::pipeline::semantic_extension::SemanticExtension, std::__1::default_delete<sorbet::pipeline::semantic_extension::SemanticExtension>>, std::__1::allocator<std::__1::unique_ptr<sorbet::pipeline::semantic_extension::SemanticExtension, std::__1::default_delete<sorbet::pipeline::semantic_extension::SemanticExtension>>>>&, int, char**, std::__1::vector<sorbet::pipeline::semantic_extension::SemanticExtensionProvider*, std::__1::allocator<sorbet::pipeline::semantic_extension::SemanticExtensionProvider*>> const&, std::__1::shared_ptr<spdlog::logger>) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x4bb20a6) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #5 0x55cac4f0379c in sorbet::realmain::realmain(int, char**) (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x308579c) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #6 0x55cac4eff162 in main (/pay/home/jez/.cache/bazel/_bazel_jez/2cc40ac946cd09178597ebd947795951/execroot/com_stripe_ruby_typer/bazel-out/k8-dbg/bin/main/sorbet+0x3081162) (BuildId: c972efcad340ab8e0e5ea671063eb36b) + #7 0x7f435c751082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 87b331c034a6458c64ce09c03939e947212e18ce) + +==1781049==ABORTING ================================================================================
1 parent 2d68c38 commit 9d383a4

29 files changed

+242
-82
lines changed

.bazelrc

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ common:test --test_env=GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1
1212
##
1313
## Custom toolchain.
1414
##
15-
build --crosstool_top=@llvm_toolchain_12_0_0//:toolchain --copt=-D_LIBCPP_ENABLE_NODISCARD
15+
build --crosstool_top=@llvm_toolchain_15_0_7//:toolchain --copt=-D_LIBCPP_ENABLE_NODISCARD
1616

1717
##
1818
## Common build options across all build configurations
@@ -35,6 +35,20 @@ build --copt=-fstack-protector
3535

3636
build --copt=-Werror --copt=-Wimplicit-fallthrough --copt=-Wmissing-field-initializers
3737

38+
# This is to break a circular dependency. The version of absl we're using
39+
# suffers from some compiler builtins that have been deprecated. Upstream absl
40+
# includes patches that avoid those warnings, but upstream absl also requires a
41+
# version of emscripten that is newer than what we currently build with.
42+
# Because emscsripten is powered by clang, then upgrading emscripten amounts to
43+
# upgrading clang and we have a cycle.
44+
#
45+
# Rather than upgrade clang AND emscripten at once, I'm choosing to silence
46+
# these warnings for the time being. This should not affect Sorbet's code,
47+
# because we don't actually use compiler builtins and I can't see that changing
48+
# in the near future.
49+
# TODO(jez) Remove this when we upgrade absl to a more recent version
50+
build --copt=-Wno-deprecated-builtins
51+
3852
build --host_copt=-O1
3953
build --host_copt=-DFORCE_DEBUG
4054
build --host_cxxopt=-Wno-unused-variable --host_cxxopt=-Wno-overloaded-virtual --host_cxxopt=-Wno-unused-const-variable # ragel violates those and we want a silent build
@@ -44,8 +58,6 @@ build --host_cxxopt=-Wno-pass-failed # host build doesn't have enough optimizati
4458
# <command line>:1:9: and <built-in>:355:9: so sadly we turn them all off
4559
build --copt=-Wno-macro-redefined
4660

47-
# Clang 12.0.0 has warnings when compiling LLVM 12.0.0 on C++20, sadly.
48-
# TODO(jez) When we upgrade to LLVM 13.0.0+ can we delete this?
4961
# TODO(jez) We will need these to build C++20, but emscripten doesn't even know about these options yet.
5062
# Leaving them commented out so we can uncomment them after upgrading emscripten.
5163
# build --host_cxxopt=-Wno-deprecated-anon-enum-enum-conversion
@@ -54,6 +66,10 @@ build --copt=-Wno-macro-redefined
5466
# build --cxxopt=-Wno-deprecated-enum-enum-conversion
5567
# build --cxxopt=-Wno-ambiguous-reversed-operator
5668

69+
# TODO(jez) Something between Clang 12 and Clang 15 seems to have introduced a
70+
# warning saying _never_ use unqualified `std` calls...
71+
build --cxxopt=-Wno-unqualified-std-cast-call --host_cxxopt=-Wno-unqualified-std-cast-call
72+
5773
##
5874
## debug configuration
5975
##
@@ -78,7 +94,6 @@ build:dbg-linux --config=dbg --platforms=@//tools/platforms:linux_x86_64
7894
##
7995
# release version: optimized, with debug symbols and version information
8096
build:release-common --define release=true
81-
build:release-common --define mimalloc=true
8297
build:release-common --compilation_mode=opt
8398
build:release-common --config=backtracesymbols
8499
build:release-common --config=static-libs
@@ -105,6 +120,15 @@ build:release-linux --config=lto-linux --config=release-common
105120
build:release-linux-aarch64 --linkopt=-Wl,-z,relro,-z,now
106121
build:release-linux-aarch64 --config=lto-linux --config=release-common
107122

123+
# It would be nice to move this back to release-common, but there is a build
124+
# failure when using clang 15 on macOS to build GNU make via rules_foreign_cc:
125+
# <https://github.com/bazelbuild/rules_foreign_cc/issues/1186>
126+
# We only use rules_foreign_cc for mimalloc and we only use mimalloc in release
127+
# builds, so I'm moving this here until we can figure out a better workaround,
128+
# or a fix lands upstream.
129+
build:release-linux --define mimalloc=true
130+
build:release-linux-aarch64 --define mimalloc=true
131+
108132
# This is to turn on vector instructions where available.
109133
# We used to do this unconditionally, but Rosetta 2 doesn't translate all vector instructions well.
110134
#
@@ -212,9 +236,9 @@ build:ubsan --define unsanitized=false
212236
build:ubsan --copt=-DHAS_SANITIZER
213237

214238
# Bazel links C++ files with $CC, not $CXX, this breaks UBSan
215-
build:sanitize-linux --linkopt=external/llvm_toolchain_12_0_0/lib/clang/12.0.0/lib/linux/libclang_rt.asan_cxx-x86_64.a
216-
build:sanitize-linux --linkopt=external/llvm_toolchain_12_0_0/lib/clang/12.0.0/lib/linux/libclang_rt.ubsan_standalone_cxx-x86_64.a
217-
build:sanitize-linux --linkopt=external/llvm_toolchain_12_0_0/lib/clang/12.0.0/lib/linux/libclang_rt.ubsan_standalone-x86_64.a
239+
build:sanitize-linux --linkopt=external/llvm_toolchain_15_0_7/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.asan_cxx.a
240+
build:sanitize-linux --linkopt=external/llvm_toolchain_15_0_7/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone_cxx.a
241+
build:sanitize-linux --linkopt=external/llvm_toolchain_15_0_7/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a
218242
build:sanitize-linux --config=sanitize
219243

220244
build:sanitize-mac --config=sanitize
@@ -260,10 +284,13 @@ build:webasm-darwin --crosstool_top=//tools/toolchain/webasm-darwin --config=web
260284
build:webasm --cpu=webasm --spawn_strategy=local --genrule_strategy=local --copt=-Oz --linkopt=-Oz --copt=-DMDB_USE_ROBUST=0
261285
build:webasm --define release=true
262286
build:webasm --compilation_mode=opt
287+
# Some of our options are only available in newer versions of clang.
288+
# TODO(jez) Remove this when we upgrade emscripten to the same version of our clang toolchain
289+
build:webasm --copt=-Wno-unknown-warning-option
263290
build:webasm --copt=-DNDEBUG --linkopt=-DNDEBUG # for some reason emscripten doesn't pass those when -O2\-Oz are specified
264291
build:webasm --copt=--llvm-lto --copt=3 --linkopt=--llvm-lto --linkopt=3
265292
# Specify a "sane" C++ toolchain for the host platform.
266-
build:webasm --host_crosstool_top=@llvm_toolchain_12_0_0//:toolchain
293+
build:webasm --host_crosstool_top=@llvm_toolchain_15_0_7//:toolchain
267294

268295
##
269296
## Stripe's ci passes --config=ci, we need it to exist

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ You are encouraged to play around with various clang-based tools which use the
10411041
10421042
After successfully compiling Sorbet, point your editor to use the
10431043
`clangd` executable located in
1044-
`bazel-sorbet/external/llvm_toolchain_12_0_0/bin/clangd`.
1044+
`bazel-sorbet/external/llvm_toolchain_15_0_7/bin/clangd`.
10451045
10461046
- [clang-format] -- Clang-based source code formatter
10471047

WORKSPACE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ bazel_toolchain_dependencies()
3636
load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
3737

3838
llvm_toolchain(
39-
name = "llvm_toolchain_12_0_0",
39+
name = "llvm_toolchain_15_0_7",
4040
absolute_paths = True,
4141
llvm_mirror_prefixes = [
4242
"https://sorbet-deps.s3-us-west-2.amazonaws.com/",
4343
"https://artifactory-content.stripe.build/artifactory/github-archives/llvm/llvm-project/releases/download/llvmorg-",
4444
"https://github.com/llvm/llvm-project/releases/download/llvmorg-",
4545
],
46-
llvm_version = "12.0.0",
46+
llvm_version = "15.0.7",
4747
)
4848

4949
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")

ast/Trees.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,11 @@ template <> inline const ExpressionPtr &ExpressionPtr::cast<ExpressionPtr>(const
339339
return tree;
340340
}
341341

342-
#define EXPRESSION(name) \
343-
class name; \
344-
template <> struct ExpressionToTag<name> { static constexpr Tag value = Tag::name; }; \
342+
#define EXPRESSION(name) \
343+
class name; \
344+
template <> struct ExpressionToTag<name> { \
345+
static constexpr Tag value = Tag::name; \
346+
}; \
345347
class __attribute__((aligned(8))) name final
346348

347349
EXPRESSION(ClassDef) {

cfg/CFG.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ string BasicBlock::toString(const core::GlobalState &gs, const CFG &cfg) const {
361361
fmt::memory_buffer buf;
362362
fmt::format_to(std::back_inserter(buf), "block[id={}, rubyRegionId={}]({})\n", this->id, this->rubyRegionId,
363363
fmt::map_join(
364-
this->args, ", ", [&](const auto &arg) -> auto { return arg.toString(gs, cfg); }));
364+
this->args, ", ", [&](const auto &arg) -> auto{ return arg.toString(gs, cfg); }));
365365

366366
if (this->outerLoops > 0) {
367367
fmt::format_to(std::back_inserter(buf), "outerLoops: {}\n", this->outerLoops);
@@ -378,7 +378,7 @@ string BasicBlock::toTextualString(const core::GlobalState &gs, const CFG &cfg)
378378
fmt::format_to(std::back_inserter(buf), "bb{}[rubyRegionId={}, firstDead={}]({}):\n", this->id, this->rubyRegionId,
379379
this->firstDeadInstructionIdx,
380380
fmt::map_join(
381-
this->args, ", ", [&](const auto &arg) -> auto { return arg.toString(gs, cfg); }));
381+
this->args, ", ", [&](const auto &arg) -> auto{ return arg.toString(gs, cfg); }));
382382

383383
if (this->outerLoops > 0) {
384384
fmt::format_to(std::back_inserter(buf), " # outerLoops: {}\n", this->outerLoops);
@@ -410,7 +410,7 @@ string BasicBlock::showRaw(const core::GlobalState &gs, const CFG &cfg) const {
410410
fmt::memory_buffer buf;
411411
fmt::format_to(std::back_inserter(buf), "block[id={}]({})\n", this->id,
412412
fmt::map_join(
413-
this->args, ", ", [&](const auto &arg) -> auto { return arg.showRaw(gs, cfg); }));
413+
this->args, ", ", [&](const auto &arg) -> auto{ return arg.showRaw(gs, cfg); }));
414414

415415
if (this->outerLoops > 0) {
416416
fmt::format_to(std::back_inserter(buf), "outerLoops: {}\n", this->outerLoops);

cfg/Instructions.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ class Instruction {
6666
friend InstructionPtr;
6767
};
6868

69-
#define INSN(name) \
70-
class name; \
71-
template <> struct InsnToTag<name> { static constexpr Tag value = Tag::name; }; \
69+
#define INSN(name) \
70+
class name; \
71+
template <> struct InsnToTag<name> { \
72+
static constexpr Tag value = Tag::name; \
73+
}; \
7274
class __attribute__((aligned(8))) name final
7375

7476
INSN(Ident) : public Instruction {

common/common.cc

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ void appendFilesInDir(string_view basePath, const string &path, const sorbet::Un
414414

415415
{
416416
JobOutput threadResult;
417+
optional<sorbet::FileNotFoundException> fileNotFound;
418+
optional<sorbet::FileNotDirException> fileNotDir;
417419
auto &logger = *spdlog::default_logger();
418420
for (auto result = resultq->wait_pop_timed(threadResult, sorbet::WorkerPool::BLOCK_INTERVAL(), logger);
419421
!result.done();
@@ -426,14 +428,28 @@ void appendFilesInDir(string_view basePath, const string &path, const sorbet::Un
426428
}
427429

428430
if (auto *e = std::get_if<sorbet::FileNotFoundException>(&threadResult)) {
429-
throw *e;
431+
if (!fileNotFound.has_value()) {
432+
fileNotFound = *e;
433+
}
430434
} else if (auto *e = std::get_if<sorbet::FileNotDirException>(&threadResult)) {
431-
throw *e;
435+
if (!fileNotDir.has_value()) {
436+
fileNotDir = *e;
437+
}
432438
} else {
433439
ENFORCE(false, "should never get here!");
434440
}
435441
}
436442
}
443+
444+
// If there was an error, don't raise it until after all the worker threads have finished,
445+
// because they might be working on something, attempting to write to the pendingJobs
446+
// variable stored on our stack, and then suddenly see that stack address gone because we've
447+
// raised and jumped elsewhere.
448+
if (fileNotFound.has_value()) {
449+
throw fileNotFound.value();
450+
} else if (fileNotDir.has_value()) {
451+
throw fileNotDir.value();
452+
}
437453
}
438454
}
439455

common/counters/Counters.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ string getCounterStatistics() {
424424

425425
fmt::format_to(std::back_inserter(buf), "{}",
426426
fmt::map_join(
427-
sortedTimings, "", [](const auto &el) -> auto { return el.second; }));
427+
sortedTimings, "", [](const auto &el) -> auto{ return el.second; }));
428428
}
429429

430430
{
@@ -440,7 +440,7 @@ string getCounterStatistics() {
440440

441441
fmt::format_to(std::back_inserter(buf), "{}",
442442
fmt::map_join(
443-
sortedOther, "", [](const auto &el) -> auto { return el.second; }));
443+
sortedOther, "", [](const auto &el) -> auto{ return el.second; }));
444444
}
445445
return to_string(buf);
446446
}

common/has_member.h

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ template <class> struct sfinae_true : std::true_type {};
2323
template <class T> \
2424
static constexpr auto __has_##name(int)->sfinae_true<decltype(std::declval<T>().name(arg_types))>; \
2525
template <class> static constexpr auto __has_##name(long)->std::false_type; \
26-
template <class T> static constexpr bool HAS_MEMBER_##name() { \
27-
return decltype(__has_##name<T>(0)){}; \
28-
}
26+
template <class T> static constexpr bool HAS_MEMBER_##name() { return decltype(__has_##name<T>(0)){}; }
2927

3028
/**
3129
* Given a method name, a default statement to run, and a list of argument types, do the following:
@@ -39,27 +37,25 @@ template <class> struct sfinae_true : std::true_type {};
3937
* CALL_MEMBER_toString<core::NameRef>::call(name, gs); // calls name.toString(gs)
4038
* CALL_MEMBER_toString<int>::call(10, gs); // returns ""
4139
*/
42-
#define GENERATE_CALL_MEMBER(method_name, default_behavior, arg_types...) \
43-
GENERATE_HAS_MEMBER(method_name, arg_types) \
44-
template <typename T, bool has> class CALL_MEMBER_impl_##method_name { \
45-
public: \
46-
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { \
47-
Exception::raise("should never be called"); \
48-
}; \
49-
}; \
50-
template <typename T> class CALL_MEMBER_impl_##method_name<T, true> { \
51-
public: \
52-
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { \
53-
return self.method_name(std::forward<Args>(args)...); \
54-
}; \
55-
}; \
56-
template <typename T> class CALL_MEMBER_impl_##method_name<T, false> { \
57-
public: \
58-
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { \
59-
default_behavior; \
60-
}; \
61-
}; \
62-
template <typename T> \
40+
#define GENERATE_CALL_MEMBER(method_name, default_behavior, arg_types...) \
41+
GENERATE_HAS_MEMBER(method_name, arg_types) \
42+
template <typename T, bool has> class CALL_MEMBER_impl_##method_name { \
43+
public: \
44+
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { \
45+
Exception::raise("should never be called"); \
46+
}; \
47+
}; \
48+
template <typename T> class CALL_MEMBER_impl_##method_name<T, true> { \
49+
public: \
50+
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { \
51+
return self.method_name(std::forward<Args>(args)...); \
52+
}; \
53+
}; \
54+
template <typename T> class CALL_MEMBER_impl_##method_name<T, false> { \
55+
public: \
56+
template <class... Args> static decltype(auto) call(T &self, Args &&...args) { default_behavior; }; \
57+
}; \
58+
template <typename T> \
6359
class CALL_MEMBER_##method_name : public CALL_MEMBER_impl_##method_name<T, HAS_MEMBER_##method_name<T>()> {};
6460

6561
} // namespace sorbet

common/typecase.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,31 @@ namespace sorbet {
1414

1515
// Begin ecatmur's code
1616
template <typename T> struct remove_class {};
17-
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { using type = R(A...); };
18-
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { using type = R(A...); };
19-
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) volatile> { using type = R(A...); };
17+
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> {
18+
using type = R(A...);
19+
};
20+
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> {
21+
using type = R(A...);
22+
};
23+
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) volatile> {
24+
using type = R(A...);
25+
};
2026
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const volatile> {
2127
using type = R(A...);
2228
};
2329

2430
template <typename T> struct get_signature_impl {
2531
using type = typename remove_class<decltype(&std::remove_reference<T>::type::operator())>::type;
2632
};
27-
template <typename R, typename... A> struct get_signature_impl<R(A...)> { using type = R(A...); };
28-
template <typename R, typename... A> struct get_signature_impl<R (&)(A...)> { using type = R(A...); };
29-
template <typename R, typename... A> struct get_signature_impl<R (*)(A...)> { using type = R(A...); };
33+
template <typename R, typename... A> struct get_signature_impl<R(A...)> {
34+
using type = R(A...);
35+
};
36+
template <typename R, typename... A> struct get_signature_impl<R (&)(A...)> {
37+
using type = R(A...);
38+
};
39+
template <typename R, typename... A> struct get_signature_impl<R (*)(A...)> {
40+
using type = R(A...);
41+
};
3042
template <typename T> using get_signature = typename get_signature_impl<T>::type;
3143
// End ecatmur's code
3244

0 commit comments

Comments
 (0)