diff --git a/.clang-tidy b/.clang-tidy index 229e2e69a..1d41cdd58 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -13,6 +13,10 @@ Checks: > -bugprone-forward-declaration-namespace, -bugprone-sizeof-expression, -bugprone-throw-keyword-missing, + -bugprone-chained-comparison, + -bugprone-incorrect-enable-if, + -bugprone-switch-missing-default-case, + -bugprone-empty-catch, -clang-analyzer-*, -clang-diagnostic-deprecated-declarations, -clang-diagnostic-constant-conversion, @@ -49,11 +53,13 @@ Checks: > -misc-misplaced-const, -misc-definitions-in-headers, -misc-unused-parameters, + -misc-include-cleaner, modernize-concat-nested-namespaces, modernize-use-using, performance-*, - -performance-noexcept-move-constructor, -performance-no-int-to-ptr, + -performance-enum-size, + -performance-avoid-endl, readability-*, -readability-avoid-const-params-in-decls, -readability-braces-around-statements, @@ -82,6 +88,10 @@ Checks: > -readability-make-member-function-const, -readability-redundant-string-init, -readability-non-const-parameter, + -readability-redundant-inline-specifier, + -readability-avoid-nested-conditional-operator, + -readability-avoid-return-with-void-value, + -readability-redundant-casting, -readability-static-accessed-through-instance WarningsAsErrors: '*' diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index d8eff0581..eabe3b813 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -192,14 +192,14 @@ jobs: CXXCOMPILER: clang++-15 CUCUMBER_TIMEOUT: 60000 - - name: clang-15-debug-clang-tidy + - name: clang-18-debug-clang-tidy continue-on-error: false node: 18 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 BUILD_TOOLS: ON BUILD_TYPE: Debug - CCOMPILER: clang-15 - CXXCOMPILER: clang++-15 + CCOMPILER: clang-18 + CXXCOMPILER: clang++-18 CUCUMBER_TIMEOUT: 60000 ENABLE_CLANG_TIDY: ON @@ -656,7 +656,7 @@ jobs: path: pr - name: Install dependencies run: | - python3 -m pip install "conan<2.0.0" "requests==2.31.0" "locust==2.28.0" + python3 -m pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4" sudo apt-get update -y && sudo apt-get install ccache - name: Prepare data run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8c566d8..ad9e06bf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - ADDED: Add support for opposite approach request parameter. [#6842](https://github.com/Project-OSRM/osrm-backend/pull/6842) - ADDED: Add support for accessing edge flags in `process_segment` [#6658](https://github.com/Project-OSRM/osrm-backend/pull/6658) - Build: + - CHANGED: Upgrade clang-format to version 15. [#6919](https://github.com/Project-OSRM/osrm-backend/pull/6919) - CHANGED: Use Debian Bookworm as base Docker image [#6904](https://github.com/Project-OSRM/osrm-backend/pull/6904) - CHANGED: Upgrade CI actions to latest versions [#6893](https://github.com/Project-OSRM/osrm-backend/pull/6893) - CHANGED: Remove outdated warnings #6894 [#6894](https://github.com/Project-OSRM/osrm-backend/pull/6894) @@ -23,6 +24,9 @@ - NodeJS: - CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452) - Misc: + - FIXED: Fix bugprone-unused-return-value clang-tidy warning. [#6934](https://github.com/Project-OSRM/osrm-backend/pull/6934) + - FIXED: Fix performance-noexcept-move-constructor clang-tidy warning. [#6931](https://github.com/Project-OSRM/osrm-backend/pull/6933) + - FIXED: Fix performance-noexcept-swap clang-tidy warning. [#6931](https://github.com/Project-OSRM/osrm-backend/pull/6931) - CHANGED: Use custom struct instead of std::pair in QueryHeap. [#6921](https://github.com/Project-OSRM/osrm-backend/pull/6921) - CHANGED: Use std::string_view::starts_with instead of boost::starts_with. [#6918](https://github.com/Project-OSRM/osrm-backend/pull/6918) - CHANGED: Get rid of boost::math::constants::* and M_PI in favor of std::numbers. [#6916](https://github.com/Project-OSRM/osrm-backend/pull/6916) diff --git a/include/extractor/serialization.hpp b/include/extractor/serialization.hpp index 779989261..98ebc7713 100644 --- a/include/extractor/serialization.hpp +++ b/include/extractor/serialization.hpp @@ -215,7 +215,6 @@ inline void read(storage::tar::FileReader &reader, const std::string &name, detail::NameTableImpl &name_table) { - std::string buffer; util::serialization::read(reader, name, name_table.indexed_data); } } // namespace osrm::extractor::serialization diff --git a/include/server/http/header.hpp b/include/server/http/header.hpp index 35d4fcc13..a6e9da858 100644 --- a/include/server/http/header.hpp +++ b/include/server/http/header.hpp @@ -12,7 +12,7 @@ struct header // explicitly use default copy c'tor as adding move c'tor header &operator=(const header &other) = default; header(std::string name, std::string value) : name(std::move(name)), value(std::move(value)) {} - header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} + header(header &&other) noexcept : name(std::move(other.name)), value(std::move(other.value)) {} void clear() { diff --git a/include/storage/shared_memory.hpp b/include/storage/shared_memory.hpp index 76a385b88..3300728b9 100644 --- a/include/storage/shared_memory.hpp +++ b/include/storage/shared_memory.hpp @@ -61,7 +61,7 @@ class SharedMemory { shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key); - util::Log(logDEBUG) << "opening " << (int)shm.get_shmid() << " from id " << (int)id; + util::Log(logDEBUG) << "opening " << shm.get_shmid() << " from id " << (int)id; region = boost::interprocess::mapped_region(shm, boost::interprocess::read_only); } diff --git a/include/util/concurrent_id_map.hpp b/include/util/concurrent_id_map.hpp index ac398725a..594f632e1 100644 --- a/include/util/concurrent_id_map.hpp +++ b/include/util/concurrent_id_map.hpp @@ -26,7 +26,7 @@ struct ConcurrentIDMap mutable UpgradableMutex mutex; ConcurrentIDMap() = default; - ConcurrentIDMap(ConcurrentIDMap &&other) + ConcurrentIDMap(ConcurrentIDMap &&other) noexcept { if (this != &other) { @@ -36,7 +36,7 @@ struct ConcurrentIDMap data = std::move(other.data); } } - ConcurrentIDMap &operator=(ConcurrentIDMap &&other) + ConcurrentIDMap &operator=(ConcurrentIDMap &&other) noexcept { if (this != &other) { diff --git a/include/util/deallocating_vector.hpp b/include/util/deallocating_vector.hpp index 9cb5641e3..32a21650d 100644 --- a/include/util/deallocating_vector.hpp +++ b/include/util/deallocating_vector.hpp @@ -166,7 +166,7 @@ class DeallocatingVectorIterator template class DeallocatingVector; -template void swap(DeallocatingVector &lhs, DeallocatingVector &rhs); +template void swap(DeallocatingVector &lhs, DeallocatingVector &rhs) noexcept; template class DeallocatingVector { @@ -204,8 +204,8 @@ template class DeallocatingVector } // moving is fine - DeallocatingVector(DeallocatingVector &&other) { swap(other); } - DeallocatingVector &operator=(DeallocatingVector &&other) + DeallocatingVector(DeallocatingVector &&other) noexcept { swap(other); } + DeallocatingVector &operator=(DeallocatingVector &&other) noexcept { swap(other); return *this; @@ -221,9 +221,10 @@ template class DeallocatingVector ~DeallocatingVector() { clear(); } - friend void swap<>(DeallocatingVector &lhs, DeallocatingVector &rhs); + friend void swap<>(DeallocatingVector &lhs, + DeallocatingVector &rhs) noexcept; - void swap(DeallocatingVector &other) + void swap(DeallocatingVector &other) noexcept { std::swap(current_size, other.current_size); bucket_list.swap(other.bucket_list); @@ -342,7 +343,7 @@ template class DeallocatingVector } }; -template void swap(DeallocatingVector &lhs, DeallocatingVector &rhs) +template void swap(DeallocatingVector &lhs, DeallocatingVector &rhs) noexcept { lhs.swap(rhs); } diff --git a/include/util/dynamic_graph.hpp b/include/util/dynamic_graph.hpp index 9efbf1402..ce65fda74 100644 --- a/include/util/dynamic_graph.hpp +++ b/include/util/dynamic_graph.hpp @@ -154,7 +154,7 @@ template class DynamicGraph return *this; } - DynamicGraph(DynamicGraph &&other) + DynamicGraph(DynamicGraph &&other) noexcept { number_of_nodes = other.number_of_nodes; // atomics can't be moved this is why we need an own constructor @@ -164,7 +164,7 @@ template class DynamicGraph edge_list = std::move(other.edge_list); } - DynamicGraph &operator=(DynamicGraph &&other) + DynamicGraph &operator=(DynamicGraph &&other) noexcept { number_of_nodes = other.number_of_nodes; // atomics can't be moved this is why we need an own constructor diff --git a/include/util/permutation.hpp b/include/util/permutation.hpp index ae046b014..34520389a 100644 --- a/include/util/permutation.hpp +++ b/include/util/permutation.hpp @@ -10,9 +10,9 @@ namespace osrm::util namespace permutation_detail { -template static inline void swap(T &a, T &b) { std::swap(a, b); } +template static inline void swap(T &a, T &b) noexcept { std::swap(a, b); } -static inline void swap(std::vector::reference a, std::vector::reference b) +static inline void swap(std::vector::reference a, std::vector::reference b) noexcept { std::vector::swap(a, b); } diff --git a/scripts/ci/e2e_benchmark.py b/scripts/ci/e2e_benchmark.py new file mode 100644 index 000000000..4fc900eb9 --- /dev/null +++ b/scripts/ci/e2e_benchmark.py @@ -0,0 +1,102 @@ +import requests +import sys +import random +from collections import defaultdict +import os +import csv +import numpy as np +import time +import argparse + +class BenchmarkRunner: + def __init__(self): + self.coordinates = [] + self.tracks = defaultdict(list) + + gps_traces_file_path = os.path.expanduser('~/gps_traces.csv') + with open(gps_traces_file_path, 'r') as file: + reader = csv.DictReader(file) + for row in reader: + coord = (float(row['Latitude']), float(row['Longitude'])) + self.coordinates.append(coord) + self.tracks[row['TrackID']].append(coord) + self.track_ids = list(self.tracks.keys()) + + def run(self, benchmark_name, host, num_requests, warmup_requests=50): + for _ in range(warmup_requests): + url = self.make_url(host, benchmark_name) + _ = requests.get(url) + + times = [] + + for _ in range(num_requests): + url = self.make_url(host, benchmark_name) + + start_time = time.time() + response = requests.get(url) + end_time = time.time() + if response.status_code != 200: + if benchmark_name == 'match': + code = response.json()['code'] + if code == 'NoSegment' or code == 'NoMatch': + continue + raise Exception(f"Error: {response.status_code} {response.text}") + times.append((end_time - start_time) * 1000) # convert to ms + + return times + + def make_url(self, host, benchmark_name): + if benchmark_name == 'route': + start = random.choice(self.coordinates) + end = random.choice(self.coordinates) + + start_coord = f"{start[1]:.6f},{start[0]:.6f}" + end_coord = f"{end[1]:.6f},{end[0]:.6f}" + return f"{host}/route/v1/driving/{start_coord};{end_coord}?overview=full&steps=true" + elif benchmark_name == 'table': + num_coords = random.randint(3, 100) + selected_coords = random.sample(self.coordinates, num_coords) + coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in selected_coords]) + return f"{host}/table/v1/driving/{coords_str}" + elif benchmark_name == 'match': + num_coords = random.randint(50, 100) + track_id = random.choice(self.track_ids) + track_coords = self.tracks[track_id][:num_coords] + coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in track_coords]) + radiues_str = ";".join([f"{random.randint(5, 20)}" for _ in range(len(track_coords))]) + return f"{host}/match/v1/driving/{coords_str}?steps=true&radiuses={radiues_str}" + elif benchmark_name == 'nearest': + coord = random.choice(self.coordinates) + coord_str = f"{coord[1]:.6f},{coord[0]:.6f}" + return f"{host}/nearest/v1/driving/{coord_str}" + elif benchmark_name == 'trip': + num_coords = random.randint(2, 10) + selected_coords = random.sample(self.coordinates, num_coords) + coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in selected_coords]) + return f"{host}/trip/v1/driving/{coords_str}?steps=true" + else: + raise Exception(f"Unknown benchmark: {benchmark_name}") + +def main(): + parser = argparse.ArgumentParser(description='Run GPS benchmark tests.') + parser.add_argument('--host', type=str, required=True, help='Host URL') + parser.add_argument('--method', type=str, required=True, choices=['route', 'table', 'match', 'nearest', 'trip'], help='Benchmark method') + parser.add_argument('--num_requests', type=int, required=True, help='Number of requests to perform') + + args = parser.parse_args() + + random.seed(42) + + runner = BenchmarkRunner() + times = runner.run(args.method, args.host, args.num_requests) + + print(f'Total: {np.sum(times)}ms') + print(f"Min time: {np.min(times)}ms") + print(f"Mean time: {np.mean(times)}ms") + print(f"Median time: {np.median(times)}ms") + print(f"95th percentile: {np.percentile(times, 95)}ms") + print(f"99th percentile: {np.percentile(times, 99)}ms") + print(f"Max time: {np.max(times)}ms") + +if __name__ == '__main__': + main() diff --git a/scripts/ci/locustfile.py b/scripts/ci/locustfile.py deleted file mode 100644 index cd46aaba9..000000000 --- a/scripts/ci/locustfile.py +++ /dev/null @@ -1,74 +0,0 @@ -from locust import HttpUser, TaskSet, task, between -import csv -import random -from collections import defaultdict -import os - -class OSRMTasks(TaskSet): - def on_start(self): - random.seed(42) - - self.coordinates = [] - self.tracks = defaultdict(list) - - gps_traces_file_path = os.path.expanduser('~/gps_traces.csv') - with open(gps_traces_file_path, 'r') as file: - reader = csv.DictReader(file) - for row in reader: - coord = (float(row['Latitude']), float(row['Longitude'])) - self.coordinates.append(coord) - self.tracks[row['TrackID']].append(coord) - self.track_ids = list(self.tracks.keys()) - - @task - def get_route(self): - start = random.choice(self.coordinates) - end = random.choice(self.coordinates) - - start_coord = f"{start[1]:.6f},{start[0]:.6f}" - end_coord = f"{end[1]:.6f},{end[0]:.6f}" - - self.client.get(f"/route/v1/driving/{start_coord};{end_coord}?overview=full&steps=true", name="route") - - @task - def get_table(self): - num_coords = random.randint(3, 100) - selected_coords = random.sample(self.coordinates, num_coords) - coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in selected_coords]) - - self.client.get(f"/table/v1/driving/{coords_str}", name="table") - - @task - def get_match(self): - num_coords = random.randint(50, 100) - track_id = random.choice(self.track_ids) - track_coords = self.tracks[track_id][:num_coords] - coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in track_coords]) - radiues_str = ";".join([f"{random.randint(5, 20)}" for _ in range(len(track_coords))]) - - with self.client.get(f"/match/v1/driving/{coords_str}?steps=true&radiuses={radiues_str}", name="match", catch_response=True) as response: - if response.status_code == 400: - j = response.json() - # it is expected that some of requests will fail with such error: map matching fails sometimes - if j['code'] == 'NoSegment' or j['code'] == 'NoMatch': - response.success() - - @task - def get_nearest(self): - coord = random.choice(self.coordinates) - coord_str = f"{coord[1]:.6f},{coord[0]:.6f}" - - self.client.get(f"/nearest/v1/driving/{coord_str}", name="nearest") - - @task - def get_trip(self): - num_coords = random.randint(2, 10) - selected_coords = random.sample(self.coordinates, num_coords) - coords_str = ";".join([f"{coord[1]:.6f},{coord[0]:.6f}" for coord in selected_coords]) - - self.client.get(f"/trip/v1/driving/{coords_str}?steps=true", name="trip") - -class OSRMUser(HttpUser): - tasks = [OSRMTasks] - # random wait time between requests to not load server for 100% - wait_time = between(0.05, 0.5) diff --git a/scripts/ci/process_locust_benchmark_results.py b/scripts/ci/process_locust_benchmark_results.py deleted file mode 100644 index ad71daf7f..000000000 --- a/scripts/ci/process_locust_benchmark_results.py +++ /dev/null @@ -1,31 +0,0 @@ -import sys -import csv - -def main(locust_csv_base_name, suffix, output_folder): - with open(f"{locust_csv_base_name}_stats.csv", 'r') as file: - reader = csv.DictReader(file) - for row in reader: - name = row['Name'] - if name == 'Aggregated': continue - - statistics = f''' -requests: {row['Request Count']} -failures: {row['Failure Count']} -req/s: {float(row['Requests/s']):.3f}req/s -avg: {float(row['Average Response Time']):.3f}ms -50%: {row['50%']}ms -75%: {row['75%']}ms -95%: {row['95%']}ms -98%: {row['98%']}ms -99%: {row['99%']}ms -min: {float(row['Min Response Time']):.3f}ms -max: {float(row['Max Response Time']):.3f}ms -''' - with open(f"{output_folder}/e2e_{name}_{suffix}.bench", 'w') as f: - f.write(statistics) - -if __name__ == '__main__': - if len(sys.argv) != 4: - print(f"Usage: {sys.argv[0]} ") - sys.exit(1) - main(sys.argv[1], sys.argv[2], sys.argv[3]) \ No newline at end of file diff --git a/scripts/ci/run_benchmarks.sh b/scripts/ci/run_benchmarks.sh index 51ced3d53..ffde03bf0 100755 --- a/scripts/ci/run_benchmarks.sh +++ b/scripts/ci/run_benchmarks.sh @@ -1,11 +1,24 @@ #!/bin/bash set -eou pipefail +function measure_peak_ram_and_time { + COMMAND=$1 + OUTPUT_FILE=$2 + + OUTPUT=$(/usr/bin/time -f "%e %M" $COMMAND 2>&1 | tail -n 1) + + TIME=$(echo $OUTPUT | awk '{print $1}') + PEAK_RAM_KB=$(echo $OUTPUT | awk '{print $2}') + PEAK_RAM_MB=$(echo "scale=2; $PEAK_RAM_KB / 1024" | bc) + echo "Time: ${TIME}s Peak RAM: ${PEAK_RAM_MB}MB" > $OUTPUT_FILE +} + function run_benchmarks_for_folder { echo "Running benchmarks for $1" FOLDER=$1 RESULTS_FOLDER=$2 + SCRIPTS_FOLDER=$3 mkdir -p $RESULTS_FOLDER @@ -23,37 +36,33 @@ function run_benchmarks_for_folder { BINARIES_FOLDER="$FOLDER/build" cp ~/data.osm.pbf $FOLDER - $BINARIES_FOLDER/osrm-extract -p $FOLDER/profiles/car.lua $FOLDER/data.osm.pbf - $BINARIES_FOLDER/osrm-partition $FOLDER/data.osrm - $BINARIES_FOLDER/osrm-customize $FOLDER/data.osrm - $BINARIES_FOLDER/osrm-contract $FOLDER/data.osrm - if [ -f "$FOLDER/scripts/ci/locustfile.py" ]; then - for ALGORITHM in mld ch; do - $BINARIES_FOLDER/osrm-routed --algorithm $ALGORITHM $FOLDER/data.osrm & - OSRM_ROUTED_PID=$! + measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-extract -p $FOLDER/profiles/car.lua $FOLDER/data.osm.pbf" "$RESULTS_FOLDER/osrm_extract.bench" + measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-partition $FOLDER/data.osrm" "$RESULTS_FOLDER/osrm_partition.bench" + measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-customize $FOLDER/data.osrm" "$RESULTS_FOLDER/osrm_customize.bench" + measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-contract $FOLDER/data.osrm" "$RESULTS_FOLDER/osrm_contract.bench" - # wait for osrm-routed to start - curl --retry-delay 3 --retry 10 --retry-all-errors "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true" - locust -f $FOLDER/scripts/ci/locustfile.py \ - --headless \ - --processes -1 \ - --users 10 \ - --spawn-rate 1 \ - --host http://localhost:5000 \ - --run-time 1m \ - --csv=locust_results_$ALGORITHM \ - --loglevel ERROR + for ALGORITHM in ch mld; do + $BINARIES_FOLDER/osrm-routed --algorithm $ALGORITHM $FOLDER/data.osrm & + OSRM_ROUTED_PID=$! - python3 $FOLDER/scripts/ci/process_locust_benchmark_results.py locust_results_$ALGORITHM $ALGORITHM $RESULTS_FOLDER + # wait for osrm-routed to start + if ! curl --retry-delay 3 --retry 10 --retry-all-errors "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"; then + echo "osrm-routed failed to start for algorithm $ALGORITHM" + kill -9 $OSRM_ROUTED_PID + continue + fi - - kill -0 $OSRM_ROUTED_PID + for METHOD in route nearest trip table match; do + python3 $SCRIPTS_FOLDER/scripts/ci/e2e_benchmark.py --host http://localhost:5000 --method $METHOD --num_requests 1000 > $RESULTS_FOLDER/e2e_${METHOD}_${ALGORITHM}.bench done - fi + + kill -9 $OSRM_ROUTED_PID + done + } -run_benchmarks_for_folder $1 "${1}_results" -run_benchmarks_for_folder $2 "${2}_results" +run_benchmarks_for_folder $1 "${1}_results" $2 +run_benchmarks_for_folder $2 "${2}_results" $2 diff --git a/src/server/connection.cpp b/src/server/connection.cpp index c3c07a340..acaed7ab6 100644 --- a/src/server/connection.cpp +++ b/src/server/connection.cpp @@ -186,6 +186,7 @@ void Connection::handle_timeout(boost::system::error_code ec) if (ec != boost::asio::error::operation_aborted) { boost::system::error_code ignore_error; + // NOLINTNEXTLINE(bugprone-unused-return-value) TCP_socket.cancel(ignore_error); handle_shutdown(); } @@ -197,6 +198,7 @@ void Connection::handle_shutdown() timer.cancel(); // Initiate graceful connection closure. boost::system::error_code ignore_error; + // NOLINTNEXTLINE(bugprone-unused-return-value) TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); } diff --git a/third_party/sol2/include/sol/sol.hpp b/third_party/sol2/include/sol/sol.hpp index 8b0b7d36e..d7da763f7 100644 --- a/third_party/sol2/include/sol/sol.hpp +++ b/third_party/sol2/include/sol/sol.hpp @@ -19416,7 +19416,14 @@ namespace sol { namespace function_detail { } template - static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { + static int call(lua_State* L) +// see https://github.com/ThePhD/sol2/issues/1581#issuecomment-2103463524 +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v) +#endif + { int nr; if constexpr (no_trampoline) { nr = real_call(L); @@ -19456,7 +19463,14 @@ namespace sol { namespace function_detail { } template - static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { + static int call(lua_State* L) +// see https://github.com/ThePhD/sol2/issues/1581#issuecomment-2103463524 +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v) +#endif + { int nr; if constexpr (no_trampoline) { nr = real_call(L); diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index 8773db6b7..27ba55d55 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -239,7 +239,6 @@ void test_route_same_coordinates(bool use_json_only_api) BOOST_CHECK(((void)name, true)); // nothing can be said about mode, contains mode of transportation - const auto mode = std::get(step_object.values.at("mode")).value; BOOST_CHECK(!name.empty()); const auto &maneuver = diff --git a/unit_tests/partitioner/bisection_graph_view.cpp b/unit_tests/partitioner/bisection_graph_view.cpp index b98ac9fae..7ebe285bb 100644 --- a/unit_tests/partitioner/bisection_graph_view.cpp +++ b/unit_tests/partitioner/bisection_graph_view.cpp @@ -16,12 +16,15 @@ using namespace osrm::util; BOOST_AUTO_TEST_SUITE(graph_view) -static void shuffle(std::vector &grid_edges) +namespace +{ +void shuffle(std::vector &grid_edges) { std::random_device rd; std::mt19937 rng(rd()); std::shuffle(grid_edges.begin(), grid_edges.end(), rng); } +} // namespace BOOST_AUTO_TEST_CASE(separate_top_bottom) { diff --git a/unit_tests/util/static_rtree.cpp b/unit_tests/util/static_rtree.cpp index 2557a2df9..c1b9b373a 100644 --- a/unit_tests/util/static_rtree.cpp +++ b/unit_tests/util/static_rtree.cpp @@ -235,8 +235,6 @@ auto make_rtree(const boost::filesystem::path &path, FixtureT &fixture) template void construction_test(const std::string &path, FixtureT &fixture) { - std::string leaves_path; - std::string nodes_path; auto rtree = make_rtree(path, fixture); LinearSearchNN lsnn(fixture.coords, fixture.edges);